@opengsd/gsd-core 1.6.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 +5 -2
- package/bin/gsd-mcp-server.js +31 -0
- package/bin/install.js +411 -1146
- package/commands/gsd/review.md +6 -0
- package/gemini-extension.json +1 -1
- package/gsd-core/bin/gsd-tools.cjs +134 -8
- package/gsd-core/bin/lib/adapter-declarative.cjs +35 -0
- package/gsd-core/bin/lib/adapter-imperative.cjs +52 -0
- package/gsd-core/bin/lib/assumption-delta.cjs +231 -0
- package/gsd-core/bin/lib/capability-lifecycle.cjs +7 -7
- package/gsd-core/bin/lib/capability-loader.cjs +45 -9
- package/gsd-core/bin/lib/capability-lock.cjs +2 -2
- package/gsd-core/bin/lib/capability-registry.cjs +891 -82
- package/gsd-core/bin/lib/capability-source.cjs +26 -11
- package/gsd-core/bin/lib/capability-validator.cjs +222 -2
- package/gsd-core/bin/lib/cli-skew-check.cjs +44 -0
- package/gsd-core/bin/lib/command-aliases.cjs +8 -0
- package/gsd-core/bin/lib/commands.cjs +2 -1
- package/gsd-core/bin/lib/config.cjs +27 -0
- package/gsd-core/bin/lib/embedding-adapter.cjs +27 -0
- package/gsd-core/bin/lib/external-descriptor-trust.cjs +70 -0
- package/gsd-core/bin/lib/frontmatter.cjs +53 -6
- package/gsd-core/bin/lib/handshake-serialized.cjs +70 -0
- package/gsd-core/bin/lib/hook-bus.cjs +81 -0
- package/gsd-core/bin/lib/host-integration-sdk.cjs +53 -0
- package/gsd-core/bin/lib/host-integration.cjs +469 -0
- package/gsd-core/bin/lib/init.cjs +35 -7
- package/gsd-core/bin/lib/install-engine.cjs +755 -0
- package/gsd-core/bin/lib/install-profiles.cjs +35 -4
- package/gsd-core/bin/lib/installer-migrations.cjs +1 -1
- package/gsd-core/bin/lib/mcp-server.cjs +194 -0
- package/gsd-core/bin/lib/milestone.cjs +68 -40
- package/gsd-core/bin/lib/model-adapter.cjs +50 -0
- package/gsd-core/bin/lib/phase-id.cjs +18 -0
- package/gsd-core/bin/lib/phase.cjs +57 -90
- package/gsd-core/bin/lib/phases-command-router.cjs +4 -3
- package/gsd-core/bin/lib/planning-workspace.cjs +1 -1
- package/gsd-core/bin/lib/probe-core.cjs +132 -2
- package/gsd-core/bin/lib/review-reviewer-selection.cjs +129 -13
- 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-upgrade.cjs +3 -2
- package/gsd-core/bin/lib/roadmap.cjs +33 -22
- package/gsd-core/bin/lib/runtime-artifact-conversion.cjs +65 -9
- package/gsd-core/bin/lib/runtime-artifact-install-plan.cjs +54 -4
- package/gsd-core/bin/lib/runtime-artifact-layout.cjs +5 -2
- package/gsd-core/bin/lib/runtime-hooks-surface.cjs +1 -1
- package/gsd-core/bin/lib/runtime-name-policy.cjs +160 -30
- package/gsd-core/bin/lib/shell-command-projection.cjs +16 -0
- package/gsd-core/bin/lib/stale-bake-guard.cjs +254 -0
- package/gsd-core/bin/lib/state-command-router.cjs +4 -0
- package/gsd-core/bin/lib/state-io.cjs +55 -0
- package/gsd-core/bin/lib/state-transition.cjs +1603 -0
- package/gsd-core/bin/lib/state.cjs +327 -683
- package/gsd-core/bin/lib/surface.cjs +4 -1
- 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/lib/workstream.cjs +4 -4
- package/gsd-core/bin/shared/config-schema.manifest.json +9 -0
- package/gsd-core/references/agent-skills-bootstrap.md +60 -0
- package/gsd-core/references/honest-verifier.md +105 -0
- package/gsd-core/references/model-profiles.md +27 -0
- package/gsd-core/references/reviewer-instances.md +99 -0
- package/gsd-core/workflows/autonomous.md +30 -32
- 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/manager.md +15 -15
- 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 +4 -159
- package/gsd-core/workflows/review.md +33 -2
- package/gsd-core/workflows/thread.md +4 -4
- package/gsd-core/workflows/verify-phase.md +11 -4
- package/gsd-core/workflows/verify-work.md +1 -2
- package/hooks/dist/gsd-graphify-update.sh +7 -1
- package/hooks/gsd-graphify-update.sh +7 -1
- package/package.json +6 -4
- package/scripts/ci-test-scope.cjs +38 -9
- package/scripts/lint-allow-test-rule-refs.allowlist.json +0 -1
- package/scripts/lint-regression-test-names.allowlist.json +3 -0
- package/scripts/lint-test-file-count.allowlist.json +19 -5
- package/scripts/mutation-matrix.cjs +45 -3
- package/scripts/prompt-injection-scan.sh +8 -0
- package/scripts/run-tests.cjs +51 -1
- package/scripts/sync-manifest-versions.cjs +66 -14
- package/skills/gsd-review/SKILL.md +6 -0
- package/scripts/lint-windows-test-portability.cjs +0 -178
|
@@ -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
|
|
|
@@ -358,13 +367,13 @@ UI_SPEC_FILE=$(ls "${PHASE_DIR}"/*-UI-SPEC.md 2>/dev/null | head -1)
|
|
|
358
367
|
|
|
359
368
|
**3b. Plan**
|
|
360
369
|
|
|
361
|
-
**If `INTERACTIVE` is set:** Background dispatch is only safe on a runtime where a backgrounded agent can still nest the pipeline's subagents (plan-checker / worktree executors / verifier).
|
|
370
|
+
**If `INTERACTIVE` is set:** Background dispatch is only safe on a runtime where a backgrounded agent can still nest the pipeline's subagents (plan-checker / worktree executors / verifier). This is determined from the documentation-sourced dispatch capability in the registry (#1708); Claude Code's backgrounded agents have no `Agent`/`Task` tool, and every other runtime either prohibits nested subagents or disables them by default. So run **inline** everywhere except where `dispatch-should-flatten` returns `false`. Resolve first:
|
|
362
371
|
|
|
363
372
|
```bash
|
|
364
|
-
|
|
373
|
+
FLATTEN=$(gsd_run query dispatch-should-flatten --raw 2>/dev/null || echo "true")
|
|
365
374
|
```
|
|
366
375
|
|
|
367
|
-
- **If `
|
|
376
|
+
- **If `FLATTEN` is `false`:** Dispatch plan as a background agent to keep the main context lean. While plan runs, the workflow can immediately start discussing the next phase (see step 4).
|
|
368
377
|
|
|
369
378
|
- If `PLAN_STRATEGY=converge`, print: `◆ Spawning background plan-convergence loop for phase ${PHASE_NUM}... (runs in a subagent — no output until it returns, ~1–5 min; expected, not a freeze)`
|
|
370
379
|
|
|
@@ -388,7 +397,7 @@ RUNTIME=$(gsd_run query config-get runtime --default claude --raw 2>/dev/null ||
|
|
|
388
397
|
|
|
389
398
|
Store the agent task_id. After discuss for the next phase completes (or if no next phase), wait for the plan agent to finish before proceeding to execute.
|
|
390
399
|
|
|
391
|
-
- **Otherwise (
|
|
400
|
+
- **Otherwise (`FLATTEN` is `true` — run inline):** Run plan **inline** (do NOT background) so the plan-checker runs. The next phase's discuss does not overlap planning here — correctness over overlap.
|
|
392
401
|
|
|
393
402
|
- If `PLAN_STRATEGY=converge`:
|
|
394
403
|
|
|
@@ -420,13 +429,13 @@ Verify plan produced output — re-run `init phase-op` and check `has_plans`. If
|
|
|
420
429
|
|
|
421
430
|
**3c. Execute**
|
|
422
431
|
|
|
423
|
-
**If `INTERACTIVE` is set:** Wait for the plan agent to complete (if not already) and verify plans exist. Background dispatch is only safe on a runtime where a backgrounded agent can still nest the pipeline's subagents (plan-checker / worktree executors / verifier).
|
|
432
|
+
**If `INTERACTIVE` is set:** Wait for the plan agent to complete (if not already) and verify plans exist. Background dispatch is only safe on a runtime where a backgrounded agent can still nest the pipeline's subagents (plan-checker / worktree executors / verifier). This is determined from the documentation-sourced dispatch capability in the registry (#1708); Claude Code's backgrounded agents have no `Agent`/`Task` tool, and every other runtime either prohibits nested subagents or disables them by default. So run **inline** everywhere except where `dispatch-should-flatten` returns `false`. Resolve first:
|
|
424
433
|
|
|
425
434
|
```bash
|
|
426
|
-
|
|
435
|
+
FLATTEN=$(gsd_run query dispatch-should-flatten --raw 2>/dev/null || echo "true")
|
|
427
436
|
```
|
|
428
437
|
|
|
429
|
-
- **If `
|
|
438
|
+
- **If `FLATTEN` is `false`:** Dispatch execute as a background agent:
|
|
430
439
|
|
|
431
440
|
```
|
|
432
441
|
Agent(
|
|
@@ -438,7 +447,7 @@ Agent(
|
|
|
438
447
|
|
|
439
448
|
Store the agent task_id. The workflow can now start discussing the next phase while this phase executes in the background. Before starting post-execution routing for this phase, wait for the execute agent to complete.
|
|
440
449
|
|
|
441
|
-
- **Otherwise (
|
|
450
|
+
- **Otherwise (`FLATTEN` is `true` — run inline):** Run execute **inline** (do NOT background) so worktree isolation and verification run:
|
|
442
451
|
|
|
443
452
|
```
|
|
444
453
|
Skill(skill="gsd-execute-phase", args="${PHASE_NUM} --no-transition")
|
|
@@ -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)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<purpose>
|
|
2
2
|
|
|
3
|
-
Interactive command center for managing a milestone from a single terminal. Shows a dashboard of all phases with visual status, dispatches discuss inline and runs plan/execute inline (backgrounded
|
|
3
|
+
Interactive command center for managing a milestone from a single terminal. Shows a dashboard of all phases with visual status, dispatches discuss inline and runs plan/execute inline (backgrounded when dispatch-should-flatten returns false), and loops back to the dashboard after each action. Enables parallel phase work from one terminal.
|
|
4
4
|
|
|
5
5
|
</purpose>
|
|
6
6
|
|
|
@@ -45,7 +45,7 @@ Display startup banner:
|
|
|
45
45
|
{milestone_version} — {milestone_name}
|
|
46
46
|
{phase_count} phases · {completed_count} complete
|
|
47
47
|
|
|
48
|
-
✓ Discuss → inline ◆ Plan/Execute → inline (background
|
|
48
|
+
✓ Discuss → inline ◆ Plan/Execute → inline (background when FLATTEN=false)
|
|
49
49
|
Dashboard auto-refreshes when background work is active.
|
|
50
50
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
51
51
|
```
|
|
@@ -222,10 +222,10 @@ Go to exit step.
|
|
|
222
222
|
|
|
223
223
|
### Compound Action (background + inline)
|
|
224
224
|
|
|
225
|
-
When the user selects a compound option, behavior depends on the runtime — the Plan Phase N / Execute Phase N handlers below resolve it via `gsd_run query
|
|
225
|
+
When the user selects a compound option, behavior depends on whether the runtime supports background dispatch of nesting-capable orchestrators — the Plan Phase N / Execute Phase N handlers below resolve it via `gsd_run query dispatch-should-flatten` (#1708):
|
|
226
226
|
|
|
227
|
-
- **
|
|
228
|
-
- **
|
|
227
|
+
- **If `FLATTEN` is `false` (the host can background a nesting-capable orchestrator — e.g. codex, cursor):** **Spawn all background agents first** (plan/execute) — dispatch them in parallel using the Plan Phase N / Execute Phase N handlers below — then run verification actions, then run the inline discuss; the background agents continue while you verify/discuss.
|
|
228
|
+
- **Otherwise (`FLATTEN` is `true` — run inline):** run the chosen plan/execute step(s) **inline** via their handlers below (in order), then run verification actions, then run the inline discuss. There is no overlap.
|
|
229
229
|
|
|
230
230
|
Inline verification:
|
|
231
231
|
|
|
@@ -254,13 +254,13 @@ After discuss completes, loop back to dashboard step.
|
|
|
254
254
|
|
|
255
255
|
### Plan Phase N
|
|
256
256
|
|
|
257
|
-
Planning runs autonomously. **First resolve
|
|
257
|
+
Planning runs autonomously. **First resolve whether background dispatch is safe.** Background dispatch is only safe on a runtime where a backgrounded agent can still nest the pipeline's subagents (plan-checker / worktree executors / verifier). This is determined from the documentation-sourced dispatch capability in the registry (#1708); Claude Code's backgrounded agents have no `Agent`/`Task` tool, and every other runtime either prohibits nested subagents or disables them by default. So run **inline** everywhere except where `dispatch-should-flatten` returns `false`.
|
|
258
258
|
|
|
259
259
|
```bash
|
|
260
|
-
|
|
260
|
+
FLATTEN=$(gsd_run query dispatch-should-flatten --raw 2>/dev/null || echo "true")
|
|
261
261
|
```
|
|
262
262
|
|
|
263
|
-
**If `
|
|
263
|
+
**If `FLATTEN` is `false`:** Spawn a background agent that delegates to the Skill pipeline with any configured flags:
|
|
264
264
|
|
|
265
265
|
```
|
|
266
266
|
Agent(
|
|
@@ -282,7 +282,7 @@ Important: You are running in the background. Do NOT use AskUserQuestion — mak
|
|
|
282
282
|
)
|
|
283
283
|
```
|
|
284
284
|
|
|
285
|
-
> **ORCHESTRATOR RULE —
|
|
285
|
+
> **ORCHESTRATOR RULE — BACKGROUND DISPATCH**: After calling Agent() above with `run_in_background=true`, do NOT do any planning work for this phase independently. Return to the dashboard immediately and wait for the background agent to report back. Only resume planning-related work when the subagent result is available.
|
|
286
286
|
|
|
287
287
|
Display:
|
|
288
288
|
|
|
@@ -292,7 +292,7 @@ Display:
|
|
|
292
292
|
|
|
293
293
|
Loop back to dashboard step.
|
|
294
294
|
|
|
295
|
-
**Otherwise (
|
|
295
|
+
**Otherwise (`FLATTEN` is `true` — run inline):** Run plan inline so the plan-checker and quality gates actually run — do NOT wrap it in `Agent(run_in_background=true, …)`:
|
|
296
296
|
|
|
297
297
|
```
|
|
298
298
|
Skill(skill="gsd-plan-phase", args="{N} --auto {manager_flags.plan}")
|
|
@@ -308,13 +308,13 @@ Then loop back to dashboard step.
|
|
|
308
308
|
|
|
309
309
|
### Execute Phase N
|
|
310
310
|
|
|
311
|
-
Execution runs autonomously. **First resolve
|
|
311
|
+
Execution runs autonomously. **First resolve whether background dispatch is safe.** Background dispatch is only safe on a runtime where a backgrounded agent can still nest the pipeline's subagents (plan-checker / worktree executors / verifier). This is determined from the documentation-sourced dispatch capability in the registry (#1708); Claude Code's backgrounded agents have no `Agent`/`Task` tool, and every other runtime either prohibits nested subagents or disables them by default. So run **inline** everywhere except where `dispatch-should-flatten` returns `false`.
|
|
312
312
|
|
|
313
313
|
```bash
|
|
314
|
-
|
|
314
|
+
FLATTEN=$(gsd_run query dispatch-should-flatten --raw 2>/dev/null || echo "true")
|
|
315
315
|
```
|
|
316
316
|
|
|
317
|
-
**If `
|
|
317
|
+
**If `FLATTEN` is `false`:** Spawn a background agent that delegates to the Skill pipeline with any configured flags:
|
|
318
318
|
|
|
319
319
|
```
|
|
320
320
|
Agent(
|
|
@@ -336,7 +336,7 @@ Important: You are running in the background. Do NOT use AskUserQuestion — mak
|
|
|
336
336
|
)
|
|
337
337
|
```
|
|
338
338
|
|
|
339
|
-
> **ORCHESTRATOR RULE —
|
|
339
|
+
> **ORCHESTRATOR RULE — BACKGROUND DISPATCH**: After calling Agent() above with `run_in_background=true`, do NOT do any execution work for this phase independently. Return to the dashboard immediately and wait for the background agent to report back. Only resume execution-related work when the subagent result is available.
|
|
340
340
|
|
|
341
341
|
Display:
|
|
342
342
|
|
|
@@ -346,7 +346,7 @@ Display:
|
|
|
346
346
|
|
|
347
347
|
Loop back to dashboard step.
|
|
348
348
|
|
|
349
|
-
**Otherwise (
|
|
349
|
+
**Otherwise (`FLATTEN` is `true` — run inline):** Run execute inline so worktree isolation and the verifier actually run — do NOT wrap it in `Agent(run_in_background=true, …)`:
|
|
350
350
|
|
|
351
351
|
```
|
|
352
352
|
Skill(skill="gsd-execute-phase", args="{N} {manager_flags.execute}")
|
|
@@ -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
|
+
```
|