Summary
During an active zstd-to-rust migration run, Phase 4 task completion is being reflected in reports/progress.md but not in state/checkpoint.json. This causes the human-readable progress report and the persisted resume state to diverge.
Observed Behavior
In the active fixture migration:
reports/progress.md contains completed task sections for:
task-188-0
task-182-0
task-171-0
- The same report still shows
0/312 tasks in the progress bar.
state/checkpoint.json has:
completedTasks: []
blockedTasks: []
failedTasks: []
- The nested Phase 4 flow checkpoint under
__phase4FlowCheckpoint contains extensive execution history, but that state is not reconciled into top-level completedTasks.
Expected Behavior
When a Phase 4 task completes successfully:
state.completedTasks should include the task ID.
- resume reconstruction should restore completed task state accurately.
reports/progress.md should show a consistent task count.
- task-level summaries and aggregate progress should come from a single source of truth, or at minimum stay synchronized.
Investigation Notes
Runtime completion path does not persist checkpoint task completion
In src/flow/steps/migration.ts, the task completion node updates the progress writer and emits a log event:
ctx.progress.updateTask(task.id, 'completed', ...)
ctx.logger.event({ type: 'task-completed', ... })
But it does not call ctx.checkpoint.completeTask(task.id, ...), which is the code path that actually appends to state.completedTasks.
Checkpoint logic exists but is not used here
src/core/checkpoint.ts already has completeTask(taskId, durationMs?), which:
- pushes the task ID into
completedTasks
- removes stale failed/blocked state
- records
phaseCursors['4'].tasks[taskId].completedSubsteps += 'completed'
That logic appears to be bypassed by the Phase 4 completion node.
Resume reconstruction depends on completedTasks
src/core/progress.ts reconstructs completed task state from state.completedTasks on resume. Because that array remains empty, the progress writer reconstructs an empty task set and derives an incorrect initial task-progress count.
progress.md has split ownership
The runtime owns aggregate progress rendering in ProgressWriter, but the code-migrator prompt also instructs agents to directly update .aamf/migration/{projectName}/reports/progress.md with task summaries.
That means the current report can contain:
- runtime-generated aggregate sections
- agent-written per-task summaries
This matches the live report, which had both:
- a runtime header and progress bar showing
0/312
- agent-authored
### Task ... completed sections
Evidence
Active fixture path:
tests/fixtures/zstd-c-project/.aamf/migration/zstd-to-rust/state/checkpoint.json
tests/fixtures/zstd-c-project/.aamf/migration/zstd-to-rust/reports/progress.md
Repository paths involved:
src/flow/steps/migration.ts
src/core/checkpoint.ts
src/core/progress.ts
src/flow/checkpoint-adapter.ts
agents/templates/code-migrator.md
Impact
- Resume state undercounts or loses completed Phase 4 work.
- Progress reporting becomes unreliable during long-running migrations.
- Observers may see completed task summaries alongside a zero-progress counter.
- Any logic depending on
completedTasks can behave as if no work has completed yet.
Minimal Reproduction Direction
- Run the
zstd-to-rust fixture migration in Phase 4.
- Allow a few tasks to complete.
- Inspect
reports/progress.md and state/checkpoint.json.
- Observe completed task summaries in the report while
completedTasks remains empty and the progress bar remains at 0/N.
Notes
This issue is based on investigation only. No code changes were made as part of the analysis.
Summary
During an active
zstd-to-rustmigration run, Phase 4 task completion is being reflected inreports/progress.mdbut not instate/checkpoint.json. This causes the human-readable progress report and the persisted resume state to diverge.Observed Behavior
In the active fixture migration:
reports/progress.mdcontains completed task sections for:task-188-0task-182-0task-171-00/312 tasksin the progress bar.state/checkpoint.jsonhas:completedTasks: []blockedTasks: []failedTasks: []__phase4FlowCheckpointcontains extensive execution history, but that state is not reconciled into top-levelcompletedTasks.Expected Behavior
When a Phase 4 task completes successfully:
state.completedTasksshould include the task ID.reports/progress.mdshould show a consistent task count.Investigation Notes
Runtime completion path does not persist checkpoint task completion
In
src/flow/steps/migration.ts, the task completion node updates the progress writer and emits a log event:ctx.progress.updateTask(task.id, 'completed', ...)ctx.logger.event({ type: 'task-completed', ... })But it does not call
ctx.checkpoint.completeTask(task.id, ...), which is the code path that actually appends tostate.completedTasks.Checkpoint logic exists but is not used here
src/core/checkpoint.tsalready hascompleteTask(taskId, durationMs?), which:completedTasksphaseCursors['4'].tasks[taskId].completedSubsteps += 'completed'That logic appears to be bypassed by the Phase 4 completion node.
Resume reconstruction depends on
completedTaskssrc/core/progress.tsreconstructs completed task state fromstate.completedTaskson resume. Because that array remains empty, the progress writer reconstructs an empty task set and derives an incorrect initial task-progress count.progress.mdhas split ownershipThe runtime owns aggregate progress rendering in
ProgressWriter, but thecode-migratorprompt also instructs agents to directly update.aamf/migration/{projectName}/reports/progress.mdwith task summaries.That means the current report can contain:
This matches the live report, which had both:
0/312### Task ...completed sectionsEvidence
Active fixture path:
tests/fixtures/zstd-c-project/.aamf/migration/zstd-to-rust/state/checkpoint.jsontests/fixtures/zstd-c-project/.aamf/migration/zstd-to-rust/reports/progress.mdRepository paths involved:
src/flow/steps/migration.tssrc/core/checkpoint.tssrc/core/progress.tssrc/flow/checkpoint-adapter.tsagents/templates/code-migrator.mdImpact
completedTaskscan behave as if no work has completed yet.Minimal Reproduction Direction
zstd-to-rustfixture migration in Phase 4.reports/progress.mdandstate/checkpoint.json.completedTasksremains empty and the progress bar remains at0/N.Notes
This issue is based on investigation only. No code changes were made as part of the analysis.