fix(#2388): gate shared requirement completion on sibling plans, revert on gaps (#2424)

* fix(#2388): gate shared-ID requirement marking and revert on gaps_found

Adds requirements.ready-ids (execute-plan.md's update_requirements step)
so a requirement ID declared by multiple plans in a phase only marks
Complete once every declaring plan has produced a SUMMARY.md, and
requirements.revert-phase (execute-phase.md's gaps_found branch) so a
gaps_found verdict reverts the phase's own prematurely-Complete IDs
before the gap report renders. Single-plan IDs still mark immediately.

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

* chore(#2388): regenerate fixtures + lint gate-prep

* fix(#2388): repair failing tests after gate verification

* chore(#2388): add changeset (#2424)

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Tom Boucher
2026-07-19 07:52:17 -04:00
committed by GitHub
parent b2f4aa9435
commit 8d2f8bcb23
47 changed files with 534 additions and 61 deletions

View File

@@ -1439,9 +1439,10 @@ Verify-work will walk you through each item and mark the phase complete when all
**If user acknowledges without reporting issues (including "ok", "noted", "ack", "got it", "approved", "done", "yes", "pass", or similar):** Stop. The phase remains pending. No further orchestrator action — wait for the user to run `/gsd:verify-work`.
**If user reports issues now (before running verify-work):** Proceed to gap closure as currently implemented.
**If user reports issues now:** Proceed to gap closure.
**If gaps_found:**
@~/.claude/gsd-core/references/execute-phase-requirement-revert.md
```
## ⚠ Phase {X}: {Name} — Gaps Found

View File

@@ -470,13 +470,21 @@ Counts PLAN vs SUMMARY files on disk. Updates progress table row with correct co
</step>
<step name="update_requirements">
Mark completed requirements from the PLAN.md frontmatter `requirements:` field:
Mark completed requirements from the PLAN.md frontmatter `requirements:` field.
Extract requirement IDs from the plan's frontmatter (e.g., `requirements: [AUTH-01, AUTH-02]`) into `REQ_IDS`. If no requirements field, skip this step.
**Shared-ID gate (#2388):** a requirement ID declared by more than one plan in this phase must not read `Complete` until every plan declaring it has finished (produced a `*-SUMMARY.md`) — otherwise the first plan to finish flips it `Complete` while its sibling plans are still running, before phase verification ever gets a chance to catch a real gap. Compute the ready subset first, then mark only those:
```bash
gsd_run query requirements.mark-complete ${REQ_IDS}
READY=$(gsd_run query requirements.ready-ids "${PLAN_PATH}" ${REQ_IDS} --raw)
READY_IDS=$(printf '%s' "$READY" | jq -r '.ready[]' 2>/dev/null | tr '\n' ' ')
if [ -n "$(printf '%s' "$READY_IDS" | tr -d '[:space:]')" ]; then
gsd_run query requirements.mark-complete ${READY_IDS}
fi
```
Extract requirement IDs from the plan's frontmatter (e.g., `requirements: [AUTH-01, AUTH-02]`). If no requirements field, skip.
`requirements.ready-ids` is read-only: it scans sibling `*-PLAN.md` files in this plan's phase directory and blocks an ID only when a sibling ALSO declares it and that sibling has no `*-SUMMARY.md` yet. An ID no sibling declares is always ready (single-plan requirements mark immediately, no added latency). A blocked ID is re-evaluated the next time any plan in this phase finishes its own `update_requirements` step, and becomes ready once the LAST declaring plan's SUMMARY exists.
</step>
<step name="git_commit_metadata">