The orchestratePhase() function runs one phase per tick using the phase-state machine:
.meta/meta.json files (no Qdrant dependency)meta.json for each discovered pathderivePhaseState() reconstructs _phaseState from legacy fields on first loadfailed → pendingselectPhaseCandidate() picks the highest-priority owed phase across the corpus (critic > builder > architect, weighted staleness tiebreak)runArchitect, runBuilder, or runCritic_phaseState and phase outputfresh, create snapshot and pruneEach meta carries _phaseState: { architect, builder, critic } where each value is one of: fresh, stale, pending, running, failed.
Key transitions:
architect: stale (cascade: builder: pending, critic: pending)architect: fresh (cascade: builder: pending if was stale)builder: fresh, critic: pendingcritic: fresh; if all three fresh → full-cycle complete (archive + increment _synthesisCount)failed; other phases untouched (surgical retry)failed phases promoted to pending for auto-retry| Module | Responsibility |
|---|---|
orchestratePhase.ts |
Per-tick driver: discover → derive → select → execute one phase |
runPhase.ts |
Per-phase executors: runArchitect, runBuilder, runCritic |
synthesizeNode.ts |
Legacy single-node full pipeline (retained for compatibility) |
finalizeCycle.ts |
Legacy lock-staged writes |
failed; other phases are untouchedpending on the next scheduler tickSpawnTimeoutError): attempts to salvage advanced _state from partial output; if _state progressed, it is persisted alongside the failed phase stateResults are staged in .lock before being committed to meta.json. If the process crashes:
meta.json is untouchedmeta.json is untouched; stale .lock cleaned at next startup