diff --git a/.changeset/vivid-moles-chatter.md b/.changeset/vivid-moles-chatter.md new file mode 100644 index 000000000..b0422f200 --- /dev/null +++ b/.changeset/vivid-moles-chatter.md @@ -0,0 +1,6 @@ +--- +type: Changed +pr: 3439 +--- +**`/gsd-progress` no longer implies re-execution when only the verification report is missing** — the routing message now explains that running `/gsd-execute-phase` on a historical phase resumes at the verification gates and does not re-run already-summarized plans, and softens the unrecognized-status message to acknowledge an intentional non-standard marker. (#1762) + diff --git a/gsd-core/workflows/progress.md b/gsd-core/workflows/progress.md index 7728a9324..6fbc1bcfe 100644 --- a/gsd-core/workflows/progress.md +++ b/gsd-core/workflows/progress.md @@ -458,7 +458,17 @@ UAT.md exists with `status: partial` — testing session ended before all items All plans have summaries, but canonical verification has not passed. The phase is implementation-complete, not phase-complete. ``` -`/gsd:execute-phase {phase} ${GSD_WS}` — re-run execution verification +--- + +## Verification Report Missing + +**Phase {phase}** has all plans summarized, but no canonical `*-VERIFICATION.md` exists yet. ${VERIFICATION_NEXT_ACTION} + +`/clear` then: + +`/gsd:execute-phase {phase} ${GSD_WS}` — resumes at the verification gates + +--- ``` --- @@ -468,7 +478,17 @@ All plans have summaries, but canonical verification has not passed. The phase i VERIFICATION.md has an unexpected status. The phase is implementation-complete, not phase-complete. ``` +--- + +## Verification Status Unexpected + +**Phase {phase}** has all plans summarized, but its `*-VERIFICATION.md` reports an unexpected status. ${VERIFICATION_NEXT_ACTION} + +`/clear` then: + `/gsd:execute-phase {phase} ${GSD_WS}` — regenerate verification + +--- ``` --- diff --git a/src/verification.cts b/src/verification.cts index 3d7c014e4..d1eeae196 100644 --- a/src/verification.cts +++ b/src/verification.cts @@ -113,7 +113,7 @@ const VERIFICATION_ROUTING_TABLE: Record = { // the file has no parseable frontmatter status. Never emitted by the verifier. missing: { status: 'missing', - next_action: 'No verification report found — the verify step never completed. Re-run execute-phase.', + next_action: 'No verification report found — the verify step never completed. Running execute-phase is safe here: it resumes at the verification gates and does not re-run plans that already have a SUMMARY.md (see #2868).', next_command: 'execute-phase', }, // INTERNAL SENTINEL: constructed when the file has a status value not in @@ -504,7 +504,7 @@ function readVerificationStatus( const unknownRoute = VERIFICATION_ROUTING_TABLE['unknown']; return { status: unknownRoute.status, - next_action: `Unexpected verification status '${rawStatus}'. Re-run execute-phase verification.`, + next_action: `Unexpected verification status '${rawStatus}'. If this is an intentional non-standard marker (e.g. a hand-set failed/superseded state), no action is needed. Otherwise, run execute-phase to regenerate verification — it will not re-run plans that already have a SUMMARY.md.`, next_command: projectNextCommand(unknownRoute.next_command, runtime, phaseArg), ...(staleCheckIndeterminate ? { staleCheckIndeterminate: true } : {}), }; diff --git a/tests/emitted-drift-acks/1762-verification-routing-wording.json b/tests/emitted-drift-acks/1762-verification-routing-wording.json new file mode 100644 index 000000000..0d199358b --- /dev/null +++ b/tests/emitted-drift-acks/1762-verification-routing-wording.json @@ -0,0 +1 @@ +{"version":1,"paths":{"progress.md":{"reason":"#1762: Route V.missing and Route V.unknown now consume the dynamic ${VERIFICATION_NEXT_ACTION} block (matching the existing V.gaps/V.human format) instead of a hardcoded duplicate string, so the routing text stays reassuring and in sync with src/verification.cts's reworded next_action — deliberate growth, not drift."}}} diff --git a/tests/emitted-drift-acks/3218-prompt-layer-plan-counts.json b/tests/emitted-drift-acks/3218-prompt-layer-plan-counts.json index d1c2fb591..8f2b4a6c7 100644 --- a/tests/emitted-drift-acks/3218-prompt-layer-plan-counts.json +++ b/tests/emitted-drift-acks/3218-prompt-layer-plan-counts.json @@ -6,9 +6,6 @@ }, "plan-review-convergence.md": { "reason": "Issue #3218 (epic #3180 phase 8): replaced a raw `ls *-PLAN.md | wc -l` re-derivation with a `gsd_run query find-phase` call plus jq extraction of the count field, routing the plan count through scanPhasePlans (ADR-3180 §7.5) so superseded plans are excluded and the review converges on the live set." - }, - "progress.md": { - "reason": "Issue #3218 (epic #3180 phase 8): replaced a raw `ls *-PLAN.md | wc -l` re-derivation with a `gsd_run query find-phase` call plus jq extraction of the count field, and additionally carries the Route-0 dead-path fix (a branch that previously reported zero plans on the nested plans/ layout is now reachable and correct)." } } } diff --git a/tests/verification-status.test.cjs b/tests/verification-status.test.cjs index 68784ffa4..9e45b8d44 100644 --- a/tests/verification-status.test.cjs +++ b/tests/verification-status.test.cjs @@ -138,6 +138,10 @@ describe('verification-status', () => { assert.equal(result.status, 'missing'); assert.equal(result.next_command, '/gsd-execute-phase'); assert.ok(result.next_action.includes('verify step never completed')); + assert.ok( + result.next_action.includes('does not re-run plans that already have a SUMMARY.md'), + `next_action must reassure the user execute-phase will not redo work (#1762); got: ${result.next_action}`, + ); } finally { cleanup(dir); } @@ -155,6 +159,10 @@ describe('verification-status', () => { result.next_action.includes('bogus'), `next_action should mention the raw value; got: ${result.next_action}`, ); + assert.ok( + result.next_action.includes('intentional non-standard marker'), + `next_action must acknowledge an unrecognized status may be an intentional marker (#1762); got: ${result.next_action}`, + ); } finally { cleanup(dir); }