feat: add parallel diagnosis before plan-fix

After UAT finds issues, spawn parallel debug agents to investigate
root causes before planning fixes. Each agent investigates one issue
with symptoms pre-filled from UAT, finds the root cause, and returns
diagnosis.

New files:
- workflows/diagnose-issues.md: Orchestrator for parallel debug agents
- templates/debug-subagent-prompt.md: Prompt template for debug subagents

Modified:
- workflows/debug.md: Add symptoms_prefilled and diagnose-only modes
- workflows/verify-work.md: Offer diagnosis step after issues found
- templates/UAT.md: Add root_cause and debug_session fields
- commands/gsd/plan-fix.md: Use root causes for targeted fix planning

Flow: UAT → diagnose (parallel) → plan-fix (with root causes) → execute

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Lex Christopherson
2026-01-14 10:11:28 -06:00
parent 2394116801
commit d498662938
6 changed files with 612 additions and 10 deletions

View File

@@ -91,10 +91,17 @@ Parse each issue:
- 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">
@@ -104,7 +111,29 @@ For each issue (or logical group):
- Create one task per issue OR
- Group related cosmetic/minor issues into single task
Task structure:
**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>
@@ -113,7 +142,7 @@ Task structure:
**Issue:** {verbatim reported description}
**Expected:** {from test}
[Specific fix approach]
[Investigate and fix - root cause unknown]
</action>
<verify>
- Reproduce original issue - confirm fixed
@@ -145,6 +174,7 @@ autonomous: true
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>
@@ -160,6 +190,11 @@ Priority: {blocker count} blocker, {major count} major, {minor count} minor, {co
**Issues being fixed:**
@.planning/phases/XX-name/{phase}-UAT.md
**Debug sessions (if diagnosed):**
@.planning/debug/uat-001-*.md
@.planning/debug/uat-002-*.md
[etc - reference each debug session for full investigation context]
**Original plans for reference:**
@.planning/phases/XX-name/{phase}-01-PLAN.md
[other relevant plans]

View File

@@ -8,7 +8,7 @@ Template for `.planning/phases/XX-name/{phase}-UAT.md` — persistent UAT sessio
```markdown
---
status: testing | complete
status: testing | complete | diagnosed
phase: XX-name
source: [list of SUMMARY.md files tested]
started: [ISO timestamp]
@@ -39,6 +39,8 @@ 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]
@@ -58,7 +60,10 @@ skipped: [N]
## Issues for /gsd:plan-fix
- UAT-001: [brief summary] (blocker) - Test 3
root_cause: [empty until diagnosed]
- UAT-002: [brief summary] (major) - Test 7
root_cause: [empty until diagnosed]
```
---
@@ -82,6 +87,7 @@ 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
@@ -90,10 +96,44 @@ skipped: [N]
**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
</section_rules>
<diagnosis_lifecycle>
**After testing complete (status: complete), if issues 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
5. status → "diagnosed"
6. Ready for /gsd:plan-fix 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/uat-001-comment-refresh.md
```
```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
```
</diagnosis_lifecycle>
<lifecycle>
**Creation:** When /gsd:verify-work starts new session
@@ -170,6 +210,8 @@ 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/uat-001-comment-refresh.md
### 3. Reply to a Comment
expected: Click Reply, inline composer appears, submit shows nested reply
@@ -198,6 +240,7 @@ skipped: 0
## 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
```
</good_example>

View File

@@ -0,0 +1,156 @@
# Debug Subagent Prompt Template
Template for spawning debug agents from diagnose-issues workflow. Each agent investigates one UAT issue with symptoms pre-filled.
---
## Template
```markdown
<objective>
Investigate UAT issue and find root cause. Do NOT fix - only diagnose.
**Issue:** {issue_id}
**Summary:** {issue_summary}
**Severity:** {severity}
Symptoms are pre-filled from UAT testing. Skip symptom gathering, start investigating immediately.
</objective>
<execution_context>
@~/.claude/get-shit-done/workflows/debug.md
@~/.claude/get-shit-done/templates/DEBUG.md
@~/.claude/get-shit-done/references/debugging/debugging-mindset.md
@~/.claude/get-shit-done/references/debugging/hypothesis-testing.md
@~/.claude/get-shit-done/references/debugging/investigation-techniques.md
</execution_context>
<context>
**Symptoms (from UAT):**
- expected: {expected}
- actual: {reported}
- severity: {severity}
- reproduction: Test {test_num} in UAT
@.planning/STATE.md
@.planning/phases/{phase_dir}/{phase}-UAT.md
</context>
<mode>
**symptoms_prefilled: true**
Skip the symptom_gathering step entirely. Symptoms section is already filled.
Start directly at investigation_loop.
**goal: find_root_cause_only**
Do NOT apply fixes. Your job is to:
1. Investigate the issue
2. Form and test hypotheses
3. Find the root cause with evidence
4. Return the diagnosis
The fix will be planned and applied separately by /gsd:plan-fix.
</mode>
<debug_file>
Create: `.planning/debug/uat-{issue_id_lower}-{slug}.md`
Example: `.planning/debug/uat-001-comment-refresh.md`
Pre-fill Symptoms section:
```markdown
## Symptoms
expected: {expected}
actual: {reported}
errors: [investigate to find]
reproduction: Test {test_num} - {test_name}
started: discovered during UAT
```
Then proceed with investigation.
</debug_file>
<return_format>
When root cause is confirmed, return:
```
## DEBUG COMPLETE: {issue_id}
**Root Cause:** [specific cause with evidence]
**Evidence:**
- [key finding 1]
- [key finding 2]
- [key finding 3]
**Files Involved:**
- [file1.ts]: [what's wrong]
- [file2.ts]: [related issue]
**Debug Session:** .planning/debug/uat-{issue_id_lower}-{slug}.md
**Suggested Fix Direction:** [brief hint for plan-fix, not implementation]
```
If unable to determine root cause after thorough investigation:
```
## DEBUG INCONCLUSIVE: {issue_id}
**Investigation Summary:**
- [what was checked]
- [what was eliminated]
**Hypotheses Remaining:**
- [possible cause 1]
- [possible cause 2]
**Recommendation:** Manual review needed
**Debug Session:** .planning/debug/uat-{issue_id_lower}-{slug}.md
```
</return_format>
<success_criteria>
- [ ] DEBUG-UAT-{NNN}.md created with symptoms pre-filled
- [ ] Investigation completed (evidence gathered, hypotheses tested)
- [ ] Root cause identified with supporting evidence
- [ ] Debug session file updated throughout
- [ ] Clear return format for orchestrator
</success_criteria>
```
---
## Placeholders
| Placeholder | Source | Example |
|-------------|--------|---------|
| `{issue_id}` | UAT issue ID | `UAT-001` |
| `{issue_id_lower}` | Lowercase for filenames | `001` |
| `{issue_summary}` | Brief description | `Comment doesn't appear until refresh` |
| `{expected}` | From UAT test | `Submit comment, appears in list` |
| `{reported}` | User's description | `works but doesn't show until refresh` |
| `{severity}` | blocker/major/minor/cosmetic | `major` |
| `{test_num}` | Test number in UAT | `2` |
| `{test_name}` | Test name | `Create Top-Level Comment` |
| `{phase}` | Phase number | `04` |
| `{phase_dir}` | Phase directory name | `04-comments` |
| `{slug}` | Generated from summary | `comment-refresh` |
---
## Usage
Orchestrator (diagnose-issues.md) fills placeholders and spawns:
```python
# Spawn all debug agents in parallel
Task(prompt=filled_template_001, subagent_type="general-purpose", description="Debug UAT-001")
Task(prompt=filled_template_002, subagent_type="general-purpose", description="Debug UAT-002")
Task(prompt=filled_template_003, subagent_type="general-purpose", description="Debug UAT-003")
```
All agents run simultaneously. Each returns with root cause or inconclusive result.

View File

@@ -2,6 +2,11 @@
Systematic debugging with persistent state that survives context resets. The debug file IS the debugging brain - create it immediately and update it continuously.
You are the debugger. The user knows what's wrong (behavior), not why (root cause). Gather symptoms, then investigate autonomously.
**Modes:**
- **Interactive (default):** User reports issue, gather symptoms through questions, investigate, fix
- **Symptoms prefilled:** Symptoms provided (e.g., from UAT), skip gathering, start investigating immediately
- **Diagnose only:** Find root cause but don't fix (for parallel diagnosis before plan-fix)
</purpose>
<philosophy>
@@ -33,6 +38,27 @@ Ask about experience. Investigate the cause yourself.
@~/.claude/get-shit-done/templates/DEBUG.md
</template>
<modes>
**Check for mode flags in prompt context:**
**symptoms_prefilled: true**
- Symptoms section already filled (from UAT or other source)
- Skip `symptom_gathering` step entirely
- Start directly at `investigation_loop`
- Create debug file with status: "investigating" (not "gathering")
**goal: find_root_cause_only**
- 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)
**Default mode (no flags):**
- Interactive debugging with user
- Gather symptoms through questions
- Investigate, fix, and verify
</modes>
<process>
<step name="check_active_session">
@@ -264,6 +290,12 @@ Append result to Evidence.
If CONFIRMED:
- Update Resolution.root_cause with evidence
**If goal: find_root_cause_only:**
- Update status to "diagnosed"
- Proceed to `return_diagnosis` (skip fix_and_verify)
**Otherwise (default):**
- Update status to "fixing"
- Proceed to `fix_and_verify`
@@ -309,6 +341,50 @@ Based on status:
The file tells you exactly where you were.
</step>
<step name="return_diagnosis">
**Return root cause without fixing (diagnose-only mode)**
This step is used when `goal: find_root_cause_only` is set (e.g., from diagnose-issues workflow).
Update status to "diagnosed".
Return structured diagnosis:
```
## DEBUG COMPLETE: {issue_id}
**Root Cause:** {from Resolution.root_cause}
**Evidence:**
{summary of key evidence entries}
**Files Involved:**
{files identified during investigation}
**Debug Session:** {path to debug file}
**Suggested Fix Direction:** {brief hint based on root cause}
```
If unable to determine root cause after thorough investigation:
```
## DEBUG INCONCLUSIVE: {issue_id}
**Investigation Summary:**
{what was checked}
**Hypotheses Remaining:**
{possible causes not yet eliminated}
**Recommendation:** Manual review needed
**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.
</step>
<step name="fix_and_verify">
**Apply fix and verify**

View File

@@ -0,0 +1,233 @@
<purpose>
Orchestrate parallel debug agents to investigate UAT issues 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.
Orchestrator stays lean: parse issues, spawn agents, collect results, update UAT.
</purpose>
<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.
Without diagnosis: "Comment doesn't refresh" → guess at fix → maybe wrong
With diagnosis: "Comment doesn't refresh" → "useEffect missing dependency" → precise fix
</core_principle>
<process>
<step name="parse_issues">
**Extract issues 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
```
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
Build issue 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: "..."},
...
]
```
</step>
<step name="report_plan">
**Report diagnosis plan to user:**
```
## Diagnosing {N} Issues
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 |
Each agent will:
1. Create DEBUG-UAT-{NNN}.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.
```
</step>
<step name="spawn_agents">
**Spawn debug agents in parallel:**
For each issue, fill the debug-subagent-prompt template and spawn:
```
Task(
prompt=filled_debug_subagent_prompt,
subagent_type="general-purpose",
description="Debug UAT-{NNN}"
)
```
**All agents spawn in single message** (parallel execution).
Template placeholders:
- `{issue_id}`: UAT-001, UAT-002, etc.
- `{issue_summary}`: Brief description
- `{expected}`: From UAT test
- `{reported}`: Verbatim user description
- `{severity}`: blocker/major/minor/cosmetic
- `{phase}`: Phase being tested
- `{phase_dir}`: Path to phase directory
</step>
<step name="collect_results">
**Collect root causes from agents:**
Each agent returns with:
```
## DEBUG COMPLETE: UAT-{NNN}
**Root Cause:** {specific cause with evidence}
**Files Involved:** {list of files}
**Debug Session:** .planning/debug/uat-{nnn}-{slug}.md
**Evidence Summary:**
- {key finding 1}
- {key finding 2}
```
Parse each return to extract:
- root_cause: The diagnosed cause
- files: Files involved
- debug_path: Path to debug session file
If agent fails or can't determine root cause:
- root_cause: "Investigation inconclusive - manual review needed"
- Note which issue needs manual attention
</step>
<step name="update_uat">
**Update UAT.md with root causes:**
For each issue in the Tests section, add root_cause field:
```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: .planning/debug/uat-001-comment-refresh.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
```
Commit the updated UAT.md:
```bash
git add ".planning/phases/XX-name/{phase}-UAT.md"
git commit -m "docs({phase}): add root causes from diagnosis"
```
</step>
<step name="report_results">
**Report diagnosis results:**
```
## 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 |
Debug sessions saved to .planning/debug/
---
Next steps:
- `/gsd:plan-fix {phase}` — Create fix plan with root causes
- Review debug sessions for details
```
</step>
<step name="offer_next">
**Offer plan-fix:**
```
Root causes identified. Ready to plan fixes?
`/gsd:plan-fix {phase}`
The fix plan will use diagnosed root causes for targeted fixes.
```
</step>
</process>
<context_efficiency>
**Orchestrator context:** ~15%
- Parse UAT.md issues
- Fill template strings
- Spawn parallel Task calls
- Collect results
- Update UAT.md
**Each debug agent:** Fresh 200k context
- Loads full debug workflow
- Loads debugging references
- Investigates with full capacity
- Returns root cause
**No symptom gathering.** Agents start with symptoms pre-filled from UAT.
**No fix application.** Agents only diagnose - plan-fix handles fixes.
</context_efficiency>
<failure_handling>
**Agent fails to find root cause:**
- Mark issue as "needs manual review"
- Continue with other issues
- Report incomplete diagnosis
**Agent times out:**
- Check DEBUG-UAT-{NNN}.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
</failure_handling>
<success_criteria>
- [ ] Issues parsed from UAT.md
- [ ] Debug agents spawned in parallel
- [ ] Root causes collected from all agents
- [ ] UAT.md updated with root causes
- [ ] Debug sessions saved to .planning/debug/
- [ ] User knows next steps (plan-fix)
</success_criteria>

View File

@@ -292,19 +292,78 @@ Present summary:
### Issues Found
[List from Issues section]
```
**If issues > 0:** Proceed to `offer_diagnosis`
**If issues == 0:**
```
All tests passed. Ready to continue.
- `/gsd:plan-phase {next}` — Plan next phase
- `/gsd:execute-phase {next}` — Execute next phase
```
</step>
<step name="offer_diagnosis">
**Offer to diagnose root causes before planning fixes:**
```
---
{N} issues found. Before planning fixes, diagnose root causes?
Diagnosis spawns parallel debug agents to investigate each issue.
Each agent finds the root cause, making fix planning more accurate.
Diagnose now? (yes/no)
```
Wait for user response.
**If yes/y/diagnose:**
- Load diagnose-issues workflow
- Follow @~/.claude/get-shit-done/workflows/diagnose-issues.md
- Spawn parallel debug agents for each issue
- Collect root causes
- Update UAT.md with root causes
- Return to `offer_plan_fix`
**If no/skip/later:**
- Proceed to `offer_plan_fix` without diagnosis
- Plan-fix will work without root causes (less precise but still functional)
</step>
<step name="offer_plan_fix">
**Offer next steps after testing (and optional diagnosis):**
Check if UAT.md has root causes (status: "diagnosed" or root_cause fields populated).
**If diagnosed:**
```
---
Root causes identified. Ready to plan fixes.
| Issue | Root Cause |
|-------|------------|
| UAT-001 | {root_cause} |
| UAT-002 | {root_cause} |
...
Next steps:
- `/gsd:plan-fix {phase}` — Create fix plan with root causes
- `/gsd:verify-work {phase}` — Re-test after fixes
```
**If not diagnosed:**
```
---
Next steps:
- `/gsd:plan-fix {phase}` — Create fix plan for issues
- `/gsd:verify-work {phase}` — Re-test after fixes
- Continue to next phase
[If issues == 0:]
All tests passed. Ready to continue.
- `/gsd:plan-phase {next}` — Plan next phase
- `/gsd:execute-phase {next}` — Execute next phase
- Continue to next phase (issues logged for later)
```
</step>