merge: resolve conflicts with main (plan_bounce + code_review_command)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Tom Boucher
2026-04-11 10:32:20 -04:00
25 changed files with 1870 additions and 144 deletions

View File

@@ -113,6 +113,15 @@ Phase: "API documentation"
<answer_validation>
**IMPORTANT: Answer validation** — After every AskUserQuestion call, check if the response is empty or whitespace-only. If so:
**Exception — "Other" with empty text:** If the user selected "Other" (or "Chat more") and the response body is empty or whitespace-only, this is NOT an empty answer — it is a signal that the user wants to type freeform input. In this case:
1. Output a single plain-text line: "What would you like to discuss?"
2. STOP generating. Do not call any tools. Do not output any further text.
3. Wait for the user's next message.
4. After receiving their message, reflect it back and continue.
Do NOT retry the AskUserQuestion or generate more questions when "Other" is selected with empty text.
**All other empty responses:** If the response is empty or whitespace-only (and the user did NOT select "Other"):
1. Retry the question once with the same parameters
2. If still empty, present the options as a plain-text numbered list and ask the user to type their choice number
Never proceed with an empty answer.

View File

@@ -202,7 +202,7 @@ Workspace created: $TARGET_PATH
Branch: $BRANCH_NAME
Next steps:
cd $TARGET_PATH
cd "$TARGET_PATH"
/gsd-new-project # Initialize GSD in the workspace
```
@@ -215,7 +215,7 @@ Workspace created with $SUCCESS_COUNT of $TOTAL_COUNT repos: $TARGET_PATH
Failed: repo3 (branch already exists), repo4 (not a git repo)
Next steps:
cd $TARGET_PATH
cd "$TARGET_PATH"
/gsd-new-project # Initialize GSD in the workspace
```
@@ -225,7 +225,7 @@ Use AskUserQuestion:
- header: "Initialize GSD"
- question: "Would you like to initialize a GSD project in the new workspace?"
- options:
- "Yes — run /gsd-new-project" → tell user to `cd $TARGET_PATH` first, then run `/gsd-new-project`
- "Yes — run /gsd-new-project" → tell user to `cd "$TARGET_PATH"` first, then run `/gsd-new-project`
- "No — I'll set it up later" → done
</process>

View File

@@ -82,12 +82,56 @@ Use `--force` to bypass this check.
```
Exit.
**Consecutive-call guard:**
After passing all gates, check a counter file `.planning/.next-call-count`:
- If file exists and count >= 6: prompt "You've called /gsd-next {N} times consecutively. Continue? [y/N]"
- If user says no, exit
- Increment the counter
- The counter file is deleted by any non-`/gsd-next` command (convention — other workflows don't need to implement this, the note here is sufficient)
**Prior-phase completeness scan:**
After passing all three hard-stop gates, scan all phases that precede the current phase in ROADMAP.md order for incomplete work. Use the existing `gsd-tools.cjs phase json <N>` output to inspect each prior phase.
Detect three categories of incomplete work:
1. **Plans without summaries** — a PLAN.md exists in a prior phase directory but no matching SUMMARY.md exists (execution started but not completed).
2. **Verification failures not overridden** — a prior phase has a VERIFICATION.md with `FAIL` items that have no override annotation.
3. **CONTEXT.md without plans** — a prior phase directory has a CONTEXT.md but no PLAN.md files (discussion happened, planning never ran).
If no incomplete prior work is found, continue to `determine_next_action` silently with no interruption.
If incomplete prior work is found, show a structured completeness report:
```
⚠ Prior phase has incomplete work
Phase {N} — "{name}" has unresolved items:
• Plan {N}-{M} ({slug}): executed but no SUMMARY.md
[... additional items ...]
Advancing before resolving these may cause:
• Verification gaps — future phase verification won't have visibility into what prior phases shipped
• Context loss — plans that ran without summaries leave no record for future agents
Options:
[C] Continue and defer these items to backlog
[S] Stop and resolve manually (recommended)
[F] Force advance without recording deferral
Choice [S]:
```
**If the user chooses "Stop" (S or Enter/default):** Exit without routing.
**If the user chooses "Continue and defer" (C):**
1. For each incomplete item, create a backlog entry in `ROADMAP.md` under `## Backlog` using the existing `999.x` numbering scheme:
```markdown
### Phase 999.{N}: Follow-up — Phase {src} incomplete plans (BACKLOG)
**Goal:** Resolve plans that ran without producing summaries during Phase {src} execution
**Source phase:** {src}
**Deferred at:** {date} during /gsd-next advancement to Phase {dest}
**Plans:**
- [ ] {N}-{M}: {slug} (ran, no SUMMARY.md)
```
2. Commit the deferral record:
```bash
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" commit "docs: defer incomplete Phase {src} items to backlog"
```
3. Continue routing to `determine_next_action` immediately — no second prompt.
**If the user chooses "Force" (F):** Continue to `determine_next_action` without recording deferral.
</step>
<step name="determine_next_action">

View File

@@ -46,7 +46,7 @@ Parse JSON for: `researcher_model`, `planner_model`, `checker_model`, `research_
## 2. Parse and Normalize Arguments
Extract from $ARGUMENTS: phase number (integer or decimal like `2.1`), flags (`--research`, `--skip-research`, `--gaps`, `--skip-verify`, `--skip-ui`, `--prd <filepath>`, `--reviews`, `--text`).
Extract from $ARGUMENTS: phase number (integer or decimal like `2.1`), flags (`--research`, `--skip-research`, `--gaps`, `--skip-verify`, `--skip-ui`, `--prd <filepath>`, `--reviews`, `--text`, `--bounce`, `--skip-bounce`).
Set `TEXT_MODE=true` if `--text` is present in $ARGUMENTS OR `text_mode` from init JSON is `true`. When `TEXT_MODE` is active, replace every `AskUserQuestion` call with a plain-text numbered list and ask the user to type their choice number. This is required for Claude Code remote sessions (`/rc` mode) where TUI menus don't work through the Claude App.
@@ -719,41 +719,70 @@ Task(
## 9. Handle Planner Return
- **`## PLANNING COMPLETE`:** Display plan count. If `--skip-verify` or `plan_checker_enabled` is false (from init): skip to step 13. Otherwise: step 10.
- **`## PHASE SPLIT RECOMMENDED`:** The planner determined the phase is too complex to implement all user decisions without simplifying them. Handle in step 9b.
- **`## PHASE SPLIT RECOMMENDED`:** The planner determined the phase exceeds the context budget for full-fidelity implementation of all source items. Handle in step 9b.
- **`## ⚠ Source Audit: Unplanned Items Found`:** The planner's multi-source coverage audit found items from REQUIREMENTS.md, RESEARCH.md, ROADMAP goal, or CONTEXT.md decisions that are not covered by any plan. Handle in step 9c.
- **`## CHECKPOINT REACHED`:** Present to user, get response, spawn continuation (step 12)
- **`## PLANNING INCONCLUSIVE`:** Show attempts, offer: Add context / Retry / Manual
## 9b. Handle Phase Split Recommendation
When the planner returns `## PHASE SPLIT RECOMMENDED`, it means the phase has too many decisions to implement at full fidelity within the plan budget. The planner proposes groupings.
When the planner returns `## PHASE SPLIT RECOMMENDED`, it means the phase's source items exceed the context budget for full-fidelity implementation. The planner proposes groupings.
**Extract from planner return:**
- Proposed sub-phases (e.g., "17a: processing core (D-01 to D-19)", "17b: billing + config UX (D-20 to D-27)")
- Which D-XX decisions go in each sub-phase
- Why the split is necessary (decision count, complexity estimate)
- Which source items (REQ-IDs, D-XX decisions, RESEARCH items) go in each sub-phase
- Why the split is necessary (context cost estimate, file count)
**Present to user:**
```
## Phase {X} is too complex for full-fidelity implementation
## Phase {X} exceeds context budget for full-fidelity implementation
The planner found {N} decisions that cannot all be implemented without
simplifying some. Instead of reducing your decisions, we recommend splitting:
The planner found {N} source items that exceed the context budget when
planned at full fidelity. Instead of reducing scope, we recommend splitting:
**Option 1: Split into sub-phases**
- Phase {X}a: {name} — {D-XX to D-YY} ({N} decisions)
- Phase {X}b: {name} — {D-XX to D-YY} ({M} decisions)
- Phase {X}a: {name} — {items} ({N} source items, ~{P}% context)
- Phase {X}b: {name} — {items} ({M} source items, ~{Q}% context)
**Option 2: Proceed anyway** (planner will attempt all, quality may degrade)
**Option 2: Proceed anyway** (planner will attempt all, quality may degrade past 50% context)
**Option 3: Prioritize** — you choose which decisions to implement now,
**Option 3: Prioritize** — you choose which items to implement now,
rest become a follow-up phase
```
Use AskUserQuestion with these 3 options.
**If "Split":** Use `/gsd-insert-phase` to create the sub-phases, then replan each.
**If "Proceed":** Return to planner with instruction to attempt all decisions at full fidelity, accepting more plans/tasks.
**If "Prioritize":** Use AskUserQuestion (multiSelect) to let user pick which D-XX are "now" vs "later". Create CONTEXT.md for each sub-phase with the selected decisions.
**If "Proceed":** Return to planner with instruction to attempt all items at full fidelity, accepting more plans/tasks.
**If "Prioritize":** Use AskUserQuestion (multiSelect) to let user pick which items are "now" vs "later". Create CONTEXT.md for each sub-phase with the selected items.
## 9c. Handle Source Audit Gaps
When the planner returns `## ⚠ Source Audit: Unplanned Items Found`, it means items from REQUIREMENTS.md, RESEARCH.md, ROADMAP goal, or CONTEXT.md decisions have no corresponding plan.
**Extract from planner return:**
- Each unplanned item with its source artifact and section
- The planner's suggested options (A: add plan, B: split phase, C: defer with confirmation)
**Present each gap to user.** For each unplanned item:
```
## ⚠ Unplanned: {item description}
Source: {RESEARCH.md / REQUIREMENTS.md / ROADMAP goal / CONTEXT.md}
Details: {why the planner flagged this}
Options:
1. Add a plan to cover this item (recommended)
2. Split phase — move to a sub-phase with related items
3. Defer — add to backlog (developer confirms this is intentional)
```
Use AskUserQuestion for each gap (or batch if multiple gaps).
**If "Add plan":** Return to planner (step 8) with instruction to add plans covering the missing items, preserving existing plans.
**If "Split":** Use `/gsd-insert-phase` for overflow items, then replan.
**If "Defer":** Record in CONTEXT.md `## Deferred Ideas` with developer's confirmation. Proceed to step 10.
## 10. Spawn gsd-plan-checker Agent
@@ -901,6 +930,77 @@ Display: `Max iterations reached. {N} issues remain:` + issue list
Offer: 1) Force proceed, 2) Provide guidance and retry, 3) Abandon
## 12.5. Plan Bounce (Optional External Refinement)
**Skip if:** `--skip-bounce` flag, `--gaps` flag, or bounce is not activated.
**Activation:** Bounce runs when `--bounce` flag is present OR `workflow.plan_bounce` config is `true`. The `--skip-bounce` flag always wins (disables bounce even if config enables it). The `--gaps` flag also disables bounce (gap-closure mode should not modify plans externally).
**Prerequisites:** `workflow.plan_bounce_script` must be set to a valid script path. If bounce is activated but no script is configured, display warning and skip:
```
⚠ Plan bounce activated but no script configured.
Set workflow.plan_bounce_script to the path of your refinement script.
Skipping bounce step.
```
**Read pass count:**
```bash
BOUNCE_PASSES=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" config-get workflow.plan_bounce_passes --default 2)
BOUNCE_SCRIPT=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" config-get workflow.plan_bounce_script)
```
Display banner:
```
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
GSD ► BOUNCING PLANS (External Refinement)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Script: ${BOUNCE_SCRIPT}
Max passes: ${BOUNCE_PASSES}
```
**For each PLAN.md file in the phase directory:**
1. **Backup:** Copy `*-PLAN.md` to `*-PLAN.pre-bounce.md`
```bash
cp "${PLAN_FILE}" "${PLAN_FILE%.md}.pre-bounce.md"
```
2. **Invoke bounce script:**
```bash
"${BOUNCE_SCRIPT}" "${PLAN_FILE}" "${BOUNCE_PASSES}"
```
3. **Validate bounced plan — YAML frontmatter integrity:**
After the script returns, check that the bounced file still has valid YAML frontmatter (opening and closing `---` delimiters with parseable content between them). If the bounced plan breaks YAML frontmatter validation, restore the original from the pre-bounce.md backup and continue to the next plan:
```
⚠ Bounced plan ${PLAN_FILE} has broken YAML frontmatter — restoring original from pre-bounce backup.
```
4. **Handle script failure:** If the bounce script exits non-zero, restore the original plan from the pre-bounce.md backup and continue to the next plan:
```
⚠ Bounce script failed for ${PLAN_FILE} (exit code ${EXIT_CODE}) — restoring original from pre-bounce backup.
```
**After all plans are bounced:**
5. **Re-run plan checker on bounced plans:** Spawn gsd-plan-checker (same as step 10) on all modified plans. If a bounced plan fails the checker, restore original from its pre-bounce.md backup:
```
⚠ Bounced plan ${PLAN_FILE} failed checker validation — restoring original from pre-bounce backup.
```
6. **Commit surviving bounced plans:** If at least one plan survived both the frontmatter validation and the checker re-run, commit the changes:
```bash
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" commit "refactor(${padded_phase}): bounce plans through external refinement" --files "${PHASE_DIR}/*-PLAN.md"
```
Display summary:
```
Plan bounce complete: {survived}/{total} plans refined
```
**Clean up:** Remove all `*-PLAN.pre-bounce.md` backup files after the bounce step completes (whether plans survived or were restored).
## 13. Requirements Coverage Gate
After plans pass the checker (or checker is skipped), verify that all phase requirements are covered by at least one plan.

View File

@@ -43,7 +43,7 @@ Cannot remove workspace "$WORKSPACE_NAME" — the following repos have uncommitt
- repo2
Commit or stash changes in these repos before removing the workspace:
cd $WORKSPACE_PATH/repo1
cd "$WORKSPACE_PATH/repo1"
git stash # or git commit
```