@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.
- package/.claude-plugin/marketplace.json +20 -0
- package/.claude-plugin/plugin.json +1 -1
- package/.opencode/plugins/gsd-core.js +711 -0
- package/agents/gsd-advisor-researcher.md +2 -0
- package/agents/gsd-ai-researcher.md +1 -1
- package/agents/gsd-assumptions-analyzer.md +2 -0
- package/agents/gsd-code-fixer.md +2 -0
- package/agents/gsd-code-reviewer.md +2 -0
- package/agents/gsd-codebase-mapper.md +2 -0
- package/agents/gsd-debugger.md +2 -0
- package/agents/gsd-doc-writer.md +2 -0
- package/agents/gsd-eval-auditor.md +2 -0
- package/agents/gsd-executor.md +9 -6
- package/agents/gsd-integration-checker.md +2 -0
- package/agents/gsd-nyquist-auditor.md +2 -0
- package/agents/gsd-phase-researcher.md +2 -0
- package/agents/gsd-plan-checker.md +2 -0
- package/agents/gsd-planner.md +2 -0
- package/agents/gsd-project-researcher.md +2 -0
- package/agents/gsd-research-synthesizer.md +2 -0
- package/agents/gsd-roadmapper.md +2 -0
- package/agents/gsd-security-auditor.md +2 -0
- package/agents/gsd-ui-auditor.md +2 -0
- package/agents/gsd-ui-checker.md +2 -0
- package/agents/gsd-ui-researcher.md +2 -0
- package/agents/gsd-verifier.md +4 -2
- package/bin/install.js +118 -1
- package/gemini-extension.json +1 -1
- package/gsd-core/bin/gsd-tools.cjs +18 -7
- package/gsd-core/bin/lib/capability-loader.cjs +27 -9
- package/gsd-core/bin/lib/capability-registry.cjs +51 -49
- package/gsd-core/bin/lib/capability-source.cjs +22 -7
- package/gsd-core/bin/lib/capability-validator.cjs +24 -2
- package/gsd-core/bin/lib/commands.cjs +2 -1
- package/gsd-core/bin/lib/frontmatter.cjs +53 -6
- package/gsd-core/bin/lib/handshake-serialized.cjs +70 -0
- package/gsd-core/bin/lib/host-integration-sdk.cjs +53 -0
- package/gsd-core/bin/lib/host-integration.cjs +61 -0
- package/gsd-core/bin/lib/init.cjs +34 -6
- package/gsd-core/bin/lib/milestone.cjs +49 -10
- package/gsd-core/bin/lib/phase-id.cjs +18 -0
- package/gsd-core/bin/lib/phase.cjs +37 -27
- package/gsd-core/bin/lib/phases-command-router.cjs +4 -3
- package/gsd-core/bin/lib/probe-core.cjs +44 -4
- package/gsd-core/bin/lib/roadmap-command-router.cjs +3 -2
- package/gsd-core/bin/lib/roadmap-parser.cjs +21 -11
- package/gsd-core/bin/lib/roadmap.cjs +28 -20
- package/gsd-core/bin/lib/state-transition.cjs +15 -0
- package/gsd-core/bin/lib/state.cjs +27 -8
- package/gsd-core/bin/lib/validate.cjs +2 -1
- package/gsd-core/bin/lib/verify.cjs +6 -4
- package/gsd-core/bin/lib/workstream-inventory-builder.cjs +12 -2
- package/gsd-core/bin/lib/workstream-inventory.cjs +28 -0
- package/gsd-core/bin/shared/model-catalog.json +8 -8
- package/gsd-core/references/agent-skills-bootstrap.md +60 -0
- package/gsd-core/references/model-profiles.md +27 -0
- package/gsd-core/workflows/autonomous.md +22 -24
- package/gsd-core/workflows/complete-milestone.md +6 -10
- package/gsd-core/workflows/execute-phase.md +1 -1
- package/gsd-core/workflows/forensics.md +3 -3
- package/gsd-core/workflows/help/modes/full.md +1 -1
- package/gsd-core/workflows/milestone-summary.md +3 -3
- package/gsd-core/workflows/new-milestone.md +6 -0
- package/gsd-core/workflows/plan-phase/steps/closed-phase-gate.md +42 -0
- package/gsd-core/workflows/plan-phase/steps/prd-express-path.md +102 -0
- package/gsd-core/workflows/plan-phase/steps/windows-troubleshooting.md +23 -0
- package/gsd-core/workflows/plan-phase.md +3 -158
- package/gsd-core/workflows/review.md +7 -2
- package/gsd-core/workflows/settings-advanced.md +10 -10
- package/gsd-core/workflows/verify-work.md +1 -2
- package/package.json +3 -1
- package/scripts/run-tests.cjs +51 -1
- package/scripts/sync-manifest-versions.cjs +66 -14
- 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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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 (
|
|
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
|
-
|
|
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
|
-
|
|
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-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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>
|