fix(#1921): preserve verify-work state across gap-closure + defer follow-ups (#2025)

* fix(#1921): preserve verify-work state across gap-closure + defer follow-ups

Resuming /gsd:verify-work after /gsd:execute-phase --gaps-only lost the
verification state: UAT ## Gaps still read status: failed even after their
fix plans executed, so verify-work re-diagnosed them as fresh blockers,
spawned a new gap plan, and reported only the new plan verified. A new
state contract links each gap to its fix plan so fixed gaps are recognized.

- verify-work.md gap YAML: stable gap_id (G-{phase}-{N}) per gap.
- plan_gap_closure planner prompt: each *-PLAN.md tags the gap_ids it
  addresses in its frontmatter (gap_closure: true, gap_ids: [...]).
- new reconcile_gaps step (run at resume_from_file entry): marks a gap
  status: resolved when its plan has a matching *-SUMMARY.md — fixed gaps
  are not re-diagnosed and do not spawn new gap plans; a re-reported break
  is treated as a fresh regression with a new gap_id.
- deferred-follow-up branch: a future-work idea (signals: 'later',
  'next version', 'out of scope', ...) is captured to UAT ## Deferred
  Follow-Ups instead of becoming a blocking gap/plan.
- workflow-size baseline recaptured (verify-work LARGE tier, 38221/61440).

Closes #1921

* docs(#1921): backfill changeset pr 2025

* fix(#1921): balance <step> tags in verify-work.md via 4-backtick outer fence

The plan_gap_closure step nested a ```yaml example inside a ``` block;
same-length fences made stripFencedCode close the outer block early,
swallowing the step's </step> (14 opens / 13 closes). Widen the outer
fence to 4 backticks so the nested yaml is contained. Regenerate golden
fixtures + size baselines.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Tom Boucher
2026-07-05 15:42:10 -04:00
committed by GitHub
parent ed79902509
commit 1bfadec2d0
18 changed files with 82 additions and 19 deletions

View File

@@ -0,0 +1,5 @@
---
type: Fixed
pr: 2025
---
**`/gsd:verify-work` preserves verification state across gap-closure execution and no longer auto-promotes deferred follow-ups into blocking gaps** — resuming after `/gsd:execute-phase --gaps-only` used to lose the verification state: the UAT `## Gaps` still read `status: failed` even after their fix plans executed, so verify-work re-diagnosed them as fresh blockers, spawned a new gap plan, and reported only the new plan as verified. A state contract now links each gap to its fix plan: every UAT gap carries a stable `gap_id` (`G-{phase}-{N}`), gap-closure plans tag the ids they address in their frontmatter (`gap_ids: […]`), and a new `reconcile_gaps` step on resume marks a gap `status: resolved` when its plan has a matching `*-SUMMARY.md` — so fixed gaps aren't re-diagnosed and the phase can close. Separately, a deferred-follow-up branch captures future-work ideas (signals like "later", "next version", "out of scope") into a `## Deferred Follow-Ups` section instead of creating a blocking gap/plan. (#1921)

View File

@@ -372,6 +372,28 @@ reason: "{verbatim user response}"
Note: Blocked tests do NOT go into the Gaps section (they aren't code issues — they're prerequisite gates).
**If response indicates a deferred follow-up (NOT a current-phase blocker):**
- "later", "future", "follow-up", "next version", "out of scope", "nice to have", "not now", "defer", "down the road", "separate phase", "phase 2"
These are future-work ideas, not code issues for the current phase. Capture them WITHOUT creating a gap plan (#1921 — a deferred follow-up must never become a blocking gap or spawn a fix plan):
Update Tests section:
```
### {N}. {name}
expected: {expected}
result: skipped
reason: "Deferred follow-up: {verbatim user response}"
```
Append to UAT.md `## Deferred Follow-Ups` (create the section if absent):
```yaml
- test: {N}
idea: "{verbatim user response}"
deferred_at: {today}
```
Do NOT append to `## Gaps` — deferred follow-ups are not blocking gaps. Continue to the next test.
**If response is anything else:**
- Treat as issue description
@@ -393,7 +415,8 @@ severity: {inferred}
Append to Gaps section (structured YAML for plan-phase --gaps):
```yaml
- truth: "{expected behavior from test}"
- gap_id: G-{phase}-{N} # Stable id (phase + test number) — gap-closure plans tag it in their frontmatter so verify-work can reconcile resolved gaps on resume (#1921).
truth: "{expected behavior from test}"
status: failed
reason: "User reported: {verbatim user response}"
severity: {inferred}
@@ -411,9 +434,35 @@ If more tests remain → Update Current Test, go to `present_test`
If no more tests → Go to `complete_session`
</step>
<step name="reconcile_gaps">
**Reconcile diagnosed gaps against completed gap-closure plans (#1921):**
When verify-work resumes after `/gsd:execute-phase --gaps-only`, the UAT `## Gaps` entries still read `status: failed` even though their fix plans have executed. Without reconciliation verify-work re-diagnoses them as fresh blockers and spawns new gap plans — losing the verification state. This step closes the loop.
Read the UAT `## Gaps` section and the phase dir `*-PLAN.md` frontmatter. For each gap with `status: failed`:
1. Find a `*-PLAN.md` whose frontmatter `gap_ids` includes the gap's `gap_id` (`G-{phase}-{N}`).
2. If such a plan exists AND has a matching `*-SUMMARY.md` in the phase dir (the plan was executed by `--gaps-only`), the gap is **resolved** — update its YAML in place:
```yaml
- gap_id: G-{phase}-{N}
status: resolved # was: failed
resolved_by: {plan basename}
resolved_at: {today}
```
3. If no plan references the `gap_id`, or the plan has no SUMMARY, leave the gap `status: failed` (still open).
Read plan frontmatter directly in-context — do not pipe it through a shell parser. After reconciliation, announce:
```
Reconciled gap-closure state: {resolved_count} gap(s) resolved by executed plans, {open_count} still open.
```
Resolved gaps are NOT re-diagnosed and do NOT spawn new gap plans. If the user later reports the same behavior as still broken, treat it as a new issue (a regression) with a fresh `gap_id`.
</step>
<step name="resume_from_file">
**Resume testing from UAT file:**
**First run `reconcile_gaps`** (above) so gaps already fixed by `/gsd:execute-phase --gaps-only` are marked `resolved` before testing resumes (#1921).
Read the full UAT file.
Find first test with `result: [pending]`.
@@ -652,7 +701,7 @@ Display:
Spawn gsd-planner in --gaps mode:
```
````
Agent(
prompt="""
<planning_context>
@@ -673,13 +722,22 @@ ${AGENT_SKILLS_PLANNER}
<downstream_consumer>
Output consumed by /gsd:execute-phase
Plans must be executable prompts.
**Gap linkage (#1921):** each created `*-PLAN.md` MUST list the UAT gap ids it addresses in its frontmatter:
```yaml
---
gap_closure: true
gap_ids: [G-{phase}-{N}, ...] # the ## Gaps gap_id values this plan fixes
---
```
This lets `/gsd:verify-work` reconcile resolved gaps on resume (a gap whose plan has a matching `*-SUMMARY.md` is marked `status: resolved`, not re-diagnosed as a fresh blocker).
</downstream_consumer>
""",
subagent_type="gsd-planner",
model="{planner_model}",
description="Plan gap fixes for Phase {phase}"
)
```
````
> **ORCHESTRATOR RULE — CODEX RUNTIME**: After calling Agent() above, stop working on this task immediately. Do not read more files, edit code, or run tests related to this task while the subagent is active. Wait for the subagent to return its result. This prevents duplicate work, conflicting edits, and wasted context. Only resume when the subagent result is available.

View File

@@ -303,7 +303,7 @@
"gsd-core/workflows/update.md": "2c58df5e21c41c31",
"gsd-core/workflows/validate-phase.md": "6c0ab739d15709fa",
"gsd-core/workflows/verify-phase.md": "8070a098ab538b33",
"gsd-core/workflows/verify-work.md": "d8e44ebee36b01e5",
"gsd-core/workflows/verify-work.md": "be699ed7920f61b0",
"hooks/gsd-check-update-worker.js": "fa301e6366270d5f",
"hooks/gsd-check-update.js": "4617a98bf529e4c3",
"hooks/gsd-config-reload.js": "96546e0e8bb47904",

View File

@@ -373,7 +373,7 @@
"gsd-core/workflows/update.md": "fd160e13f8b7e83c",
"gsd-core/workflows/validate-phase.md": "2c6d7671fcaabcaa",
"gsd-core/workflows/verify-phase.md": "98a995046bdb6c3c",
"gsd-core/workflows/verify-work.md": "5ed471293dc6835f",
"gsd-core/workflows/verify-work.md": "34e980a6950cd83c",
"hooks/gsd-check-update-worker.js": "cc1ef5f840f9dfc9",
"hooks/gsd-check-update.js": "7b3a7983d5f1f5d3",
"hooks/gsd-config-reload.js": "96546e0e8bb47904",

View File

@@ -302,7 +302,7 @@
"gsd-core/workflows/update.md": "f9e7d8a760d0d3c8",
"gsd-core/workflows/validate-phase.md": "2ac231dc541441c2",
"gsd-core/workflows/verify-phase.md": "0d4ffabc1caa473a",
"gsd-core/workflows/verify-work.md": "2b49359ed055f9c4",
"gsd-core/workflows/verify-work.md": "efe57bdbbb3af03f",
"hooks/gsd-check-update-worker.js": "a530efdb5fdc0da3",
"hooks/gsd-check-update.js": "25cde66a12d6b886",
"hooks/gsd-config-reload.js": "96546e0e8bb47904",

View File

@@ -306,7 +306,7 @@
"gsd-core/workflows/update.md": "165beec33490bd28",
"gsd-core/workflows/validate-phase.md": "5b4ae14c87859bd2",
"gsd-core/workflows/verify-phase.md": "20e90407e1e531fc",
"gsd-core/workflows/verify-work.md": "343a1c8615c06c2b",
"gsd-core/workflows/verify-work.md": "6fa216623778c541",
"scripts/changeset/README.md": "86ff89331dfd94b2",
"scripts/changeset/cli.cjs": "68f92a344b199271",
"scripts/changeset/github-release-notes.cjs": "795677f0c009b132",

View File

@@ -373,7 +373,7 @@
"gsd-core/workflows/update.md": "5ff1f77222977648",
"gsd-core/workflows/validate-phase.md": "2c6d7671fcaabcaa",
"gsd-core/workflows/verify-phase.md": "98a995046bdb6c3c",
"gsd-core/workflows/verify-work.md": "5ed471293dc6835f",
"gsd-core/workflows/verify-work.md": "34e980a6950cd83c",
"hooks/gsd-check-update-worker.js": "bdc9324a2f080ddd",
"hooks/gsd-check-update.js": "b7669f605631e506",
"hooks/gsd-config-reload.js": "96546e0e8bb47904",

View File

@@ -338,7 +338,7 @@
"gsd-core/workflows/update.md": "5c35c0ec0f462ea6",
"gsd-core/workflows/validate-phase.md": "020201a41049679f",
"gsd-core/workflows/verify-phase.md": "b9f70235e777aa81",
"gsd-core/workflows/verify-work.md": "d24a21519c50b1f8",
"gsd-core/workflows/verify-work.md": "69e27f6f419d0bba",
"hooks/gsd-check-update.js": "ef48957eb6ac6a10",
"hooks/gsd-context-monitor.js": "76fecaaa2babd6c1",
"scripts/changeset/README.md": "86ff89331dfd94b2",

View File

@@ -304,7 +304,7 @@
"gsd-core/workflows/update.md": "f444a7cfcd246cfb",
"gsd-core/workflows/validate-phase.md": "2f705775a4b76d42",
"gsd-core/workflows/verify-phase.md": "59d1046b3a2bc481",
"gsd-core/workflows/verify-work.md": "74d024e92d8ca2b0",
"gsd-core/workflows/verify-work.md": "58e9b1b16f773b53",
"hooks/gsd-session.json": "0a462834f2a28fee",
"scripts/changeset/README.md": "86ff89331dfd94b2",
"scripts/changeset/cli.cjs": "68f92a344b199271",

View File

@@ -373,7 +373,7 @@
"gsd-core/workflows/update.md": "23e294ba707c3580",
"gsd-core/workflows/validate-phase.md": "2df0c6e298a5f249",
"gsd-core/workflows/verify-phase.md": "0d4ffabc1caa473a",
"gsd-core/workflows/verify-work.md": "74f5f7349ea9f757",
"gsd-core/workflows/verify-work.md": "145596b2542c457a",
"hooks/gsd-cursor-post-tool.js": "019d503aee8b4a3f",
"hooks/gsd-cursor-session-start.js": "c6e04ed597ea7020",
"scripts/changeset/README.md": "86ff89331dfd94b2",

View File

@@ -303,7 +303,7 @@
"gsd-core/workflows/update.md": "7499bb4cb2a3ce6f",
"gsd-core/workflows/validate-phase.md": "75e8971d3981d06b",
"gsd-core/workflows/verify-phase.md": "84e00bd685006870",
"gsd-core/workflows/verify-work.md": "f7750a6cce6d5391",
"gsd-core/workflows/verify-work.md": "e56e07475d5eb51e",
"hooks/gsd-check-update-worker.js": "7989cc2bedd1138d",
"hooks/gsd-check-update.js": "25f5ad726f76fc11",
"hooks/gsd-config-reload.js": "880b696458e85e9b",

View File

@@ -373,7 +373,7 @@
"gsd-core/workflows/update.md": "07dc2fba78ad1865",
"gsd-core/workflows/validate-phase.md": "557e3251e3b9349a",
"gsd-core/workflows/verify-phase.md": "0d4ffabc1caa473a",
"gsd-core/workflows/verify-work.md": "41a198eb414e051e",
"gsd-core/workflows/verify-work.md": "b68ac37f6301a3b5",
"hooks/gsd-check-update-worker.js": "c992bbad91d0e994",
"hooks/gsd-check-update.js": "fdd77abe7ef26a2d",
"hooks/gsd-config-reload.js": "96546e0e8bb47904",

View File

@@ -339,7 +339,7 @@
"gsd-core/workflows/update.md": "6718e0632bba26ca",
"gsd-core/workflows/validate-phase.md": "2c6d7671fcaabcaa",
"gsd-core/workflows/verify-phase.md": "98a995046bdb6c3c",
"gsd-core/workflows/verify-work.md": "5ed471293dc6835f",
"gsd-core/workflows/verify-work.md": "34e980a6950cd83c",
"scripts/changeset/README.md": "86ff89331dfd94b2",
"scripts/changeset/cli.cjs": "68f92a344b199271",
"scripts/changeset/github-release-notes.cjs": "795677f0c009b132",

View File

@@ -373,7 +373,7 @@
"gsd-core/workflows/update.md": "71b6cd852f38b4bc",
"gsd-core/workflows/validate-phase.md": "abcdbc1b56780565",
"gsd-core/workflows/verify-phase.md": "5bd04b040cd071dd",
"gsd-core/workflows/verify-work.md": "f7dad67215e6b730",
"gsd-core/workflows/verify-work.md": "f0d205568abfaf74",
"hooks/gsd-check-update-worker.js": "385fb7c67810baf6",
"hooks/gsd-check-update.js": "4549451414ffa7d7",
"hooks/gsd-config-reload.js": "96546e0e8bb47904",

View File

@@ -303,7 +303,7 @@
"gsd-core/workflows/update.md": "b34cb866152d4de3",
"gsd-core/workflows/validate-phase.md": "e989cbaa4228564c",
"gsd-core/workflows/verify-phase.md": "a8679ba1d84145c5",
"gsd-core/workflows/verify-work.md": "5d523d416fef66f0",
"gsd-core/workflows/verify-work.md": "b5afb65fdf311301",
"hooks/gsd-check-update-worker.js": "4bb354044e0dff91",
"hooks/gsd-check-update.js": "d2065cb3e725a42a",
"hooks/gsd-config-reload.js": "4f52b8a0120bb1b8",

View File

@@ -303,7 +303,7 @@
"gsd-core/workflows/update.md": "1f935251fca1f276",
"gsd-core/workflows/validate-phase.md": "1c0ebe56d96a14d1",
"gsd-core/workflows/verify-phase.md": "53cbdce394dcdac0",
"gsd-core/workflows/verify-work.md": "17b2f2591c3f642e",
"gsd-core/workflows/verify-work.md": "d3a0970205acc6a5",
"scripts/changeset/README.md": "86ff89331dfd94b2",
"scripts/changeset/cli.cjs": "68f92a344b199271",
"scripts/changeset/github-release-notes.cjs": "795677f0c009b132",

View File

@@ -303,7 +303,7 @@
"gsd-core/workflows/update.md": "79aaf4b8f1f83045",
"gsd-core/workflows/validate-phase.md": "2db47bf5547d7b9d",
"gsd-core/workflows/verify-phase.md": "ea7f8a705b297e27",
"gsd-core/workflows/verify-work.md": "bbf699e62d93d05b",
"gsd-core/workflows/verify-work.md": "5ad63a5edfb6acac",
"scripts/changeset/README.md": "86ff89331dfd94b2",
"scripts/changeset/cli.cjs": "68f92a344b199271",
"scripts/changeset/github-release-notes.cjs": "795677f0c009b132",

View File

@@ -88,5 +88,5 @@
"update.md": 20914,
"validate-phase.md": 10789,
"verify-phase.md": 40772,
"verify-work.md": 35215
"verify-work.md": 38267
}