Skip to content

refactor(flow): replace Phase 5 step with Cadre subflow primitive#179

Open
jafreck wants to merge 1 commit intomainfrom
refactor/phase5-subflow
Open

refactor(flow): replace Phase 5 step with Cadre subflow primitive#179
jafreck wants to merge 1 commit intomainfrom
refactor/phase5-subflow

Conversation

@jafreck
Copy link
Owner

@jafreck jafreck commented Mar 20, 2026

Summary

Replace the manual FlowRunner.run() inside executeIterativeMigration() with the framework's declarative subflow() node from @cadre-dev/framework. Phase 5's iterative migration is now expressed as a first-class child flow in the pipeline DSL rather than an opaque step that internally spawns its own runner.

Motivation

executeIterativeMigration was a step() that internally built a FlowDefinition, instantiated its own FlowRunner, and managed checkpoint/concurrency manually — exactly the pattern subflow() was designed to replace. With subflow(), the parent flow's runner manages the child flow lifecycle, checkpoint propagation, abort signal forwarding, and error handling automatically.

Changes

src/flow/migration-flow.ts

  • Replace step() for 'iterative-migration' with subflow() using a flow thunk
  • The thunk dynamically builds the child flow via buildPhase5Subflow() and populates runner options (checkpoint adapter + concurrency) before execution
  • contextMap identity-maps MigrationFlowContext (same type for parent and child)
  • Remove unused fromStep, PhaseResult imports

src/flow/steps/migration.ts

  • Extract discoverTasks() and sortTasksSccAware() as internal helpers
  • Export buildPhase5Subflow() — task discovery, SCC-aware sort, cost projection, and child flow construction (per-task or wave-barrier)
  • Export computePhase5Concurrency() and computePhase5RunnerOptions()
  • Delete executeIterativeMigration() — no longer needed

Tests

  • Replace all executeIterativeMigration() calls with local runPhase5() helpers that call buildPhase5Subflow() + FlowRunner.run() directly
  • Update assertions from PhaseResult (.success / .phase) to FlowRunResult (.status)

Verification

  • tsc --noEmit — clean
  • 254/254 flow tests pass
  • Zero remaining references to executeIterativeMigration in the codebase

Replace the manual FlowRunner.run() inside executeIterativeMigration()
with the framework's declarative subflow() node, which was added in
@cadre-dev/framework v0.2.1.

migration-flow.ts:
- Import subflow from @cadre-dev/framework/flow
- Replace step() for 'iterative-migration' with subflow() that uses a
  flow thunk to dynamically build the Phase 5 child flow
- contextMap identity-maps MigrationFlowContext to the child
- Shared mutable _phase5RunnerOpts ref populated by the thunk before
  the runner reads it (per runner execution contract)
- Remove unused fromStep, PhaseResult imports

migration.ts:
- Extract discoverTasks() and sortTasksSccAware() helpers
- Export buildPhase5Subflow() — task discovery, SCC-aware sort, cost
  projection, and child flow construction (per-task or wave-barrier)
- Export computePhase5Concurrency() and computePhase5RunnerOptions()
- Remove executeIterativeMigra- Remove executeIterativeMigra- Remove executeIterativeMigra- RemovTerminalExhaustionError imports

Tests:
- Replace al- Replace al- Replace al- Replace al- Replace al- Replace al- Rlpers th- Replace al- Replace al- Replace al- Replace al- Replace al- Rte as- Replace al- Replace al- (.su- Replace al- to
  FlowRunResult (.status)
@jafreck jafreck force-pushed the refactor/phase5-subflow branch from 503e1af to f0f1222 Compare March 20, 2026 08:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant