Skip to content

Contributing

albertoodev edited this page Jul 21, 2026 · 6 revisions

Contributing

Thanks for considering a contribution to SPM. This page covers the workflow and the project-specific conventions a change is expected to follow. For build/test commands and the testing rules in depth, see Development; for the layer model, see Architecture.

Getting set up

git clone https://github.com/albertoodev/spm.git
cd spm
dart pub get
dart analyze     # must be clean
dart test        # must be green

Requirements match the rest of the toolchain: Dart SDK ≥ 3.9, Flutter ≥ 3.3.

Before you open a PR

Run the full local gate. A change is not ready until all three pass:

dart analyze                  # zero issues
dart test                     # all tests green
dart format .                 # formatted

A PR is expected to:

  • keep dart analyze clean and dart test green;
  • add or update tests for the behavior it changes (see the per-area guides below);
  • stay within one feature module where possible, since analysis/, isolation/, injection/, profiler/, and validation/ are independent;
  • follow the code conventions below.

Use a topic branch (not master) and keep the commit history readable.

Code conventions

These are enforced by review, and most are called out in Architecture / Development:

  • Type aliases. Use the aliases in core/types.dart (Result<T>, AsyncResult<T>, AsyncVoidResult, AsyncVoid, JsonRecord, …); never spell the full types out inline.
  • Error handling. Return Either<Failure, T> (Left is the error case) throughout the data and domain layers. Only throw at the outermost CLI boundary. Data sources may throw; the repository layer maps those exceptions to a typed Failure.
  • New error types go in core/errors/failures.dart as a Failure subclass; aggregate several with CompoundFailure.
  • Logging goes through SpmLogger, never print.
  • DI. Each feature has a static service locator (AnalysisDI, IsolationDI, InjectionDI, ValidationDI) built on lazy ??= getters. When wiring a new dependency, add it there.

Testing conventions

The suite has firm rules, so read Development before writing tests. The essentials:

  • Hand-written fakes only, never mocks. Implement the repository/data-source interface directly. Repository fakes expose givenSuccess() / givenFailure(Failure); data-source fakes expose givenSuccess() / givenThrows(Exception).
  • Copy list references when capturing call arguments in a fake: List.of(targets).
  • Async exception tests are async and await the call inside a try/catch.
  • File-I/O tests create a Directory.systemTemp.createTempSync(...) in setUp and delete it in tearDown. Never write test artifacts into the repo.
  • When testing through the DI layer, call the feature DI's reset() in setUp/tearDown.

Adding to a feature

A new analysis metric / extractor

  1. Add a fixture Dart file under test/fixtures/analysis/ that exercises the case.
  2. Add the extractor/visitor in the relevant analysis/data/data_sources/ set.
  3. If it produces a new output field, add it to AnalysisResultModel.toJson and document it in Output Formats and Extracted Features. The wiki lists the exact field set, so a new key must land in both.
  4. Add a test under test/features/analysis/, preferring getResultsForFixture(...) from test/features/analysis/utils/test_helper.dart over re-wiring the pipeline.

A new isolation pattern

  1. Add a realistic fixture under test/fixtures/isolation/.
  2. Teach the rebuild-scope visitor about the new builder/class pattern.
  3. Add a test under test/features/isolation/.

A new validation check

  1. Add the code to the ViolationCode enum in validation/domain/entities/validation_report.dart (keep the JSON schema stable).
  2. Implement the check so it appends a Violation{code, severity, detail}.
  3. Add a fixture case under test/fixtures/validation/<case>/{base.dart, mutation.dart} proving the violation, and a test under test/features/validation/.
  4. Update validate and Validate: AST Internals to move the code from the "not yet implemented" list into the checks table.

Keeping docs in sync

This wiki documents exact field names and schemas taken from the code. If your change touches a toJson, a CLI flag, an event name, or a Failure/ViolationCode, update the corresponding wiki page in the same PR so the two never drift.

Clone this wiki locally