fix: enforce mandatory verification before phase/milestone completion routing
- Rewrite offer_next step in execute-phase.md as mandatory verification gate - Rewrite offer_next_phase step in transition.md with explicit verification - Rewrite route step in progress.md with numbered verification steps - Replace broken regex [0-9] (only matched single digits) with ROADMAP.md reading - Add decision tables mapping conditions to explicit routes (A, B, C, D) - Require Claude to "State the counts" before any routing decision - Add "Do NOT skip this verification" instruction to prevent premature completion claims Fixes issue where Claude would declare "phase complete" or "milestone complete" without verifying remaining plans actually exist. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -90,84 +90,164 @@ CONTEXT: [✓ if CONTEXT.md exists | - if not]
|
||||
</step>
|
||||
|
||||
<step name="route">
|
||||
**Determine next action:**
|
||||
**Determine next action based on verified counts.**
|
||||
|
||||
Find the next plan number that needs work.
|
||||
Check if `{phase}-{plan}-PLAN.md` exists for that number.
|
||||
**Step 1: Count plans and summaries in current phase**
|
||||
|
||||
**If PLAN.md exists (unexecuted):**
|
||||
List files in the current phase directory:
|
||||
|
||||
- Read its `<objective>` section
|
||||
- Show: "Ready to execute: [path] - [objective summary]"
|
||||
- Display (see ~/.claude/get-shit-done/references/continuation-format.md):
|
||||
```
|
||||
---
|
||||
```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
|
||||
```
|
||||
|
||||
## ▶ Next Up
|
||||
State: "This phase has {X} plans and {Y} summaries."
|
||||
|
||||
**{phase}-{plan}: [Plan Name]** — [objective summary from PLAN.md]
|
||||
**Step 2: Route based on counts**
|
||||
|
||||
`/gsd:execute-plan [full-path-to-PLAN.md]`
|
||||
| Condition | Meaning | Action |
|
||||
|-----------|---------|--------|
|
||||
| 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** |
|
||||
|
||||
<sub>`/clear` first → fresh context window</sub>
|
||||
---
|
||||
|
||||
---
|
||||
```
|
||||
**Route A: Unexecuted plan exists**
|
||||
|
||||
**If PLAN.md does NOT exist:**
|
||||
Find the first PLAN.md without matching SUMMARY.md.
|
||||
Read its `<objective>` section.
|
||||
|
||||
- Check if `{phase}-CONTEXT.md` exists in phase directory
|
||||
- Show: "Next plan not yet created: [expected path]"
|
||||
- Show phase objective from ROADMAP
|
||||
```
|
||||
---
|
||||
|
||||
## ▶ Next Up
|
||||
|
||||
**{phase}-{plan}: [Plan Name]** — [objective summary from PLAN.md]
|
||||
|
||||
`/gsd:execute-plan [full-path-to-PLAN.md]`
|
||||
|
||||
<sub>`/clear` first → fresh context window</sub>
|
||||
|
||||
---
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**Route B: Phase needs planning**
|
||||
|
||||
Check if `{phase}-CONTEXT.md` exists in phase directory.
|
||||
|
||||
**If CONTEXT.md exists:**
|
||||
|
||||
- Display: "✓ Context gathered, ready to plan"
|
||||
- Display:
|
||||
```
|
||||
---
|
||||
```
|
||||
---
|
||||
|
||||
## ▶ Next Up
|
||||
## ▶ Next Up
|
||||
|
||||
**Phase [N]: [Name]** — [Goal from ROADMAP.md]
|
||||
**Phase {N}: {Name}** — {Goal from ROADMAP.md}
|
||||
<sub>✓ Context gathered, ready to plan</sub>
|
||||
|
||||
`/gsd:plan-phase [phase-number]`
|
||||
`/gsd:plan-phase {phase-number}`
|
||||
|
||||
<sub>`/clear` first → fresh context window</sub>
|
||||
<sub>`/clear` first → fresh context window</sub>
|
||||
|
||||
---
|
||||
```
|
||||
---
|
||||
```
|
||||
|
||||
**If CONTEXT.md does NOT exist:**
|
||||
|
||||
- Display:
|
||||
```
|
||||
---
|
||||
```
|
||||
---
|
||||
|
||||
## ▶ Next Up
|
||||
## ▶ Next Up
|
||||
|
||||
**Phase [N]: [Name]** — [Goal from ROADMAP.md]
|
||||
**Phase {N}: {Name}** — {Goal from ROADMAP.md}
|
||||
|
||||
`/gsd:plan-phase [phase]`
|
||||
`/gsd:plan-phase {phase}`
|
||||
|
||||
<sub>`/clear` first → fresh context window</sub>
|
||||
<sub>`/clear` first → fresh context window</sub>
|
||||
|
||||
---
|
||||
---
|
||||
|
||||
**Also available:**
|
||||
- `/gsd:discuss-phase [phase]` — gather context first
|
||||
- `/gsd:research-phase [phase]` — investigate unknowns
|
||||
- `/gsd:list-phase-assumptions [phase]` — see Claude's assumptions
|
||||
**Also available:**
|
||||
- `/gsd:discuss-phase {phase}` — gather context first
|
||||
- `/gsd:research-phase {phase}` — investigate unknowns
|
||||
- `/gsd:list-phase-assumptions {phase}` — see Claude's assumptions
|
||||
|
||||
---
|
||||
```
|
||||
---
|
||||
```
|
||||
|
||||
**If all plans complete for current phase:**
|
||||
---
|
||||
|
||||
- Check if more phases exist in ROADMAP
|
||||
- If yes: Show `/gsd:plan-phase [next-phase]` command to paste
|
||||
- If no (milestone 100% complete): Show `/gsd:complete-milestone` command to paste
|
||||
</step>
|
||||
**Step 3: Check milestone status (only when phase complete)**
|
||||
|
||||
Read ROADMAP.md and identify:
|
||||
1. Current phase number
|
||||
2. All phase numbers in the current milestone section
|
||||
|
||||
Count total phases and identify the highest phase number.
|
||||
|
||||
State: "Current phase is {X}. Milestone has {N} phases (highest: {Y})."
|
||||
|
||||
**Route based on milestone status:**
|
||||
|
||||
| Condition | Meaning | Action |
|
||||
|-----------|---------|--------|
|
||||
| current phase < highest phase | More phases remain | Go to **Route C** |
|
||||
| current phase = highest phase | Milestone complete | Go to **Route D** |
|
||||
|
||||
---
|
||||
|
||||
**Route C: Phase complete, more phases remain**
|
||||
|
||||
Read ROADMAP.md to get the next phase's name and goal.
|
||||
|
||||
```
|
||||
---
|
||||
|
||||
## ✓ Phase {Z} Complete
|
||||
|
||||
## ▶ Next Up
|
||||
|
||||
**Phase {Z+1}: {Name}** — {Goal from ROADMAP.md}
|
||||
|
||||
`/gsd:plan-phase {Z+1}`
|
||||
|
||||
<sub>`/clear` first → fresh context window</sub>
|
||||
|
||||
---
|
||||
|
||||
**Also available:**
|
||||
- `/gsd:discuss-phase {Z+1}` — gather context first
|
||||
- `/gsd:research-phase {Z+1}` — investigate unknowns
|
||||
|
||||
---
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**Route D: Milestone complete**
|
||||
|
||||
```
|
||||
---
|
||||
|
||||
## 🎉 Milestone Complete
|
||||
|
||||
All {N} phases finished!
|
||||
|
||||
## ▶ Next Up
|
||||
|
||||
**Complete Milestone** — archive and prepare for next
|
||||
|
||||
`/gsd:complete-milestone`
|
||||
|
||||
<sub>`/clear` first → fresh context window</sub>
|
||||
|
||||
---
|
||||
```
|
||||
|
||||
</step>
|
||||
|
||||
<step name="edge_cases">
|
||||
**Handle edge cases:**
|
||||
|
||||
@@ -1437,33 +1437,44 @@ Use AskUserQuestion:
|
||||
</step>
|
||||
|
||||
<step name="offer_next">
|
||||
**First, determine if more plans exist in this phase:**
|
||||
**MANDATORY: Verify remaining work before presenting next steps.**
|
||||
|
||||
Do NOT skip this verification. Do NOT assume phase or milestone completion without checking.
|
||||
|
||||
**Step 1: Count plans and summaries in current phase**
|
||||
|
||||
List files in the phase directory:
|
||||
|
||||
```bash
|
||||
# Get current phase directory from the plan we just executed
|
||||
PHASE_DIR=$(dirname "$PLAN_PATH")
|
||||
|
||||
# Count PLAN files vs SUMMARY files
|
||||
PLAN_COUNT=$(ls "$PHASE_DIR"/*-PLAN.md 2>/dev/null | wc -l | tr -d ' ')
|
||||
SUMMARY_COUNT=$(ls "$PHASE_DIR"/*-SUMMARY.md 2>/dev/null | wc -l | tr -d ' ')
|
||||
|
||||
echo "Plans: $PLAN_COUNT, Summaries: $SUMMARY_COUNT"
|
||||
|
||||
if [[ $SUMMARY_COUNT -lt $PLAN_COUNT ]]; then
|
||||
echo "MORE_PLANS_EXIST"
|
||||
else
|
||||
echo "PHASE_COMPLETE"
|
||||
fi
|
||||
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
|
||||
```
|
||||
|
||||
**If MORE_PLANS_EXIST (more plans in this phase):**
|
||||
State the counts: "This phase has [X] plans and [Y] summaries."
|
||||
|
||||
**Step 2: Route based on plan completion**
|
||||
|
||||
Compare the counts from Step 1:
|
||||
|
||||
| Condition | Meaning | Action |
|
||||
|-----------|---------|--------|
|
||||
| summaries < plans | More plans remain | Go to **Route A** |
|
||||
| summaries = plans | Phase complete | Go to Step 3 |
|
||||
|
||||
---
|
||||
|
||||
**Route A: More plans remain in this phase**
|
||||
|
||||
Identify the next unexecuted plan:
|
||||
- Find the first PLAN.md file that has no matching SUMMARY.md
|
||||
- Read its `<objective>` section
|
||||
|
||||
<if mode="yolo">
|
||||
```
|
||||
Plan {phase}-{plan} complete.
|
||||
Summary: .planning/phases/XX-name/{phase}-{plan}-SUMMARY.md
|
||||
Summary: .planning/phases/{phase-dir}/{phase}-{plan}-SUMMARY.md
|
||||
|
||||
[X] of [Y] plans complete for Phase Z.
|
||||
{Y} of {X} plans complete for Phase {Z}.
|
||||
|
||||
⚡ Auto-continuing: Execute next plan ({phase}-{next-plan})
|
||||
```
|
||||
@@ -1474,9 +1485,9 @@ Loop back to identify_plan step automatically.
|
||||
<if mode="interactive" OR="custom with gates.execute_next_plan true">
|
||||
```
|
||||
Plan {phase}-{plan} complete.
|
||||
Summary: .planning/phases/XX-name/{phase}-{plan}-SUMMARY.md
|
||||
Summary: .planning/phases/{phase-dir}/{phase}-{plan}-SUMMARY.md
|
||||
|
||||
[X] of [Y] plans complete for Phase Z.
|
||||
{Y} of {X} plans complete for Phase {Z}.
|
||||
|
||||
---
|
||||
|
||||
@@ -1484,7 +1495,7 @@ Summary: .planning/phases/XX-name/{phase}-{plan}-SUMMARY.md
|
||||
|
||||
**{phase}-{next-plan}: [Plan Name]** — [objective from next PLAN.md]
|
||||
|
||||
`/gsd:execute-plan .planning/phases/XX-name/{phase}-{next-plan}-PLAN.md`
|
||||
`/gsd:execute-plan .planning/phases/{phase-dir}/{phase}-{next-plan}-PLAN.md`
|
||||
|
||||
<sub>`/clear` first → fresh context window</sub>
|
||||
|
||||
@@ -1499,37 +1510,82 @@ Summary: .planning/phases/XX-name/{phase}-{plan}-SUMMARY.md
|
||||
Wait for user to clear and run next command.
|
||||
</if>
|
||||
|
||||
**If phase complete (last plan done):**
|
||||
**STOP here if Route A applies. Do not continue to Step 3.**
|
||||
|
||||
First, check if this is also the last phase in the milestone (milestone complete):
|
||||
---
|
||||
|
||||
```bash
|
||||
# Count total phases in ROADMAP.md
|
||||
TOTAL_PHASES=$(grep -c "^### Phase [0-9]" .planning/ROADMAP.md)
|
||||
**Step 3: Check milestone status (only when all plans in phase are complete)**
|
||||
|
||||
# Get current phase number from the just-completed plan
|
||||
CURRENT_PHASE=$(echo "{phase}" | grep -oE '^[0-9]+')
|
||||
Read ROADMAP.md and extract:
|
||||
1. Current phase number (from the plan just completed)
|
||||
2. All phase numbers listed in the current milestone section
|
||||
|
||||
# Check if current phase == total phases
|
||||
if [[ "$CURRENT_PHASE" -eq "$TOTAL_PHASES" ]]; then
|
||||
# Milestone complete
|
||||
MILESTONE_COMPLETE=true
|
||||
fi
|
||||
To find phases in the current milestone, look for:
|
||||
- Phase headers: lines starting with `### Phase` or `#### Phase`
|
||||
- Phase list items: lines like `- [ ] **Phase X:` or `- [x] **Phase X:`
|
||||
|
||||
Count total phases in the current milestone and identify the highest phase number.
|
||||
|
||||
State: "Current phase is {X}. Milestone has {N} phases (highest: {Y})."
|
||||
|
||||
**Step 4: Route based on milestone status**
|
||||
|
||||
| Condition | Meaning | Action |
|
||||
|-----------|---------|--------|
|
||||
| current phase < highest phase | More phases remain | Go to **Route B** |
|
||||
| current phase = highest phase | Milestone complete | Go to **Route C** |
|
||||
|
||||
---
|
||||
|
||||
**Route B: Phase complete, more phases remain in milestone**
|
||||
|
||||
Read ROADMAP.md to get the next phase's name and goal.
|
||||
|
||||
```
|
||||
Plan {phase}-{plan} complete.
|
||||
Summary: .planning/phases/{phase-dir}/{phase}-{plan}-SUMMARY.md
|
||||
|
||||
## ✓ Phase {Z}: {Phase Name} Complete
|
||||
|
||||
All {Y} plans finished.
|
||||
|
||||
---
|
||||
|
||||
## ▶ Next Up
|
||||
|
||||
**Phase {Z+1}: {Next Phase Name}** — {Goal from ROADMAP.md}
|
||||
|
||||
`/gsd:plan-phase {Z+1}`
|
||||
|
||||
<sub>`/clear` first → fresh context window</sub>
|
||||
|
||||
---
|
||||
|
||||
**Also available:**
|
||||
- `/gsd:discuss-phase {Z+1}` — gather context first
|
||||
- `/gsd:research-phase {Z+1}` — investigate unknowns
|
||||
- Review phase accomplishments before continuing
|
||||
|
||||
---
|
||||
```
|
||||
|
||||
**If milestone complete (final phase of roadmap done):**
|
||||
---
|
||||
|
||||
**Route C: Milestone complete (all phases done)**
|
||||
|
||||
```
|
||||
🎉 MILESTONE COMPLETE!
|
||||
|
||||
Plan {phase}-{plan} complete.
|
||||
Summary: .planning/phases/XX-name/{phase}-{plan}-SUMMARY.md
|
||||
Summary: .planning/phases/{phase-dir}/{phase}-{plan}-SUMMARY.md
|
||||
|
||||
Phase [Z]: [Name] COMPLETE - all [Y] plans finished.
|
||||
## ✓ Phase {Z}: {Phase Name} Complete
|
||||
|
||||
All {Y} plans finished.
|
||||
|
||||
════════════════════════════════════════
|
||||
All [N] phases complete!
|
||||
This milestone is 100% done.
|
||||
All {N} phases complete!
|
||||
Milestone is 100% done.
|
||||
════════════════════════════════════════
|
||||
|
||||
---
|
||||
@@ -1545,42 +1601,12 @@ This milestone is 100% done.
|
||||
---
|
||||
|
||||
**Also available:**
|
||||
- `/gsd:add-phase <description>` — add another phase
|
||||
- `/gsd:add-phase <description>` — add another phase before completing
|
||||
- Review accomplishments before archiving
|
||||
|
||||
---
|
||||
```
|
||||
|
||||
**If phase complete but more phases remain:**
|
||||
|
||||
```
|
||||
Plan {phase}-{plan} complete.
|
||||
Summary: .planning/phases/XX-name/{phase}-{plan}-SUMMARY.md
|
||||
|
||||
## ✓ Phase [Z] Complete
|
||||
|
||||
All [Y] plans finished.
|
||||
|
||||
---
|
||||
|
||||
## ▶ Next Up
|
||||
|
||||
**Phase [X+1]: [Name]** — [Goal from ROADMAP.md]
|
||||
|
||||
`/gsd:plan-phase [X+1]`
|
||||
|
||||
<sub>`/clear` first → fresh context window</sub>
|
||||
|
||||
---
|
||||
|
||||
**Also available:**
|
||||
- `/gsd:discuss-phase [X+1]` — gather context first
|
||||
- `/gsd:research-phase [X+1]` — investigate unknowns
|
||||
- Review phase accomplishments before continuing
|
||||
|
||||
---
|
||||
```
|
||||
|
||||
</step>
|
||||
|
||||
</process>
|
||||
|
||||
@@ -408,14 +408,34 @@ Resume file: None
|
||||
|
||||
<step name="offer_next_phase">
|
||||
|
||||
**Check if there's a next phase in the current milestone:**
|
||||
**MANDATORY: Verify milestone status before presenting next steps.**
|
||||
|
||||
Re-read the ROADMAP file:
|
||||
**Step 1: Read ROADMAP.md and identify phases in current milestone**
|
||||
|
||||
- Parse current milestone version (e.g., "v1.0" from "## Current Milestone: v1.0 Foundation")
|
||||
- Look for phases after the current one in the current milestone section
|
||||
- If next phase exists: offer to plan it
|
||||
- If no next phase (milestone 100% complete): offer to complete milestone with parsed version
|
||||
Read the ROADMAP.md file and extract:
|
||||
1. Current phase number (the phase just transitioned from)
|
||||
2. All phase numbers in the current milestone section
|
||||
|
||||
To find phases, look for:
|
||||
- Phase headers: lines starting with `### Phase` or `#### Phase`
|
||||
- Phase list items: lines like `- [ ] **Phase X:` or `- [x] **Phase X:`
|
||||
|
||||
Count total phases and identify the highest phase number in the milestone.
|
||||
|
||||
State: "Current phase is {X}. Milestone has {N} phases (highest: {Y})."
|
||||
|
||||
**Step 2: Route based on milestone status**
|
||||
|
||||
| Condition | Meaning | Action |
|
||||
|-----------|---------|--------|
|
||||
| current phase < highest phase | More phases remain | Go to **Route A** |
|
||||
| current phase = highest phase | Milestone complete | Go to **Route B** |
|
||||
|
||||
---
|
||||
|
||||
**Route A: More phases remain in milestone**
|
||||
|
||||
Read ROADMAP.md to get the next phase's name and goal.
|
||||
|
||||
**If next phase exists:**
|
||||
|
||||
@@ -460,36 +480,38 @@ Exit skill and invoke SlashCommand("/gsd:plan-phase [X+1]")
|
||||
|
||||
</if>
|
||||
|
||||
**If no next phase (milestone 100% complete):**
|
||||
---
|
||||
|
||||
**Route B: Milestone complete (all phases done)**
|
||||
|
||||
<if mode="yolo">
|
||||
|
||||
```
|
||||
Phase [X] marked complete.
|
||||
Phase {X} marked complete.
|
||||
|
||||
🎉 Milestone [version] is 100% complete — all phases finished!
|
||||
🎉 Milestone {version} is 100% complete — all {N} phases finished!
|
||||
|
||||
⚡ Auto-continuing: Complete milestone and archive
|
||||
```
|
||||
|
||||
Exit skill and invoke SlashCommand("/gsd:complete-milestone [version]")
|
||||
Exit skill and invoke SlashCommand("/gsd:complete-milestone {version}")
|
||||
|
||||
</if>
|
||||
|
||||
<if mode="interactive" OR="custom with gates.confirm_transition true">
|
||||
|
||||
```
|
||||
## ✓ Phase [X] Complete
|
||||
## ✓ Phase {X}: {Phase Name} Complete
|
||||
|
||||
🎉 Milestone [version] is 100% complete — all phases finished!
|
||||
🎉 Milestone {version} is 100% complete — all {N} phases finished!
|
||||
|
||||
---
|
||||
|
||||
## ▶ Next Up
|
||||
|
||||
**Complete Milestone [version]** — archive and prepare for next
|
||||
**Complete Milestone {version}** — archive and prepare for next
|
||||
|
||||
`/gsd:complete-milestone [version]`
|
||||
`/gsd:complete-milestone {version}`
|
||||
|
||||
<sub>`/clear` first → fresh context window</sub>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user