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 stage — test-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.
Problem
src/lib/loops/development-run-transitions.tsis 2,930 lines — ~3× the next-largest source file and ~15% of the entiresrctree in a single module. It holds ~8 development-loop stage transitions of 200–520 lines each:recordDevelopmentLoopPlanArtifactapplyDevelopmentLoopTestWritingResultapplyDevelopmentLoopImplementationResultapplyDevelopmentLoopValidationReportapplyDevelopmentLoopPrPreparationResultapplyDevelopmentLoopValidationReviewResultexecuteDevelopmentLoopPrStagefinalize/complete/retryThis 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 stage —
test-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:
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
index.tsso callers are untouched — specificallydevelopment-run-reconciliation.tsanddevelopment-run-reconciliation-store.ts, which import from the current module.bun run validate.Not doing
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.