fix: close requirements verification loop and enforce MUST language

Tighten all requirements references to use MUST/REQUIRED/CRITICAL language
instead of passive suggestions. Close the verification loop by extracting
phase requirement IDs from ROADMAP and passing them through the full chain:
researcher receives IDs → planner writes to PLAN frontmatter → executor
copies to SUMMARY → verifier cross-references against REQUIREMENTS.md with
orphan detection.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Lex Christopherson
2026-02-16 13:03:14 -06:00
parent cbf809417a
commit 9ef582ef23
9 changed files with 58 additions and 16 deletions

View File

@@ -308,6 +308,7 @@ Verified patterns from official sources:
## Step 1: Receive Scope and Load Context
Orchestrator provides: phase number/name, description/goal, requirements, constraints, output path.
- Phase requirement IDs (e.g., AUTH-01, AUTH-02) — the specific requirements this phase MUST address
Load phase context using init command:
```bash
@@ -377,6 +378,20 @@ For each domain: Context7 first → Official docs → WebSearch → Cross-verify
</user_constraints>
```
**If phase requirement IDs were provided**, MUST include a `<phase_requirements>` section:
```markdown
<phase_requirements>
## Phase Requirements
| ID | Description | Research Support |
|----|-------------|-----------------|
| {REQ-ID} | {from REQUIREMENTS.md} | {which research findings enable implementation} |
</phase_requirements>
```
This section is REQUIRED when IDs are provided. The planner uses it to map requirements to plans.
Write to: `$PHASE_DIR/$PADDED_PHASE-RESEARCH.md`
⚠️ `commit_docs` controls git only, NOT file writing. Always write first.

View File

@@ -73,6 +73,8 @@ Same methodology (goal-backward), different timing, different subject matter.
4. For each requirement, find covering task(s) in the plan that claims it
5. Flag requirements with no coverage or missing from all plans' `requirements` fields
**FAIL the verification** if any requirement ID from the roadmap is absent from all plans' `requirements` fields. This is a blocking issue, not a warning.
**Red flags:**
- Requirement has zero tasks addressing it
- Multiple requirements share one vague task ("implement auth" for login, logout, session)

View File

@@ -345,7 +345,7 @@ wave: N # Execution wave (1, 2, 3...)
depends_on: [] # Plan IDs this plan requires
files_modified: [] # Files this plan touches
autonomous: true # false if plan has checkpoints
requirements: [] # Requirement IDs this plan addresses (from ROADMAP)
requirements: [] # REQUIRED — Requirement IDs from ROADMAP this plan addresses. MUST NOT be empty.
user_setup: [] # Human-required setup (omit if empty)
must_haves:
@@ -411,7 +411,7 @@ After completion, create `.planning/phases/XX-name/{phase}-{plan}-SUMMARY.md`
| `depends_on` | Yes | Plan IDs this plan requires |
| `files_modified` | Yes | Files this plan touches |
| `autonomous` | Yes | `true` if no checkpoints |
| `requirements` | Yes | Requirement IDs this plan addresses (from ROADMAP) |
| `requirements` | Yes | **MUST** list requirement IDs from ROADMAP. Every roadmap requirement ID MUST appear in at least one plan. |
| `user_setup` | No | Human-required setup items |
| `must_haves` | Yes | Goal-backward verification criteria |
@@ -453,7 +453,7 @@ Only include what Claude literally cannot do.
## The Process
**Step 0: Extract Requirement IDs**
Read ROADMAP.md `**Requirements:**` line for this phase. Strip brackets if present (e.g., `[AUTH-01, AUTH-02]` → `AUTH-01, AUTH-02`). Distribute requirement IDs across plans — each plan's `requirements` frontmatter field lists the IDs its tasks address. Every requirement ID must appear in at least one plan.
Read ROADMAP.md `**Requirements:**` line for this phase. Strip brackets if present (e.g., `[AUTH-01, AUTH-02]` → `AUTH-01, AUTH-02`). Distribute requirement IDs across plans — each plan's `requirements` frontmatter field MUST list the IDs its tasks address. **CRITICAL:** Every requirement ID MUST appear in at least one plan. Plans with an empty `requirements` field are invalid.
**Step 1: State the Goal**
Take phase goal from ROADMAP.md. Must be outcome-shaped, not task-shaped.

View File

@@ -233,17 +233,31 @@ Status: WIRED (state displayed) | NOT_WIRED (state exists, not rendered)
## Step 6: Check Requirements Coverage
If REQUIREMENTS.md has requirements mapped to this phase:
**6a. Extract requirement IDs from PLAN frontmatter:**
```bash
grep -A5 "^requirements:" "$PHASE_DIR"/*-PLAN.md 2>/dev/null
```
Collect ALL requirement IDs declared across plans for this phase.
**6b. Cross-reference against REQUIREMENTS.md:**
For each requirement ID from plans:
1. Find its full description in REQUIREMENTS.md (`**REQ-ID**: description`)
2. Map to supporting truths/artifacts verified in Steps 3-5
3. Determine status:
- ✓ SATISFIED: Implementation evidence found that fulfills the requirement
- ✗ BLOCKED: No evidence or contradicting evidence
- ? NEEDS HUMAN: Can't verify programmatically (UI behavior, UX quality)
**6c. Check for orphaned requirements:**
```bash
grep -E "Phase $PHASE_NUM" .planning/REQUIREMENTS.md 2>/dev/null
```
For each requirement: parse description → identify supporting truths/artifacts → determine status.
- ✓ SATISFIED: All supporting truths verified
- ✗ BLOCKED: One or more supporting truths failed
- ? NEEDS HUMAN: Can't verify programmatically
If REQUIREMENTS.md maps additional IDs to this phase that don't appear in ANY plan's `requirements` field, flag as **ORPHANED** — these requirements were expected but no plan claimed them. ORPHANED requirements MUST appear in the verification report.
## Step 7: Scan for Anti-Patterns
@@ -396,8 +410,8 @@ human_verification: # Only if status: human_needed
### Requirements Coverage
| Requirement | Status | Blocking Issue |
| ----------- | ------ | -------------- |
| Requirement | Source Plan | Description | Status | Evidence |
| ----------- | ---------- | ----------- | ------ | -------- |
### Anti-Patterns Found

View File

@@ -20,7 +20,7 @@ wave: N # Execution wave (1, 2, 3...). Pre-computed at plan
depends_on: [] # Plan IDs this plan requires (e.g., ["01-01"]).
files_modified: [] # Files this plan modifies.
autonomous: true # false if plan has checkpoints requiring user interaction
requirements: [] # Requirement IDs this plan addresses (from ROADMAP)
requirements: [] # REQUIRED — Requirement IDs from ROADMAP this plan addresses. MUST NOT be empty.
user_setup: [] # Human-required setup Claude cannot automate (see below)
# Goal-backward verification (derived during planning, verified after execution)
@@ -130,7 +130,7 @@ After completion, create `.planning/phases/XX-name/{phase}-{plan}-SUMMARY.md`
| `depends_on` | Yes | Array of plan IDs this plan requires. |
| `files_modified` | Yes | Files this plan touches. |
| `autonomous` | Yes | `true` if no checkpoints, `false` if has checkpoints |
| `requirements` | Yes | Requirement IDs this plan addresses (from ROADMAP) |
| `requirements` | Yes | **MUST** list requirement IDs from ROADMAP. Every roadmap requirement MUST appear in at least one plan. |
| `user_setup` | No | Array of human-required setup items (external services) |
| `must_haves` | Yes | Goal-backward verification criteria (see below) |

View File

@@ -38,7 +38,7 @@ patterns-established:
- "Pattern 1: description"
- "Pattern 2: description"
requirements-completed: [] # Requirement IDs addressed by this plan (from PLAN frontmatter)
requirements-completed: [] # REQUIRED — Copy ALL requirement IDs from this plan's `requirements` frontmatter field.
# Metrics
duration: Xmin

View File

@@ -291,12 +291,19 @@ node ~/.claude/get-shit-done/bin/gsd-tools.cjs commit "docs(phase-${PARENT_PHASE
<step name="verify_phase_goal">
Verify phase achieved its GOAL, not just completed tasks.
```bash
PHASE_REQ_IDS=$(node ~/.claude/get-shit-done/bin/gsd-tools.cjs roadmap get-phase "${PHASE_NUMBER}" | jq -r '.section' | grep -i "Requirements:" | sed 's/.*Requirements:\*\*\s*//' | sed 's/[\[\]]//g')
```
```
Task(
prompt="Verify phase {phase_number} goal achievement.
Phase directory: {phase_dir}
Phase goal: {goal from ROADMAP.md}
Check must_haves against actual codebase. Create VERIFICATION.md.",
Phase requirement IDs: {phase_req_ids}
Check must_haves against actual codebase.
Cross-reference requirement IDs from PLAN frontmatter against REQUIREMENTS.md — every ID MUST be accounted for.
Create VERIFICATION.md.",
subagent_type="gsd-verifier",
model="{verifier_model}"
)

View File

@@ -322,7 +322,7 @@ If user_setup exists: create `{phase}-USER-SETUP.md` using template `~/.claude/g
<step name="create_summary">
Create `{phase}-{plan}-SUMMARY.md` at `.planning/phases/XX-name/`. Use `~/.claude/get-shit-done/templates/summary.md`.
**Frontmatter:** phase, plan, subsystem, tags | requires/provides/affects | tech-stack.added/patterns | key-files.created/modified | key-decisions | requirements-completed (from PLAN.md requirements field) | duration ($DURATION), completed ($PLAN_END_TIME date).
**Frontmatter:** phase, plan, subsystem, tags | requires/provides/affects | tech-stack.added/patterns | key-files.created/modified | key-decisions | requirements-completed (**MUST** copy `requirements` array from PLAN.md frontmatter verbatim) | duration ($DURATION), completed ($PLAN_END_TIME date).
Title: `# Phase [X] Plan [Y]: [Name] Summary`

View File

@@ -96,6 +96,7 @@ Display banner:
PHASE_DESC=$(node ~/.claude/get-shit-done/bin/gsd-tools.cjs roadmap get-phase "${PHASE}" | jq -r '.section')
# Use requirements_content from INIT (already loaded via --include requirements)
REQUIREMENTS=$(echo "$INIT" | jq -r '.requirements_content // empty' | grep -A100 "## Requirements" | head -50)
PHASE_REQ_IDS=$(echo "$INIT" | jq -r '.roadmap_content // empty' | grep -i "Requirements:" | head -1 | sed 's/.*Requirements:\*\*\s*//' | sed 's/[\[\]]//g' | tr ',' '\n' | sed 's/^ *//;s/ *$//' | grep -v '^$' | tr '\n' ',' | sed 's/,$//')
STATE_SNAP=$(node ~/.claude/get-shit-done/bin/gsd-tools.cjs state-snapshot)
# Extract decisions from state-snapshot JSON: jq '.decisions[] | "\(.phase): \(.summary) - \(.rationale)"'
```
@@ -119,6 +120,7 @@ IMPORTANT: If CONTEXT.md exists below, it contains user decisions from /gsd:disc
<additional_context>
**Phase description:** {phase_description}
**Phase requirement IDs (MUST address):** {phase_req_ids}
**Requirements:** {requirements}
**Prior decisions:** {decisions}
</additional_context>
@@ -185,6 +187,7 @@ Planner prompt:
**Project State:** {state_content}
**Roadmap:** {roadmap_content}
**Phase requirement IDs (every ID MUST appear in a plan's `requirements` field):** {phase_req_ids}
**Requirements:** {requirements_content}
**Phase Context:**
@@ -255,6 +258,7 @@ Checker prompt:
**Phase Goal:** {goal from ROADMAP}
**Plans to verify:** {plans_content}
**Phase requirement IDs (MUST ALL be covered):** {phase_req_ids}
**Requirements:** {requirements_content}
**Phase Context:**