* fix(#3127): make state.begin-phase idempotent on mid-flight phases Root cause: cmdStateBeginPhase() unconditionally overwrote execution- progress fields regardless of current phase status. When execute-phase called it on a phase already mid-flight (--wave N resume), it regressed: - Current Plan to 1 (from e.g. 3) - Last Activity Description to 'context gathered; ready for plan-phase' - Plan: N of M body line to 'Plan: 1 of M' - last_updated timestamp to an older value - progress.percent could decrease Fix: read Status field before writing. If phase is already executing (Status: Executing Phase N), skip execution-progress fields and only update fields safe on resume: - Last Activity date (always safe) - Resume-specific 'execution resumed (wave continue)' activity line First-time execution (Status != Executing Phase N) writes all fields as before -- no regression on the normal path. Regression test: 4 real unit tests using synthetic STATE.md files: - mid-flight phase does not reset Current Plan (was the bug) - mid-flight phase does not overwrite stopped_at narrative - fresh phase sets Current Plan to 1 (normal path, no regression) - both paths update Last Activity date (safe field) Suite: 6990/6990. Closes #3127. * fix(lint+state): allow-test-rule, escapeRegex phaseNumber in idempotency guard
650 B
650 B
type, pr
| type | pr |
|---|---|
| Fixed | 3127 |
state.begin-phase is now idempotent — when called on a phase already in-flight (e.g. --wave N resume), it no longer overwrites Current Plan, stopped_at narrative, Plan: N of M body line, or Last Activity Description with stale values from the last plan-phase run. An idempotency guard reads the current Status field before writing: if it already contains Executing Phase N, only the Last Activity date and a resume-specific activity line are updated; all execution-progress fields are preserved. First-time execution (Status ≠ Executing) continues to write all fields as before. Closes #3127.