@opengsd/gsd-core 1.8.0 → 1.9.1
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 +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/.opencode/plugins/gsd-core.js +31 -1
- package/agents/gsd-code-fixer.md +107 -34
- package/agents/gsd-codebase-mapper.md +1 -1
- package/agents/gsd-debug-session-manager.md +36 -0
- package/agents/gsd-executor.md +20 -7
- package/agents/gsd-intel-updater.md +3 -3
- package/agents/gsd-phase-researcher.md +4 -2
- package/agents/gsd-plan-checker.md +20 -0
- package/agents/gsd-planner.md +15 -23
- package/agents/gsd-project-researcher.md +2 -2
- package/agents/gsd-ui-auditor.md +0 -40
- package/bin/install.js +236 -107
- package/commands/gsd/plan-review-convergence.md +5 -1
- package/gsd-core/bin/gsd-tools.cjs +882 -4
- package/gsd-core/bin/lib/api-coverage.cjs +22 -8
- package/gsd-core/bin/lib/audit.cjs +8 -8
- package/gsd-core/bin/lib/capability-consent.cjs +40 -1
- package/gsd-core/bin/lib/capability-lifecycle.cjs +58 -0
- package/gsd-core/bin/lib/capability-loader.cjs +23 -1
- package/gsd-core/bin/lib/capability-registry.cjs +1353 -132
- package/gsd-core/bin/lib/capability-trust.cjs +468 -33
- package/gsd-core/bin/lib/capability-validator.cjs +882 -6
- package/gsd-core/bin/lib/check-command-router.cjs +12 -2
- package/gsd-core/bin/lib/cjs-command-router-adapter.cjs +15 -0
- package/gsd-core/bin/lib/claude-orchestration-command-router.cjs +102 -12
- package/gsd-core/bin/lib/claude-orchestration.cjs +125 -22
- package/gsd-core/bin/lib/commands.cjs +246 -18
- package/gsd-core/bin/lib/config-loader.cjs +200 -28
- package/gsd-core/bin/lib/config.cjs +90 -5
- package/gsd-core/bin/lib/estimate-cli.cjs +336 -0
- package/gsd-core/bin/lib/frontmatter.cjs +125 -15
- package/gsd-core/bin/lib/host-integration.cjs +215 -8
- package/gsd-core/bin/lib/init.cjs +44 -19
- package/gsd-core/bin/lib/install-engine.cjs +1 -0
- package/gsd-core/bin/lib/milestone.cjs +36 -9
- package/gsd-core/bin/lib/model-catalog.cjs +51 -1
- package/gsd-core/bin/lib/observability/logger.cjs +7 -2
- package/gsd-core/bin/lib/phase-command-router.cjs +10 -1
- package/gsd-core/bin/lib/phase-estimation.cjs +398 -0
- package/gsd-core/bin/lib/phase-id.cjs +278 -5
- package/gsd-core/bin/lib/phase.cjs +61 -6
- package/gsd-core/bin/lib/plan-drift-guard.cjs +1 -1
- package/gsd-core/bin/lib/plan-scan.cjs +1 -1
- package/gsd-core/bin/lib/planning-workspace.cjs +9 -2
- package/gsd-core/bin/lib/profile-output.cjs +34 -8
- package/gsd-core/bin/lib/project-root.cjs +48 -0
- package/gsd-core/bin/lib/review-lane-descriptor.cjs +927 -0
- package/gsd-core/bin/lib/review-lane-invocation.cjs +348 -0
- package/gsd-core/bin/lib/review-lane-runner.cjs +594 -0
- package/gsd-core/bin/lib/review-reviewer-selection.cjs +114 -32
- package/gsd-core/bin/lib/roadmap-parser.cjs +54 -6
- package/gsd-core/bin/lib/roadmap.cjs +10 -4
- package/gsd-core/bin/lib/runtime-artifact-conversion.cjs +31 -4
- package/gsd-core/bin/lib/runtime-artifact-layout.cjs +1 -1
- package/gsd-core/bin/lib/runtime-hooks-surface.cjs +140 -0
- package/gsd-core/bin/lib/runtime-name-policy.cjs +15 -2
- package/gsd-core/bin/lib/smart-entry.cjs +1 -1
- package/gsd-core/bin/lib/state-document.cjs +164 -20
- package/gsd-core/bin/lib/state-transition.cjs +28 -10
- package/gsd-core/bin/lib/state.cjs +141 -21
- package/gsd-core/bin/lib/uat-predicate.cjs +6 -4
- package/gsd-core/bin/lib/uat.cjs +9 -7
- package/gsd-core/bin/lib/ui-consideration-probe.cjs +2 -2
- package/gsd-core/bin/lib/unusable-input.cjs +216 -0
- package/gsd-core/bin/lib/validate.cjs +32 -0
- package/gsd-core/bin/lib/verification.cjs +51 -14
- package/gsd-core/bin/lib/verify.cjs +146 -22
- package/gsd-core/bin/lib/worktree-safety.cjs +360 -15
- package/gsd-core/bin/shared/config-defaults.manifest.json +1 -0
- package/gsd-core/bin/shared/config-schema.manifest.json +1 -13
- package/gsd-core/bin/shared/model-catalog.json +5 -0
- package/gsd-core/bin/shared/runtime-aliases.manifest.json +5 -0
- package/gsd-core/references/context-budget.md +40 -0
- package/gsd-core/references/gate-prompts.md +6 -3
- package/gsd-core/references/model-profile-resolution.md +64 -13
- package/gsd-core/references/offer-next.md +88 -0
- package/gsd-core/references/planning-config.md +2 -1
- package/gsd-core/references/reviewer-instances.md +28 -21
- package/gsd-core/references/runtime-aware-dispatch.md +42 -0
- package/gsd-core/references/ui-consideration-probe.md +2 -2
- package/gsd-core/references/worktree-branch-check.md +4 -4
- package/gsd-core/templates/summary-minimal.md +4 -0
- package/gsd-core/templates/summary-standard.md +4 -0
- package/gsd-core/templates/summary.md +7 -0
- package/gsd-core/workflows/ai-integration-phase.md +4 -4
- package/gsd-core/workflows/audit-fix.md +4 -0
- package/gsd-core/workflows/audit-milestone.md +8 -0
- package/gsd-core/workflows/autonomous.md +19 -15
- package/gsd-core/workflows/check-todos.md +2 -2
- package/gsd-core/workflows/code-review-fix.md +14 -6
- package/gsd-core/workflows/code-review.md +93 -21
- package/gsd-core/workflows/debug.md +10 -2
- package/gsd-core/workflows/diagnose-issues.md +4 -0
- package/gsd-core/workflows/discuss-phase/modes/advisor.md +2 -4
- package/gsd-core/workflows/discuss-phase/modes/auto.md +0 -6
- package/gsd-core/workflows/discuss-phase-assumptions.md +15 -9
- package/gsd-core/workflows/discuss-phase.md +2 -2
- package/gsd-core/workflows/docs-update.md +8 -0
- package/gsd-core/workflows/eval-review.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/codebase-drift-gate.md +4 -0
- package/gsd-core/workflows/execute-phase/steps/executor-isolation-dispatch.md +160 -0
- package/gsd-core/workflows/execute-phase.md +85 -115
- package/gsd-core/workflows/execute-plan.md +5 -4
- package/gsd-core/workflows/explore.md +4 -0
- package/gsd-core/workflows/extract-learnings.md +21 -0
- package/gsd-core/workflows/help/modes/full.md +3 -3
- package/gsd-core/workflows/import.md +4 -1
- package/gsd-core/workflows/ingest-docs.md +4 -0
- package/gsd-core/workflows/map-codebase.md +13 -6
- package/gsd-core/workflows/new-milestone.md +10 -2
- package/gsd-core/workflows/new-project.md +11 -4
- package/gsd-core/workflows/next.md +5 -2
- package/gsd-core/workflows/plan-phase.md +42 -46
- package/gsd-core/workflows/plan-review-convergence.md +18 -14
- package/gsd-core/workflows/progress.md +1 -1
- package/gsd-core/workflows/quick.md +14 -3
- package/gsd-core/workflows/review.md +146 -575
- package/gsd-core/workflows/scan.md +9 -1
- package/gsd-core/workflows/secure-phase.md +10 -2
- package/gsd-core/workflows/ship.md +41 -11
- package/gsd-core/workflows/smart-entry.md +1 -1
- package/gsd-core/workflows/ui-phase.md +8 -1
- package/gsd-core/workflows/ui-review.md +8 -1
- package/gsd-core/workflows/update.md +104 -5
- package/gsd-core/workflows/validate-phase.md +10 -2
- package/gsd-core/workflows/verify-work.md +8 -1
- package/hooks/dist/gsd-cursor-session-start.js +6 -2
- package/hooks/dist/gsd-cursor-stop.js +6 -2
- package/hooks/dist/gsd-cursor-subagent-start.js +6 -2
- package/hooks/dist/gsd-graphify-update.sh +9 -0
- package/hooks/dist/gsd-phase-boundary.sh +14 -2
- package/hooks/dist/gsd-prompt-guard.js +101 -2
- package/hooks/dist/gsd-read-guard.js +100 -2
- package/hooks/dist/gsd-read-injection-scanner.js +109 -2
- package/hooks/dist/gsd-statusline.js +9 -6
- package/hooks/dist/gsd-workflow-guard.js +110 -6
- package/hooks/dist/gsd-worktree-path-guard.js +132 -8
- package/hooks/dist/lib/cursor-workspace.js +74 -0
- package/hooks/gsd-cursor-session-start.js +6 -2
- package/hooks/gsd-cursor-stop.js +6 -2
- package/hooks/gsd-cursor-subagent-start.js +6 -2
- package/hooks/gsd-graphify-update.sh +9 -0
- package/hooks/gsd-phase-boundary.sh +14 -2
- package/hooks/gsd-prompt-guard.js +101 -2
- package/hooks/gsd-read-guard.js +100 -2
- package/hooks/gsd-read-injection-scanner.js +109 -2
- package/hooks/gsd-statusline.js +9 -6
- package/hooks/gsd-workflow-guard.js +110 -6
- package/hooks/gsd-worktree-path-guard.js +132 -8
- package/hooks/lib/cursor-workspace.js +74 -0
- package/package.json +7 -7
- package/pi/gsd.cjs +26 -1
- package/scripts/check-coverage-gate.cjs +51 -0
- package/scripts/check-glossary-refs.cjs +24 -0
- package/scripts/ci-test-scope.cjs +67 -17
- package/scripts/gen-adr-index.cjs +6 -4
- package/scripts/gen-capability-matrix.cjs +26 -2
- package/scripts/gen-capability-registry.cjs +132 -34
- package/scripts/gen-emitted-baseline.cjs +145 -0
- package/scripts/gen-registry.cjs +39 -15
- package/scripts/lint-compiled-artifact-sync.cjs +146 -0
- package/scripts/lint-emitted-drift-ack.cjs +149 -0
- package/scripts/lint-fix-has-regression-test.cjs +131 -0
- package/scripts/lint-resolution-provenance.cjs +9 -0
- package/scripts/mutation-matrix.cjs +4 -0
- package/scripts/prompt-injection-scan.sh +6 -0
- package/scripts/registry-schema.cjs +372 -94
- package/scripts/release-notes/conventional-title.cjs +19 -1
- package/scripts/release-notes/format-github-release-notes.cjs +7 -3
- package/scripts/validate-registry.cjs +10 -6
- package/scripts/workflow-size.cjs +16 -8
- package/skills/gsd-plan-review-convergence/SKILL.md +5 -1
- package/vscode/package.json +1 -1
- package/scripts/gen-golden-install-parity-zcode.cjs +0 -77
- package/scripts/update-size-baseline.cjs +0 -68
|
@@ -13,6 +13,10 @@ Execute all plans in a phase using wave-based parallel execution. Orchestrator s
|
|
|
13
13
|
Orchestrator coordinates, not executes. Each subagent loads the full execute-plan context. Orchestrator: discover plans → analyze deps → group waves → spawn agents → handle checkpoints → collect results.
|
|
14
14
|
</core_principle>
|
|
15
15
|
|
|
16
|
+
<!-- #2508 runtime-aware-dispatch -->
|
|
17
|
+
|
|
18
|
+
> **Runtime-aware dispatch (#2508 Phase 4).** GSD workflows dispatch specialized subagents by role. Before dispatching on a built-in-only runtime (kimi-code — three built-ins only), resolve the role to a built-in via `gsd_run query resolve-dispatch-type --requested <role> --raw`. On named-dispatch runtimes (Claude/OpenCode/…) the role is returned unchanged; on kimi-code it maps to `coder`/`explore`/`plan` by role-suffix. The persona rides `${AGENT_SKILLS_<ROLE>}` (Phase 3) regardless. See @gsd-core/references/runtime-aware-dispatch.md.
|
|
19
|
+
|
|
16
20
|
<runtime_compatibility>
|
|
17
21
|
**Subagent spawning is runtime-specific:**
|
|
18
22
|
- **Claude Code:** Uses `Agent(subagent_type="gsd-executor", ...)` — blocks until complete, returns result
|
|
@@ -96,24 +100,14 @@ USE_WORKTREES=$(gsd_run query config-get workflow.use_worktrees --raw 2>/dev/nul
|
|
|
96
100
|
EXECUTOR_STALL_INTERVAL_MINUTES=$(gsd_run query config-get executor.stall_detect_interval_minutes 2>/dev/null || echo "5")
|
|
97
101
|
EXECUTOR_STALL_THRESHOLD_MINUTES=$(gsd_run query config-get executor.stall_threshold_minutes 2>/dev/null || echo "10")
|
|
98
102
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
#
|
|
104
|
-
[ "$USE_WORKTREES" != "false" ] && gsd_run query worktree.reap-orphans 2>/dev/null || true
|
|
105
|
-
# Auto-degrade to sequential if HEAD has diverged from the worktree fork base (#683).
|
|
106
|
-
# Only applies to Claude Code (isolation="worktree" is Claude-Code-specific).
|
|
107
|
-
if [ "$RUNTIME" = "claude" ] && [ "$USE_WORKTREES" != "false" ]; then
|
|
108
|
-
_SHOULD_DEGRADE=$(gsd_run query worktree.base-check --pick shouldDegrade 2>/dev/null || true)
|
|
109
|
-
if [ "$_SHOULD_DEGRADE" = "true" ]; then
|
|
110
|
-
_DEGRADE_MSG=$(gsd_run query worktree.base-check --pick message 2>/dev/null || true)
|
|
111
|
-
[ -n "$_DEGRADE_MSG" ] && printf '%s\n' "$_DEGRADE_MSG" >&2
|
|
112
|
-
USE_WORKTREES=false
|
|
113
|
-
fi
|
|
114
|
-
fi
|
|
103
|
+
# Resolve ISOLATION + apply its guards: read and execute the "Resolve ISOLATION"
|
|
104
|
+
# section of execute-phase/steps/executor-isolation-dispatch.md. It sets
|
|
105
|
+
# ISOLATION (harness-worktree|orchestrator-worktree|none), forces none when
|
|
106
|
+
# USE_WORKTREES=false, fails closed when a host has no primitive, sweeps orphans,
|
|
107
|
+
# and applies the #683 fork-base auto-degrade.
|
|
115
108
|
```
|
|
116
|
-
|
|
109
|
+
|
|
110
|
+
`ISOLATION` — not `RUNTIME` — is the ONLY fan-out branch point; **never add a `RUNTIME = "codex"` test here.** Per-host dispatch detail lives in `execute-phase/steps/executor-isolation-dispatch.md` (read from step 3).
|
|
117
111
|
|
|
118
112
|
If the project uses git submodules, worktree isolation is unsafe **only when a plan touches a submodule path** — the executor commit protocol cannot correctly handle submodule commits inside isolated worktrees. Compute submodule paths once and intersect them per-plan with the plan's declared `files_modified` frontmatter.
|
|
119
113
|
|
|
@@ -129,9 +123,9 @@ fi
|
|
|
129
123
|
|
|
130
124
|
`SUBMODULE_PATHS` is exported to the `execute_waves` step, where the per-plan decision happens (see "Per-plan worktree decision" sub-step inside `execute_waves`). The decision is per-plan because different plans in the same wave can touch different files — only plans whose paths intersect a submodule must drop worktree isolation; plans nowhere near a submodule keep parallel isolation.
|
|
131
125
|
|
|
132
|
-
When `USE_WORKTREES`
|
|
126
|
+
When `USE_WORKTREES` is `false`, `ISOLATION` is forced to `none`: executors run sequentially on the main working tree. The per-plan decision below has no effect when worktrees are project-disabled.
|
|
133
127
|
|
|
134
|
-
`USE_WORKTREES`
|
|
128
|
+
`USE_WORKTREES` and `ISOLATION` are also reset for the run when `worktree base-check` detects the orchestrator HEAD has diverged from the worktree fork base (#683 — e.g. an unmerged milestone branch). This runs for **any** isolated run, not only Claude: fork-base divergence is a property of the repository, so it degrades a GSD-created worktree exactly as a harness-created one. The auto-degrade prints a one-line warning to stderr and falls through to the sequential path so executors do not hit the exit-42 worktree-branch-check halt. To restore parallel worktree execution, set `worktree.baseRef:"head"` in `.claude/settings.local.json` (or run `gsd_run worktree set-baseref`) — this makes the fork base track the live HEAD instead of a fixed remote ref. The `worktree-branch-check` exit-42 guard inside each executor remains in place as a backstop.
|
|
135
129
|
|
|
136
130
|
Read context window size for adaptive prompt enrichment:
|
|
137
131
|
|
|
@@ -307,10 +301,8 @@ else
|
|
|
307
301
|
else
|
|
308
302
|
git switch --quiet "$DEFAULT_BRANCH" 2>/dev/null && git merge --ff-only --quiet "origin/$DEFAULT_BRANCH" 2>/dev/null || true
|
|
309
303
|
fi
|
|
310
|
-
# Pinned base
|
|
311
|
-
|
|
312
|
-
# explicit base argument here is the single source of correctness for #2916.
|
|
313
|
-
git checkout -b "$BRANCH_NAME" "origin/$DEFAULT_BRANCH" \
|
|
304
|
+
# Pinned base (#2916); --no-track (#2498) so default autoSetupMerge doesn't wire upstream to origin/$DEFAULT_BRANCH.
|
|
305
|
+
git checkout -b "$BRANCH_NAME" "origin/$DEFAULT_BRANCH" --no-track \
|
|
314
306
|
|| { echo "ERROR: Could not create '$BRANCH_NAME' from origin/$DEFAULT_BRANCH (#2916)." >&2; exit 1; }
|
|
315
307
|
fi
|
|
316
308
|
```
|
|
@@ -441,18 +433,63 @@ cwd inside an agent worktree (or a subdirectory of one). Every subsequent
|
|
|
441
433
|
orchestrator-side git call would then target the wrong tree — this is how a wrong-base
|
|
442
434
|
merge nearly shipped ~1000 files. Resolve the *worktree root* (so a subdirectory cwd
|
|
443
435
|
cannot skew the check) and refuse if it is an agent worktree. The discriminator is the
|
|
444
|
-
per-agent branch namespace `worktree-agent-*`, NOT the `.claude/worktrees/` path: the
|
|
436
|
+
per-agent branch namespace `agent-*` / `worktree-agent-*`, NOT the `.claude/worktrees/` path: the
|
|
445
437
|
orchestrator may itself be legitimately invoked from a feature worktree under
|
|
446
438
|
`.claude/worktrees/`, so a path-substring refusal would break legitimate runs. Do NOT
|
|
447
439
|
pin to `git worktree list`'s first entry — that is the main worktree, the wrong target
|
|
448
440
|
when the orchestrator legitimately runs from a feature worktree.
|
|
449
441
|
|
|
450
442
|
```bash
|
|
443
|
+
# gsd:guard=orchestrator-cwd-drift
|
|
451
444
|
ORCHESTRATOR_WT=$(git rev-parse --show-toplevel 2>/dev/null) || {
|
|
452
445
|
echo "FATAL: execute_waves entry is not inside a git worktree (#48)." >&2; exit 1; }
|
|
453
446
|
ORCH_BRANCH=$(git rev-parse --abbrev-ref HEAD 2>/dev/null)
|
|
454
|
-
if printf '%s' "$ORCH_BRANCH" | grep -Eq '^worktree-agent-'; then
|
|
447
|
+
if printf '%s' "$ORCH_BRANCH" | grep -Eq '^(worktree-)?agent-'; then
|
|
455
448
|
echo "FATAL: orchestrator cwd is inside an agent worktree (branch '$ORCH_BRANCH', root '$ORCHESTRATOR_WT') — refusing to execute waves (#48). A prior isolation=\"worktree\" dispatch drifted the cwd; re-run from the orchestrator's own worktree." >&2
|
|
449
|
+
# #1856 handoff: the refusal above is correct, but on its own it is a dead end —
|
|
450
|
+
# this worktree may hold committed fixes AND uncommitted work, and "re-run from
|
|
451
|
+
# the orchestrator's worktree" silently means abandoning them. Report exactly
|
|
452
|
+
# what is stranded and how to integrate it. Every command here is DIAGNOSTIC:
|
|
453
|
+
# each is `|| true`-guarded so a failure degrades to the plain refusal above
|
|
454
|
+
# rather than crashing before the message prints.
|
|
455
|
+
_WT_BASE=""
|
|
456
|
+
for _ref in "$(git rev-parse --abbrev-ref --symbolic-full-name '@{u}' 2>/dev/null || true)" \
|
|
457
|
+
origin/next origin/main next main; do
|
|
458
|
+
[ -n "$_ref" ] || continue
|
|
459
|
+
if git rev-parse --verify --quiet "$_ref" >/dev/null 2>&1; then _WT_BASE="$_ref"; break; fi
|
|
460
|
+
done
|
|
461
|
+
_WT_AHEAD=""
|
|
462
|
+
[ -n "$_WT_BASE" ] && _WT_AHEAD=$(git rev-list --count "$_WT_BASE..HEAD" 2>/dev/null || true)
|
|
463
|
+
# Count BEFORE truncating, so a long list reports its true size rather than
|
|
464
|
+
# under-reporting what is stranded — which is the whole point of this report.
|
|
465
|
+
_WT_DIRTY_ALL=$(git status --porcelain 2>/dev/null || true)
|
|
466
|
+
_WT_DIRTY_N=0
|
|
467
|
+
[ -n "$_WT_DIRTY_ALL" ] && _WT_DIRTY_N=$(printf '%s\n' "$_WT_DIRTY_ALL" | wc -l | tr -d ' ')
|
|
468
|
+
_WT_HAS_COMMITS=0
|
|
469
|
+
[ -n "$_WT_AHEAD" ] && [ "$_WT_AHEAD" -gt 0 ] 2>/dev/null && _WT_HAS_COMMITS=1
|
|
470
|
+
|
|
471
|
+
echo "" >&2
|
|
472
|
+
echo "── Handoff: what is in this worktree (#1856) ──" >&2
|
|
473
|
+
if [ "$_WT_HAS_COMMITS" -eq 1 ]; then
|
|
474
|
+
echo " $_WT_AHEAD commit(s) on '$ORCH_BRANCH' not on '$_WT_BASE':" >&2
|
|
475
|
+
git log --oneline --no-decorate "$_WT_BASE..HEAD" 2>/dev/null | head -20 | sed 's/^/ /' >&2 || true
|
|
476
|
+
[ "$_WT_AHEAD" -gt 20 ] 2>/dev/null && echo " … and $((_WT_AHEAD - 20)) more" >&2
|
|
477
|
+
echo " These live ONLY on this branch. Switching away without integrating loses them." >&2
|
|
478
|
+
fi
|
|
479
|
+
if [ -n "$_WT_DIRTY_ALL" ]; then
|
|
480
|
+
echo " $_WT_DIRTY_N uncommitted change(s) still in this worktree:" >&2
|
|
481
|
+
printf '%s\n' "$_WT_DIRTY_ALL" | head -20 | sed 's/^/ /' >&2
|
|
482
|
+
[ "$_WT_DIRTY_N" -gt 20 ] 2>/dev/null && echo " … and $((_WT_DIRTY_N - 20)) more" >&2
|
|
483
|
+
fi
|
|
484
|
+
if [ "$_WT_HAS_COMMITS" -eq 1 ] || [ -n "$_WT_DIRTY_ALL" ]; then
|
|
485
|
+
echo "" >&2
|
|
486
|
+
echo " To integrate before continuing:" >&2
|
|
487
|
+
[ -n "$_WT_DIRTY_ALL" ] && echo " 1. git add -A && git commit -m 'wip: recover worktree state' # from THIS worktree" >&2
|
|
488
|
+
echo " 2. cd <orchestrator worktree> # a checkout whose branch is NOT agent-*/worktree-agent-*" >&2
|
|
489
|
+
echo " 3. git merge --no-ff $ORCH_BRANCH # or: git cherry-pick <sha>... for selected commits" >&2
|
|
490
|
+
echo " 4. re-run the phase from there" >&2
|
|
491
|
+
echo " Verify with: git log --oneline ${_WT_BASE:-HEAD}..$ORCH_BRANCH" >&2
|
|
492
|
+
fi
|
|
456
493
|
exit 1
|
|
457
494
|
fi
|
|
458
495
|
# Pin to the worktree root; each later orchestrator-side block re-pins the same way
|
|
@@ -553,7 +590,7 @@ increases monotonically across waves. `{status}` is `complete` (success),
|
|
|
553
590
|
|
|
554
591
|
Read and execute `gsd-core/workflows/execute-phase/steps/per-plan-worktree-gate.md` for each plan. It extracts `PLAN_FILES` from the plan's JSON, intersects against `SUBMODULE_PATHS` (with normalization, bidirectional matching, and glob-prefix handling), and sets `USE_WORKTREES_FOR_PLAN` to `false` when the plan touches a submodule path. Append `plan_id` to a `WAVE_WORKTREE_PLANS` accumulator when `USE_WORKTREES_FOR_PLAN != false`.
|
|
555
592
|
|
|
556
|
-
The dispatch branches in step 3
|
|
593
|
+
The dispatch branches in step 3 gate on both `USE_WORKTREES` and `USE_WORKTREES_FOR_PLAN` (#2474).
|
|
557
594
|
|
|
558
595
|
2.75. **Execute:wave:pre capability dispatch:**
|
|
559
596
|
|
|
@@ -574,14 +611,14 @@ increases monotonically across waves. `{status}` is `complete` (success),
|
|
|
574
611
|
For 200k models, this keeps orchestrator context lean (~10-15%).
|
|
575
612
|
For 1M+ models (Opus 4.6, Sonnet 4.6), richer context can be passed directly.
|
|
576
613
|
|
|
577
|
-
**Worktree mode** (`USE_WORKTREES_FOR_PLAN`
|
|
614
|
+
**Worktree mode** (`USE_WORKTREES` and `USE_WORKTREES_FOR_PLAN` not `false`):
|
|
578
615
|
|
|
579
616
|
Before spawning, capture the current HEAD:
|
|
580
617
|
```bash
|
|
581
618
|
EXPECTED_BASE=$(git rev-parse HEAD)
|
|
582
619
|
DISPATCH_TS=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
|
|
583
620
|
EXPECTED_BRANCH=$(git rev-parse --abbrev-ref HEAD)
|
|
584
|
-
|
|
621
|
+
if [ "${USE_WORKTREES:-true}" != "false" ] && [ "${USE_WORKTREES_FOR_PLAN:-true}" != "false" ] && [ -z "${WAVE_WORKTREE_MANIFEST:-}" ]; then
|
|
585
622
|
M=$(mktemp "${TMPDIR:-/tmp}/gsd-worktree-wave-XXXXXX") && mv "$M" "$M.json" && WAVE_WORKTREE_MANIFEST="$M.json" || exit 1 # XXXXXX must be path-final on BSD/macOS (#1520)
|
|
586
623
|
# Persist the dispatch-time orchestrator worktree root so wave-cleanup can pin back to the
|
|
587
624
|
# orchestrator's OWN worktree — NOT `git worktree list`'s first entry (always the main
|
|
@@ -593,6 +630,8 @@ increases monotonically across waves. `{status}` is `complete` (success),
|
|
|
593
630
|
fi
|
|
594
631
|
```
|
|
595
632
|
|
|
633
|
+
**Isolation model.** The block below is the **`harness-worktree`** path. For `orchestrator-worktree` use the dispatch below it; for `none` use sequential mode. Both are detailed in `execute-phase/steps/executor-isolation-dispatch.md`.
|
|
634
|
+
|
|
596
635
|
**Sequential dispatch for parallel execution (waves with 2+ agents):**
|
|
597
636
|
Dispatch each `Agent()` call **one at a time with `run_in_background: true`**. Do NOT
|
|
598
637
|
send all Agent calls in a single message: simultaneous `git worktree add` calls race
|
|
@@ -611,7 +650,10 @@ increases monotonically across waves. `{status}` is `complete` (success),
|
|
|
611
650
|
# When executor_model is "inherit", omit this parameter entirely so
|
|
612
651
|
# Claude Code inherits the orchestrator model automatically.
|
|
613
652
|
model="{executor_model}", # omit this line when executor_model == "inherit"
|
|
614
|
-
isolation
|
|
653
|
+
# The host's OWN declared isolation flag (`harnessFlag` from
|
|
654
|
+
# `dispatch-isolation --json`; see the isolation-dispatch fragment).
|
|
655
|
+
# Emit the declared token — do NOT hardcode a runtime's flag.
|
|
656
|
+
{harnessFlag},
|
|
615
657
|
prompt="
|
|
616
658
|
<objective>
|
|
617
659
|
Execute plan {plan_number} of phase {phase_number}-{phase_name}.
|
|
@@ -695,6 +737,8 @@ increases monotonically across waves. `{status}` is `complete` (success),
|
|
|
695
737
|
|
|
696
738
|
> **ORCHESTRATOR RULE — CODEX RUNTIME**: After calling Agent() above to spawn executor agent(s), stop working on this task immediately. Do not read more files, edit code, or run tests related to this task while the subagent is active. Wait for the subagent to return its result. This prevents duplicate work, conflicting edits, and wasted context. Only resume when the subagent result is available.
|
|
697
739
|
|
|
740
|
+
**Orchestrator-managed worktree dispatch** (`ISOLATION=orchestrator-worktree`): read and execute `execute-phase/steps/executor-isolation-dispatch.md`. GSD creates each worktree (`worktree create`) and spawns the executor into it; the orchestrator performs every git operation. Merge-back and cleanup are the existing manifest-scoped gauntlet, unchanged.
|
|
741
|
+
|
|
698
742
|
**Sequential mode** (`USE_WORKTREES_FOR_PLAN` is `false` — either project-level `USE_WORKTREES=false`, or per-plan submodule intersection forced it false in step 2.5):
|
|
699
743
|
|
|
700
744
|
Omit `isolation="worktree"` from the Agent call. Replace the `<parallel_execution>` block with:
|
|
@@ -1511,7 +1555,7 @@ Copy failure must NOT block phase completion.
|
|
|
1511
1555
|
<step name="close_phase_todos">
|
|
1512
1556
|
**Auto-close pending todos tagged for this phase (#2433).**
|
|
1513
1557
|
|
|
1514
|
-
|
|
1558
|
+
After `update_roadmap`, moves todos whose `resolves_phase` matches to `completed/`.
|
|
1515
1559
|
|
|
1516
1560
|
```bash
|
|
1517
1561
|
PHASE_NUM="${PHASE_NUMBER}"
|
|
@@ -1519,12 +1563,19 @@ PENDING_DIR=".planning/todos/pending"
|
|
|
1519
1563
|
COMPLETED_DIR=".planning/todos/completed"
|
|
1520
1564
|
mkdir -p "$COMPLETED_DIR"
|
|
1521
1565
|
|
|
1566
|
+
# "05"=="5" (#2576).
|
|
1567
|
+
normalize_phase_num() {
|
|
1568
|
+
local p="${1//\"/}"; printf '%s' "$p" | sed 's/^0*\([0-9]\)/\1/'
|
|
1569
|
+
}
|
|
1570
|
+
PHASE_NUM_NORM=$(normalize_phase_num "$PHASE_NUM")
|
|
1571
|
+
|
|
1522
1572
|
CLOSED=()
|
|
1523
1573
|
for TODO_FILE in "$PENDING_DIR"/*.md; do
|
|
1524
1574
|
[ -f "$TODO_FILE" ] || continue
|
|
1525
|
-
#
|
|
1575
|
+
# resolves_phase from first frontmatter block
|
|
1526
1576
|
RP=$(awk '/^---/{c++;next} c==1 && /^resolves_phase:/{print $2;exit} c==2{exit}' "$TODO_FILE" 2>/dev/null || true)
|
|
1527
|
-
|
|
1577
|
+
RP_NORM=$(normalize_phase_num "$RP")
|
|
1578
|
+
if [ -n "$RP_NORM" ] && [ "$RP_NORM" = "$PHASE_NUM_NORM" ]; then
|
|
1528
1579
|
mv "$TODO_FILE" "$COMPLETED_DIR/"
|
|
1529
1580
|
CLOSED+=("$(basename "$TODO_FILE")")
|
|
1530
1581
|
fi
|
|
@@ -1537,7 +1588,7 @@ if [ ${#CLOSED[@]} -gt 0 ]; then
|
|
|
1537
1588
|
fi
|
|
1538
1589
|
```
|
|
1539
1590
|
|
|
1540
|
-
**
|
|
1591
|
+
**No matches:** skip silently (always additive, non-blocking).
|
|
1541
1592
|
</step>
|
|
1542
1593
|
|
|
1543
1594
|
<step name="update_project_md">
|
|
@@ -1563,88 +1614,7 @@ gsd_run query commit "docs(phase-{X}): evolve PROJECT.md after phase completion"
|
|
|
1563
1614
|
</step>
|
|
1564
1615
|
|
|
1565
1616
|
<step name="offer_next">
|
|
1566
|
-
|
|
1567
|
-
**Exception:** If `gaps_found`, the `verify_phase_goal` step already presents the gap-closure path (`/gsd:plan-phase {X} --gaps`). No additional routing needed — skip auto-advance.
|
|
1568
|
-
|
|
1569
|
-
**No-transition check (spawned by auto-advance chain):**
|
|
1570
|
-
|
|
1571
|
-
Parse `--no-transition` flag from $ARGUMENTS.
|
|
1572
|
-
|
|
1573
|
-
**If `--no-transition` flag present:**
|
|
1574
|
-
|
|
1575
|
-
Execute-phase was spawned by plan-phase's auto-advance. Do NOT run transition.md.
|
|
1576
|
-
After verification passes and roadmap is updated, return completion status to parent:
|
|
1577
|
-
|
|
1578
|
-
```
|
|
1579
|
-
## PHASE COMPLETE
|
|
1580
|
-
|
|
1581
|
-
Phase: ${PHASE_NUMBER} - ${PHASE_NAME}
|
|
1582
|
-
Plans: ${completed_count}/${total_count}
|
|
1583
|
-
Verification: {Passed | Gaps Found}
|
|
1584
|
-
|
|
1585
|
-
[Include aggregate_results output]
|
|
1586
|
-
```
|
|
1587
|
-
|
|
1588
|
-
STOP. Do not proceed to auto-advance or transition.
|
|
1589
|
-
|
|
1590
|
-
**If `--no-transition` flag is NOT present:**
|
|
1591
|
-
|
|
1592
|
-
**Auto-advance detection:**
|
|
1593
|
-
|
|
1594
|
-
1. Parse `--auto` flag from $ARGUMENTS
|
|
1595
|
-
2. Read consolidated auto-mode (`active` = chain flag OR user preference; chain flag already synced in init step):
|
|
1596
|
-
```bash
|
|
1597
|
-
AUTO_MODE=$(gsd_run query check auto-mode --pick active 2>/dev/null || echo "false")
|
|
1598
|
-
```
|
|
1599
|
-
|
|
1600
|
-
**If `--auto` flag present OR `AUTO_MODE` is true (AND verification passed with no gaps):**
|
|
1601
|
-
|
|
1602
|
-
```
|
|
1603
|
-
╔══════════════════════════════════════════╗
|
|
1604
|
-
║ AUTO-ADVANCING → TRANSITION ║
|
|
1605
|
-
║ Phase {X} verified, continuing chain ║
|
|
1606
|
-
╚══════════════════════════════════════════╝
|
|
1607
|
-
```
|
|
1608
|
-
|
|
1609
|
-
Execute the transition workflow inline (do NOT use Agent — orchestrator context is ~10-15%, transition needs phase completion data already in context):
|
|
1610
|
-
|
|
1611
|
-
Read and follow `~/.claude/gsd-core/workflows/transition.md`, passing through the `--auto` flag so it propagates to the next phase invocation.
|
|
1612
|
-
|
|
1613
|
-
**If neither `--auto` nor `AUTO_MODE` is true:**
|
|
1614
|
-
|
|
1615
|
-
**STOP. Do not auto-advance. Do not execute transition. Do not plan next phase. Present options to the user and wait.**
|
|
1616
|
-
|
|
1617
|
-
**IMPORTANT: There is NO `/gsd-transition` command. Never suggest it. The transition workflow is internal only.**
|
|
1618
|
-
|
|
1619
|
-
Check whether CONTEXT.md already exists for the next phase:
|
|
1620
|
-
|
|
1621
|
-
```bash
|
|
1622
|
-
ls .planning/phases/*{next}*/{next}-CONTEXT.md 2>/dev/null || echo "no-context"
|
|
1623
|
-
```
|
|
1624
|
-
|
|
1625
|
-
If CONTEXT.md does **not** exist for the next phase, present:
|
|
1626
|
-
|
|
1627
|
-
```
|
|
1628
|
-
## ✓ Phase {X}: {Name} Complete
|
|
1629
|
-
|
|
1630
|
-
/gsd:progress ${GSD_WS} — see updated roadmap
|
|
1631
|
-
/gsd:discuss-phase {next} ${GSD_WS} — start here: discuss next phase before planning ← recommended
|
|
1632
|
-
/gsd:plan-phase {next} ${GSD_WS} — plan next phase (skip discuss)
|
|
1633
|
-
/gsd:execute-phase {next} ${GSD_WS} — execute next phase (skip discuss and plan)
|
|
1634
|
-
```
|
|
1635
|
-
|
|
1636
|
-
If CONTEXT.md **exists** for the next phase, present:
|
|
1637
|
-
|
|
1638
|
-
```
|
|
1639
|
-
## ✓ Phase {X}: {Name} Complete
|
|
1640
|
-
|
|
1641
|
-
/gsd:progress ${GSD_WS} — see updated roadmap
|
|
1642
|
-
/gsd:plan-phase {next} ${GSD_WS} — start here: plan next phase (CONTEXT.md already present) ← recommended
|
|
1643
|
-
/gsd:discuss-phase {next} ${GSD_WS} — re-discuss next phase
|
|
1644
|
-
/gsd:execute-phase {next} ${GSD_WS} — execute next phase (skip planning)
|
|
1645
|
-
```
|
|
1646
|
-
|
|
1647
|
-
Only suggest the commands listed above. Do not invent or hallucinate command names.
|
|
1617
|
+
@~/.claude/gsd-core/references/offer-next.md
|
|
1648
1618
|
</step>
|
|
1649
1619
|
|
|
1650
1620
|
</process>
|
|
@@ -109,7 +109,11 @@ Otherwise: Apply checkpoint-based routing below.
|
|
|
109
109
|
| Verify-only | B (segmented) | Segments between checkpoints. After none/human-verify → SUBAGENT. After decision/human-action → MAIN |
|
|
110
110
|
| Decision | C (main) | Execute entirely in main context |
|
|
111
111
|
|
|
112
|
-
|
|
112
|
+
<!-- #2508 runtime-aware-dispatch -->
|
|
113
|
+
|
|
114
|
+
> **Runtime-aware dispatch (#2508 Phase 4).** GSD workflows dispatch specialized subagents by role. Before dispatching on a built-in-only runtime (kimi-code — three built-ins only), resolve the role to a built-in via `gsd_run query resolve-dispatch-type --requested <role> --raw`. On named-dispatch runtimes (Claude/OpenCode/…) the role is returned unchanged; on kimi-code it maps to `coder`/`explore`/`plan` by role-suffix. The persona rides `${AGENT_SKILLS_<ROLE>}` (Phase 3) regardless. See @gsd-core/references/runtime-aware-dispatch.md.
|
|
115
|
+
|
|
116
|
+
**Pattern A:** init_agent_tracking → capture `EXPECTED_BASE=$(git rev-parse HEAD)` → print `Spawning executor agent (runs in a subagent — no output until it returns, ~1–5 min; expected, not a freeze)` → spawn Agent(subagent_type="gsd-executor", model=executor_model) with prompt: execute plan at [path], autonomous, all tasks + SUMMARY + commit, follow deviation/auth rules, report: plan name, tasks, SUMMARY path, commit hash → track agent_id → wait → update tracking → report. **Include `isolation="worktree"` only if `workflow.use_worktrees` is not `false`** (read via `config-get workflow.use_worktrees`). **When using `isolation="worktree"`, embed the `<worktree_branch_check>` block from `gsd-core/references/worktree-branch-check.md` into the prompt, substituting `{EXPECTED_BASE}` with the captured base SHA.** That guard is **verify-only and fail-closed** (#48): it asserts a per-agent `agent-*` / `worktree-agent-*` branch and the exact base, forbids `git update-ref` self-recovery (#2924), and on any mismatch prints `FATAL:` and `exit 42` so the orchestrator can recover — the sub-agent never rewrites a worktree it did not create. This supersedes the former self-recovery (#2015), whose destructive base rewrite could fail silently under a deny rule; the base-drift it addressed affects all platforms, and base correction is now the orchestrator's responsibility.
|
|
113
117
|
|
|
114
118
|
**Pattern B:** Execute segment-by-segment. Autonomous segments: spawn subagent for assigned tasks only (no SUMMARY/commit). Checkpoints: main context. After all segments: aggregate, create SUMMARY, commit. See segment_execution.
|
|
115
119
|
|
|
@@ -159,9 +163,6 @@ Pattern B only (verify-only checkpoints). Skip for A/C.
|
|
|
159
163
|
|
|
160
164
|
**Known Claude Code bug (classifyHandoffIfNeeded):** If any segment agent reports "failed" with `classifyHandoffIfNeeded is not defined`, this is a Claude Code runtime bug — not a real failure. Run spot-checks; if they pass, treat as successful.
|
|
161
165
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
166
|
</step>
|
|
166
167
|
|
|
167
168
|
<step name="load_prompt">
|
|
@@ -60,6 +60,10 @@ This would take ~30 seconds and might surface useful context.
|
|
|
60
60
|
|
|
61
61
|
If yes, spawn a research agent:
|
|
62
62
|
|
|
63
|
+
<!-- #2508 runtime-aware-dispatch -->
|
|
64
|
+
|
|
65
|
+
> **Runtime-aware dispatch (#2508 Phase 4).** GSD workflows dispatch specialized subagents by role. Before dispatching on a built-in-only runtime (kimi-code — three built-ins only), resolve the role to a built-in via `gsd_run query resolve-dispatch-type --requested <role> --raw`. On named-dispatch runtimes (Claude/OpenCode/…) the role is returned unchanged; on kimi-code it maps to `coder`/`explore`/`plan` by role-suffix. The persona rides `${AGENT_SKILLS_<ROLE>}` (Phase 3) regardless. See @gsd-core/references/runtime-aware-dispatch.md.
|
|
66
|
+
|
|
63
67
|
Print: `◆ Spawning explorer... (runs in a subagent — no output until it returns, ~1–5 min; expected, not a freeze)`
|
|
64
68
|
```
|
|
65
69
|
Agent(
|
|
@@ -186,6 +186,27 @@ The body follows this structure:
|
|
|
186
186
|
```
|
|
187
187
|
</step>
|
|
188
188
|
|
|
189
|
+
<step name="calibrate_estimates">
|
|
190
|
+
Rebuild the estimate-vs-actual calibration from every completed phase (#2632, ADR-2629).
|
|
191
|
+
|
|
192
|
+
```bash
|
|
193
|
+
gsd_run query estimate-calibrate
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
This pairs each phase's PLAN `estimate` with its SUMMARY `actuals`, writes
|
|
197
|
+
`.planning/estimation-calibration.json`, and reports the resulting correction factor.
|
|
198
|
+
The planner reads it on the next `/gsd:plan-phase`, so estimates improve for THIS project
|
|
199
|
+
over time.
|
|
200
|
+
|
|
201
|
+
Report the returned `factor`, `sample_count`, and `confidence` in the summary output.
|
|
202
|
+
`applied: false` means fewer than 3 phases carry both an estimate and actuals — that is
|
|
203
|
+
expected early and is not an error. The verb rebuilds from scratch each run, so it is safe
|
|
204
|
+
to re-run and never accumulates duplicates.
|
|
205
|
+
|
|
206
|
+
Phases missing either side are skipped rather than guessed: a fabricated sample would
|
|
207
|
+
steer every future estimate.
|
|
208
|
+
</step>
|
|
209
|
+
|
|
189
210
|
<step name="update_state">
|
|
190
211
|
Update STATE.md to reflect the learning extraction:
|
|
191
212
|
|
|
@@ -417,7 +417,7 @@ List pending todos and select one to work on.
|
|
|
417
417
|
- Optional area filter (e.g., `/gsd:capture --list api`)
|
|
418
418
|
- Loads full context for selected todo
|
|
419
419
|
- Routes to appropriate action (work now, add to phase, brainstorm)
|
|
420
|
-
- Moves todo to
|
|
420
|
+
- Moves todo to completed/ when work begins
|
|
421
421
|
|
|
422
422
|
Usage: `/gsd:capture --list`
|
|
423
423
|
Usage: `/gsd:capture --list api`
|
|
@@ -624,7 +624,7 @@ The commands above cover the most common day-to-day flows. Every command listed
|
|
|
624
624
|
|
|
625
625
|
- **`/gsd:mvp-phase <phase-number>`** — Plan a phase as a vertical MVP slice (user story + SPIDR splitting) before handing off to plan-phase. Same end-state as `/gsd:plan-phase --mvp`, with a guided MVP-shaping intro.
|
|
626
626
|
- **`/gsd:ultraplan-phase [phase]`** — [BETA] Offload plan phase to Claude Code's ultraplan cloud; review in browser and import back.
|
|
627
|
-
- **`/gsd:plan-review-convergence <phase> [--
|
|
627
|
+
- **`/gsd:plan-review-convergence <phase> [--gemini] [--claude] [--codex] [--coderabbit] [--opencode] [--qwen] [--cursor] [--agy/--antigravity] [--ollama] [--lm-studio] [--llama-cpp] [--kimi-code] [--all] [--text] [--ws <name>] [--max-cycles N]`** — Cross-AI plan convergence loop — replan with review feedback until no HIGH concerns remain. Supports both cloud reviewers (Gemini/Claude/Codex/CodeRabbit/OpenCode/Qwen/Cursor/Antigravity/Kimi Code) and local model runtimes (Ollama, LM Studio, llama.cpp).
|
|
628
628
|
- **`/gsd:autonomous [--from N] [--to N] [--only N] [--interactive] [--converge]`** — Run all remaining phases autonomously: discuss → plan → execute per phase. `--converge` routes planning through plan-review convergence; `--cross-ai` is an alias.
|
|
629
629
|
|
|
630
630
|
### Quality, Review & Verification
|
|
@@ -688,7 +688,7 @@ These six skills exist primarily for the model to perform two-stage hierarchical
|
|
|
688
688
|
├── config.json # Workflow mode & gates
|
|
689
689
|
├── todos/ # Captured ideas and tasks
|
|
690
690
|
│ ├── pending/ # Todos waiting to be worked on
|
|
691
|
-
│ └──
|
|
691
|
+
│ └── completed/ # Completed todos
|
|
692
692
|
├── spikes/ # Spike experiments (/gsd:spike)
|
|
693
693
|
│ ├── MANIFEST.md # Spike inventory and verdicts
|
|
694
694
|
│ └── NNN-name/ # Individual spike directories
|
|
@@ -18,7 +18,6 @@ RESPONSE_LANGUAGE=$(gsd_run query config-get response_language --default "" 2>/d
|
|
|
18
18
|
|
|
19
19
|
**If `response_language` is set:** All user-facing questions, prompts, and explanations in this workflow MUST be presented in `{response_language}`. Technical terms, code, file paths, and subagent prompts stay in English — only user-facing output is translated.
|
|
20
20
|
|
|
21
|
-
|
|
22
21
|
```
|
|
23
22
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
24
23
|
GSD ► IMPORT
|
|
@@ -205,6 +204,10 @@ Delegate validation to gsd-plan-checker:
|
|
|
205
204
|
|
|
206
205
|
Print: "Delegating to gsd-plan-checker (runs in a subagent — no output until it returns, ~1–5 min; expected, not a freeze)"
|
|
207
206
|
|
|
207
|
+
<!-- #2508 runtime-aware-dispatch -->
|
|
208
|
+
|
|
209
|
+
> **Runtime-aware dispatch (#2508 Phase 4).** GSD workflows dispatch specialized subagents by role. Before dispatching on a built-in-only runtime (kimi-code — three built-ins only), resolve the role to a built-in via `gsd_run query resolve-dispatch-type --requested <role> --raw`. On named-dispatch runtimes (Claude/OpenCode/…) the role is returned unchanged; on kimi-code it maps to `coder`/`explore`/`plan` by role-suffix. The persona rides `${AGENT_SKILLS_<ROLE>}` (Phase 3) regardless. See @gsd-core/references/runtime-aware-dispatch.md.
|
|
210
|
+
|
|
208
211
|
```
|
|
209
212
|
Agent({
|
|
210
213
|
subagent_type: "gsd-plan-checker",
|
|
@@ -188,6 +188,10 @@ Collect the one-line confirmations from each classifier. If any classifier error
|
|
|
188
188
|
|
|
189
189
|
Spawn `gsd-doc-synthesizer` once (runs in a subagent — no output until it returns, ~1–5 min; expected, not a freeze):
|
|
190
190
|
|
|
191
|
+
<!-- #2508 runtime-aware-dispatch -->
|
|
192
|
+
|
|
193
|
+
> **Runtime-aware dispatch (#2508 Phase 4).** GSD workflows dispatch specialized subagents by role. Before dispatching on a built-in-only runtime (kimi-code — three built-ins only), resolve the role to a built-in via `gsd_run query resolve-dispatch-type --requested <role> --raw`. On named-dispatch runtimes (Claude/OpenCode/…) the role is returned unchanged; on kimi-code it maps to `coder`/`explore`/`plan` by role-suffix. The persona rides `${AGENT_SKILLS_<ROLE>}` (Phase 3) regardless. See @gsd-core/references/runtime-aware-dispatch.md.
|
|
194
|
+
|
|
191
195
|
```
|
|
192
196
|
Agent({
|
|
193
197
|
subagent_type: "gsd-doc-synthesizer",
|
|
@@ -140,6 +140,14 @@ Before spawning agents, detect whether the current runtime supports the `Agent`
|
|
|
140
140
|
<step name="spawn_agents" condition="Agent tool is available">
|
|
141
141
|
Spawn 4 parallel gsd-codebase-mapper agents.
|
|
142
142
|
|
|
143
|
+
<!-- #2508 runtime-aware-dispatch -->
|
|
144
|
+
|
|
145
|
+
> **Runtime-aware dispatch (#2508 Phase 4).** GSD workflows dispatch specialized subagents by role. Before dispatching on a built-in-only runtime (kimi-code — three built-ins only), resolve the role to a built-in via `gsd_run query resolve-dispatch-type --requested <role> --raw`. On named-dispatch runtimes (Claude/OpenCode/…) the role is returned unchanged; on kimi-code it maps to `coder`/`explore`/`plan` by role-suffix. The persona rides `${AGENT_SKILLS_<ROLE>}` (Phase 3) regardless. See @gsd-core/references/runtime-aware-dispatch.md.
|
|
146
|
+
|
|
147
|
+
<!-- #2517 model-omit-on-inherit -->
|
|
148
|
+
|
|
149
|
+
> **Model omission (#2517).** Omit the `model` parameter entirely when the value it would carry (`mapper_model`) is `"inherit"` or empty. An empty value 404s on runtimes without native tier aliases — the default on non-Claude runtimes. Omitting it inherits the orchestrator's model. See @gsd-core/references/model-profile-resolution.md.
|
|
150
|
+
|
|
143
151
|
Use Agent tool with `subagent_type="gsd-codebase-mapper"`, `model="{mapper_model}"`, and `run_in_background=true` for parallel execution.
|
|
144
152
|
|
|
145
153
|
**CRITICAL:** Use the dedicated `gsd-codebase-mapper` agent, NOT `Explore` or `browser_subagent`. The mapper agent writes documents directly.
|
|
@@ -163,7 +171,7 @@ Write these documents to {codebase_dir}/:
|
|
|
163
171
|
- STACK.md - Languages, runtime, frameworks, dependencies, configuration
|
|
164
172
|
- INTEGRATIONS.md - External APIs, databases, auth providers, webhooks
|
|
165
173
|
|
|
166
|
-
IMPORTANT:
|
|
174
|
+
IMPORTANT: Set all date stamps (`**Analysis Date:**`, footer `*... analysis: ...*`, `<!-- refreshed: ... -->`) to {date}, overwriting any existing date.
|
|
167
175
|
|
|
168
176
|
Scope: ${PATH_SCOPE_HINT:-(full repo)} — when --paths is supplied, restrict exploration to those prefixes only.
|
|
169
177
|
|
|
@@ -189,7 +197,7 @@ Write these documents to {codebase_dir}/:
|
|
|
189
197
|
- ARCHITECTURE.md - Pattern, layers, data flow, abstractions, entry points
|
|
190
198
|
- STRUCTURE.md - Directory layout, key locations, naming conventions
|
|
191
199
|
|
|
192
|
-
IMPORTANT:
|
|
200
|
+
IMPORTANT: Set all date stamps (`**Analysis Date:**`, footer `*... analysis: ...*`, `<!-- refreshed: ... -->`) to {date}, overwriting any existing date.
|
|
193
201
|
|
|
194
202
|
Scope: ${PATH_SCOPE_HINT:-(full repo)} — when --paths is supplied, restrict exploration to those prefixes only.
|
|
195
203
|
|
|
@@ -215,7 +223,7 @@ Write these documents to {codebase_dir}/:
|
|
|
215
223
|
- CONVENTIONS.md - Code style, naming, patterns, error handling
|
|
216
224
|
- TESTING.md - Framework, structure, mocking, coverage
|
|
217
225
|
|
|
218
|
-
IMPORTANT:
|
|
226
|
+
IMPORTANT: Set all date stamps (`**Analysis Date:**`, footer `*... analysis: ...*`, `<!-- refreshed: ... -->`) to {date}, overwriting any existing date.
|
|
219
227
|
|
|
220
228
|
Scope: ${PATH_SCOPE_HINT:-(full repo)} — when --paths is supplied, restrict exploration to those prefixes only.
|
|
221
229
|
|
|
@@ -240,7 +248,7 @@ Analyze this codebase for technical debt, known issues, and areas of concern.
|
|
|
240
248
|
Write this document to {codebase_dir}/:
|
|
241
249
|
- CONCERNS.md - Tech debt, bugs, security, performance, fragile areas
|
|
242
250
|
|
|
243
|
-
IMPORTANT:
|
|
251
|
+
IMPORTANT: Set all date stamps (`**Analysis Date:**`, footer `*... analysis: ...*`, `<!-- refreshed: ... -->`) to {date}, overwriting any existing date.
|
|
244
252
|
|
|
245
253
|
Scope: ${PATH_SCOPE_HINT:-(full repo)} — when --paths is supplied, restrict exploration to those prefixes only.
|
|
246
254
|
|
|
@@ -293,7 +301,7 @@ When the `Agent` tool is unavailable, perform codebase mapping sequentially in t
|
|
|
293
301
|
|
|
294
302
|
**IMPORTANT:** Do NOT use `browser_subagent`, `Explore`, or any browser-based tool. Use only file system tools (Read, Bash, Write, Grep, Glob, list_dir, view_file, grep_search, or equivalent tools available in your runtime).
|
|
295
303
|
|
|
296
|
-
**IMPORTANT:**
|
|
304
|
+
**IMPORTANT:** Set all date stamps (`**Analysis Date:**`, footer, `<!-- refreshed -->`) to `{date}` from init context, overwriting any existing date — Update runs seed from files with concrete prior dates, so merely replacing `[YYYY-MM-DD]` placeholders is not sufficient. NEVER guess the date.
|
|
297
305
|
|
|
298
306
|
**SCOPE:** When `${PATH_SCOPE_HINT}` is non-empty (i.e. `--paths` was supplied), restrict every pass below to the validated path prefixes in `${SCOPED_PATHS}`. Do NOT scan files outside those prefixes. When `${PATH_SCOPE_HINT}` is empty, perform a full-repo scan.
|
|
299
307
|
|
|
@@ -407,7 +415,6 @@ Created .planning/codebase/:
|
|
|
407
415
|
- INTEGRATIONS.md ([N] lines) - External services and APIs
|
|
408
416
|
- CONCERNS.md ([N] lines) - Technical debt and issues
|
|
409
417
|
|
|
410
|
-
|
|
411
418
|
---
|
|
412
419
|
|
|
413
420
|
## ▶ Next Up — [${PROJECT_CODE}] ${PROJECT_TITLE}
|
|
@@ -352,6 +352,10 @@ mkdir -p .planning/research
|
|
|
352
352
|
Spawn 4 parallel gsd-project-researcher agents. Each uses this template with dimension-specific fields:
|
|
353
353
|
|
|
354
354
|
**Common structure for all 4 researchers:**
|
|
355
|
+
<!-- #2517 model-omit-on-inherit -->
|
|
356
|
+
|
|
357
|
+
> **Model omission (#2517).** Omit the `model` parameter entirely when the value it would carry (`researcher_model`, `synthesizer_model`, `roadmapper_model`) is `"inherit"` or empty. An empty value 404s on runtimes without native tier aliases — the default on non-Claude runtimes. Omitting it inherits the orchestrator's model. See @gsd-core/references/model-profile-resolution.md.
|
|
358
|
+
|
|
355
359
|
```text
|
|
356
360
|
Agent(prompt="
|
|
357
361
|
<research_type>Project Research — {DIMENSION} for [new features].</research_type>
|
|
@@ -374,6 +378,10 @@ ${AGENT_SKILLS_RESEARCHER}
|
|
|
374
378
|
|
|
375
379
|
<quality_gate>{GATES}</quality_gate>
|
|
376
380
|
|
|
381
|
+
<!-- #2508 runtime-aware-dispatch -->
|
|
382
|
+
|
|
383
|
+
> **Runtime-aware dispatch (#2508 Phase 4).** GSD workflows dispatch specialized subagents by role. Before dispatching on a built-in-only runtime (kimi-code — three built-ins only), resolve the role to a built-in via `gsd_run query resolve-dispatch-type --requested <role> --raw`. On named-dispatch runtimes (Claude/OpenCode/…) the role is returned unchanged; on kimi-code it maps to `coder`/`explore`/`plan` by role-suffix. The persona rides `${AGENT_SKILLS_<ROLE>}` (Phase 3) regardless. See @gsd-core/references/runtime-aware-dispatch.md.
|
|
384
|
+
|
|
377
385
|
<output>
|
|
378
386
|
Write to: {research_dir}/{FILE}
|
|
379
387
|
Use template: ~/.claude/gsd-core/templates/research-project/{FILE}
|
|
@@ -418,8 +426,8 @@ Commit after writing.
|
|
|
418
426
|
|
|
419
427
|
**Synthesizer output self-heal (#222) — verify SUMMARY.md materialized:** The synthesizer's canonical output is `.planning/research/SUMMARY.md` on disk; its brief structured return (`## SYNTHESIS COMPLETE` plus a few `###` confirmation lines) is NOT the file content. A known LLM false-refusal (issue #222) sometimes makes the agent return the full SUMMARY.md document inline — fabricating a write restriction (e.g. "the runtime is blocking file writes") — instead of writing the file. Prompt hardening alone does not fully eliminate it, so the orchestrator MUST absorb the failure deterministically before spawning `gsd-roadmapper`:
|
|
420
428
|
|
|
421
|
-
1. Verify `.planning/research/SUMMARY.md` exists AND is substantive — non-empty, and free of any leftover `<!-- gsd:write-continue -->` continuation sentinel (which marks a truncated/incomplete write). You may validate with `
|
|
422
|
-
2. If it is MISSING or invalid AND the synthesizer's return message contains the FULL SUMMARY.md document — recognizable by the template's top-level markers `# Project Research Summary`, `## Key Findings`, `## Implications for Roadmap`, and `## Sources`, not merely the brief `## SYNTHESIS COMPLETE` confirmation — the false-refusal fired: write that returned document to `.planning/research/SUMMARY.md` with the Write tool, then commit ALL research artifacts the synthesizer owns (it commits on behalf of the four researchers) with `
|
|
429
|
+
1. Verify `.planning/research/SUMMARY.md` exists AND is substantive — non-empty, and free of any leftover `<!-- gsd:write-continue -->` continuation sentinel (which marks a truncated/incomplete write). You may validate with `gsd_run verify-summary .planning/research/SUMMARY.md` — it exits 0 regardless, so check its JSON `passed` field (`"passed": false` means missing or invalid), not the process exit code. If it passes, continue normally.
|
|
430
|
+
2. If it is MISSING or invalid AND the synthesizer's return message contains the FULL SUMMARY.md document — recognizable by the template's top-level markers `# Project Research Summary`, `## Key Findings`, `## Implications for Roadmap`, and `## Sources`, not merely the brief `## SYNTHESIS COMPLETE` confirmation — the false-refusal fired: write that returned document to `.planning/research/SUMMARY.md` with the Write tool, then commit ALL research artifacts the synthesizer owns (it commits on behalf of the four researchers) with `gsd_run query commit "docs: complete project research" --files .planning/research/` unless they are already committed. Log `⚠ #222 self-heal: synthesizer returned SUMMARY.md inline without writing it; orchestrator persisted the file.`
|
|
423
431
|
3. If it is MISSING or invalid AND the return is only a brief confirmation (no full SUMMARY document to recover), the synthesizer genuinely failed — surface the error and stop; do NOT spawn `gsd-roadmapper` against a missing or incomplete SUMMARY.md.
|
|
424
432
|
|
|
425
433
|
This guarantees `gsd-roadmapper` (which lists SUMMARY.md as required reading) never runs against a missing or truncated SUMMARY.md.
|
|
@@ -111,7 +111,7 @@ elif [ -n "$OPENCODE_CONFIG_DIR" ] || [ -n "$OPENCODE_CONFIG" ]; then RUNTIME="o
|
|
|
111
111
|
else RUNTIME="claude"; fi
|
|
112
112
|
```
|
|
113
113
|
|
|
114
|
-
Set the instruction file variable via the shared runtime-name policy adapter (`
|
|
114
|
+
Set the instruction file variable via the shared runtime-name policy adapter (`gsd_run query project-instruction-file`, backed by `getProjectInstructionFile` in `runtime-name-policy.cjs` — the single source of truth shared with `profile-output.cjs`):
|
|
115
115
|
```bash
|
|
116
116
|
INSTRUCTION_FILE=$(gsd_run query project-instruction-file --runtime "$RUNTIME")
|
|
117
117
|
```
|
|
@@ -132,7 +132,6 @@ All subsequent references to the project instruction file use `$INSTRUCTION_FILE
|
|
|
132
132
|
|
|
133
133
|
**If `needs_codebase_map` is true** (from init — existing code detected but no codebase map):
|
|
134
134
|
|
|
135
|
-
|
|
136
135
|
**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.
|
|
137
136
|
Use AskUserQuestion:
|
|
138
137
|
|
|
@@ -946,6 +945,10 @@ Display spawning indicator:
|
|
|
946
945
|
|
|
947
946
|
Spawn 4 parallel gsd-project-researcher agents with path references:
|
|
948
947
|
|
|
948
|
+
<!-- #2517 model-omit-on-inherit -->
|
|
949
|
+
|
|
950
|
+
> **Model omission (#2517).** Omit the `model` parameter entirely when the value it would carry (`researcher_model`, `synthesizer_model`, `roadmapper_model`) is `"inherit"` or empty. An empty value 404s on runtimes without native tier aliases — the default on non-Claude runtimes. Omitting it inherits the orchestrator's model. See @gsd-core/references/model-profile-resolution.md.
|
|
951
|
+
|
|
949
952
|
```text
|
|
950
953
|
Agent(prompt="<research_type>
|
|
951
954
|
Project Research — Stack dimension for [domain].
|
|
@@ -981,6 +984,10 @@ Your STACK.md feeds into roadmap creation. Be prescriptive:
|
|
|
981
984
|
- [ ] Confidence levels assigned to each recommendation
|
|
982
985
|
</quality_gate>
|
|
983
986
|
|
|
987
|
+
<!-- #2508 runtime-aware-dispatch -->
|
|
988
|
+
|
|
989
|
+
> **Runtime-aware dispatch (#2508 Phase 4).** GSD workflows dispatch specialized subagents by role. Before dispatching on a built-in-only runtime (kimi-code — three built-ins only), resolve the role to a built-in via `gsd_run query resolve-dispatch-type --requested <role> --raw`. On named-dispatch runtimes (Claude/OpenCode/…) the role is returned unchanged; on kimi-code it maps to `coder`/`explore`/`plan` by role-suffix. The persona rides `${AGENT_SKILLS_<ROLE>}` (Phase 3) regardless. See @gsd-core/references/runtime-aware-dispatch.md.
|
|
990
|
+
|
|
984
991
|
<output>
|
|
985
992
|
Write to: {research_dir}/STACK.md
|
|
986
993
|
Use template: ~/.claude/gsd-core/templates/research-project/STACK.md
|
|
@@ -1139,8 +1146,8 @@ Commit after writing.
|
|
|
1139
1146
|
|
|
1140
1147
|
**Synthesizer output self-heal (#222) — verify SUMMARY.md materialized:** The synthesizer's canonical output is `.planning/research/SUMMARY.md` on disk; its brief structured return (`## SYNTHESIS COMPLETE` plus a few `###` confirmation lines) is NOT the file content. A known LLM false-refusal (issue #222) sometimes makes the agent return the full SUMMARY.md document inline — fabricating a write restriction (e.g. "the runtime is blocking file writes") — instead of writing the file. Prompt hardening alone does not fully eliminate it, so the orchestrator MUST absorb the failure deterministically before spawning `gsd-roadmapper`:
|
|
1141
1148
|
|
|
1142
|
-
1. Verify `.planning/research/SUMMARY.md` exists AND is substantive — non-empty, and free of any leftover `<!-- gsd:write-continue -->` continuation sentinel (which marks a truncated/incomplete write). You may validate with `
|
|
1143
|
-
2. If it is MISSING or invalid AND the synthesizer's return message contains the FULL SUMMARY.md document — recognizable by the template's top-level markers `# Project Research Summary`, `## Key Findings`, `## Implications for Roadmap`, and `## Sources`, not merely the brief `## SYNTHESIS COMPLETE` confirmation — the false-refusal fired: write that returned document to `.planning/research/SUMMARY.md` with the Write tool, then commit ALL research artifacts the synthesizer owns (it commits on behalf of the four researchers) with `
|
|
1149
|
+
1. Verify `.planning/research/SUMMARY.md` exists AND is substantive — non-empty, and free of any leftover `<!-- gsd:write-continue -->` continuation sentinel (which marks a truncated/incomplete write). You may validate with `gsd_run verify-summary .planning/research/SUMMARY.md` — it exits 0 regardless, so check its JSON `passed` field (`"passed": false` means missing or invalid), not the process exit code. If it passes, continue normally.
|
|
1150
|
+
2. If it is MISSING or invalid AND the synthesizer's return message contains the FULL SUMMARY.md document — recognizable by the template's top-level markers `# Project Research Summary`, `## Key Findings`, `## Implications for Roadmap`, and `## Sources`, not merely the brief `## SYNTHESIS COMPLETE` confirmation — the false-refusal fired: write that returned document to `.planning/research/SUMMARY.md` with the Write tool, then commit ALL research artifacts the synthesizer owns (it commits on behalf of the four researchers) with `gsd_run query commit "docs: complete project research" --files .planning/research/` unless they are already committed. Log `⚠ #222 self-heal: synthesizer returned SUMMARY.md inline without writing it; orchestrator persisted the file.`
|
|
1144
1151
|
3. If it is MISSING or invalid AND the return is only a brief confirmation (no full SUMMARY document to recover), the synthesizer genuinely failed — surface the error and stop; do NOT spawn `gsd-roadmapper` against a missing or incomplete SUMMARY.md.
|
|
1145
1152
|
|
|
1146
1153
|
This guarantees `gsd-roadmapper` (which lists SUMMARY.md as required reading) never runs against a missing or truncated SUMMARY.md.
|