Skip to content

Extract per-stage development-loop transition modules behind a stable barrel #99

Description

@ncolesummers

Problem

src/lib/loops/development-run-transitions.ts is 2,930 lines — ~3× the next-largest source file and ~15% of the entire src tree in a single module. It holds ~8 development-loop stage transitions of 200–520 lines each:

Stage fn ~size
recordDevelopmentLoopPlanArtifact 120
applyDevelopmentLoopTestWritingResult 250
applyDevelopmentLoopImplementationResult 300
applyDevelopmentLoopValidationReport 230
applyDevelopmentLoopPrPreparationResult 190
applyDevelopmentLoopValidationReviewResult 450
executeDevelopmentLoopPrStage 520
finalize / complete / retry 210

This is cohesive by domain (one loop state machine), so it is not a correctness or bloat problem. It is a devex/maintainability problem: two stage functions are each larger than the repo's median source file, and adding a new loop stage today means appending another ~300-line function to the monolith.

The strongest signal that the seams already exist: the test suite is already split per stagetest-writing-transition.test.ts, implementation-transition.test.ts, pr-stage.test.ts, pr-preparation-transition.test.ts, validation-review-transition.test.ts. The source module simply hasn't followed the decomposition the tests already assume.

Proposed shape

Extract per-stage modules and re-export through a barrel:

src/lib/loops/transitions/
  plan.ts
  test-writing.ts
  implementation.ts
  validation.ts
  pr-preparation.ts
  validation-review.ts
  pr-stage.ts
  finalization.ts        # finalize + complete + retry
  shared.ts              # cross-stage helpers
  index.ts               # re-exports current public surface

Cross-stage helpers that must live in shared.ts (used by multiple stages): durationSecondsBetween (7 refs), metadataWithoutBlockedReason (5 refs), validationReviewHistory (4 refs), plus the metadata/metrics helper cluster.

Constraints

  • Pure move-and-re-export. No behavior change, no transition-semantics change.
  • Preserve the public surface via index.ts so callers are untouched — specifically development-run-reconciliation.ts and development-run-reconciliation-store.ts, which import from the current module.
  • Per-stage source files should end up 1:1 with their existing per-stage test files.
  • Verify with bun run validate.

Not doing

  • Rewriting the state machine or changing any transition semantics.
  • Touching the reconciliation logic beyond its import path (which the barrel keeps stable).

Why M9

Not blocking any MVP milestone — the machine works today, so this doesn't belong in M3/M4. M9 is about adding new loop stages/extensions; every new stage currently grows the monolith, so this extraction is the natural enabling work for M9 rather than orphaned debt.

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:loopsLoop registry, manifests, and execution stages.priority:p1High priority after P0 work.

    Projects

    Status
    Todo

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions