@opengsd/gsd-core 1.7.0-rc.1 → 1.7.0-rc.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. package/.claude-plugin/marketplace.json +20 -0
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/.opencode/plugins/gsd-core.js +711 -0
  4. package/agents/gsd-advisor-researcher.md +2 -0
  5. package/agents/gsd-ai-researcher.md +1 -1
  6. package/agents/gsd-assumptions-analyzer.md +2 -0
  7. package/agents/gsd-code-fixer.md +2 -0
  8. package/agents/gsd-code-reviewer.md +2 -0
  9. package/agents/gsd-codebase-mapper.md +2 -0
  10. package/agents/gsd-debugger.md +2 -0
  11. package/agents/gsd-doc-writer.md +2 -0
  12. package/agents/gsd-eval-auditor.md +2 -0
  13. package/agents/gsd-executor.md +9 -6
  14. package/agents/gsd-integration-checker.md +2 -0
  15. package/agents/gsd-nyquist-auditor.md +2 -0
  16. package/agents/gsd-phase-researcher.md +2 -0
  17. package/agents/gsd-plan-checker.md +2 -0
  18. package/agents/gsd-planner.md +2 -0
  19. package/agents/gsd-project-researcher.md +2 -0
  20. package/agents/gsd-research-synthesizer.md +2 -0
  21. package/agents/gsd-roadmapper.md +2 -0
  22. package/agents/gsd-security-auditor.md +2 -0
  23. package/agents/gsd-ui-auditor.md +2 -0
  24. package/agents/gsd-ui-checker.md +2 -0
  25. package/agents/gsd-ui-researcher.md +2 -0
  26. package/agents/gsd-verifier.md +4 -2
  27. package/bin/install.js +118 -1
  28. package/gemini-extension.json +1 -1
  29. package/gsd-core/bin/gsd-tools.cjs +18 -7
  30. package/gsd-core/bin/lib/capability-loader.cjs +27 -9
  31. package/gsd-core/bin/lib/capability-registry.cjs +51 -49
  32. package/gsd-core/bin/lib/capability-source.cjs +22 -7
  33. package/gsd-core/bin/lib/capability-validator.cjs +24 -2
  34. package/gsd-core/bin/lib/commands.cjs +2 -1
  35. package/gsd-core/bin/lib/frontmatter.cjs +53 -6
  36. package/gsd-core/bin/lib/handshake-serialized.cjs +70 -0
  37. package/gsd-core/bin/lib/host-integration-sdk.cjs +53 -0
  38. package/gsd-core/bin/lib/host-integration.cjs +61 -0
  39. package/gsd-core/bin/lib/init.cjs +34 -6
  40. package/gsd-core/bin/lib/milestone.cjs +49 -10
  41. package/gsd-core/bin/lib/phase-id.cjs +18 -0
  42. package/gsd-core/bin/lib/phase.cjs +37 -27
  43. package/gsd-core/bin/lib/phases-command-router.cjs +4 -3
  44. package/gsd-core/bin/lib/probe-core.cjs +44 -4
  45. package/gsd-core/bin/lib/roadmap-command-router.cjs +3 -2
  46. package/gsd-core/bin/lib/roadmap-parser.cjs +21 -11
  47. package/gsd-core/bin/lib/roadmap.cjs +28 -20
  48. package/gsd-core/bin/lib/state-transition.cjs +15 -0
  49. package/gsd-core/bin/lib/state.cjs +27 -8
  50. package/gsd-core/bin/lib/validate.cjs +2 -1
  51. package/gsd-core/bin/lib/verify.cjs +6 -4
  52. package/gsd-core/bin/lib/workstream-inventory-builder.cjs +12 -2
  53. package/gsd-core/bin/lib/workstream-inventory.cjs +28 -0
  54. package/gsd-core/bin/shared/model-catalog.json +8 -8
  55. package/gsd-core/references/agent-skills-bootstrap.md +60 -0
  56. package/gsd-core/references/model-profiles.md +27 -0
  57. package/gsd-core/workflows/autonomous.md +22 -24
  58. package/gsd-core/workflows/complete-milestone.md +6 -10
  59. package/gsd-core/workflows/execute-phase.md +1 -1
  60. package/gsd-core/workflows/forensics.md +3 -3
  61. package/gsd-core/workflows/help/modes/full.md +1 -1
  62. package/gsd-core/workflows/milestone-summary.md +3 -3
  63. package/gsd-core/workflows/new-milestone.md +6 -0
  64. package/gsd-core/workflows/plan-phase/steps/closed-phase-gate.md +42 -0
  65. package/gsd-core/workflows/plan-phase/steps/prd-express-path.md +102 -0
  66. package/gsd-core/workflows/plan-phase/steps/windows-troubleshooting.md +23 -0
  67. package/gsd-core/workflows/plan-phase.md +3 -158
  68. package/gsd-core/workflows/review.md +7 -2
  69. package/gsd-core/workflows/settings-advanced.md +10 -10
  70. package/gsd-core/workflows/verify-work.md +1 -2
  71. package/package.json +3 -1
  72. package/scripts/run-tests.cjs +51 -1
  73. package/scripts/sync-manifest-versions.cjs +66 -14
  74. package/skills/gsd-review/SKILL.md +6 -0
@@ -133,6 +133,33 @@ If you're using Claude Code with OpenRouter, a local model, or any non-Anthropic
133
133
 
134
134
  Without `inherit`, GSD's default `balanced` profile spawns specific Anthropic models (`opus`, `sonnet`, `haiku`) for each agent type, which can result in additional API costs through your non-Anthropic provider.
135
135
 
136
+ ## Advisor Tool (Claude Code)
137
+
138
+ Claude Code (v2.1.98+) can pair the session's executor model with a stronger **advisor** model that it consults mid-generation for strategy and course-correction (Anthropic's [advisor tool](https://platform.claude.com/docs/en/agents-and-tools/tool-use/advisor-tool)). This is a host-runtime feature, not a GSD setting — GSD selects each agent's *executor* model through the profile/tier system above; Claude Code supplies the advisor.
139
+
140
+ Set it once at the session level with `/advisor <model>` (or the `advisorModel` setting / `--advisor` flag). **Subagents inherit the session advisor automatically**, so every GSD subagent an orchestrator spawns gets the same advisor with no per-agent configuration. It composes cleanly with GSD's tiering: the profile keeps executors cheap where the work is mechanical, and the advisor adds a stronger reviewer inline on the turns that benefit.
141
+
142
+ ### Candidate pairings
143
+
144
+ Per Anthropic's advisor-tool docs the advisor must be at least as capable as the executor. Candidate pairings by profile — evaluate on your own workload; the quality/cost characterizations below are Anthropic-reported, not GSD guarantees:
145
+
146
+ | Profile | Typical executors | Candidate advisor | Rationale (per Anthropic docs) |
147
+ |---|---|---|---|
148
+ | `budget` | Haiku / Sonnet | Fable 5 or Opus | A step up in intelligence over Haiku alone, at lower cost than switching the executor to a larger model |
149
+ | `balanced` | Sonnet | Fable 5 or Opus | A quality lift at similar or lower total cost than Sonnet-solo on complex tasks |
150
+ | `quality` / `adaptive` | Opus (planning), Sonnet | Fable 5 or Opus | Marginal on turns already at top capability; most valuable on the Sonnet-executor agents |
151
+
152
+ Fable 5 is a valid advisor for Haiku 4.5, Sonnet 4.6/5, and Opus 4.8 executors, so it pairs with any tier a profile assigns.
153
+
154
+ ### When it's worth enabling
155
+
156
+ - **Worth it:** long, multi-step agent loops where the plan matters but most turns are mechanical — e.g. `execute-phase` and `debug`. Anthropic's docs note advisor prompt-caching pays off at roughly three or more advisor calls, which these long loops make.
157
+ - **Skip it:** short, one-shot agents (mappers, quick audits, single-file checks) — there is little to plan, and the advisor adds cost without a commensurate quality gain.
158
+
159
+ ### Constraint: session-level only (today)
160
+
161
+ The advisor is a single session-wide setting inherited by all subagents; there is **no per-agent advisor selection**, so GSD cannot vary the advisor by role the way it varies the executor model (e.g. "no advisor on the Haiku mapper, a Fable 5 advisor on the Sonnet executor"). Per-agent advisor control is tracked upstream at [anthropics/claude-code#73072](https://github.com/anthropics/claude-code/issues/73072); until it lands, pick one session advisor that fits the most valuable agents in your run.
162
+
136
163
  ## Dynamic Routing with Failure-Tier Escalation (#3024)
137
164
 
138
165
  When `dynamic_routing.enabled = true` in `.planning/config.json`, the resolver picks a model from a tier-mapped table based on the agent's *default tier* (light / standard / heavy) and escalates to the next tier up on orchestrator-detected soft failure.
@@ -61,7 +61,7 @@ fi
61
61
 
62
62
  When `--only` is set, also set `FROM_PHASE` to the same value so existing filter logic applies.
63
63
 
64
- When `--interactive` is set, discuss runs inline with questions. When `dispatch-should-flatten` returns `false` (e.g. codex, cursor — runtimes where a backgrounded agent can still spawn subagents), plan and execute are dispatched as background agents — keeping the main context lean (only discuss conversations accumulate) and enabling overlap. When `dispatch-should-flatten` returns `true` (e.g. claude and other runtimes where backgrounded agents cannot reliably nest subagents), plan and execute run inline to preserve worktree isolation and independent verification, and phases run sequentially with their work accumulating in the main context. Either way, user input is preserved on all design decisions.
64
+ When `--interactive` is set, discuss stays inline. If `dispatch-should-flatten` returns `false`, dispatch plan and execute as background agents; if it returns `true`, run them inline and keep phases sequential. Preserve user input on all design decisions.
65
65
 
66
66
  When `PLAN_STRATEGY=converge`, the planning step MUST invoke the plan-review convergence workflow instead of `gsd-plan-phase`. `--cross-ai` is an alias for `--converge`. Forward `CONVERGENCE_ARGS` exactly as parsed so reviewer flags and `--max-cycles N` retain the same meaning as they have on `/gsd:plan-review-convergence`.
67
67
 
@@ -114,6 +114,8 @@ If `TO_PHASE` is set, display: `Stopping after phase ${TO_PHASE}`
114
114
  If `INTERACTIVE` is set, display: `Mode: Interactive (discuss inline, plan+execute inline — background on Codex only)`
115
115
  If `PLAN_STRATEGY` is `converge`, display: `Planning: Plan-review convergence enabled`
116
116
 
117
+ **Agent skills (delegated agents self-load):** This workflow delegates plan/execute/review via flat `Skill()` invocations rather than resolving `agent_skills` itself. Each consumer agent (`gsd-planner`, `gsd-executor`, `gsd-plan-checker`, `gsd-verifier`, …) self-loads its configured `.planning/config.json` `agent_skills` in its own mandatory init step per `@~/.claude/gsd-core/references/agent-skills-bootstrap.md`. This is the durable path that works on every runtime — including Cursor, where `Skill()`-delegated workflow bash init does not reliably execute. No per-delegation injection is needed here. See open-gsd/gsd-core#1866.
118
+
117
119
  </step>
118
120
 
119
121
  <step name="discover_phases">
@@ -125,10 +127,17 @@ Run phase discovery:
125
127
  ```bash
126
128
  INIT_MANAGER=$(gsd_run query init.manager)
127
129
  if [[ "$INIT_MANAGER" == @file:* ]]; then INIT_MANAGER=$(cat "${INIT_MANAGER#@file:}"); fi
130
+ STATE_CONTENT=$(cat .planning/STATE.md 2>/dev/null || true)
128
131
  ```
129
132
 
130
133
  Parse the JSON `phases` array.
131
134
 
135
+ Parse the optional `## Deferred Verification` table from `STATE_CONTENT` into a phase-number map:
136
+ - `verification_deferred_human` -> `/gsd:verify-work <phase>`
137
+ - `verification_deferred_gaps` -> `/gsd:plan-phase <phase> --gaps`
138
+
139
+ **Skip deferred phases on autonomous re-entry:** drop any phase whose number appears in the deferred-phase map from this run's queue; resume it only through the recorded command.
140
+
132
141
  **Filter to incomplete phases:** Keep `phase_complete !== true`, including implemented phases with `verification_status !== "passed"`.
133
142
 
134
143
  **Apply `--from N`:** If set, filter out phases where `number < FROM_PHASE` (numeric compare; handles "5.1").
@@ -180,6 +189,8 @@ Exit cleanly.
180
189
  | 8 | Lifecycle Orchestration | Not Started |
181
190
  ```
182
191
 
192
+ **If any deferred phases were skipped:** display `## Deferred Verification (Skipped on Re-entry)` with the skipped rows and resume commands, then omit them from this run's queue.
193
+
183
194
  **Fetch details for each phase:**
184
195
 
185
196
  ```bash
@@ -202,9 +213,7 @@ For the current phase, display the progress banner:
202
213
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
203
214
  ```
204
215
 
205
- Where N = current phase number (from the ROADMAP, e.g., 63), T = total milestone phases (from `phase_count` parsed in initialize step, e.g., 67). **Important:** T must be `phase_count` (the total number of phases in this milestone), NOT the count of remaining/incomplete phases. When phases are numbered 61-67, T=7 and the banner should read `Phase 63/7` (phase 63, 7 total in milestone), not `Phase 63/3` (which would confuse 3 remaining with 3 total). P = percentage of all milestone phases completed so far. Calculate P as: (number of phases with `disk_status` "complete" from the latest `roadmap analyze` / T × 100). Use █ for filled and ░ for empty segments in the progress bar (8 characters wide).
206
-
207
- **Alternative display when phase numbers exceed total** (e.g., multi-milestone projects where phases are numbered globally): If N > T (phase number exceeds milestone phase count), use the format `Phase {N} ({position}/{T})` where `position` is the 1-based index of this phase among incomplete phases being processed. This prevents confusing displays like "Phase 63/5".
216
+ Where N is the ROADMAP phase number, T is the milestone `phase_count`, and P = completed milestone phases / T × 100. Use `phase_count`, not remaining phases: phase 63 in a 7-phase milestone is `Phase 63/7`, not `Phase 63/3`. If N > T, render `Phase {N} ({position}/{T})`. Use an 8-character bar with █ and ░.
208
217
 
209
218
  **3a. Smart Discuss**
210
219
 
@@ -496,13 +505,7 @@ Display `Phase ${PHASE_NUM} ✅ ${PHASE_NAME} — Verification passed`, run `@~/
496
505
 
497
506
  **If `human_needed`:**
498
507
 
499
- Read `human_verification` items. In text mode (`--text` or init `text_mode=true`), replace AskUserQuestion with a numbered list and typed choice. Otherwise display items and ask:
500
- - **question:** "Phase ${PHASE_NUM} has items needing manual verification. Validate now or continue to next phase?"
501
- - **options:** "Validate now" / "Continue without validation"
502
-
503
- On **"Validate now"**: Present items, then ask:
504
- - **question:** "Validation result?"
505
- - **options:** "All good — continue" / "Found issues"
508
+ Read `human_verification` items. In text mode (`--text` or init `text_mode=true`), replace AskUserQuestion with a plain-text numbered list. Otherwise ask whether to validate now or continue without validation. If validating now, present items, then ask `Validation result?` with `All good — continue` / `Found issues`.
506
509
 
507
510
  On "All good — continue": set VERIFICATION frontmatter `status: passed`, display `Phase ${PHASE_NUM} ✅ Human validation passed`, run `@~/.claude/gsd-core/workflows/transition.md`, then iterate.
508
511
 
@@ -528,9 +531,7 @@ Read gap score/items from VERIFICATION.md. Display:
528
531
  Score: {N}/{M} must-haves verified
529
532
  ```
530
533
 
531
- Ask user via AskUserQuestion:
532
- - **question:** "Gaps found in phase ${PHASE_NUM}. How to proceed?"
533
- - **options:** "Run gap closure" / "Continue without fixing" / "Stop autonomous mode"
534
+ Ask how to proceed: `Run gap closure` / `Continue without fixing` / `Stop autonomous mode`.
534
535
 
535
536
  On **"Run gap closure"**: one gap-closure attempt:
536
537
 
@@ -554,9 +555,7 @@ If `passed` or `human_needed`: route normally.
554
555
 
555
556
  If `stale`: handle_blocker: "Stale verification for phase ${PHASE_NUM}."
556
557
 
557
- If still `gaps_found` after this retry: Display "Gaps persist after closure attempt." and ask via AskUserQuestion:
558
- - **question:** "Gap closure did not fully resolve issues. How to proceed?"
559
- - **options:** "Continue anyway" / "Stop autonomous mode"
558
+ If still `gaps_found` after this retry, display `Gaps persist after closure attempt.` and ask `Continue anyway` / `Stop autonomous mode`.
560
559
 
561
560
  On "Continue anyway": record `verification_deferred_gaps` using the table below, display `Phase ${PHASE_NUM} ⏭ verification_deferred_gaps — resume with /gsd:plan-phase ${PHASE_NUM} --gaps`, then handle_blocker: "Verification gaps deferred for phase ${PHASE_NUM}."
562
561
  On "Stop autonomous mode": Go to handle_blocker.
@@ -645,13 +644,10 @@ Proceed to lifecycle step (partial completion skips audit/complete/cleanup). Exi
645
644
  ```bash
646
645
  INIT_MANAGER=$(gsd_run query init.manager)
647
646
  if [[ "$INIT_MANAGER" == @file:* ]]; then INIT_MANAGER=$(cat "${INIT_MANAGER#@file:}"); fi
647
+ STATE_CONTENT=$(cat .planning/STATE.md 2>/dev/null || true)
648
648
  ```
649
649
 
650
- Re-filter incomplete phases using the same logic as discover_phases:
651
- - Keep phases where `phase_complete !== true` or `verification_status !== "passed"`
652
- - Apply `--from N` filter if originally provided
653
- - Apply `--to N` filter if originally provided
654
- - Sort by number ascending
650
+ Re-filter incomplete phases using discover_phases logic: keep phases where `phase_complete !== true` or `verification_status !== "passed"`, drop deferred phases from the autonomous queue, re-apply `--from` / `--to`, then sort by number ascending.
655
651
 
656
652
  Read STATE.md fresh:
657
653
 
@@ -663,12 +659,14 @@ Check for blockers in the Blockers/Concerns section. If blockers are found, go t
663
659
 
664
660
  If incomplete phases remain: proceed to next phase, loop back to execute_phase.
665
661
 
666
- **Interactive mode overlap:** When `INTERACTIVE` is set, the iterate step enables pipeline parallelism **on Codex** (on every other runtime, plan/execute run inline — see 3b/3c — so there is no overlap and phases run sequentially):
662
+ If no runnable phases remain but deferred phases were skipped, display `Autonomous run stopped with deferred verification phases still pending. Resume them with the commands listed in Deferred Verification.` Proceed to lifecycle only if every non-deferred phase is complete; otherwise go to handle_blocker.
663
+
664
+ **Interactive mode overlap:** When `INTERACTIVE` is set, Codex can overlap discuss for Phase N+1 with background plan+execute for Phase N. Other runtimes keep plan/execute inline, so phases stay sequential:
667
665
  1. After discuss completes for Phase N, dispatch plan+execute as background agents
668
666
  2. Immediately start discuss for Phase N+1 (the next incomplete phase) while Phase N builds
669
667
  3. Before starting plan for Phase N+1, wait for Phase N's execute agent to complete and handle its post-execution routing (verification, gap closure, etc.)
670
668
 
671
- This means the user is always answering discuss questions (lightweight, interactive) while the heavy work (planning, code generation) runs in the background. The main context only accumulates discuss conversations — plan and execute contexts are isolated in their agents. (On Claude Code and all other non-Codex runtimes, plan and execute run inline, so they run sequentially and their work accumulates in the main context.)
669
+ The main context only accumulates discuss conversations; background plan/execute work stays isolated in its agents.
672
670
 
673
671
  If all phases complete, proceed to lifecycle step.
674
672
 
@@ -453,21 +453,17 @@ Extract from result: `version`, `date`, `phases`, `plans`, `tasks`, `accomplishm
453
453
 
454
454
  Verify: `✅ Milestone archived to .planning/milestones/`
455
455
 
456
- **Phase archival (optional):** After archival completes, ask the user:
456
+ **Phase archival (default-on):** `milestone complete` archives phase directories to `milestones/v[X.Y]-phases/` by default (#1871), so the next `/gsd:new-milestone` never inherits un-archived dirs. No manual `mkdir`/`mv` or `--archive-phases` flag is needed.
457
457
 
458
+ If the user explicitly wants to keep phase directories in place as raw execution history, invoke `milestone complete` with `--no-archive-phases`:
458
459
 
459
- **Text mode (`workflow.text_mode: true` in config or `--text` flag):** 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 non-Claude runtimes (OpenAI Codex, Gemini CLI, etc.) where `AskUserQuestion` is not available.
460
- AskUserQuestion(header="Archive Phases", question="Archive phase directories to milestones/?", options: "Yes — move to milestones/v[X.Y]-phases/" | "Skip — keep phases in place")
461
-
462
- If "Yes": move phase directories to the milestone archive:
463
460
  ```bash
464
- mkdir -p .planning/milestones/v[X.Y]-phases
465
- # For each phase directory in .planning/phases/:
466
- mv .planning/phases/{phase-dir} .planning/milestones/v[X.Y]-phases/
461
+ gsd_run query milestone complete v[X.Y] --no-archive-phases
467
462
  ```
468
- Verify: `✅ Phase directories archived to .planning/milestones/v[X.Y]-phases/`
469
463
 
470
- If "Skip": Phase directories remain in `.planning/phases/` as raw execution history. Use `/gsd:cleanup` later to archive retroactively.
464
+ Verify after a default (archived) completion: `✅ Phase directories archived to .planning/milestones/v[X.Y]-phases/`
465
+
466
+ **Text mode (`workflow.text_mode: true` in config or `--text` flag):** 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 non-Claude runtimes (OpenAI Codex, Gemini CLI, etc.) where `AskUserQuestion` is not available.
471
467
 
472
468
  After archival, the AI still handles:
473
469
  - Reorganizing ROADMAP.md with milestone grouping (requires judgment) — overwrite in place after extracting Backlog section
@@ -84,7 +84,7 @@ AGENT_SKILLS=$(gsd_run query agent-skills gsd-executor)
84
84
 
85
85
  Parse JSON for: `executor_model`, `verifier_model`, `commit_docs`, `parallelization`, `branching_strategy`, `branch_name`, `phase_found`, `phase_dir`, `phase_number`, `phase_name`, `phase_slug`, `plans`, `incomplete_plans`, `plan_count`, `incomplete_count`, `state_exists`, `roadmap_exists`, `phase_req_ids`, `response_language`.
86
86
 
87
- **Model resolution:** If `executor_model` is `"inherit"`, omit the `model=` parameter from all `Agent()` calls — do NOT pass `model="inherit"` to Agent. Omitting the `model=` parameter causes Claude Code to inherit the current orchestrator model automatically. Only set `model=` when `executor_model` is an explicit model name (e.g., `"claude-sonnet-4-6"`, `"claude-opus-4-7"`).
87
+ **Model resolution:** If `executor_model` is `"inherit"`, omit the `model=` parameter from all `Agent()` calls — do NOT pass `model="inherit"` to Agent. Omitting the `model=` parameter causes Claude Code to inherit the current orchestrator model automatically. Only set `model=` when `executor_model` is an explicit model name (e.g., `"claude-sonnet-5"`, `"claude-opus-4-8"`).
88
88
 
89
89
  **If `response_language` is set:** Include `response_language: {value}` in all spawned subagent prompts so any user-facing output stays in the configured language.
90
90
 
@@ -273,7 +273,7 @@ gh issue create \
273
273
 
274
274
  ```bash
275
275
  _GSD_SHIM_NAME="gsd-tools.cjs"; _GSD_RUNTIME_ROOT="${RUNTIME_DIR:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}"; GSD_TOOLS="${_GSD_RUNTIME_ROOT}/gsd-core/bin/${_GSD_SHIM_NAME}"; if [ -f "$GSD_TOOLS" ]; then gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${_GSD_RUNTIME_ROOT}/.claude/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${_GSD_RUNTIME_ROOT}/.claude/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${_GSD_RUNTIME_ROOT}/.codex/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${_GSD_RUNTIME_ROOT}/.codex/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif command -v gsd-tools >/dev/null 2>&1; then GSD_TOOLS="$(command -v gsd-tools)"; gsd_run() { "$GSD_TOOLS" "$@"; }; elif [ -f "$HOME/.claude/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="$HOME/.claude/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${HERMES_HOME:-$HOME/.hermes}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${HERMES_HOME:-$HOME/.hermes}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${CURSOR_CONFIG_DIR:-$HOME/.cursor}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CURSOR_CONFIG_DIR:-$HOME/.cursor}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${CODEX_HOME:-$HOME/.codex}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CODEX_HOME:-$HOME/.codex}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${GEMINI_CONFIG_DIR:-$HOME/.gemini}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${GEMINI_CONFIG_DIR:-$HOME/.gemini}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${COPILOT_CONFIG_DIR:-$HOME/.copilot}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${COPILOT_CONFIG_DIR:-$HOME/.copilot}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${WINDSURF_CONFIG_DIR:-$HOME/.codeium/windsurf}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${WINDSURF_CONFIG_DIR:-$HOME/.codeium/windsurf}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${AUGMENT_CONFIG_DIR:-$HOME/.augment}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${AUGMENT_CONFIG_DIR:-$HOME/.augment}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${TRAE_CONFIG_DIR:-$HOME/.trae}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${TRAE_CONFIG_DIR:-$HOME/.trae}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${QWEN_CONFIG_DIR:-$HOME/.qwen}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${QWEN_CONFIG_DIR:-$HOME/.qwen}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${CODEBUDDY_CONFIG_DIR:-$HOME/.codebuddy}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CODEBUDDY_CONFIG_DIR:-$HOME/.codebuddy}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${CLINE_CONFIG_DIR:-$HOME/.cline}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CLINE_CONFIG_DIR:-$HOME/.cline}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${GROK_AGENTS_HOME:-$HOME/.agents}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${GROK_AGENTS_HOME:-$HOME/.agents}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${ANTIGRAVITY_CONFIG_DIR:-$HOME/.gemini/antigravity}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${ANTIGRAVITY_CONFIG_DIR:-$HOME/.gemini/antigravity}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${OPENCODE_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/opencode}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${OPENCODE_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/opencode}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${KILO_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/kilo}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${KILO_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/kilo}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; else echo "ERROR: gsd-tools.cjs not found at $GSD_TOOLS and gsd-tools is not on PATH. Run: npx -y @opengsd/gsd-core@latest --claude --local" >&2; exit 1; fi; if [ -n "${CLAUDE_ENV_FILE:-}" ] && [ -n "${GSD_TOOLS:-}" ]; then printf "export PATH='%s':\"\$PATH\"\n" "${GSD_TOOLS%/*}" >> "$CLAUDE_ENV_FILE" 2>/dev/null || true; fi
276
- gsd_run query state.record-session "" \
277
- "Forensic investigation complete" \
278
- ".planning/forensics/report-{timestamp}.md"
276
+ gsd_run query state.record-session \
277
+ --stopped-at "Forensic investigation complete" \
278
+ --resume-file ".planning/forensics/report-{timestamp}.md"
279
279
  ```
@@ -673,7 +673,7 @@ These six skills exist primarily for the model to perform two-stage hierarchical
673
673
  ├── milestones/
674
674
  │ ├── v1.0-ROADMAP.md # Archived roadmap snapshot
675
675
  │ ├── v1.0-REQUIREMENTS.md # Archived requirements
676
- │ └── v1.0-phases/ # Archived phase dirs (via /gsd:cleanup or --archive-phases)
676
+ │ └── v1.0-phases/ # Archived phase dirs (via /gsd:cleanup or milestone complete, which archives by default)
677
677
  │ ├── 01-foundation/
678
678
  │ └── 02-core-features/
679
679
  ├── codebase/ # Codebase map (brownfield projects)
@@ -218,7 +218,7 @@ If the user is done:
218
218
  ## Step 9: Update STATE.md
219
219
 
220
220
  ```bash
221
- gsd_run query state.record-session "" \
222
- "Milestone v${VERSION} summary generated" \
223
- ".planning/reports/MILESTONE_SUMMARY-v${VERSION}.md"
221
+ gsd_run query state.record-session \
222
+ --stopped-at "Milestone v${VERSION} summary generated" \
223
+ --resume-file ".planning/reports/MILESTONE_SUMMARY-v${VERSION}.md"
224
224
  ```
@@ -212,6 +212,12 @@ Clear leftover phase directories from the previous milestone:
212
212
  gsd_run query phases.clear --confirm
213
213
  ```
214
214
 
215
+ Stage the phase archive move + source removal so they land in the same commit as the milestone start (atomic — no orphaned uncommitted deletions, no un-archived dirs carried forward). `phases.clear` archives each non-999 dir to `milestones/<version>-phases/`; staging both dirs captures the new archive and the removals together (#1871).
216
+
217
+ ```bash
218
+ git add .planning/milestones/ .planning/phases/ 2>/dev/null || true
219
+ ```
220
+
215
221
  ```bash
216
222
  gsd_run query commit "docs: start milestone v[X.Y] [Name]" --files .planning/PROJECT.md .planning/STATE.md
217
223
  ```
@@ -0,0 +1,42 @@
1
+ # Closed-Phase Gate (#3569)
2
+
3
+ The init JSON includes `phase_status` — one of `Pending | Planned | In Progress | Executed | Complete | Needs Review`. `Complete` means the phase has all summaries AND a `VERIFICATION.md` with `status: passed`. Replanning a closed phase silently rewrites plan docs that no longer match the shipped code, so the workflow must hard-stop here unless the operator explicitly overrides.
4
+
5
+ Parse `phase_status` from the init JSON, then:
6
+
7
+ ```bash
8
+ FORCE_REPLAN=false
9
+ if [[ "$ARGUMENTS" =~ (^|[[:space:]])--force([[:space:]]|$) ]]; then
10
+ FORCE_REPLAN=true
11
+ fi
12
+
13
+ if [ "${phase_status}" = "Complete" ]; then
14
+ if [[ "$ARGUMENTS" =~ (^|[[:space:]])--reviews([[:space:]]|$) ]]; then
15
+ # --reviews on a closed phase is never legitimate — concerns belong in a
16
+ # new phase or issue against the closed phase's commits.
17
+ cat <<EOF >&2
18
+ Phase ${phase_number} (${phase_name}) is already CLOSED (VERIFICATION status: passed).
19
+ /gsd:plan-phase --reviews cannot replan a closed phase. If the review surfaced
20
+ real concerns, open a follow-up phase or file an issue against the closed
21
+ phase's commits. There is no --force override for --reviews on a closed phase.
22
+ EOF
23
+ exit 1
24
+ fi
25
+ if [ "$FORCE_REPLAN" != "true" ]; then
26
+ cat <<EOF >&2
27
+ Phase ${phase_number} (${phase_name}) is already CLOSED (VERIFICATION status: passed).
28
+ Replanning a closed phase will overwrite plan docs that no longer match the
29
+ shipped code. If you intentionally want to replan over closed work, re-run
30
+ with: /gsd:plan-phase ${phase_number} --force
31
+
32
+ Otherwise, to view what shipped, see: ${verification_path}
33
+ EOF
34
+ exit 1
35
+ fi
36
+ # FORCE_REPLAN=true: continue, but emit a banner so the operator sees the
37
+ # decision in the transcript and in any committed plan docs.
38
+ echo "WARNING: Replanning CLOSED phase ${phase_number} under --force. Verify the closeout was wrong before committing new plan docs." >&2
39
+ fi
40
+ ```
41
+
42
+ The gate fires only on `Complete`. `Executed` and `Needs Review` are not gated — those states mean planning was finished but verification did not pass, and replanning is a legitimate next step.
@@ -0,0 +1,102 @@
1
+ # PRD Express Path — generate CONTEXT.md from a PRD
2
+
3
+ Runs when `--prd <filepath>` is provided (§3.5 of `plan-phase.md`).
4
+
5
+ 1. Read the PRD file:
6
+ ```bash
7
+ PRD_CONTENT=$(cat "$PRD_FILE" 2>/dev/null)
8
+ if [ -z "$PRD_CONTENT" ]; then
9
+ echo "Error: PRD file not found: $PRD_FILE"
10
+ exit 1
11
+ fi
12
+ ```
13
+
14
+ 2. Display banner:
15
+ ```
16
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
17
+ GSD ► PRD EXPRESS PATH
18
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
19
+
20
+ Using PRD: {PRD_FILE}
21
+ Generating CONTEXT.md from requirements...
22
+ ```
23
+
24
+ 3. Parse the PRD content and generate CONTEXT.md. The orchestrator should:
25
+ - Extract all requirements, user stories, acceptance criteria, and constraints from the PRD
26
+ - Map each to a locked decision (everything in the PRD is treated as a locked decision)
27
+ - Identify any areas the PRD doesn't cover and mark as "Claude's Discretion"
28
+ - **Extract canonical refs** from ROADMAP.md for this phase, plus any specs/ADRs referenced in the PRD — expand to full file paths (MANDATORY)
29
+ - Create CONTEXT.md in the phase directory
30
+
31
+ 4. Write CONTEXT.md:
32
+ ```markdown
33
+ # Phase [X]: [Name] - Context
34
+
35
+ **Gathered:** [date]
36
+ **Status:** Ready for planning
37
+ **Source:** PRD Express Path ({PRD_FILE})
38
+
39
+ <domain>
40
+ ## Phase Boundary
41
+
42
+ [Extracted from PRD — what this phase delivers]
43
+
44
+ </domain>
45
+
46
+ <decisions>
47
+ ## Implementation Decisions
48
+
49
+ {For each requirement/story/criterion in the PRD:}
50
+ ### [Category derived from content]
51
+ - [Requirement as locked decision]
52
+
53
+ ### Claude's Discretion
54
+ [Areas not covered by PRD — implementation details, technical choices]
55
+
56
+ </decisions>
57
+
58
+ <canonical_refs>
59
+ ## Canonical References
60
+
61
+ **Downstream agents MUST read these before planning or implementing.**
62
+
63
+ [MANDATORY. Extract from ROADMAP.md and any docs referenced in the PRD.
64
+ Use full relative paths. Group by topic area.]
65
+
66
+ ### [Topic area]
67
+ - `path/to/spec-or-adr.md` — [What it decides/defines]
68
+
69
+ [If no external specs: "No external specs — requirements fully captured in decisions above"]
70
+
71
+ </canonical_refs>
72
+
73
+ <specifics>
74
+ ## Specific Ideas
75
+
76
+ [Any specific references, examples, or concrete requirements from PRD]
77
+
78
+ </specifics>
79
+
80
+ <deferred>
81
+ ## Deferred Ideas
82
+
83
+ [Items in PRD explicitly marked as future/v2/out-of-scope]
84
+ [If none: "None — PRD covers phase scope"]
85
+
86
+ </deferred>
87
+
88
+ ---
89
+
90
+ *Phase: XX-name*
91
+ *Context gathered: [date] via PRD Express Path*
92
+ ```
93
+
94
+ 5. Commit:
95
+ ```bash
96
+ _GSD_SHIM_NAME="gsd-tools.cjs"; _GSD_RUNTIME_ROOT="${RUNTIME_DIR:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}"; GSD_TOOLS="${_GSD_RUNTIME_ROOT}/gsd-core/bin/${_GSD_SHIM_NAME}"; if [ -f "$GSD_TOOLS" ]; then gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${_GSD_RUNTIME_ROOT}/.claude/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${_GSD_RUNTIME_ROOT}/.claude/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${_GSD_RUNTIME_ROOT}/.codex/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${_GSD_RUNTIME_ROOT}/.codex/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif command -v gsd-tools >/dev/null 2>&1; then GSD_TOOLS="$(command -v gsd-tools)"; gsd_run() { "$GSD_TOOLS" "$@"; }; elif [ -f "$HOME/.claude/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="$HOME/.claude/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${HERMES_HOME:-$HOME/.hermes}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${HERMES_HOME:-$HOME/.hermes}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${CURSOR_CONFIG_DIR:-$HOME/.cursor}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CURSOR_CONFIG_DIR:-$HOME/.cursor}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${CODEX_HOME:-$HOME/.codex}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CODEX_HOME:-$HOME/.codex}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${GEMINI_CONFIG_DIR:-$HOME/.gemini}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${GEMINI_CONFIG_DIR:-$HOME/.gemini}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${COPILOT_CONFIG_DIR:-$HOME/.copilot}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${COPILOT_CONFIG_DIR:-$HOME/.copilot}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${WINDSURF_CONFIG_DIR:-$HOME/.codeium/windsurf}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${WINDSURF_CONFIG_DIR:-$HOME/.codeium/windsurf}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${AUGMENT_CONFIG_DIR:-$HOME/.augment}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${AUGMENT_CONFIG_DIR:-$HOME/.augment}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${TRAE_CONFIG_DIR:-$HOME/.trae}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${TRAE_CONFIG_DIR:-$HOME/.trae}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${QWEN_CONFIG_DIR:-$HOME/.qwen}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${QWEN_CONFIG_DIR:-$HOME/.qwen}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${CODEBUDDY_CONFIG_DIR:-$HOME/.codebuddy}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CODEBUDDY_CONFIG_DIR:-$HOME/.codebuddy}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${CLINE_CONFIG_DIR:-$HOME/.cline}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CLINE_CONFIG_DIR:-$HOME/.cline}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${GROK_AGENTS_HOME:-$HOME/.agents}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${GROK_AGENTS_HOME:-$HOME/.agents}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${ANTIGRAVITY_CONFIG_DIR:-$HOME/.gemini/antigravity}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${ANTIGRAVITY_CONFIG_DIR:-$HOME/.gemini/antigravity}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${OPENCODE_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/opencode}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${OPENCODE_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/opencode}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${KILO_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/kilo}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${KILO_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/kilo}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; else echo "ERROR: gsd-tools.cjs not found at $GSD_TOOLS and gsd-tools is not on PATH. Run: npx -y @opengsd/gsd-core@latest --claude --local" >&2; exit 1; fi; if [ -n "${CLAUDE_ENV_FILE:-}" ] && [ -n "${GSD_TOOLS:-}" ]; then printf "export PATH='%s':\"\$PATH\"\n" "${GSD_TOOLS%/*}" >> "$CLAUDE_ENV_FILE" 2>/dev/null || true; fi
97
+ gsd_run query commit "docs(${padded_phase}): generate context from PRD" --files "${phase_dir}/${padded_phase}-CONTEXT.md"
98
+ ```
99
+
100
+ 6. Set `context_content` to the generated CONTEXT.md content and continue to step 5 (Handle Research).
101
+
102
+ **Effect:** This completely bypasses step 4 (Load CONTEXT.md) since we just created it. The rest of the workflow (research, planning, verification) proceeds normally with the PRD-derived context.
@@ -0,0 +1,23 @@
1
+ # Windows Troubleshooting
2
+
3
+ **Windows users:** If plan-phase freezes during agent spawning (common on Windows due to
4
+ stdio deadlocks with MCP servers — see Claude Code issue anthropics/claude-code#28126):
5
+
6
+ 1. **Force-kill:** Close the terminal (Ctrl+C may not work)
7
+ 2. **Clean up orphaned processes:**
8
+ ```powershell
9
+ # Kill orphaned node processes from stale MCP servers
10
+ Get-Process node -ErrorAction SilentlyContinue | Where-Object {$_.StartTime -lt (Get-Date).AddHours(-1)} | Stop-Process -Force
11
+ ```
12
+ 3. **Clean up stale task directories:**
13
+ ```powershell
14
+ # Remove stale subagent task dirs (Claude Code never cleans these on crash)
15
+ Remove-Item -Recurse -Force "$env:USERPROFILE\.claude\tasks\*" -ErrorAction SilentlyContinue
16
+ ```
17
+ 4. **Reduce MCP server count:** Temporarily disable non-essential MCP servers in settings.json
18
+ 5. **Retry:** Restart Claude Code and run `/gsd:plan-phase` again
19
+
20
+ If freezes persist, try `--skip-research` to reduce the agent chain from 3 to 2 agents:
21
+ ```
22
+ /gsd:plan-phase N --skip-research
23
+ ```
@@ -91,46 +91,7 @@ Parse JSON for: `researcher_model`, `planner_model`, `checker_model`, `research_
91
91
 
92
92
  ## 1.5. Closed-Phase Gate (#3569)
93
93
 
94
- The init JSON includes `phase_status` — one of `Pending | Planned | In Progress | Executed | Complete | Needs Review`. `Complete` means the phase has all summaries AND a `VERIFICATION.md` with `status: passed`. Replanning a closed phase silently rewrites plan docs that no longer match the shipped code, so the workflow must hard-stop here unless the operator explicitly overrides.
95
-
96
- Parse `phase_status` from the init JSON, then:
97
-
98
- ```bash
99
- FORCE_REPLAN=false
100
- if [[ "$ARGUMENTS" =~ (^|[[:space:]])--force([[:space:]]|$) ]]; then
101
- FORCE_REPLAN=true
102
- fi
103
-
104
- if [ "${phase_status}" = "Complete" ]; then
105
- if [[ "$ARGUMENTS" =~ (^|[[:space:]])--reviews([[:space:]]|$) ]]; then
106
- # --reviews on a closed phase is never legitimate — concerns belong in a
107
- # new phase or issue against the closed phase's commits.
108
- cat <<EOF >&2
109
- Phase ${phase_number} (${phase_name}) is already CLOSED (VERIFICATION status: passed).
110
- /gsd:plan-phase --reviews cannot replan a closed phase. If the review surfaced
111
- real concerns, open a follow-up phase or file an issue against the closed
112
- phase's commits. There is no --force override for --reviews on a closed phase.
113
- EOF
114
- exit 1
115
- fi
116
- if [ "$FORCE_REPLAN" != "true" ]; then
117
- cat <<EOF >&2
118
- Phase ${phase_number} (${phase_name}) is already CLOSED (VERIFICATION status: passed).
119
- Replanning a closed phase will overwrite plan docs that no longer match the
120
- shipped code. If you intentionally want to replan over closed work, re-run
121
- with: /gsd:plan-phase ${phase_number} --force
122
-
123
- Otherwise, to view what shipped, see: ${verification_path}
124
- EOF
125
- exit 1
126
- fi
127
- # FORCE_REPLAN=true: continue, but emit a banner so the operator sees the
128
- # decision in the transcript and in any committed plan docs.
129
- echo "WARNING: Replanning CLOSED phase ${phase_number} under --force. Verify the closeout was wrong before committing new plan docs." >&2
130
- fi
131
- ```
132
-
133
- The gate fires only on `Complete`. `Executed` and `Needs Review` are not gated — those states mean planning was finished but verification did not pass, and replanning is a legitimate next step.
94
+ Read and execute `gsd-core/workflows/plan-phase/steps/closed-phase-gate.md` — it parses `phase_status` from the init JSON, sets `FORCE_REPLAN` from `$ARGUMENTS`, and hard-stops replanning a `Complete` phase: `--reviews` on a closed phase is never overridable (exit 1), and replanning otherwise requires `--force` (else exit 1, pointing at `${verification_path}`); under `--force` it continues but emits a WARNING banner. Only `Complete` is gated — `Executed` / `Needs Review` are legitimate replans.
134
95
 
135
96
  ## 2. Parse and Normalize Arguments
136
97
 
@@ -249,103 +210,7 @@ MVP_MODE=$(gsd_run query phase.mvp-mode "${PHASE}" $MVP_FLAG_ARG --pick active)
249
210
 
250
211
  **If `--prd <filepath>` provided:**
251
212
 
252
- 1. Read the PRD file:
253
- ```bash
254
- PRD_CONTENT=$(cat "$PRD_FILE" 2>/dev/null)
255
- if [ -z "$PRD_CONTENT" ]; then
256
- echo "Error: PRD file not found: $PRD_FILE"
257
- exit 1
258
- fi
259
- ```
260
-
261
- 2. Display banner:
262
- ```
263
- ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
264
- GSD ► PRD EXPRESS PATH
265
- ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
266
-
267
- Using PRD: {PRD_FILE}
268
- Generating CONTEXT.md from requirements...
269
- ```
270
-
271
- 3. Parse the PRD content and generate CONTEXT.md. The orchestrator should:
272
- - Extract all requirements, user stories, acceptance criteria, and constraints from the PRD
273
- - Map each to a locked decision (everything in the PRD is treated as a locked decision)
274
- - Identify any areas the PRD doesn't cover and mark as "Claude's Discretion"
275
- - **Extract canonical refs** from ROADMAP.md for this phase, plus any specs/ADRs referenced in the PRD — expand to full file paths (MANDATORY)
276
- - Create CONTEXT.md in the phase directory
277
-
278
- 4. Write CONTEXT.md:
279
- ```markdown
280
- # Phase [X]: [Name] - Context
281
-
282
- **Gathered:** [date]
283
- **Status:** Ready for planning
284
- **Source:** PRD Express Path ({PRD_FILE})
285
-
286
- <domain>
287
- ## Phase Boundary
288
-
289
- [Extracted from PRD — what this phase delivers]
290
-
291
- </domain>
292
-
293
- <decisions>
294
- ## Implementation Decisions
295
-
296
- {For each requirement/story/criterion in the PRD:}
297
- ### [Category derived from content]
298
- - [Requirement as locked decision]
299
-
300
- ### Claude's Discretion
301
- [Areas not covered by PRD — implementation details, technical choices]
302
-
303
- </decisions>
304
-
305
- <canonical_refs>
306
- ## Canonical References
307
-
308
- **Downstream agents MUST read these before planning or implementing.**
309
-
310
- [MANDATORY. Extract from ROADMAP.md and any docs referenced in the PRD.
311
- Use full relative paths. Group by topic area.]
312
-
313
- ### [Topic area]
314
- - `path/to/spec-or-adr.md` — [What it decides/defines]
315
-
316
- [If no external specs: "No external specs — requirements fully captured in decisions above"]
317
-
318
- </canonical_refs>
319
-
320
- <specifics>
321
- ## Specific Ideas
322
-
323
- [Any specific references, examples, or concrete requirements from PRD]
324
-
325
- </specifics>
326
-
327
- <deferred>
328
- ## Deferred Ideas
329
-
330
- [Items in PRD explicitly marked as future/v2/out-of-scope]
331
- [If none: "None — PRD covers phase scope"]
332
-
333
- </deferred>
334
-
335
- ---
336
-
337
- *Phase: XX-name*
338
- *Context gathered: [date] via PRD Express Path*
339
- ```
340
-
341
- 5. Commit:
342
- ```bash
343
- gsd_run query commit "docs(${padded_phase}): generate context from PRD" --files "${phase_dir}/${padded_phase}-CONTEXT.md"
344
- ```
345
-
346
- 6. Set `context_content` to the generated CONTEXT.md content and continue to step 5 (Handle Research).
347
-
348
- **Effect:** This completely bypasses step 4 (Load CONTEXT.md) since we just created it. The rest of the workflow (research, planning, verification) proceeds normally with the PRD-derived context.
213
+ Read and execute `gsd-core/workflows/plan-phase/steps/prd-express-path.md` — it reads the PRD (`$PRD_FILE`), generates `CONTEXT.md` (every PRD requirement/story/criterion → locked decision, uncovered areas → "Claude's Discretion", canonical refs extracted from ROADMAP.md + PRD-referenced specs), commits it, sets `context_content`, and bypasses step 4 (Load CONTEXT.md). The rest of the workflow proceeds normally with the PRD-derived context.
349
214
 
350
215
  ## 3.6. Handle ADR Ingest Express Path
351
216
 
@@ -1730,27 +1595,7 @@ Verification: {Passed | Passed with override | Skipped}
1730
1595
  </offer_next>
1731
1596
 
1732
1597
  <windows_troubleshooting>
1733
- **Windows users:** If plan-phase freezes during agent spawning (common on Windows due to
1734
- stdio deadlocks with MCP servers — see Claude Code issue anthropics/claude-code#28126):
1735
-
1736
- 1. **Force-kill:** Close the terminal (Ctrl+C may not work)
1737
- 2. **Clean up orphaned processes:**
1738
- ```powershell
1739
- # Kill orphaned node processes from stale MCP servers
1740
- Get-Process node -ErrorAction SilentlyContinue | Where-Object {$_.StartTime -lt (Get-Date).AddHours(-1)} | Stop-Process -Force
1741
- ```
1742
- 3. **Clean up stale task directories:**
1743
- ```powershell
1744
- # Remove stale subagent task dirs (Claude Code never cleans these on crash)
1745
- Remove-Item -Recurse -Force "$env:USERPROFILE\.claude\tasks\*" -ErrorAction SilentlyContinue
1746
- ```
1747
- 4. **Reduce MCP server count:** Temporarily disable non-essential MCP servers in settings.json
1748
- 5. **Retry:** Restart Claude Code and run `/gsd:plan-phase` again
1749
-
1750
- If freezes persist, try `--skip-research` to reduce the agent chain from 3 to 2 agents:
1751
- ```
1752
- /gsd:plan-phase N --skip-research
1753
- ```
1598
+ Read `gsd-core/workflows/plan-phase/steps/windows-troubleshooting.md` if plan-phase freezes on Windows during agent spawning (stdio deadlocks with MCP servers, anthropics/claude-code#28126) — it covers force-kill, orphaned-node cleanup, stale task-dir cleanup, reducing the MCP server count, and the `--skip-research` fallback.
1754
1599
  </windows_troubleshooting>
1755
1600
 
1756
1601
  <success_criteria>