Skip to content

Phase 4 task completion is not persisted to checkpoint, causing progress.md and resume state to diverge #206

Description

@jafreck

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

  1. Run the zstd-to-rust fixture migration in Phase 4.
  2. Allow a few tasks to complete.
  3. Inspect reports/progress.md and state/checkpoint.json.
  4. 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions