refactor(verify-work): consolidate plan-fix into plan-phase --gaps

Unify gap handling - whether discovered by code verification or user
testing, gaps feed into the same plan-phase --gaps workflow.

Changes:
- Delete commands/gsd/plan-fix.md (redundant)
- Update verify-work to route to plan-phase --gaps
- Update progress Route E to detect UAT gaps
- Change UAT.md "Issues" section to "Gaps" with YAML format
- Extend plan-phase --gaps to read from both VERIFICATION.md and UAT.md
- Update diagnose-issues to output gaps in YAML format
- Update all references (debug, templates, workflows)

One path: gap discovered → diagnosed → plan-phase --gaps → fixed

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Lex Christopherson
2026-01-15 15:38:21 -06:00
parent 8c66a7167a
commit 2869fee206
11 changed files with 199 additions and 454 deletions

View File

@@ -377,7 +377,6 @@ You're never locked in. The system adapts.
| Command | What it does |
|---------|--------------|
| `/gsd:verify-work [N]` | User acceptance test of phase or plan ¹ |
| `/gsd:plan-fix [plan]` | Plan fixes for UAT issues |
### Milestones

View File

@@ -96,7 +96,7 @@ Task(
- Display root cause and evidence summary
- Offer options:
- "Fix now" → spawn fix subagent
- "Plan fix" → suggest /gsd:plan-fix
- "Plan fix" → suggest /gsd:plan-phase --gaps
- "Manual fix" → done
**If `## CHECKPOINT REACHED`:**

View File

@@ -1,270 +0,0 @@
---
name: gsd:plan-fix
description: Plan fixes for UAT issues from verify-work
argument-hint: "<phase, e.g., '4'>"
allowed-tools:
- Read
- Bash
- Write
- Glob
- Grep
- AskUserQuestion
- SlashCommand
---
<objective>
Create FIX.md plan from UAT issues found during verify-work.
Purpose: Plan fixes for issues logged in {phase}-UAT.md.
Output: {phase}-FIX.md in the phase directory, ready for execution.
</objective>
<execution_context>
@~/.claude/get-shit-done/references/plan-format.md
@~/.claude/get-shit-done/references/checkpoints.md
</execution_context>
<context>
Phase: $ARGUMENTS (required - e.g., "4")
@.planning/STATE.md
@.planning/ROADMAP.md
</context>
<process>
<step name="parse">
**Parse phase argument:**
$ARGUMENTS should be a phase number like "4" or "04".
If no argument provided:
```
Error: Phase number required.
Usage: /gsd:plan-fix 4
This creates a fix plan from .planning/phases/04-name/04-UAT.md
```
Exit.
</step>
<step name="find">
**Find UAT.md file:**
```bash
ls .planning/phases/${PHASE_ARG}*/*-UAT.md 2>/dev/null
```
If not found:
```
No UAT.md found for phase {phase}.
UAT.md files are created by /gsd:verify-work during testing.
Run /gsd:verify-work {phase} first.
```
Exit.
If found but status is "testing":
```
UAT session still in progress.
Run /gsd:verify-work to complete testing first.
```
Exit.
</step>
<step name="read">
**Read issues from UAT.md:**
Read the "Issues for /gsd:plan-fix" section.
If section is empty or says "[none yet]":
```
No issues found in UAT.md.
All tests passed - no fix plan needed.
```
Exit.
Parse each issue:
- ID (UAT-XXX)
- Brief summary
- Severity (blocker/major/minor/cosmetic)
- Test number (for context)
- **root_cause** (if diagnosed - may be empty)
Also read the corresponding test from "Tests" section to get:
- expected behavior
- reported issue (verbatim user description)
- root_cause (if diagnosed)
- debug_session (path to debug file, if diagnosed)
**Check if diagnosed:**
- If UAT.md status is "diagnosed" OR root_cause fields are populated → issues have been investigated
- If not diagnosed → plan based on symptoms only (less precise)
</step>
<step name="plan">
**Create fix tasks:**
For each issue (or logical group):
- Create one task per issue OR
- Group related cosmetic/minor issues into single task
**If diagnosed (root_cause available):**
```xml
<task type="auto">
<name>Fix UAT-{NNN}: {issue summary}</name>
<files>{files from diagnosis}</files>
<action>
**Root Cause:** {root_cause from diagnosis}
**Issue:** {verbatim reported description}
**Expected:** {from test}
**Fix:** {specific fix based on diagnosed root cause}
Debug session: {debug_session path} (for reference)
</action>
<verify>
- Confirm root cause addressed
- {expected behavior} now works correctly
</verify>
<done>UAT-{NNN} resolved - {root_cause} fixed</done>
</task>
```
**If NOT diagnosed (symptoms only):**
```xml
<task type="auto">
<name>Fix UAT-{NNN}: {issue summary}</name>
<files>[affected files - infer from test context]</files>
<action>
**Issue:** {verbatim reported description}
**Expected:** {from test}
[Investigate and fix - root cause unknown]
</action>
<verify>
- Reproduce original issue - confirm fixed
- {expected behavior} now works correctly
</verify>
<done>UAT-{NNN} resolved - {expected behavior} works</done>
</task>
```
Prioritize: blocker → major → minor → cosmetic
</step>
<step name="write">
**Write FIX.md:**
Create `.planning/phases/XX-name/{phase}-FIX.md`:
```markdown
---
phase: XX-name
plan: {phase}-FIX
type: fix
wave: 1
depends_on: []
autonomous: true
---
<objective>
Fix {N} UAT issues from phase {phase}.
Source: {phase}-UAT.md
Diagnosed: {yes/no - whether root causes were identified}
Priority: {blocker count} blocker, {major count} major, {minor count} minor, {cosmetic count} cosmetic
</objective>
<execution_context>
@~/.claude/get-shit-done/workflows/execute-plan.md
@~/.claude/get-shit-done/templates/summary.md
</execution_context>
<context>
@.planning/STATE.md
@.planning/ROADMAP.md
**Issues being fixed:**
@.planning/phases/XX-name/{phase}-UAT.md
**Debug sessions (if diagnosed):**
[Reference each debug_session path from UAT.md for full investigation context]
**Original plans for reference:**
@.planning/phases/XX-name/{phase}-01-PLAN.md
[other relevant plans]
</context>
<tasks>
[Generated fix tasks]
</tasks>
<verification>
Before declaring plan complete:
- [ ] All blocker issues fixed
- [ ] All major issues fixed
- [ ] Minor/cosmetic issues fixed or documented as deferred
- [ ] Each fix verified against original reported issue
</verification>
<success_criteria>
- All UAT issues from {phase}-UAT.md addressed
- Tests pass
- Ready for re-verification with /gsd:verify-work {phase}
</success_criteria>
<output>
After completion, create `.planning/phases/XX-name/{phase}-FIX-SUMMARY.md`
</output>
```
</step>
<step name="offer">
**Offer execution:**
```
## Fix Plan Created
**{phase}-FIX.md** — {N} issues to fix
| Severity | Count |
|----------|-------|
| Blocker | {n} |
| Major | {n} |
| Minor | {n} |
| Cosmetic | {n} |
```
Use AskUserQuestion:
- header: "Next"
- question: "What would you like to do?"
- options:
- "Execute fix plan" — Run the fixes now
- "Review plan first" — Look at the plan before executing
- "Done for now" — Come back later
**If "Execute fix plan":**
Invoke `/gsd:execute-plan .planning/phases/XX-name/{phase}-FIX.md`
**If "Review plan first":**
Display the plan contents, then ask again whether to execute.
**If "Done for now":**
```
Fix plan saved. Run when ready:
`/gsd:execute-plan .planning/phases/XX-name/{phase}-FIX.md`
```
</step>
</process>
<success_criteria>
- [ ] UAT.md found and issues parsed
- [ ] Fix tasks created for each issue
- [ ] FIX.md written with proper structure
- [ ] User offered next steps
</success_criteria>

View File

@@ -114,28 +114,28 @@ List files in the current phase directory:
```bash
ls -1 .planning/phases/[current-phase-dir]/*-PLAN.md 2>/dev/null | wc -l
ls -1 .planning/phases/[current-phase-dir]/*-SUMMARY.md 2>/dev/null | wc -l
ls -1 .planning/phases/[current-phase-dir]/*-ISSUES.md 2>/dev/null | wc -l
ls -1 .planning/phases/[current-phase-dir]/*-FIX.md 2>/dev/null | wc -l
ls -1 .planning/phases/[current-phase-dir]/*-FIX-SUMMARY.md 2>/dev/null | wc -l
ls -1 .planning/phases/[current-phase-dir]/*-UAT.md 2>/dev/null | wc -l
```
State: "This phase has {X} plans, {Y} summaries, {Z} issues files, {W} fix plans."
State: "This phase has {X} plans, {Y} summaries."
**Step 1.5: Check for unaddressed UAT issues**
**Step 1.5: Check for unaddressed UAT gaps**
For each *-ISSUES.md file, check if matching *-FIX.md exists.
For each *-FIX.md file, check if matching *-FIX-SUMMARY.md exists.
Check for UAT.md files with status "diagnosed" (has gaps needing fixes).
```bash
# Check for diagnosed UAT with gaps
grep -l "status: diagnosed" .planning/phases/[current-phase-dir]/*-UAT.md 2>/dev/null
```
Track:
- `issues_without_fix`: ISSUES.md files without FIX.md
- `fixes_without_summary`: FIX.md files without FIX-SUMMARY.md
- `uat_with_gaps`: UAT.md files with status "diagnosed" (gaps need fixing)
**Step 2: Route based on counts**
| Condition | Meaning | Action |
|-----------|---------|--------|
| fixes_without_summary > 0 | Unexecuted fix plans exist | Go to **Route A** (with FIX.md) |
| issues_without_fix > 0 | UAT issues need fix plans | Go to **Route E** |
| uat_with_gaps > 0 | UAT gaps need fix plans | Go to **Route E** |
| summaries < plans | Unexecuted plans exist | Go to **Route A** |
| summaries = plans AND plans > 0 | Phase complete | Go to Step 3 |
| plans = 0 | Phase not yet planned | Go to **Route B** |
@@ -209,18 +209,18 @@ Check if `{phase}-CONTEXT.md` exists in phase directory.
---
**Route E: UAT issues need fix plans**
**Route E: UAT gaps need fix plans**
ISSUES.md exists without matching FIX.md. User needs to plan fixes.
UAT.md exists with gaps (diagnosed issues). User needs to plan fixes.
```
---
## ⚠ UAT Issues Found
## ⚠ UAT Gaps Found
**{plan}-ISSUES.md** has {N} issues without a fix plan.
**{phase}-UAT.md** has {N} gaps requiring fixes.
`/gsd:plan-fix {plan}`
`/gsd:plan-phase {phase} --gaps`
<sub>`/clear` first → fresh context window</sub>

View File

@@ -16,7 +16,7 @@ Validate built features through conversational testing with persistent state.
Purpose: Confirm what Claude built actually works from user's perspective. One test at a time, plain text responses, no interrogation.
Output: {phase}-UAT.md tracking all test results, issues logged for /gsd:plan-fix
Output: {phase}-UAT.md tracking all test results, gaps logged for /gsd:plan-phase --gaps
</objective>
<execution_context>
@@ -51,7 +51,7 @@ Phase: $ARGUMENTS (optional)
- Don't ask severity — infer from description
- Don't present full checklist upfront — one test at a time
- Don't run automated tests — this is manual user validation
- Don't fix issues during testing — log for /gsd:plan-fix
- Don't fix issues during testing — log as gaps for /gsd:plan-phase --gaps
</anti_patterns>
<success_criteria>

View File

@@ -39,8 +39,6 @@ expected: [observable behavior]
result: issue
reported: "[verbatim user response]"
severity: major
root_cause: [filled by diagnose-issues, empty until diagnosed]
debug_session: [path to DEBUG file, empty until diagnosed]
### 4. [Test Name]
expected: [observable behavior]
@@ -57,13 +55,18 @@ issues: [N]
pending: [N]
skipped: [N]
## Issues for /gsd:plan-fix
## Gaps
- UAT-001: [brief summary] (blocker) - Test 3
root_cause: [empty until diagnosed]
- UAT-002: [brief summary] (major) - Test 7
root_cause: [empty until diagnosed]
<!-- YAML format for plan-phase --gaps consumption -->
- truth: "[expected behavior from test]"
status: failed
reason: "User reported: [verbatim response]"
severity: blocker | major | minor | cosmetic
test: [N]
root_cause: "" # Filled by diagnosis
artifacts: [] # Filled by diagnosis
missing: [] # Filled by diagnosis
debug_session: "" # Filled by diagnosis
```
---
@@ -87,49 +90,46 @@ skipped: [N]
- `result` values: [pending], pass, issue, skipped
- If issue: add `reported` (verbatim) and `severity` (inferred)
- If skipped: add `reason` if provided
- After diagnosis: add `root_cause` and `debug_session` fields to issues
**Summary:**
- OVERWRITE counts after each response
- Tracks: total, passed, issues, pending, skipped
**Issues for /gsd:plan-fix:**
- APPEND only when issue found
- Format: `- UAT-{NNN}: {summary} ({severity}) - Test {N}`
- After diagnosis: add `root_cause:` line under each issue
- This section feeds directly into /gsd:plan-fix
**Gaps:**
- APPEND only when issue found (YAML format)
- After diagnosis: fill `root_cause`, `artifacts`, `missing`, `debug_session`
- This section feeds directly into /gsd:plan-phase --gaps
</section_rules>
<diagnosis_lifecycle>
**After testing complete (status: complete), if issues exist:**
**After testing complete (status: complete), if gaps exist:**
1. User runs diagnosis (from verify-work offer or manually)
2. diagnose-issues workflow spawns parallel debug agents
3. Each agent investigates one issue, returns root cause
4. UAT.md updated with root causes:
- Each issue test gets `root_cause:` and `debug_session:` fields
- Issues section gets `root_cause:` under each issue
3. Each agent investigates one gap, returns root cause
4. UAT.md Gaps section updated with diagnosis:
- Each gap gets `root_cause`, `artifacts`, `missing`, `debug_session` filled
5. status → "diagnosed"
6. Ready for /gsd:plan-fix with root causes
6. Ready for /gsd:plan-phase --gaps with root causes
**After diagnosis:**
```markdown
### 2. Create Top-Level Comment
expected: Submit comment via rich text editor, appears in list with author info
result: issue
reported: "works but doesn't show until I refresh the page"
severity: major
root_cause: useEffect in CommentList.tsx missing commentCount dependency
debug_session: .planning/debug/comment-not-refreshing.md
```
```yaml
## Gaps
```markdown
## Issues for /gsd:plan-fix
- UAT-001: Comment doesn't appear until refresh (major) - Test 2
root_cause: useEffect in CommentList.tsx missing commentCount dependency
- truth: "Comment appears immediately after submission"
status: failed
reason: "User reported: works but doesn't show until I refresh the page"
severity: major
test: 2
root_cause: "useEffect in CommentList.tsx missing commentCount dependency"
artifacts:
- path: "src/components/CommentList.tsx"
issue: "useEffect missing dependency"
missing:
- "Add commentCount to useEffect dependency array"
debug_session: ".planning/debug/comment-not-refreshing.md"
```
</diagnosis_lifecycle>
@@ -147,7 +147,7 @@ debug_session: .planning/debug/comment-not-refreshing.md
- User responds with pass confirmation or issue description
- Update test result (pass/issue/skipped)
- Update Summary counts
- If issue: append to Issues section, infer severity
- If issue: append to Gaps section (YAML format), infer severity
- Move Current Test to next pending test
**On completion:**
@@ -182,7 +182,7 @@ Default: **major** (safe default, user can clarify if wrong)
<good_example>
```markdown
---
status: testing
status: diagnosed
phase: 04-comments
source: 04-01-SUMMARY.md, 04-02-SUMMARY.md
started: 2025-01-15T10:30:00Z
@@ -191,13 +191,7 @@ updated: 2025-01-15T10:45:00Z
## Current Test
number: 4
name: Visual Nesting
expected: |
Create 3+ level deep thread.
Each level shows increased indentation with left border.
Nesting caps at reasonable depth.
awaiting: user response
[testing complete]
## Tests
@@ -210,8 +204,6 @@ expected: Submit comment via rich text editor, appears in list with author info
result: issue
reported: "works but doesn't show until I refresh the page"
severity: major
root_cause: useEffect in CommentList.tsx missing commentCount dependency
debug_session: .planning/debug/comment-not-refreshing.md
### 3. Reply to a Comment
expected: Click Reply, inline composer appears, submit shows nested reply
@@ -219,27 +211,37 @@ result: pass
### 4. Visual Nesting
expected: 3+ level thread shows indentation, left borders, caps at reasonable depth
result: [pending]
result: pass
### 5. Delete Own Comment
expected: Click delete on own comment, removed or shows [deleted] if has replies
result: [pending]
result: pass
### 6. Comment Count
expected: Post shows accurate count, increments when adding comment
result: [pending]
result: pass
## Summary
total: 6
passed: 2
passed: 5
issues: 1
pending: 3
pending: 0
skipped: 0
## Issues for /gsd:plan-fix
## Gaps
- UAT-001: Comment doesn't appear until refresh (major) - Test 2
root_cause: useEffect in CommentList.tsx missing commentCount dependency
- truth: "Comment appears immediately after submission in list"
status: failed
reason: "User reported: works but doesn't show until I refresh the page"
severity: major
test: 2
root_cause: "useEffect in CommentList.tsx missing commentCount dependency"
artifacts:
- path: "src/components/CommentList.tsx"
issue: "useEffect missing dependency"
missing:
- "Add commentCount to useEffect dependency array"
debug_session: ".planning/debug/comment-not-refreshing.md"
```
</good_example>

View File

@@ -46,7 +46,7 @@ Start directly at investigation_loop.
**goal: {goal}**
- `find_root_cause_only` — Diagnose but do NOT fix. Return root cause to orchestrator. Used by UAT diagnosis flow where plan-fix handles the fix.
- `find_root_cause_only` — Diagnose but do NOT fix. Return root cause to orchestrator. Used by UAT diagnosis flow where plan-phase --gaps handles the fix.
- `find_and_fix` — Find root cause, then fix and verify. Used by interactive /gsd:debug where user wants immediate resolution.
</mode>
@@ -167,7 +167,7 @@ If you cannot proceed without user action or verification:
- [file1]: [what's wrong]
- [file2]: [related issue]
**Suggested Fix Direction:** [brief hint for plan-fix, not implementation]
**Suggested Fix Direction:** [brief hint for gap closure plan, not implementation]
```
---

View File

@@ -213,7 +213,7 @@ Reply with A or B (or describe alternative)
- Diagnose but don't fix
- Stop after confirming root cause
- Skip `fix_and_verify` step
- Return root cause to caller (for plan-fix to handle)
- Return root cause to caller (for plan-phase --gaps to handle)
**Default mode (no flags):**
- Interactive debugging with user
@@ -544,7 +544,7 @@ If unable to determine root cause after thorough investigation:
**Debug Session:** {path to debug file}
```
**Do NOT proceed to fix_and_verify.** The fix will be planned by /gsd:plan-fix using this diagnosis.
**Do NOT proceed to fix_and_verify.** The fix will be planned by /gsd:plan-phase --gaps using this diagnosis.
</step>
<step name="fix_and_verify">

View File

@@ -1,9 +1,9 @@
<purpose>
Orchestrate parallel debug agents to investigate UAT issues and find root causes.
Orchestrate parallel debug agents to investigate UAT gaps and find root causes.
After UAT finds issues, spawn one debug agent per issue. Each agent investigates autonomously with symptoms pre-filled from UAT. Collect root causes, update UAT.md, then hand off to plan-fix with actual diagnoses.
After UAT finds gaps, spawn one debug agent per gap. Each agent investigates autonomously with symptoms pre-filled from UAT. Collect root causes, update UAT.md gaps with diagnosis, then hand off to plan-phase --gaps with actual diagnoses.
Orchestrator stays lean: parse issues, spawn agents, collect results, update UAT.
Orchestrator stays lean: parse gaps, spawn agents, collect results, update UAT.
</purpose>
<paths>
@@ -15,7 +15,7 @@ Debug files use the `.planning/debug/` path (hidden directory with leading dot).
<core_principle>
**Diagnose before planning fixes.**
UAT tells us WHAT is broken (symptoms). Debug agents find WHY (root cause). Plan-fix then creates targeted fixes based on actual causes, not guesses.
UAT tells us WHAT is broken (symptoms). Debug agents find WHY (root cause). plan-phase --gaps then creates targeted fixes based on actual causes, not guesses.
Without diagnosis: "Comment doesn't refresh" → guess at fix → maybe wrong
With diagnosis: "Comment doesn't refresh" → "useEffect missing dependency" → precise fix
@@ -23,26 +23,27 @@ With diagnosis: "Comment doesn't refresh" → "useEffect missing dependency" →
<process>
<step name="parse_issues">
**Extract issues from UAT.md:**
<step name="parse_gaps">
**Extract gaps from UAT.md:**
Read the "Issues for /gsd:plan-fix" section:
```
- UAT-001: Comment doesn't appear until refresh (major) - Test 2
- UAT-002: Reply button position wrong (minor) - Test 5
- UAT-003: Delete doesn't work (blocker) - Test 6
Read the "Gaps" section (YAML format):
```yaml
- truth: "Comment appears immediately after submission"
status: failed
reason: "User reported: works but doesn't show until I refresh the page"
severity: major
test: 2
artifacts: []
missing: []
```
For each issue, also read the corresponding test from "Tests" section to get:
- expected: What should happen
- reported: What user described (verbatim)
- severity: blocker/major/minor/cosmetic
For each gap, also read the corresponding test from "Tests" section to get full context.
Build issue list:
Build gap list:
```
issues = [
{id: "UAT-001", summary: "Comment doesn't appear until refresh", severity: "major", test_num: 2, expected: "...", reported: "..."},
{id: "UAT-002", summary: "Reply button position wrong", severity: "minor", test_num: 5, expected: "...", reported: "..."},
gaps = [
{truth: "Comment appears immediately...", severity: "major", test_num: 2, reason: "..."},
{truth: "Reply button positioned correctly...", severity: "minor", test_num: 5, reason: "..."},
...
]
```
@@ -52,50 +53,49 @@ issues = [
**Report diagnosis plan to user:**
```
## Diagnosing {N} Issues
## Diagnosing {N} Gaps
Spawning parallel debug agents to investigate root causes:
| Issue | Summary | Severity |
|-------|---------|----------|
| UAT-001 | Comment doesn't appear until refresh | major |
| UAT-002 | Reply button position wrong | minor |
| UAT-003 | Delete doesn't work | blocker |
| Gap (Truth) | Severity |
|-------------|----------|
| Comment appears immediately after submission | major |
| Reply button positioned correctly | minor |
| Delete removes comment | blocker |
Each agent will:
1. Create DEBUG-UAT-{NNN}.md with symptoms pre-filled
1. Create DEBUG-{slug}.md with symptoms pre-filled
2. Investigate autonomously (read code, form hypotheses, test)
3. Return root cause
This runs in parallel - all issues investigated simultaneously.
This runs in parallel - all gaps investigated simultaneously.
```
</step>
<step name="spawn_agents">
**Spawn debug agents in parallel:**
For each issue, fill the debug-subagent-prompt template and spawn:
For each gap, fill the debug-subagent-prompt template and spawn:
```
Task(
prompt=filled_debug_subagent_prompt,
subagent_type="general-purpose",
description="Debug UAT-{NNN}"
description="Debug: {truth_short}"
)
```
**All agents spawn in single message** (parallel execution).
Template placeholders:
- `{issue_id}`: UAT-001, UAT-002, etc.
- `{issue_summary}`: Brief description
- `{truth}`: The expected behavior that failed
- `{expected}`: From UAT test
- `{actual}`: Verbatim user description (what actually happened)
- `{actual}`: Verbatim user description from reason field
- `{errors}`: Any error messages from UAT (or "None reported")
- `{reproduction}`: "Test {test_num} in UAT"
- `{timeline}`: "Discovered during UAT"
- `{goal}`: `find_root_cause_only` (UAT flow - plan-fix handles fixes)
- `{slug}`: Generated from issue_summary
- `{goal}`: `find_root_cause_only` (UAT flow - plan-phase --gaps handles fixes)
- `{slug}`: Generated from truth
</step>
<step name="collect_results">
@@ -118,14 +118,14 @@ Each agent returns with:
- {file1}: {what's wrong}
- {file2}: {related issue}
**Suggested Fix Direction:** {brief hint for plan-fix}
**Suggested Fix Direction:** {brief hint for plan-phase --gaps}
```
Parse each return to extract:
- root_cause: The diagnosed cause
- files: Files involved
- debug_path: Path to debug session file
- suggested_fix: Hint for plan-fix
- suggested_fix: Hint for gap closure plan
If agent returns `## INVESTIGATION INCONCLUSIVE`:
- root_cause: "Investigation inconclusive - manual review needed"
@@ -134,34 +134,27 @@ If agent returns `## INVESTIGATION INCONCLUSIVE`:
</step>
<step name="update_uat">
**Update UAT.md with root causes:**
**Update UAT.md gaps with diagnosis:**
For each issue in the Tests section, add root_cause field:
For each gap in the Gaps section, add artifacts and missing fields:
```markdown
### 2. Create Top-Level Comment
expected: Submit comment via rich text editor, appears in list with author info
result: issue
reported: "works but doesn't show until I refresh the page"
severity: major
root_cause: "useEffect in CommentList.tsx missing commentCount dependency - doesn't re-render when new comment added"
debug_session: ${DEBUG_DIR}/comment-not-refreshing.md
```yaml
- truth: "Comment appears immediately after submission"
status: failed
reason: "User reported: works but doesn't show until I refresh the page"
severity: major
test: 2
root_cause: "useEffect in CommentList.tsx missing commentCount dependency"
artifacts:
- path: "src/components/CommentList.tsx"
issue: "useEffect missing dependency"
missing:
- "Add commentCount to useEffect dependency array"
- "Trigger re-render when new comment added"
debug_session: .planning/debug/comment-not-refreshing.md
```
Update the "Issues for /gsd:plan-fix" section with root causes:
```markdown
## Issues for /gsd:plan-fix
- UAT-001: Comment doesn't appear until refresh (major) - Test 2
root_cause: useEffect missing dependency in CommentList.tsx
- UAT-002: Reply button position wrong (minor) - Test 5
root_cause: CSS flex order incorrect in ReplyButton.tsx
- UAT-003: Delete doesn't work (blocker) - Test 6
root_cause: API endpoint returns 403 - missing auth header
```
Update status in frontmatter to "diagnosed".
Commit the updated UAT.md:
```bash
@@ -176,31 +169,31 @@ git commit -m "docs({phase}): add root causes from diagnosis"
```
## Diagnosis Complete
| Issue | Root Cause | Files |
|-------|------------|-------|
| UAT-001 | useEffect missing dependency | CommentList.tsx |
| UAT-002 | CSS flex order incorrect | ReplyButton.tsx |
| UAT-003 | API missing auth header | api/comments.ts |
| Gap (Truth) | Root Cause | Files |
|-------------|------------|-------|
| Comment appears immediately | useEffect missing dependency | CommentList.tsx |
| Reply button positioned correctly | CSS flex order incorrect | ReplyButton.tsx |
| Delete removes comment | API missing auth header | api/comments.ts |
Debug sessions saved to ${DEBUG_DIR}/
---
Next steps:
- `/gsd:plan-fix {phase}` — Create fix plan with root causes
- `/gsd:plan-phase {phase} --gaps` — Create fix plans from diagnosed gaps
- Review debug sessions for details
```
</step>
<step name="offer_next">
**Offer plan-fix:**
**Offer gap closure:**
```
Root causes identified. Ready to plan fixes?
`/gsd:plan-fix {phase}`
`/gsd:plan-phase {phase} --gaps`
The fix plan will use diagnosed root causes for targeted fixes.
The fix plans will use diagnosed root causes for targeted fixes.
```
</step>
@@ -208,7 +201,7 @@ The fix plan will use diagnosed root causes for targeted fixes.
<context_efficiency>
**Orchestrator context:** ~15%
- Parse UAT.md issues
- Parse UAT.md gaps
- Fill template strings
- Spawn parallel Task calls
- Collect results
@@ -221,30 +214,30 @@ The fix plan will use diagnosed root causes for targeted fixes.
- Returns root cause
**No symptom gathering.** Agents start with symptoms pre-filled from UAT.
**No fix application.** Agents only diagnose - plan-fix handles fixes.
**No fix application.** Agents only diagnose - plan-phase --gaps handles fixes.
</context_efficiency>
<failure_handling>
**Agent fails to find root cause:**
- Mark issue as "needs manual review"
- Continue with other issues
- Mark gap as "needs manual review"
- Continue with other gaps
- Report incomplete diagnosis
**Agent times out:**
- Check DEBUG-UAT-{NNN}.md for partial progress
- Check DEBUG-{slug}.md for partial progress
- Can resume with /gsd:debug
**All agents fail:**
- Something systemic (permissions, git, etc.)
- Report for manual investigation
- Fall back to plan-fix without root causes
- Fall back to plan-phase --gaps without root causes (less precise)
</failure_handling>
<success_criteria>
- [ ] Issues parsed from UAT.md
- [ ] Gaps parsed from UAT.md
- [ ] Debug agents spawned in parallel
- [ ] Root causes collected from all agents
- [ ] UAT.md updated with root causes
- [ ] UAT.md gaps updated with artifacts and missing
- [ ] Debug sessions saved to ${DEBUG_DIR}/
- [ ] User knows next steps (plan-fix)
- [ ] User knows next steps (plan-phase --gaps)
</success_criteria>

View File

@@ -102,18 +102,29 @@ If `--gaps` present in arguments, switch to gap_closure_mode (see `<step name="g
</step>
<step name="gap_closure_mode">
**Triggered by `--gaps` flag.** Plans address verification gaps.
**Triggered by `--gaps` flag.** Plans address verification gaps OR UAT gaps.
**1. Load VERIFICATION.md:**
**1. Find gap sources:**
```bash
PHASE_DIR=$(ls -d .planning/phases/${PHASE_ARG}* 2>/dev/null | head -1)
cat "$PHASE_DIR"/*-VERIFICATION.md
# Check for VERIFICATION.md (code verification gaps)
ls "$PHASE_DIR"/*-VERIFICATION.md 2>/dev/null
# Check for UAT.md with diagnosed status (user testing gaps)
grep -l "status: diagnosed" "$PHASE_DIR"/*-UAT.md 2>/dev/null
```
**2. Parse gaps from YAML frontmatter:**
**Priority:** If both exist, load both and combine gaps. UAT gaps (user-discovered) may overlap with verification gaps (code-discovered).
Extract `gaps:` array. Each gap has:
**2. Parse gaps:**
**From VERIFICATION.md** (if exists): Parse `gaps:` from YAML frontmatter.
**From UAT.md** (if exists with status: diagnosed): Parse gaps from `## Gaps` section (YAML format).
Each gap has:
- `truth`: The observable behavior that failed
- `reason`: Why it failed
- `artifacts`: Files with issues

View File

@@ -1,5 +1,5 @@
<purpose>
Validate built features through conversational testing with persistent state. Creates UAT.md that tracks test progress, survives /clear, and feeds into /gsd:plan-fix.
Validate built features through conversational testing with persistent state. Creates UAT.md that tracks test progress, survives /clear, and feeds gaps into /gsd:plan-phase --gaps.
User tests, Claude records. One test at a time. Plain text responses.
</purpose>
@@ -153,7 +153,7 @@ issues: 0
pending: [N]
skipped: 0
## Issues for /gsd:plan-fix
## Gaps
[none yet]
```
@@ -224,9 +224,15 @@ reported: "{verbatim user response}"
severity: {inferred}
```
Append to Issues section:
```
- UAT-{NNN}: {brief summary from response} ({severity}) - Test {N}
Append to Gaps section (structured YAML for plan-phase --gaps):
```yaml
- truth: "{expected behavior from test}"
status: failed
reason: "User reported: {verbatim user response}"
severity: {inferred}
test: {N}
artifacts: [] # Filled by diagnosis
missing: [] # Filled by diagnosis
```
**After any response:**
@@ -321,12 +327,12 @@ Spawning parallel debug agents to investigate each issue.
- Spawn parallel debug agents for each issue
- Collect root causes
- Update UAT.md with root causes
- Proceed to `offer_plan_fix`
- Proceed to `offer_gap_closure`
Diagnosis runs automatically - no user prompt. Parallel agents investigate simultaneously, so overhead is minimal and fixes are more accurate.
</step>
<step name="offer_plan_fix">
<step name="offer_gap_closure">
**Offer next steps after diagnosis:**
```
@@ -334,14 +340,14 @@ Diagnosis runs automatically - no user prompt. Parallel agents investigate simul
## Diagnosis Complete
| Issue | Root Cause |
|-------|------------|
| UAT-001 | {root_cause} |
| UAT-002 | {root_cause} |
| Gap | Root Cause |
|-----|------------|
| {truth 1} | {root_cause} |
| {truth 2} | {root_cause} |
...
Next steps:
- `/gsd:plan-fix {phase}` — Create fix plan with root causes
- `/gsd:plan-phase {phase} --gaps` — Create fix plans from diagnosed gaps
- `/gsd:verify-work {phase}` — Re-test after fixes
```
</step>
@@ -349,18 +355,23 @@ Next steps:
</process>
<update_rules>
**Section update rules:**
**Batched writes for efficiency:**
| Section | Rule | When |
|---------|------|------|
Keep results in memory. Write to file only when:
1. **Issue found** — Preserve the problem immediately
2. **Session complete** — Final write before commit
3. **Checkpoint** — Every 5 passed tests (safety net)
| Section | Rule | When Written |
|---------|------|--------------|
| Frontmatter.status | OVERWRITE | Start, complete |
| Frontmatter.updated | OVERWRITE | Every update |
| Current Test | OVERWRITE | Each test transition |
| Tests.{N}.result | OVERWRITE | When user responds |
| Summary | OVERWRITE | After each response |
| Issues | APPEND | When issue found |
| Frontmatter.updated | OVERWRITE | On any file write |
| Current Test | OVERWRITE | On any file write |
| Tests.{N}.result | OVERWRITE | On any file write |
| Summary | OVERWRITE | On any file write |
| Gaps | APPEND | When issue found |
**Update file AFTER processing each response.** If context resets, file shows exactly where to resume.
On context reset: File shows last checkpoint. Resume from there.
</update_rules>
<severity_inference>
@@ -383,8 +394,7 @@ Default to **major** if unclear. User can correct if needed.
- [ ] Tests presented one at a time with expected behavior
- [ ] User responses processed as pass/issue/skip
- [ ] Severity inferred from description (never asked)
- [ ] File updated after each response
- [ ] Can resume perfectly from any /clear
- [ ] Batched writes: on issue, every 5 passes, or completion
- [ ] Committed on completion
- [ ] Clear next steps based on results
- [ ] Clear next steps based on results (plan-phase --gaps if issues)
</success_criteria>