@opengsd/gsd-core 1.7.0 → 1.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (261) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/.opencode/plugins/gsd-core.js +45 -1
  4. package/README.md +2 -0
  5. package/agents/gsd-code-fixer.md +1 -1
  6. package/agents/gsd-codebase-mapper.md +1 -1
  7. package/agents/gsd-debug-session-manager.md +78 -4
  8. package/agents/gsd-debugger.md +87 -29
  9. package/agents/gsd-executor.md +49 -9
  10. package/agents/gsd-intel-updater.md +3 -3
  11. package/agents/gsd-phase-researcher.md +4 -2
  12. package/agents/gsd-plan-checker.md +20 -0
  13. package/agents/gsd-planner.md +44 -59
  14. package/agents/gsd-project-researcher.md +2 -2
  15. package/agents/gsd-ui-auditor.md +0 -40
  16. package/agents/gsd-verifier.md +2 -2
  17. package/bin/install.js +1338 -135
  18. package/commands/gsd/ai-integration-phase.md +1 -1
  19. package/commands/gsd/mempalace-capture.md +9 -5
  20. package/commands/gsd/new-milestone.md +1 -1
  21. package/commands/gsd/plan-phase.md +5 -3
  22. package/commands/gsd/plan-review-convergence.md +7 -2
  23. package/gsd-core/bin/gsd-tools.cjs +2690 -2472
  24. package/gsd-core/bin/lib/adapter-imperative.cjs +8 -1
  25. package/gsd-core/bin/lib/agent-command-router.cjs +20 -5
  26. package/gsd-core/bin/lib/api-coverage.cjs +360 -53
  27. package/gsd-core/bin/lib/audit.cjs +8 -8
  28. package/gsd-core/bin/lib/broken-windows.cjs +716 -0
  29. package/gsd-core/bin/lib/capability-command-router.cjs +733 -0
  30. package/gsd-core/bin/lib/capability-consent.cjs +40 -1
  31. package/gsd-core/bin/lib/capability-lifecycle.cjs +58 -0
  32. package/gsd-core/bin/lib/capability-loader.cjs +23 -1
  33. package/gsd-core/bin/lib/capability-registry.cjs +1450 -160
  34. package/gsd-core/bin/lib/capability-trust.cjs +468 -33
  35. package/gsd-core/bin/lib/capability-validator.cjs +882 -6
  36. package/gsd-core/bin/lib/capability-writer.cjs +6 -1
  37. package/gsd-core/bin/lib/check-command-router.cjs +140 -27
  38. package/gsd-core/bin/lib/cjs-command-router-adapter.cjs +15 -0
  39. package/gsd-core/bin/lib/claude-orchestration-command-router.cjs +209 -31
  40. package/gsd-core/bin/lib/claude-orchestration.cjs +203 -25
  41. package/gsd-core/bin/lib/command-aliases.cjs +14 -0
  42. package/gsd-core/bin/lib/commands.cjs +326 -21
  43. package/gsd-core/bin/lib/config-loader.cjs +214 -30
  44. package/gsd-core/bin/lib/config.cjs +158 -22
  45. package/gsd-core/bin/lib/core-utils.cjs +6 -1
  46. package/gsd-core/bin/lib/decisions.cjs +32 -8
  47. package/gsd-core/bin/lib/docs.cjs +6 -0
  48. package/gsd-core/bin/lib/estimate-cli.cjs +336 -0
  49. package/gsd-core/bin/lib/external-descriptor-trust.cjs +14 -2
  50. package/gsd-core/bin/lib/frontmatter.cjs +125 -15
  51. package/gsd-core/bin/lib/gap-checker.cjs +17 -2
  52. package/gsd-core/bin/lib/host-integration.cjs +215 -8
  53. package/gsd-core/bin/lib/init.cjs +155 -66
  54. package/gsd-core/bin/lib/install-engine.cjs +299 -23
  55. package/gsd-core/bin/lib/install-profiles.cjs +239 -1
  56. package/gsd-core/bin/lib/installer-migrations/005-opencode-baseline-commands-dir.cjs +146 -0
  57. package/gsd-core/bin/lib/installer-migrations/006-pi-extension-cjs-to-js.cjs +91 -0
  58. package/gsd-core/bin/lib/installer-migrations.cjs +44 -5
  59. package/gsd-core/bin/lib/markdown-sectionizer.cjs +107 -0
  60. package/gsd-core/bin/lib/milestone.cjs +248 -14
  61. package/gsd-core/bin/lib/model-catalog.cjs +69 -4
  62. package/gsd-core/bin/lib/model-resolver.cjs +189 -7
  63. package/gsd-core/bin/lib/observability/logger.cjs +7 -2
  64. package/gsd-core/bin/lib/onboard-projection.cjs +11 -8
  65. package/gsd-core/bin/lib/phase-command-router.cjs +10 -1
  66. package/gsd-core/bin/lib/phase-estimation.cjs +398 -0
  67. package/gsd-core/bin/lib/phase-id.cjs +304 -9
  68. package/gsd-core/bin/lib/phase.cjs +258 -17
  69. package/gsd-core/bin/lib/plan-drift-guard.cjs +1 -1
  70. package/gsd-core/bin/lib/plan-scan.cjs +70 -2
  71. package/gsd-core/bin/lib/planning-workspace.cjs +9 -2
  72. package/gsd-core/bin/lib/profile-output.cjs +34 -8
  73. package/gsd-core/bin/lib/review-lane-descriptor.cjs +927 -0
  74. package/gsd-core/bin/lib/review-lane-invocation.cjs +348 -0
  75. package/gsd-core/bin/lib/review-lane-runner.cjs +594 -0
  76. package/gsd-core/bin/lib/review-reviewer-selection.cjs +114 -32
  77. package/gsd-core/bin/lib/roadmap-parser.cjs +61 -10
  78. package/gsd-core/bin/lib/roadmap.cjs +23 -7
  79. package/gsd-core/bin/lib/runtime-artifact-conversion.cjs +38 -5
  80. package/gsd-core/bin/lib/runtime-artifact-layout.cjs +23 -9
  81. package/gsd-core/bin/lib/runtime-hooks-surface.cjs +156 -0
  82. package/gsd-core/bin/lib/runtime-name-policy.cjs +15 -2
  83. package/gsd-core/bin/lib/smart-entry.cjs +70 -5
  84. package/gsd-core/bin/lib/state-document.cjs +171 -24
  85. package/gsd-core/bin/lib/state-transition.cjs +50 -11
  86. package/gsd-core/bin/lib/state.cjs +206 -32
  87. package/gsd-core/bin/lib/surface.cjs +51 -9
  88. package/gsd-core/bin/lib/uat-predicate.cjs +6 -4
  89. package/gsd-core/bin/lib/uat.cjs +428 -11
  90. package/gsd-core/bin/lib/ui-consideration-probe.cjs +2 -2
  91. package/gsd-core/bin/lib/unusable-input.cjs +216 -0
  92. package/gsd-core/bin/lib/validate.cjs +44 -8
  93. package/gsd-core/bin/lib/verification.cjs +163 -31
  94. package/gsd-core/bin/lib/verify.cjs +348 -42
  95. package/gsd-core/bin/lib/worktree-safety.cjs +360 -15
  96. package/gsd-core/bin/shared/config-defaults.manifest.json +1 -0
  97. package/gsd-core/bin/shared/config-schema.manifest.json +4 -15
  98. package/gsd-core/bin/shared/model-catalog.json +5 -0
  99. package/gsd-core/bin/shared/runtime-aliases.manifest.json +5 -0
  100. package/gsd-core/references/api-coverage.md +37 -7
  101. package/gsd-core/references/checkpoints.md +1 -1
  102. package/gsd-core/references/common-bug-patterns.md +13 -0
  103. package/gsd-core/references/context-budget.md +40 -0
  104. package/gsd-core/references/debugger-bug-taxonomy.md +111 -0
  105. package/gsd-core/references/debugger-fix-acceptance.md +157 -0
  106. package/gsd-core/references/debugger-philosophy.md +1 -0
  107. package/gsd-core/references/debugger-prevention.md +98 -0
  108. package/gsd-core/references/debugger-rca-branching.md +98 -0
  109. package/gsd-core/references/debugger-repro-hardening.md +130 -0
  110. package/gsd-core/references/debugger-sbfl.md +110 -0
  111. package/gsd-core/references/debugger-semantic-recall.md +81 -0
  112. package/gsd-core/references/execute-phase-quota-recovery.md +55 -0
  113. package/gsd-core/references/execute-phase-requirement-revert.md +8 -0
  114. package/gsd-core/references/execute-phase-response-language.md +7 -0
  115. package/gsd-core/references/gate-prompts.md +6 -3
  116. package/gsd-core/references/model-profile-resolution.md +64 -13
  117. package/gsd-core/references/offer-next.md +88 -0
  118. package/gsd-core/references/planner-antipatterns.md +6 -0
  119. package/gsd-core/references/planner-mvp-mode.md +12 -13
  120. package/gsd-core/references/planner-preconditions.md +156 -0
  121. package/gsd-core/references/planner-reversibility.md +132 -0
  122. package/gsd-core/references/planning-config.md +2 -1
  123. package/gsd-core/references/reviewer-instances.md +28 -19
  124. package/gsd-core/references/runtime-aware-dispatch.md +42 -0
  125. package/gsd-core/references/skeleton-template.md +1 -1
  126. package/gsd-core/references/thinking-models-planning.md +3 -1
  127. package/gsd-core/references/ui-consideration-probe.md +2 -2
  128. package/gsd-core/references/worktree-branch-check.md +4 -4
  129. package/gsd-core/templates/DEBUG.md +5 -3
  130. package/gsd-core/templates/summary-minimal.md +4 -0
  131. package/gsd-core/templates/summary-standard.md +4 -0
  132. package/gsd-core/templates/summary.md +7 -0
  133. package/gsd-core/workflows/add-phase.md +2 -0
  134. package/gsd-core/workflows/add-tests.md +3 -1
  135. package/gsd-core/workflows/add-todo.md +32 -1
  136. package/gsd-core/workflows/ai-integration-phase.md +8 -6
  137. package/gsd-core/workflows/audit-fix.md +6 -2
  138. package/gsd-core/workflows/audit-milestone.md +8 -0
  139. package/gsd-core/workflows/autonomous.md +19 -15
  140. package/gsd-core/workflows/check-todos.md +5 -3
  141. package/gsd-core/workflows/cleanup.md +7 -1
  142. package/gsd-core/workflows/code-review-fix.md +14 -6
  143. package/gsd-core/workflows/code-review.md +93 -24
  144. package/gsd-core/workflows/complete-milestone.md +3 -0
  145. package/gsd-core/workflows/debug.md +35 -7
  146. package/gsd-core/workflows/diagnose-issues.md +5 -1
  147. package/gsd-core/workflows/discovery-phase.md +7 -0
  148. package/gsd-core/workflows/discuss-phase/modes/advisor.md +2 -4
  149. package/gsd-core/workflows/discuss-phase/modes/auto.md +0 -6
  150. package/gsd-core/workflows/discuss-phase/templates/context.md +16 -2
  151. package/gsd-core/workflows/discuss-phase-assumptions.md +18 -9
  152. package/gsd-core/workflows/discuss-phase.md +2 -2
  153. package/gsd-core/workflows/do.md +7 -1
  154. package/gsd-core/workflows/docs-update.md +9 -0
  155. package/gsd-core/workflows/eval-review.md +4 -1
  156. package/gsd-core/workflows/execute-phase/steps/codebase-drift-gate.md +4 -0
  157. package/gsd-core/workflows/execute-phase/steps/executor-isolation-dispatch.md +160 -0
  158. package/gsd-core/workflows/execute-phase/steps/post-merge-gate.md +4 -4
  159. package/gsd-core/workflows/execute-phase/steps/regression-gate.md +2 -2
  160. package/gsd-core/workflows/execute-phase.md +110 -149
  161. package/gsd-core/workflows/execute-plan.md +20 -8
  162. package/gsd-core/workflows/explore.md +4 -0
  163. package/gsd-core/workflows/extract-learnings.md +21 -0
  164. package/gsd-core/workflows/graduation.md +3 -0
  165. package/gsd-core/workflows/health.md +7 -1
  166. package/gsd-core/workflows/help/modes/full.md +9 -5
  167. package/gsd-core/workflows/import.md +11 -2
  168. package/gsd-core/workflows/inbox.md +7 -0
  169. package/gsd-core/workflows/ingest-docs.md +19 -10
  170. package/gsd-core/workflows/manager.md +3 -1
  171. package/gsd-core/workflows/map-codebase.md +17 -10
  172. package/gsd-core/workflows/mvp-phase.md +3 -0
  173. package/gsd-core/workflows/new-milestone.md +79 -23
  174. package/gsd-core/workflows/new-project.md +28 -19
  175. package/gsd-core/workflows/new-workspace.md +3 -1
  176. package/gsd-core/workflows/next.md +5 -2
  177. package/gsd-core/workflows/onboard.md +3 -0
  178. package/gsd-core/workflows/plan-phase.md +56 -51
  179. package/gsd-core/workflows/plan-review-convergence.md +61 -12
  180. package/gsd-core/workflows/plant-seed.md +3 -0
  181. package/gsd-core/workflows/profile-user.md +7 -1
  182. package/gsd-core/workflows/progress.md +31 -3
  183. package/gsd-core/workflows/quick.md +33 -10
  184. package/gsd-core/workflows/remove-workspace.md +3 -0
  185. package/gsd-core/workflows/review.md +172 -585
  186. package/gsd-core/workflows/scan.md +10 -2
  187. package/gsd-core/workflows/secure-phase.md +13 -2
  188. package/gsd-core/workflows/settings-integrations.md +3 -0
  189. package/gsd-core/workflows/settings.md +3 -0
  190. package/gsd-core/workflows/ship.md +88 -11
  191. package/gsd-core/workflows/sketch.md +3 -0
  192. package/gsd-core/workflows/smart-entry.md +4 -1
  193. package/gsd-core/workflows/spike.md +7 -1
  194. package/gsd-core/workflows/ui-phase.md +11 -2
  195. package/gsd-core/workflows/ui-review.md +11 -1
  196. package/gsd-core/workflows/undo.md +7 -0
  197. package/gsd-core/workflows/update.md +106 -5
  198. package/gsd-core/workflows/validate-phase.md +13 -2
  199. package/gsd-core/workflows/verify-phase.md +2 -2
  200. package/gsd-core/workflows/verify-work.md +15 -4
  201. package/hooks/dist/gsd-context-monitor.js +27 -9
  202. package/hooks/dist/gsd-cursor-session-start.js +6 -2
  203. package/hooks/dist/gsd-cursor-stop.js +6 -2
  204. package/hooks/dist/gsd-cursor-subagent-start.js +6 -2
  205. package/hooks/dist/gsd-graphify-update.sh +9 -0
  206. package/hooks/dist/gsd-phase-boundary.sh +14 -2
  207. package/hooks/dist/gsd-prompt-guard.js +101 -2
  208. package/hooks/dist/gsd-read-guard.js +100 -2
  209. package/hooks/dist/gsd-read-injection-scanner.js +109 -2
  210. package/hooks/dist/gsd-statusline.js +97 -9
  211. package/hooks/dist/gsd-workflow-guard.js +110 -6
  212. package/hooks/dist/gsd-worktree-path-guard.js +132 -8
  213. package/hooks/dist/lib/cursor-workspace.js +74 -0
  214. package/hooks/gsd-context-monitor.js +27 -9
  215. package/hooks/gsd-cursor-session-start.js +6 -2
  216. package/hooks/gsd-cursor-stop.js +6 -2
  217. package/hooks/gsd-cursor-subagent-start.js +6 -2
  218. package/hooks/gsd-graphify-update.sh +9 -0
  219. package/hooks/gsd-phase-boundary.sh +14 -2
  220. package/hooks/gsd-prompt-guard.js +101 -2
  221. package/hooks/gsd-read-guard.js +100 -2
  222. package/hooks/gsd-read-injection-scanner.js +109 -2
  223. package/hooks/gsd-statusline.js +97 -9
  224. package/hooks/gsd-workflow-guard.js +110 -6
  225. package/hooks/gsd-worktree-path-guard.js +132 -8
  226. package/hooks/lib/cursor-workspace.js +74 -0
  227. package/package.json +10 -8
  228. package/pi/gsd.cjs +34 -3
  229. package/scripts/changeset/lint.cjs +1 -0
  230. package/scripts/changeset/parse.cjs +26 -0
  231. package/scripts/check-coverage-gate.cjs +51 -0
  232. package/scripts/check-glossary-refs.cjs +244 -0
  233. package/scripts/ci-rebase-check.cjs +48 -4
  234. package/scripts/ci-test-scope.cjs +67 -17
  235. package/scripts/gen-adr-index.cjs +528 -0
  236. package/scripts/gen-capability-matrix.cjs +26 -2
  237. package/scripts/gen-capability-registry.cjs +132 -34
  238. package/scripts/gen-emitted-baseline.cjs +145 -0
  239. package/scripts/gen-test-timings.cjs +201 -0
  240. package/scripts/lint-compiled-artifact-sync.cjs +146 -0
  241. package/scripts/lint-emitted-drift-ack.cjs +149 -0
  242. package/scripts/lint-fix-has-regression-test.cjs +131 -0
  243. package/scripts/lint-portable-timeout.cjs +140 -0
  244. package/scripts/lint-resolution-provenance.cjs +9 -0
  245. package/scripts/lint-test-file-count.allowlist.json +1 -0
  246. package/scripts/mutation-matrix.cjs +4 -0
  247. package/scripts/prompt-injection-scan.sh +6 -0
  248. package/scripts/registry-schema.cjs +57 -8
  249. package/scripts/release-notes/conventional-title.cjs +19 -1
  250. package/scripts/release-notes/format-github-release-notes.cjs +7 -3
  251. package/scripts/release-tarball-smoke.cjs +18 -11
  252. package/scripts/run-tests.cjs +420 -58
  253. package/scripts/workflow-size.cjs +16 -8
  254. package/skills/gsd-ai-integration-phase/SKILL.md +1 -1
  255. package/skills/gsd-mempalace-capture/SKILL.md +9 -5
  256. package/skills/gsd-new-milestone/SKILL.md +1 -1
  257. package/skills/gsd-plan-phase/SKILL.md +5 -3
  258. package/skills/gsd-plan-review-convergence/SKILL.md +7 -2
  259. package/vscode/package.json +1 -1
  260. package/scripts/gen-golden-install-parity-zcode.cjs +0 -77
  261. 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
@@ -82,11 +86,11 @@ if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
82
86
  AGENT_SKILLS=$(gsd_run query agent-skills gsd-executor)
83
87
  ```
84
88
 
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`.
89
+ 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`, `requirements_path`.
86
90
 
87
91
  **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
92
 
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.
93
+ @~/.claude/gsd-core/references/execute-phase-response-language.md
90
94
 
91
95
  Read runtime/worktree config and fail closed before any executor dispatch:
92
96
 
@@ -96,26 +100,16 @@ 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
- if [ "$RUNTIME" != "claude" ] && [ "$USE_WORKTREES" != "false" ]; then
100
- echo "FATAL: git worktree isolation (isolation=\"worktree\") is unsupported on runtime '$RUNTIME' — it would run executor agents unisolated against the main checkout. Set workflow.use_worktrees=false." >&2
101
- exit 1
102
- fi
103
- # Sweep orphaned locked worktrees from prior crashed sessions before spawning executors (#3707).
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
- `isolation="worktree"` is a Claude-Code-specific agent primitive; no other runtime can honor it (Codex maps subagents to `spawn_agent`, others prohibit or omit worktree binding). Failing closed prevents main-checkout edits while the workflow believes agents are isolated.
117
109
 
118
- 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. The previous behavior unconditionally disabled worktree isolation whenever `.gitmodules` existed, which penalised every plan in a submodule project even when the plan was nowhere near a submodule. Compute submodule paths once and intersect them per-plan with the plan's declared `files_modified` frontmatter.
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).
111
+
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
 
120
114
  ```bash
121
115
  # Parse submodule paths from .gitmodules once (empty if no .gitmodules).
@@ -127,11 +121,11 @@ else
127
121
  fi
128
122
  ```
129
123
 
130
- `SUBMODULE_PATHS` is exported to the `execute_waves` step, where the per-plan decision actually 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.
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` (project-level) is `false`, all executor agents run without `isolation="worktree"` — they execute sequentially on the main working tree instead of in parallel worktrees. The per-plan decision below has no effect when worktrees are project-disabled.
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` is also automatically set to `false` for the duration of a run when `worktree base-check` detects that the orchestrator HEAD has diverged from the worktree fork base (the #683 condition — e.g. an unmerged milestone or feature branch). This check runs only when `RUNTIME=claude` because `isolation="worktree"` is a Claude Code-specific feature; other runtimes do not use it. 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-tools 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.
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
 
@@ -277,12 +271,6 @@ checkpoints between tasks. The user can review, modify, or redirect work at any
277
271
 
278
272
  3. After all plans: proceed to verification (same as normal mode).
279
273
 
280
- **Benefits of interactive mode:**
281
- - No subagent overhead — dramatically lower token usage
282
- - User catches mistakes early — saves costly verification cycles
283
- - Maintains GSD's planning/tracking structure
284
- - Best for: small phases, bug fixes, verification gaps, learning GSD
285
-
286
274
  **Skip to handle_branching step** (interactive plans execute inline after grouping).
287
275
  </step>
288
276
 
@@ -313,10 +301,8 @@ else
313
301
  else
314
302
  git switch --quiet "$DEFAULT_BRANCH" 2>/dev/null && git merge --ff-only --quiet "origin/$DEFAULT_BRANCH" 2>/dev/null || true
315
303
  fi
316
- # Pinned base + fail-fast: on success HEAD is exactly at origin/$DEFAULT_BRANCH,
317
- # so a post-creation merge-base or "ahead-of" guard would be unreachable. The
318
- # explicit base argument here is the single source of correctness for #2916.
319
- 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 \
320
306
  || { echo "ERROR: Could not create '$BRANCH_NAME' from origin/$DEFAULT_BRANCH (#2916)." >&2; exit 1; }
321
307
  fi
322
308
  ```
@@ -409,7 +395,7 @@ CROSS_AI_TIMEOUT=$(gsd_run query config-get workflow.cross_ai_timeout 2>/dev/nul
409
395
  3. **Run the external command** from the project root, writing the prompt to stdin.
410
396
  Never shell-interpolate the prompt — always pipe via stdin to prevent injection:
411
397
  ```bash
412
- echo "$TASK_PROMPT" | timeout "${CROSS_AI_TIMEOUT}s" ${CROSS_AI_CMD} > "$CANDIDATE_SUMMARY" 2>"$ERROR_LOG"
398
+ echo "$TASK_PROMPT" | gsd_run run-with-timeout "${CROSS_AI_TIMEOUT}" -- ${CROSS_AI_CMD} > "$CANDIDATE_SUMMARY" 2>"$ERROR_LOG"
413
399
  EXIT_CODE=$?
414
400
  ```
415
401
 
@@ -447,18 +433,63 @@ cwd inside an agent worktree (or a subdirectory of one). Every subsequent
447
433
  orchestrator-side git call would then target the wrong tree — this is how a wrong-base
448
434
  merge nearly shipped ~1000 files. Resolve the *worktree root* (so a subdirectory cwd
449
435
  cannot skew the check) and refuse if it is an agent worktree. The discriminator is the
450
- 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
451
437
  orchestrator may itself be legitimately invoked from a feature worktree under
452
438
  `.claude/worktrees/`, so a path-substring refusal would break legitimate runs. Do NOT
453
439
  pin to `git worktree list`'s first entry — that is the main worktree, the wrong target
454
440
  when the orchestrator legitimately runs from a feature worktree.
455
441
 
456
442
  ```bash
443
+ # gsd:guard=orchestrator-cwd-drift
457
444
  ORCHESTRATOR_WT=$(git rev-parse --show-toplevel 2>/dev/null) || {
458
445
  echo "FATAL: execute_waves entry is not inside a git worktree (#48)." >&2; exit 1; }
459
446
  ORCH_BRANCH=$(git rev-parse --abbrev-ref HEAD 2>/dev/null)
460
- if printf '%s' "$ORCH_BRANCH" | grep -Eq '^worktree-agent-'; then
447
+ if printf '%s' "$ORCH_BRANCH" | grep -Eq '^(worktree-)?agent-'; then
461
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
462
493
  exit 1
463
494
  fi
464
495
  # Pin to the worktree root; each later orchestrator-side block re-pins the same way
@@ -553,13 +584,21 @@ increases monotonically across waves. `{status}` is `complete` (success),
553
584
  ```
554
585
 
555
586
  - Bad: "Executing terrain generation plan"
556
- - Good: "Procedural terrain generator using Perlin noise — creates height maps, biome zones, and collision meshes. Required before vehicle physics can interact with ground."
587
+ - Good: "Procedural terrain generator using Perlin noise — creates height maps and biome zones. Required before vehicle physics."
557
588
 
558
589
  2.5. **Per-plan worktree decision (run for each plan in this wave BEFORE its dispatch):**
559
590
 
560
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`.
561
592
 
562
- The dispatch branches in step 3 below MUST gate on `USE_WORKTREES_FOR_PLAN` for the current plan, not on the project-level `USE_WORKTREES`.
593
+ The dispatch branches in step 3 gate on both `USE_WORKTREES` and `USE_WORKTREES_FOR_PLAN` (#2474).
594
+
595
+ 2.75. **Execute:wave:pre capability dispatch:**
596
+
597
+ ```bash
598
+ WAVE_PRE_HOOKS_JSON=$(gsd_run loop render-hooks execute:wave:pre --raw)
599
+ ```
600
+
601
+ If a contribution's `activeHooks` entry provides an alternate wave dispatch, follow it instead of step 3's inline loop; otherwise proceed to step 3.
563
602
 
564
603
  3. **Spawn executor agents:**
565
604
 
@@ -572,14 +611,14 @@ increases monotonically across waves. `{status}` is `complete` (success),
572
611
  For 200k models, this keeps orchestrator context lean (~10-15%).
573
612
  For 1M+ models (Opus 4.6, Sonnet 4.6), richer context can be passed directly.
574
613
 
575
- **Worktree mode** (`USE_WORKTREES_FOR_PLAN` is not `false` — evaluated per-plan in step 2.5):
614
+ **Worktree mode** (`USE_WORKTREES` and `USE_WORKTREES_FOR_PLAN` not `false`):
576
615
 
577
616
  Before spawning, capture the current HEAD:
578
617
  ```bash
579
618
  EXPECTED_BASE=$(git rev-parse HEAD)
580
619
  DISPATCH_TS=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
581
620
  EXPECTED_BRANCH=$(git rev-parse --abbrev-ref HEAD)
582
- if [ "${USE_WORKTREES_FOR_PLAN:-true}" != "false" ] && [ -z "${WAVE_WORKTREE_MANIFEST:-}" ]; then
621
+ if [ "${USE_WORKTREES:-true}" != "false" ] && [ "${USE_WORKTREES_FOR_PLAN:-true}" != "false" ] && [ -z "${WAVE_WORKTREE_MANIFEST:-}" ]; then
583
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)
584
623
  # Persist the dispatch-time orchestrator worktree root so wave-cleanup can pin back to the
585
624
  # orchestrator's OWN worktree — NOT `git worktree list`'s first entry (always the main
@@ -591,6 +630,8 @@ increases monotonically across waves. `{status}` is `complete` (success),
591
630
  fi
592
631
  ```
593
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
+
594
635
  **Sequential dispatch for parallel execution (waves with 2+ agents):**
595
636
  Dispatch each `Agent()` call **one at a time with `run_in_background: true`**. Do NOT
596
637
  send all Agent calls in a single message: simultaneous `git worktree add` calls race
@@ -609,7 +650,10 @@ increases monotonically across waves. `{status}` is `complete` (success),
609
650
  # When executor_model is "inherit", omit this parameter entirely so
610
651
  # Claude Code inherits the orchestrator model automatically.
611
652
  model="{executor_model}", # omit this line when executor_model == "inherit"
612
- isolation="worktree",
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},
613
657
  prompt="
614
658
  <objective>
615
659
  Execute plan {plan_number} of phase {phase_number}-{phase_name}.
@@ -693,6 +737,8 @@ increases monotonically across waves. `{status}` is `complete` (success),
693
737
 
694
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.
695
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
+
696
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):
697
743
 
698
744
  Omit `isolation="worktree"` from the Agent call. Replace the `<parallel_execution>` block with:
@@ -974,7 +1020,7 @@ increases monotonically across waves. `{status}` is `complete` (success),
974
1020
  Note: If `WAVE_FAILURE_COUNT > 1`, strongly recommend "Fix now" — compounding
975
1021
  failures across multiple waves become exponentially harder to diagnose.
976
1022
 
977
- If "Fix now": diagnose failures (typically import conflicts, missing types,
1023
+ If "Fix now": diagnose failures (import conflicts, missing types,
978
1024
  or changed function signatures from parallel plans modifying the same module).
979
1025
  Fix, commit as `fix: resolve post-merge conflicts from wave {N}`, re-run tests.
980
1026
 
@@ -992,8 +1038,6 @@ increases monotonically across waves. `{status}` is `complete` (success),
992
1038
  [checkpoint] phase {PHASE_NUMBER} wave {N}/{M} complete, {P}/{Q} plans done ({wave_success}/{wave_plan_count} ok)
993
1039
  ```
994
1040
 
995
-
996
-
997
1041
  For each SUMMARY.md:
998
1042
  - Verify first 2 files from `key-files.created` exist on disk
999
1043
  - Check `git log --oneline --all --grep="{phase}-{plan}"` returns ≥1 commit
@@ -1024,24 +1068,14 @@ increases monotonically across waves. `{status}` is `complete` (success),
1024
1068
  if [ -n "$RETRY_AFTER" ]; then RETRY_HINT=" Provider hinted retry-after: ${RETRY_AFTER}s"; else RETRY_HINT=""; fi
1025
1069
  ```
1026
1070
  One classifier branch handles sentinels across Claude/Copilot/Codex/Gemini. Reference: `docs/research/provider-rate-limit-signals.md`.
1027
- **Step 7.1 — `class == "quota-exceeded"`:**
1028
- Do not offer "retry now". Run step-5 spot-check first; if SUMMARY.md is missing but commits exist, route to safe-resume (`state.verify-against-disk`) instead of immediate redispatch.
1029
- ```text
1030
- ⚠ Plan {plan_id} terminated by provider quota / rate limit
1031
- Runtime sentinel: {SENTINEL}
1032
- {RETRY_HINT}
1033
- Partial commits on worktree branch: {N}
1034
- SUMMARY.md present: {yes|no}
1035
- 1. Wait for quota reset, then resume (recommended)
1036
- 2. Switch to a different runtime / model and resume
1037
- 3. Abort phase and report partial state
1038
- ```
1039
- Re-run `/gsd:execute-phase` after quota reset for Option 1.
1071
+ **Step 7.1 — `class == "quota-exceeded"`:** follow the quota-recovery fragment below.
1040
1072
  **Step 7.2 — `class == "classify-handoff-bug"`:**
1041
1073
  If error contains `classifyHandoffIfNeeded is not defined`, treat as Claude runtime bug. Run the same step-5 spot-checks; PASS => treat as success, FAIL => fall through.
1042
1074
  **Step 7.3 — `class == "unknown-failure"`:**
1043
1075
  Report failed plan and ask Continue/Stop; continuing may cascade into dependent plan failures.
1044
1076
 
1077
+ @~/.claude/gsd-core/references/execute-phase-quota-recovery.md
1078
+
1045
1079
  @~/.claude/gsd-core/references/execute-phase-between-wave-reset.md
1046
1080
 
1047
1081
  8. **Execute checkpoint plans between waves** — see `<checkpoint_handling>`.
@@ -1342,7 +1376,7 @@ Create VERIFICATION.md.
1342
1376
  Read these files before verification:
1343
1377
  - {phase_dir}/*-PLAN.md (All plans — understand intent, check must_haves)
1344
1378
  - {phase_dir}/*-SUMMARY.md (All summaries — cross-reference claimed vs actual)
1345
- - .planning/REQUIREMENTS.md (Requirement traceability)
1379
+ - {requirements_path} (Requirement traceability)
1346
1380
  ${CONTEXT_WINDOW >= 500000 ? `- {phase_dir}/*-CONTEXT.md (User decisions — verify they were honored)
1347
1381
  - {phase_dir}/*-RESEARCH.md (Known pitfalls — check for traps)
1348
1382
  - Prior VERIFICATION.md files from earlier phases (regression check)
@@ -1415,7 +1449,7 @@ Commit the file:
1415
1449
  gsd_run query commit "test({phase_num}): persist human verification items as UAT" --files "{phase_dir}/{phase_num}-UAT.md"
1416
1450
  ```
1417
1451
 
1418
- **Step B: Present to user:**
1452
+ **Step B: Present to user**:
1419
1453
 
1420
1454
  ```
1421
1455
  ## ◷ Phase {X}: {Name} — Human Verification Needed
@@ -1437,9 +1471,10 @@ Verify-work will walk you through each item and mark the phase complete when all
1437
1471
 
1438
1472
  **If user acknowledges without reporting issues (including "ok", "noted", "ack", "got it", "approved", "done", "yes", "pass", or similar):** Stop. The phase remains pending. No further orchestrator action — wait for the user to run `/gsd:verify-work`.
1439
1473
 
1440
- **If user reports issues now (before running verify-work):** Proceed to gap closure as currently implemented.
1474
+ **If user reports issues now:** Proceed to gap closure.
1441
1475
 
1442
1476
  **If gaps_found:**
1477
+ @~/.claude/gsd-core/references/execute-phase-requirement-revert.md
1443
1478
  ```
1444
1479
  ## ⚠ Phase {X}: {Name} — Gaps Found
1445
1480
 
@@ -1480,7 +1515,7 @@ The CLI handles:
1480
1515
 
1481
1516
  Extract from result: `next_phase`, `next_phase_name`, `is_last_phase`, `warnings`, `has_warnings`.
1482
1517
 
1483
- **If has_warnings is true:**
1518
+ **If has_warnings is true**:
1484
1519
  ```
1485
1520
  ## Phase {X} marked complete with {N} warnings:
1486
1521
 
@@ -1520,7 +1555,7 @@ Copy failure must NOT block phase completion.
1520
1555
  <step name="close_phase_todos">
1521
1556
  **Auto-close pending todos tagged for this phase (#2433).**
1522
1557
 
1523
- This step runs AFTER `update_roadmap` marks the phase complete. It moves any pending todos that carry `resolves_phase: <current-phase-number>` to the completed directory.
1558
+ After `update_roadmap`, moves todos whose `resolves_phase` matches to `completed/`.
1524
1559
 
1525
1560
  ```bash
1526
1561
  PHASE_NUM="${PHASE_NUMBER}"
@@ -1528,25 +1563,32 @@ PENDING_DIR=".planning/todos/pending"
1528
1563
  COMPLETED_DIR=".planning/todos/completed"
1529
1564
  mkdir -p "$COMPLETED_DIR"
1530
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
+
1531
1572
  CLOSED=()
1532
1573
  for TODO_FILE in "$PENDING_DIR"/*.md; do
1533
1574
  [ -f "$TODO_FILE" ] || continue
1534
- # Extract resolves_phase from YAML frontmatter (first --- block only)
1575
+ # resolves_phase from first frontmatter block
1535
1576
  RP=$(awk '/^---/{c++;next} c==1 && /^resolves_phase:/{print $2;exit} c==2{exit}' "$TODO_FILE" 2>/dev/null || true)
1536
- if [ "$RP" = "$PHASE_NUM" ] || [ "$RP" = "\"$PHASE_NUM\"" ]; then
1577
+ RP_NORM=$(normalize_phase_num "$RP")
1578
+ if [ -n "$RP_NORM" ] && [ "$RP_NORM" = "$PHASE_NUM_NORM" ]; then
1537
1579
  mv "$TODO_FILE" "$COMPLETED_DIR/"
1538
1580
  CLOSED+=("$(basename "$TODO_FILE")")
1539
1581
  fi
1540
1582
  done
1541
1583
 
1542
1584
  if [ ${#CLOSED[@]} -gt 0 ]; then
1543
- gsd_run query commit "docs(phase-${PHASE_NUMBER}): auto-close ${#CLOSED[@]} todo(s) resolved by this phase" --files .planning/todos/completed/ .planning/STATE.md|| true
1585
+ gsd_run query commit "docs(phase-${PHASE_NUMBER}): close ${#CLOSED[@]} resolved todo(s)" --files .planning/todos/completed/ .planning/todos/pending/ .planning/STATE.md|| true
1544
1586
  echo "◆ Closed ${#CLOSED[@]} todo(s) resolved by Phase ${PHASE_NUMBER}:"
1545
1587
  for f in "${CLOSED[@]}"; do echo " ✓ $f"; done
1546
1588
  fi
1547
1589
  ```
1548
1590
 
1549
- **If no todos have `resolves_phase: <this-phase>`:** Skip silently — this step is always additive and never blocks phase completion.
1591
+ **No matches:** skip silently (always additive, non-blocking).
1550
1592
  </step>
1551
1593
 
1552
1594
  <step name="update_project_md">
@@ -1572,88 +1614,7 @@ gsd_run query commit "docs(phase-{X}): evolve PROJECT.md after phase completion"
1572
1614
  </step>
1573
1615
 
1574
1616
  <step name="offer_next">
1575
-
1576
- **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.
1577
-
1578
- **No-transition check (spawned by auto-advance chain):**
1579
-
1580
- Parse `--no-transition` flag from $ARGUMENTS.
1581
-
1582
- **If `--no-transition` flag present:**
1583
-
1584
- Execute-phase was spawned by plan-phase's auto-advance. Do NOT run transition.md.
1585
- After verification passes and roadmap is updated, return completion status to parent:
1586
-
1587
- ```
1588
- ## PHASE COMPLETE
1589
-
1590
- Phase: ${PHASE_NUMBER} - ${PHASE_NAME}
1591
- Plans: ${completed_count}/${total_count}
1592
- Verification: {Passed | Gaps Found}
1593
-
1594
- [Include aggregate_results output]
1595
- ```
1596
-
1597
- STOP. Do not proceed to auto-advance or transition.
1598
-
1599
- **If `--no-transition` flag is NOT present:**
1600
-
1601
- **Auto-advance detection:**
1602
-
1603
- 1. Parse `--auto` flag from $ARGUMENTS
1604
- 2. Read consolidated auto-mode (`active` = chain flag OR user preference; chain flag already synced in init step):
1605
- ```bash
1606
- AUTO_MODE=$(gsd_run query check auto-mode --pick active 2>/dev/null || echo "false")
1607
- ```
1608
-
1609
- **If `--auto` flag present OR `AUTO_MODE` is true (AND verification passed with no gaps):**
1610
-
1611
- ```
1612
- ╔══════════════════════════════════════════╗
1613
- ║ AUTO-ADVANCING → TRANSITION ║
1614
- ║ Phase {X} verified, continuing chain ║
1615
- ╚══════════════════════════════════════════╝
1616
- ```
1617
-
1618
- Execute the transition workflow inline (do NOT use Agent — orchestrator context is ~10-15%, transition needs phase completion data already in context):
1619
-
1620
- Read and follow `~/.claude/gsd-core/workflows/transition.md`, passing through the `--auto` flag so it propagates to the next phase invocation.
1621
-
1622
- **If neither `--auto` nor `AUTO_MODE` is true:**
1623
-
1624
- **STOP. Do not auto-advance. Do not execute transition. Do not plan next phase. Present options to the user and wait.**
1625
-
1626
- **IMPORTANT: There is NO `/gsd-transition` command. Never suggest it. The transition workflow is internal only.**
1627
-
1628
- Check whether CONTEXT.md already exists for the next phase:
1629
-
1630
- ```bash
1631
- ls .planning/phases/*{next}*/{next}-CONTEXT.md 2>/dev/null || echo "no-context"
1632
- ```
1633
-
1634
- If CONTEXT.md does **not** exist for the next phase, present:
1635
-
1636
- ```
1637
- ## ✓ Phase {X}: {Name} Complete
1638
-
1639
- /gsd:progress ${GSD_WS} — see updated roadmap
1640
- /gsd:discuss-phase {next} ${GSD_WS} — start here: discuss next phase before planning ← recommended
1641
- /gsd:plan-phase {next} ${GSD_WS} — plan next phase (skip discuss)
1642
- /gsd:execute-phase {next} ${GSD_WS} — execute next phase (skip discuss and plan)
1643
- ```
1644
-
1645
- If CONTEXT.md **exists** for the next phase, present:
1646
-
1647
- ```
1648
- ## ✓ Phase {X}: {Name} Complete
1649
-
1650
- /gsd:progress ${GSD_WS} — see updated roadmap
1651
- /gsd:plan-phase {next} ${GSD_WS} — start here: plan next phase (CONTEXT.md already present) ← recommended
1652
- /gsd:discuss-phase {next} ${GSD_WS} — re-discuss next phase
1653
- /gsd:execute-phase {next} ${GSD_WS} — execute next phase (skip planning)
1654
- ```
1655
-
1656
- Only suggest the commands listed above. Do not invent or hallucinate command names.
1617
+ @~/.claude/gsd-core/references/offer-next.md
1657
1618
  </step>
1658
1619
 
1659
1620
  </process>
@@ -1663,7 +1624,7 @@ Orchestrator: ~10-15% context for 200k windows, can use more for 1M+ windows.
1663
1624
  Subagents: fresh context each (200k-1M depending on model). No polling (Agent blocks). No context bleed.
1664
1625
 
1665
1626
  For 1M+ context models, consider:
1666
- - Passing richer context (code snippets, dependency outputs) directly to executors instead of just file paths
1627
+ - Passing richer context (code snippets, dependency outputs) directly to executors instead of file paths
1667
1628
  - Running small phases (≤3 plans, no dependencies) inline without subagent spawning overhead
1668
1629
  - Relaxing /clear recommendations — context rot onset is much further out with 5x window
1669
1630
  </context_efficiency>
@@ -48,7 +48,9 @@ INIT=$(gsd_run query init.execute-phase "${PHASE}")
48
48
  if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
49
49
  ```
50
50
 
51
- Extract from init JSON: `executor_model`, `commit_docs`, `sub_repos`, `phase_dir`, `phase_number`, `plans`, `summaries`, `incomplete_plans`, `state_path`, `config_path`.
51
+ Extract from init JSON: `executor_model`, `commit_docs`, `sub_repos`, `phase_dir`, `phase_number`, `plans`, `summaries`, `incomplete_plans`, `state_path`, `config_path`, `response_language`.
52
+
53
+ **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.
52
54
 
53
55
  If `.planning/` missing: error.
54
56
  </step>
@@ -107,7 +109,11 @@ Otherwise: Apply checkpoint-based routing below.
107
109
  | Verify-only | B (segmented) | Segments between checkpoints. After none/human-verify → SUBAGENT. After decision/human-action → MAIN |
108
110
  | Decision | C (main) | Execute entirely in main context |
109
111
 
110
- **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 `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.
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.
111
117
 
112
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.
113
119
 
@@ -157,9 +163,6 @@ Pattern B only (verify-only checkpoints). Skip for A/C.
157
163
 
158
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.
159
165
 
160
-
161
-
162
-
163
166
  </step>
164
167
 
165
168
  <step name="load_prompt">
@@ -189,6 +192,7 @@ Deviations are normal — handle via rules below.
189
192
  3. Per task:
190
193
  - **MANDATORY read_first gate:** If the task has a `<read_first>` field, you MUST read every listed file BEFORE making any edits. This is not optional. Do not skip files because you "already know" what's in them — read them. The read_first files establish ground truth for the task.
191
194
  - `type="auto"`: if `tdd="true"` → TDD execution. Implement with deviation rules + auth gates. Verify done criteria. Commit (see task_commit). Track hash for Summary.
195
+ - `type="tracer"`: execute like `type="auto"` (production-quality, real `<verify>`, commit), then run the tracer feedback gate BEFORE any expansion task — an early integration checkpoint. Auto mode active (`AUTO_CHAIN` or `AUTO_CFG`): re-run the tracer `<verify>`; on failure HALT and surface (deviation) — do NOT start expansion tasks. Interactive: STOP → return a `checkpoint:human-verify` for the tracer via checkpoint_protocol before expansion.
192
196
  - `type="checkpoint:*"`: STOP → checkpoint_protocol → wait for user → continue only after confirmation.
193
197
  - **HARD GATE — acceptance_criteria verification:** After completing each task, if it has `<acceptance_criteria>`, you MUST run a verification loop before proceeding:
194
198
  1. For each criterion: execute the grep, file check, or CLI command that proves it passes
@@ -469,13 +473,21 @@ Counts PLAN vs SUMMARY files on disk. Updates progress table row with correct co
469
473
  </step>
470
474
 
471
475
  <step name="update_requirements">
472
- Mark completed requirements from the PLAN.md frontmatter `requirements:` field:
476
+ Mark completed requirements from the PLAN.md frontmatter `requirements:` field.
477
+
478
+ Extract requirement IDs from the plan's frontmatter (e.g., `requirements: [AUTH-01, AUTH-02]`) into `REQ_IDS`. If no requirements field, skip this step.
479
+
480
+ **Shared-ID gate (#2388):** a requirement ID declared by more than one plan in this phase must not read `Complete` until every plan declaring it has finished (produced a `*-SUMMARY.md`) — otherwise the first plan to finish flips it `Complete` while its sibling plans are still running, before phase verification ever gets a chance to catch a real gap. Compute the ready subset first, then mark only those:
473
481
 
474
482
  ```bash
475
- gsd_run query requirements.mark-complete ${REQ_IDS}
483
+ READY=$(gsd_run query requirements.ready-ids "${PLAN_PATH}" ${REQ_IDS} --raw)
484
+ READY_IDS=$(printf '%s' "$READY" | jq -r '.ready[]' 2>/dev/null | tr '\n' ' ')
485
+ if [ -n "$(printf '%s' "$READY_IDS" | tr -d '[:space:]')" ]; then
486
+ gsd_run query requirements.mark-complete ${READY_IDS}
487
+ fi
476
488
  ```
477
489
 
478
- Extract requirement IDs from the plan's frontmatter (e.g., `requirements: [AUTH-01, AUTH-02]`). If no requirements field, skip.
490
+ `requirements.ready-ids` is read-only: it scans sibling `*-PLAN.md` files in this plan's phase directory and blocks an ID only when a sibling ALSO declares it and that sibling has no `*-SUMMARY.md` yet. An ID no sibling declares is always ready (single-plan requirements mark immediately, no added latency). A blocked ID is re-evaluated the next time any plan in this phase finishes its own `update_requirements` step, and becomes ready once the LAST declaring plan's SUMMARY exists.
479
491
  </step>
480
492
 
481
493
  <step name="git_commit_metadata">
@@ -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
 
@@ -22,11 +22,14 @@ Read from project config (`config.json`):
22
22
 
23
23
  ```bash
24
24
  _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 "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CLAUDE_CONFIG_DIR:-$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
25
+ RESPONSE_LANGUAGE=$(gsd_run query config-get response_language --default "" 2>/dev/null || echo "")
25
26
  GRADUATION_ENABLED=$(gsd_run query config-get features.graduation 2>/dev/null || echo "true")
26
27
  GRADUATION_WINDOW=$(gsd_run query config-get features.graduation_window 2>/dev/null || echo "5")
27
28
  GRADUATION_THRESHOLD=$(gsd_run query config-get features.graduation_threshold 2>/dev/null || echo "3")
28
29
  ```
29
30
 
31
+ **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.
32
+
30
33
  **Skip silently (print nothing) if:**
31
34
  - `features.graduation` is `false`
32
35
  - Fewer than `graduation_threshold` completed prior phases exist (not enough data)