@opengsd/gsd-core 1.16.0 → 1.18.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 (211) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -2
  3. package/.opencode/plugins/gsd-core.js +251 -1
  4. package/.opencode/plugins/gsd-statusline/tui.tsx +55 -0
  5. package/GEMINI.md +1 -1
  6. package/agents/gsd-advisor-researcher.compact.md +1 -1
  7. package/agents/gsd-advisor-researcher.md +1 -1
  8. package/agents/gsd-assumptions-analyzer.compact.md +1 -1
  9. package/agents/gsd-assumptions-analyzer.md +1 -1
  10. package/agents/gsd-code-fixer.compact.md +1 -1
  11. package/agents/gsd-code-fixer.md +1 -1
  12. package/agents/gsd-code-reviewer.compact.md +1 -1
  13. package/agents/gsd-code-reviewer.md +1 -1
  14. package/agents/gsd-codebase-mapper.compact.md +1 -1
  15. package/agents/gsd-codebase-mapper.md +1 -1
  16. package/agents/gsd-debug-session-manager.compact.md +6 -0
  17. package/agents/gsd-debug-session-manager.md +6 -0
  18. package/agents/gsd-debugger.md +1 -1
  19. package/agents/gsd-doc-verifier.compact.md +4 -4
  20. package/agents/gsd-doc-verifier.md +4 -3
  21. package/agents/gsd-doc-writer.compact.md +23 -5
  22. package/agents/gsd-doc-writer.md +19 -6
  23. package/agents/gsd-eval-auditor.compact.md +1 -1
  24. package/agents/gsd-eval-auditor.md +1 -1
  25. package/agents/gsd-executor.md +7 -3
  26. package/agents/gsd-integration-checker.compact.md +1 -1
  27. package/agents/gsd-integration-checker.md +1 -1
  28. package/agents/gsd-nyquist-auditor.compact.md +1 -1
  29. package/agents/gsd-nyquist-auditor.md +1 -1
  30. package/agents/gsd-phase-researcher.md +1 -1
  31. package/agents/gsd-plan-checker.md +2 -1
  32. package/agents/gsd-planner.md +5 -4
  33. package/agents/gsd-project-researcher.compact.md +1 -1
  34. package/agents/gsd-project-researcher.md +1 -1
  35. package/agents/gsd-research-synthesizer.compact.md +5 -5
  36. package/agents/gsd-research-synthesizer.md +5 -5
  37. package/agents/gsd-roadmapper.compact.md +1 -1
  38. package/agents/gsd-roadmapper.md +1 -1
  39. package/agents/gsd-security-auditor.compact.md +1 -1
  40. package/agents/gsd-security-auditor.md +1 -1
  41. package/agents/gsd-ui-auditor.compact.md +1 -1
  42. package/agents/gsd-ui-auditor.md +1 -1
  43. package/agents/gsd-ui-checker.compact.md +1 -1
  44. package/agents/gsd-ui-checker.md +1 -1
  45. package/agents/gsd-ui-researcher.compact.md +13 -1
  46. package/agents/gsd-ui-researcher.md +28 -1
  47. package/agents/gsd-verifier.md +1 -1
  48. package/bin/gsd-mcp-server.js +3 -1
  49. package/bin/install.js +398 -95
  50. package/commands/gsd/code-review.md +8 -0
  51. package/commands/gsd/pause-work.md +1 -1
  52. package/gsd-core/bin/gsd-tools.cjs +34 -12
  53. package/gsd-core/bin/lib/adr-parser.cjs +37 -5
  54. package/gsd-core/bin/lib/capability-ledger.cjs +25 -0
  55. package/gsd-core/bin/lib/capability-lock.cjs +29 -7
  56. package/gsd-core/bin/lib/capability-registry.cjs +138 -80
  57. package/gsd-core/bin/lib/capability-source.cjs +3 -1
  58. package/gsd-core/bin/lib/capability-state.cjs +6 -3
  59. package/gsd-core/bin/lib/capability-validator.cjs +8 -5
  60. package/gsd-core/bin/lib/capability-writer.cjs +2 -1
  61. package/gsd-core/bin/lib/commands.cjs +33 -9
  62. package/gsd-core/bin/lib/config-loader.cjs +3 -3
  63. package/gsd-core/bin/lib/decision-coverage-support.cjs +19 -0
  64. package/gsd-core/bin/lib/gate-context-drift.cjs +5 -4
  65. package/gsd-core/bin/lib/gate-decision-coverage-plan.cjs +15 -0
  66. package/gsd-core/bin/lib/gate-decision-coverage-verify.cjs +13 -0
  67. package/gsd-core/bin/lib/gate-predicate-evaluator.cjs +23 -3
  68. package/gsd-core/bin/lib/gate-predicate.cjs +8 -12
  69. package/gsd-core/bin/lib/gate-tdd-review-checkpoint.cjs +60 -5
  70. package/gsd-core/bin/lib/gate-ui-safety.cjs +2 -1
  71. package/gsd-core/bin/lib/graphify.cjs +3 -2
  72. package/gsd-core/bin/lib/init.cjs +43 -16
  73. package/gsd-core/bin/lib/install-effort-resolver.cjs +2 -2
  74. package/gsd-core/bin/lib/install-engine.cjs +11 -0
  75. package/gsd-core/bin/lib/install-model-override-resolver.cjs +4 -3
  76. package/gsd-core/bin/lib/install-profiles.cjs +5 -3
  77. package/gsd-core/bin/lib/install-shadow-report.cjs +12 -0
  78. package/gsd-core/bin/lib/installer-migrations/011-opencode-mcp-no-prompts.cjs +99 -0
  79. package/gsd-core/bin/lib/installer-migrations.cjs +54 -1
  80. package/gsd-core/bin/lib/jsonc-edit.cjs +418 -0
  81. package/gsd-core/bin/lib/loop-host-contract.cjs +2 -1
  82. package/gsd-core/bin/lib/mcp-server.cjs +5 -1
  83. package/gsd-core/bin/lib/opencode-mcp-entry.cjs +39 -0
  84. package/gsd-core/bin/lib/opencode-version.cjs +486 -0
  85. package/gsd-core/bin/lib/phase.cjs +141 -11
  86. package/gsd-core/bin/lib/quick-batch-dispatch.cjs +2 -1
  87. package/gsd-core/bin/lib/report-parser.cjs +57 -1
  88. package/gsd-core/bin/lib/review-lane-invocation.cjs +40 -0
  89. package/gsd-core/bin/lib/review-reviewer-selection.cjs +20 -1
  90. package/gsd-core/bin/lib/roadmap.cjs +56 -5
  91. package/gsd-core/bin/lib/runtime-artifact-conversion.cjs +142 -6
  92. package/gsd-core/bin/lib/runtime-homes.cjs +18 -0
  93. package/gsd-core/bin/lib/runtime-hooks-surface.cjs +58 -3
  94. package/gsd-core/bin/lib/runtime-slash.cjs +13 -0
  95. package/gsd-core/bin/lib/shell-command-projection.cjs +2 -0
  96. package/gsd-core/bin/lib/smart-entry.cjs +100 -53
  97. package/gsd-core/bin/lib/state-document.cjs +37 -3
  98. package/gsd-core/bin/lib/state-transition.cjs +98 -19
  99. package/gsd-core/bin/lib/state.cjs +544 -126
  100. package/gsd-core/bin/lib/task-command-router.cjs +2 -3
  101. package/gsd-core/bin/lib/tdd-red-evidence.cjs +5 -0
  102. package/gsd-core/bin/lib/tdd-test-files.cjs +42 -0
  103. package/gsd-core/bin/lib/update-context.cjs +18 -1
  104. package/gsd-core/bin/lib/verification.cjs +107 -17
  105. package/gsd-core/bin/lib/verify.cjs +36 -1
  106. package/gsd-core/references/agent-contracts.md +1 -1
  107. package/gsd-core/references/agent-skills-bootstrap.md +26 -7
  108. package/gsd-core/references/git-integration.md +3 -3
  109. package/gsd-core/references/planner-reversibility.md +18 -4
  110. package/gsd-core/references/planner-verify-command-grounding.md +18 -0
  111. package/gsd-core/references/tdd.md +4 -3
  112. package/gsd-core/references/verifier-phase-gates.md +8 -1
  113. package/gsd-core/workflows/add-backlog.md +10 -2
  114. package/gsd-core/workflows/add-phase.md +5 -1
  115. package/gsd-core/workflows/add-tests.md +5 -1
  116. package/gsd-core/workflows/add-todo.md +5 -1
  117. package/gsd-core/workflows/ai-integration-phase.md +5 -1
  118. package/gsd-core/workflows/audit-milestone.md +21 -9
  119. package/gsd-core/workflows/autonomous/templates/minimal-context.md +41 -0
  120. package/gsd-core/workflows/autonomous.md +52 -64
  121. package/gsd-core/workflows/check-todos.md +5 -1
  122. package/gsd-core/workflows/code-review-fix.md +5 -1
  123. package/gsd-core/workflows/code-review.md +21 -2
  124. package/gsd-core/workflows/complete-milestone/detail/elaboration.md +5 -1
  125. package/gsd-core/workflows/complete-milestone.md +25 -5
  126. package/gsd-core/workflows/debug.md +5 -1
  127. package/gsd-core/workflows/diagnose-issues.md +5 -1
  128. package/gsd-core/workflows/discuss-phase/modes/chain.md +5 -1
  129. package/gsd-core/workflows/discuss-phase-assumptions.md +11 -3
  130. package/gsd-core/workflows/discuss-phase.md +5 -1
  131. package/gsd-core/workflows/docs-update/detail/elaboration.md +7 -6
  132. package/gsd-core/workflows/docs-update.md +27 -5
  133. package/gsd-core/workflows/edit-phase.md +5 -1
  134. package/gsd-core/workflows/eval-review.md +11 -3
  135. package/gsd-core/workflows/execute-phase/steps/codebase-drift-gate.md +5 -1
  136. package/gsd-core/workflows/execute-phase/steps/executor-isolation-dispatch.md +1 -1
  137. package/gsd-core/workflows/execute-phase/steps/post-merge-gate.md +12 -6
  138. package/gsd-core/workflows/execute-phase/steps/regression-gate-run.md +19 -2
  139. package/gsd-core/workflows/execute-phase/steps/regression-gate.md +18 -1
  140. package/gsd-core/workflows/execute-phase/steps/verify-phase-goal.md +5 -1
  141. package/gsd-core/workflows/execute-phase.md +40 -7
  142. package/gsd-core/workflows/execute-plan.md +8 -4
  143. package/gsd-core/workflows/extract-learnings.md +6 -2
  144. package/gsd-core/workflows/forensics.md +5 -1
  145. package/gsd-core/workflows/import.md +5 -1
  146. package/gsd-core/workflows/insert-phase.md +5 -1
  147. package/gsd-core/workflows/manager.md +10 -2
  148. package/gsd-core/workflows/map-codebase.md +5 -1
  149. package/gsd-core/workflows/milestone-summary.md +10 -2
  150. package/gsd-core/workflows/new-milestone.md +13 -5
  151. package/gsd-core/workflows/new-project.md +9 -5
  152. package/gsd-core/workflows/next.md +8 -4
  153. package/gsd-core/workflows/pause-work.md +3 -3
  154. package/gsd-core/workflows/plan-phase/steps/auto-advance-check.md +70 -0
  155. package/gsd-core/workflows/plan-phase/steps/chunked-planning-mode.md +5 -1
  156. package/gsd-core/workflows/plan-phase/steps/closed-phase-gate.md +6 -2
  157. package/gsd-core/workflows/plan-phase.md +41 -73
  158. package/gsd-core/workflows/plan-review-convergence.md +17 -5
  159. package/gsd-core/workflows/plant-seed.md +8 -4
  160. package/gsd-core/workflows/progress.md +6 -2
  161. package/gsd-core/workflows/quick-batch.md +5 -1
  162. package/gsd-core/workflows/quick.md +22 -7
  163. package/gsd-core/workflows/remove-phase.md +5 -1
  164. package/gsd-core/workflows/resume-project.md +19 -11
  165. package/gsd-core/workflows/review.md +6 -2
  166. package/gsd-core/workflows/scan.md +5 -1
  167. package/gsd-core/workflows/secure-phase.md +6 -2
  168. package/gsd-core/workflows/settings.md +3 -3
  169. package/gsd-core/workflows/ship.md +13 -10
  170. package/gsd-core/workflows/thread.md +10 -2
  171. package/gsd-core/workflows/transition.md +5 -1
  172. package/gsd-core/workflows/ui-phase.md +5 -1
  173. package/gsd-core/workflows/ui-review.md +6 -2
  174. package/gsd-core/workflows/ultraplan-phase.md +5 -1
  175. package/gsd-core/workflows/update.md +5 -1
  176. package/gsd-core/workflows/validate-phase.md +6 -2
  177. package/gsd-core/workflows/verify-work/detail/elaboration.md +1 -1
  178. package/gsd-core/workflows/verify-work/steps/mvp-uat-framing.md +5 -1
  179. package/gsd-core/workflows/verify-work.md +11 -3
  180. package/hooks/dist/gsd-agent-isolation-guard.js +3 -1
  181. package/hooks/dist/gsd-check-update.js +26 -20
  182. package/hooks/dist/gsd-context-monitor.js +14 -5
  183. package/hooks/dist/gsd-cursor-subagent-start.js +2 -1
  184. package/hooks/dist/gsd-secret-read-guard.js +189 -15
  185. package/hooks/dist/gsd-statusline.js +321 -22
  186. package/hooks/dist/gsd-validate-commit.sh +27 -5
  187. package/hooks/gsd-agent-isolation-guard.js +3 -1
  188. package/hooks/gsd-check-update.js +26 -20
  189. package/hooks/gsd-context-monitor.js +14 -5
  190. package/hooks/gsd-cursor-subagent-start.js +2 -1
  191. package/hooks/gsd-secret-read-guard.js +189 -15
  192. package/hooks/gsd-statusline.js +321 -22
  193. package/hooks/gsd-validate-commit.sh +27 -5
  194. package/package.json +1 -1
  195. package/scripts/audit-workflow-script-paths.cjs +1 -1
  196. package/scripts/diagnose-validate-commit-in-tier.cjs +270 -0
  197. package/scripts/diagnose-validate-commit-phases.cjs +348 -0
  198. package/scripts/diagnose-windows-spawn-watcher.cjs +317 -0
  199. package/scripts/docs-guard-registry.cjs +2 -0
  200. package/scripts/gen-capability-registry.cjs +7 -1
  201. package/scripts/gen-loop-host-contract.cjs +4 -1
  202. package/scripts/lib/macos-conformance-tier.generated.cjs +13 -0
  203. package/scripts/lib/platform-conformance-tier.generated.cjs +26 -0
  204. package/scripts/lint-phase-arg-assignment.cjs +2 -2
  205. package/scripts/lint-workflow-shellcheck-baseline.json +16 -16
  206. package/scripts/mutation-matrix.cjs +3 -1
  207. package/scripts/release-tarball-smoke.cjs +15 -7
  208. package/scripts/xtrace-phase-timing.cjs +205 -0
  209. package/skills/gsd-code-review/SKILL.md +8 -0
  210. package/skills/gsd-pause-work/SKILL.md +1 -1
  211. package/vscode/package.json +1 -1
@@ -18,9 +18,13 @@ Analyze completed phase artifacts (PLAN.md, SUMMARY.md, VERIFICATION.md, UAT.md,
18
18
  Parse arguments and load project state:
19
19
 
20
20
  ```bash
21
+ IFS= read -rd '' GSD_ARGS <<'GSD_ARGS_END' || true
22
+ $ARGUMENTS
23
+ GSD_ARGS_END
24
+ GSD_ARGS=${GSD_ARGS%$'\n'}
21
25
  _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}"; _gsd_at() { for _p; do if [ -f "$_p" ]; then GSD_TOOLS="$_p"; return 0; fi; done; return 1; }; _gsd_id_ok() { case "$("$1" runtime-identity --raw 2>/dev/null || true)" in '{"packageName":"@opengsd/gsd-core"'*'}') return 0;; *) return 1;; esac; }; _gsd_homes() { set -- "${CLAUDE_CONFIG_DIR:-$HOME/.claude}" "${ANTIGRAVITY_CONFIG_DIR:-$HOME/.gemini/antigravity}" "$HOME/.gemini/antigravity-ide" "$HOME/.gemini/antigravity-cli" "${AUGMENT_CONFIG_DIR:-$HOME/.augment}" "${CLINE_CONFIG_DIR:-$HOME/.cline}" "${CODEBUDDY_CONFIG_DIR:-$HOME/.codebuddy}" "${CODEX_HOME:-$HOME/.codex}" "${COPILOT_CONFIG_DIR:-${COPILOT_HOME:-$HOME/.copilot}}" "${CURSOR_CONFIG_DIR:-$HOME/.cursor}" "${HERMES_HOME:-$HOME/.hermes}" "${KILO_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/kilo}" "${KIMI_CONFIG_DIR:-$HOME/.config/agents}" "$HOME/.agents" "${KIMI_CODE_HOME:-$HOME/.kimi-code}" "${OPENCODE_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/opencode}" "${PI_CODING_AGENT_DIR:-$HOME/.pi/agent}" "${QWEN_CONFIG_DIR:-$HOME/.qwen}" "${TRAE_CONFIG_DIR:-$HOME/.trae}" "${WINDSURF_CONFIG_DIR:-$HOME/.codeium/windsurf}" "${ZCODE_CONFIG_DIR:-$HOME/.zcode}" "${GROK_AGENTS_HOME:-$HOME/.agents}"; for _h; do _gsd_at "$_h/gsd-core/bin/${_GSD_SHIM_NAME}" && return 0; done; return 1; }; if _gsd_at "${_GSD_RUNTIME_ROOT}/gsd-core/bin/${_GSD_SHIM_NAME}" "${_GSD_RUNTIME_ROOT}/.claude/gsd-core/bin/${_GSD_SHIM_NAME}" "${_GSD_RUNTIME_ROOT}/.codex/gsd-core/bin/${_GSD_SHIM_NAME}"; then gsd_run() { node "$GSD_TOOLS" "$@"; }; elif _gsd_homes; then gsd_run() { node "$GSD_TOOLS" "$@"; }; elif unset -f gsd_run; _G="$(command -v gsd_run)"; [ -n "$_G" ] && _gsd_id_ok "$_G"; then GSD_TOOLS="$_G"; gsd_run() { "$GSD_TOOLS" "$@"; }; else echo "ERROR: gsd-tools.cjs not found at $GSD_TOOLS and no identity-proving gsd_run is on PATH. Run: npx -y @opengsd/gsd-core@latest --claude --local" >&2; exit 1; fi; GSD_IDENTITY_STATUS=unverified; _gsd_id_ok gsd_run && GSD_IDENTITY_STATUS=ok; export GSD_IDENTITY_STATUS; [ "$GSD_IDENTITY_STATUS" = ok ] || echo "WARNING: \"$GSD_TOOLS\" did not prove it is @opengsd/gsd-core - it is either a different package or an @opengsd/gsd-core older than the runtime-identity verb. See docs/how-to/diagnose-a-foreign-gsd-tools.md" >&2; 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
22
- PHASE_ARG=$(echo "$ARGUMENTS" | sed -E 's/--ws[[:space:]]+[A-Za-z0-9._-]+//g' | xargs)
23
- GSD_WS=$(echo " $ARGUMENTS" | sed -nE 's/.* --ws +([A-Za-z0-9][A-Za-z0-9._-]*).*/--ws \1/p' | head -n 1)
26
+ PHASE_ARG=$(echo "$GSD_ARGS" | sed -E 's/--ws[[:space:]]+[A-Za-z0-9._-]+//g' | xargs)
27
+ GSD_WS=$(echo " $GSD_ARGS" | sed -nE 's/.* --ws +([A-Za-z0-9][A-Za-z0-9._-]*).*/--ws \1/p' | head -n 1)
24
28
  INIT=$(gsd_run query init.phase-op ${GSD_WS:+--ws=${GSD_WS##* }} "${PHASE_ARG}")
25
29
  if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
26
30
  ```
@@ -14,7 +14,11 @@ Only write the forensic report.
14
14
  ## Step 1: Get Problem Description
15
15
 
16
16
  ```bash
17
- PROBLEM="$ARGUMENTS"
17
+ IFS= read -rd '' GSD_ARGS <<'GSD_ARGS_END' || true
18
+ $ARGUMENTS
19
+ GSD_ARGS_END
20
+ GSD_ARGS=${GSD_ARGS%$'\n'}
21
+ PROBLEM="$GSD_ARGS"
18
22
  ```
19
23
 
20
24
  If `$ARGUMENTS` is empty, ask the user:
@@ -178,7 +178,11 @@ Apply GSD naming convention for the output filename:
178
178
  Determine the target directory by querying `init.phase-op` for the phase number extracted in `plan_read_input`. This ensures the `project_code` prefix from `.planning/config.json` is applied:
179
179
 
180
180
  ```bash
181
- GSD_WS=$(echo " $ARGUMENTS" | sed -nE 's/.* --ws +([A-Za-z0-9][A-Za-z0-9._-]*).*/--ws \1/p' | head -n 1)
181
+ IFS= read -rd '' GSD_ARGS <<'GSD_ARGS_END' || true
182
+ $ARGUMENTS
183
+ GSD_ARGS_END
184
+ GSD_ARGS=${GSD_ARGS%$'\n'}
185
+ GSD_WS=$(echo " $GSD_ARGS" | sed -nE 's/.* --ws +([A-Za-z0-9][A-Za-z0-9._-]*).*/--ws \1/p' | head -n 1)
182
186
  INIT=$(gsd_run query init.phase-op ${GSD_WS:+--ws=${GSD_WS##* }} "{NN}")
183
187
  if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
184
188
  expected_phase_dir=$(echo "$INIT" | node -e "process.stdout.write(JSON.parse(require('fs').readFileSync('/dev/stdin','utf8')).expected_phase_dir)")
@@ -36,8 +36,12 @@ Validate first argument is an integer.
36
36
  Load phase operation context:
37
37
 
38
38
  ```bash
39
+ IFS= read -rd '' GSD_ARGS <<'GSD_ARGS_END' || true
40
+ $ARGUMENTS
41
+ GSD_ARGS_END
42
+ GSD_ARGS=${GSD_ARGS%$'\n'}
39
43
  _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}"; _gsd_at() { for _p; do if [ -f "$_p" ]; then GSD_TOOLS="$_p"; return 0; fi; done; return 1; }; _gsd_id_ok() { case "$("$1" runtime-identity --raw 2>/dev/null || true)" in '{"packageName":"@opengsd/gsd-core"'*'}') return 0;; *) return 1;; esac; }; _gsd_homes() { set -- "${CLAUDE_CONFIG_DIR:-$HOME/.claude}" "${ANTIGRAVITY_CONFIG_DIR:-$HOME/.gemini/antigravity}" "$HOME/.gemini/antigravity-ide" "$HOME/.gemini/antigravity-cli" "${AUGMENT_CONFIG_DIR:-$HOME/.augment}" "${CLINE_CONFIG_DIR:-$HOME/.cline}" "${CODEBUDDY_CONFIG_DIR:-$HOME/.codebuddy}" "${CODEX_HOME:-$HOME/.codex}" "${COPILOT_CONFIG_DIR:-${COPILOT_HOME:-$HOME/.copilot}}" "${CURSOR_CONFIG_DIR:-$HOME/.cursor}" "${HERMES_HOME:-$HOME/.hermes}" "${KILO_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/kilo}" "${KIMI_CONFIG_DIR:-$HOME/.config/agents}" "$HOME/.agents" "${KIMI_CODE_HOME:-$HOME/.kimi-code}" "${OPENCODE_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/opencode}" "${PI_CODING_AGENT_DIR:-$HOME/.pi/agent}" "${QWEN_CONFIG_DIR:-$HOME/.qwen}" "${TRAE_CONFIG_DIR:-$HOME/.trae}" "${WINDSURF_CONFIG_DIR:-$HOME/.codeium/windsurf}" "${ZCODE_CONFIG_DIR:-$HOME/.zcode}" "${GROK_AGENTS_HOME:-$HOME/.agents}"; for _h; do _gsd_at "$_h/gsd-core/bin/${_GSD_SHIM_NAME}" && return 0; done; return 1; }; if _gsd_at "${_GSD_RUNTIME_ROOT}/gsd-core/bin/${_GSD_SHIM_NAME}" "${_GSD_RUNTIME_ROOT}/.claude/gsd-core/bin/${_GSD_SHIM_NAME}" "${_GSD_RUNTIME_ROOT}/.codex/gsd-core/bin/${_GSD_SHIM_NAME}"; then gsd_run() { node "$GSD_TOOLS" "$@"; }; elif _gsd_homes; then gsd_run() { node "$GSD_TOOLS" "$@"; }; elif unset -f gsd_run; _G="$(command -v gsd_run)"; [ -n "$_G" ] && _gsd_id_ok "$_G"; then GSD_TOOLS="$_G"; gsd_run() { "$GSD_TOOLS" "$@"; }; else echo "ERROR: gsd-tools.cjs not found at $GSD_TOOLS and no identity-proving gsd_run is on PATH. Run: npx -y @opengsd/gsd-core@latest --claude --local" >&2; exit 1; fi; GSD_IDENTITY_STATUS=unverified; _gsd_id_ok gsd_run && GSD_IDENTITY_STATUS=ok; export GSD_IDENTITY_STATUS; [ "$GSD_IDENTITY_STATUS" = ok ] || echo "WARNING: \"$GSD_TOOLS\" did not prove it is @opengsd/gsd-core - it is either a different package or an @opengsd/gsd-core older than the runtime-identity verb. See docs/how-to/diagnose-a-foreign-gsd-tools.md" >&2; 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
40
- GSD_WS=$(echo " $ARGUMENTS" | sed -nE 's/.* --ws +([A-Za-z0-9][A-Za-z0-9._-]*).*/--ws \1/p' | head -n 1)
44
+ GSD_WS=$(echo " $GSD_ARGS" | sed -nE 's/.* --ws +([A-Za-z0-9][A-Za-z0-9._-]*).*/--ws \1/p' | head -n 1)
41
45
  INIT=$(gsd_run query init.phase-op ${GSD_WS:+--ws=${GSD_WS##* }} "${after_phase}")
42
46
  if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
43
47
  ```
@@ -19,8 +19,12 @@ Read all files referenced by the invoking prompt's execution_context before star
19
19
  Bootstrap via manager init:
20
20
 
21
21
  ```bash
22
+ IFS= read -rd '' GSD_ARGS <<'GSD_ARGS_END' || true
23
+ $ARGUMENTS
24
+ GSD_ARGS_END
25
+ GSD_ARGS=${GSD_ARGS%$'\n'}
22
26
  _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}"; _gsd_at() { for _p; do if [ -f "$_p" ]; then GSD_TOOLS="$_p"; return 0; fi; done; return 1; }; _gsd_id_ok() { case "$("$1" runtime-identity --raw 2>/dev/null || true)" in '{"packageName":"@opengsd/gsd-core"'*'}') return 0;; *) return 1;; esac; }; _gsd_homes() { set -- "${CLAUDE_CONFIG_DIR:-$HOME/.claude}" "${ANTIGRAVITY_CONFIG_DIR:-$HOME/.gemini/antigravity}" "$HOME/.gemini/antigravity-ide" "$HOME/.gemini/antigravity-cli" "${AUGMENT_CONFIG_DIR:-$HOME/.augment}" "${CLINE_CONFIG_DIR:-$HOME/.cline}" "${CODEBUDDY_CONFIG_DIR:-$HOME/.codebuddy}" "${CODEX_HOME:-$HOME/.codex}" "${COPILOT_CONFIG_DIR:-${COPILOT_HOME:-$HOME/.copilot}}" "${CURSOR_CONFIG_DIR:-$HOME/.cursor}" "${HERMES_HOME:-$HOME/.hermes}" "${KILO_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/kilo}" "${KIMI_CONFIG_DIR:-$HOME/.config/agents}" "$HOME/.agents" "${KIMI_CODE_HOME:-$HOME/.kimi-code}" "${OPENCODE_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/opencode}" "${PI_CODING_AGENT_DIR:-$HOME/.pi/agent}" "${QWEN_CONFIG_DIR:-$HOME/.qwen}" "${TRAE_CONFIG_DIR:-$HOME/.trae}" "${WINDSURF_CONFIG_DIR:-$HOME/.codeium/windsurf}" "${ZCODE_CONFIG_DIR:-$HOME/.zcode}" "${GROK_AGENTS_HOME:-$HOME/.agents}"; for _h; do _gsd_at "$_h/gsd-core/bin/${_GSD_SHIM_NAME}" && return 0; done; return 1; }; if _gsd_at "${_GSD_RUNTIME_ROOT}/gsd-core/bin/${_GSD_SHIM_NAME}" "${_GSD_RUNTIME_ROOT}/.claude/gsd-core/bin/${_GSD_SHIM_NAME}" "${_GSD_RUNTIME_ROOT}/.codex/gsd-core/bin/${_GSD_SHIM_NAME}"; then gsd_run() { node "$GSD_TOOLS" "$@"; }; elif _gsd_homes; then gsd_run() { node "$GSD_TOOLS" "$@"; }; elif unset -f gsd_run; _G="$(command -v gsd_run)"; [ -n "$_G" ] && _gsd_id_ok "$_G"; then GSD_TOOLS="$_G"; gsd_run() { "$GSD_TOOLS" "$@"; }; else echo "ERROR: gsd-tools.cjs not found at $GSD_TOOLS and no identity-proving gsd_run is on PATH. Run: npx -y @opengsd/gsd-core@latest --claude --local" >&2; exit 1; fi; GSD_IDENTITY_STATUS=unverified; _gsd_id_ok gsd_run && GSD_IDENTITY_STATUS=ok; export GSD_IDENTITY_STATUS; [ "$GSD_IDENTITY_STATUS" = ok ] || echo "WARNING: \"$GSD_TOOLS\" did not prove it is @opengsd/gsd-core - it is either a different package or an @opengsd/gsd-core older than the runtime-identity verb. See docs/how-to/diagnose-a-foreign-gsd-tools.md" >&2; 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
23
- GSD_WS=$(echo " $ARGUMENTS" | sed -nE 's/.* --ws +([A-Za-z0-9][A-Za-z0-9._-]*).*/--ws \1/p' | head -n 1)
27
+ GSD_WS=$(echo " $GSD_ARGS" | sed -nE 's/.* --ws +([A-Za-z0-9][A-Za-z0-9._-]*).*/--ws \1/p' | head -n 1)
24
28
  INIT=$(gsd_run query init.manager ${GSD_WS:+--ws=${GSD_WS##* }})
25
29
  if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
26
30
  ```
@@ -63,7 +67,11 @@ Proceed to dashboard step.
63
67
  **Every time this step is reached**, re-read state from disk to pick up changes from background agents:
64
68
 
65
69
  ```bash
66
- GSD_WS=$(echo " $ARGUMENTS" | sed -nE 's/.* --ws +([A-Za-z0-9][A-Za-z0-9._-]*).*/--ws \1/p' | head -n 1)
70
+ IFS= read -rd '' GSD_ARGS <<'GSD_ARGS_END' || true
71
+ $ARGUMENTS
72
+ GSD_ARGS_END
73
+ GSD_ARGS=${GSD_ARGS%$'\n'}
74
+ GSD_WS=$(echo " $GSD_ARGS" | sed -nE 's/.* --ws +([A-Za-z0-9][A-Za-z0-9._-]*).*/--ws \1/p' | head -n 1)
67
75
  INIT=$(gsd_run query init.manager ${GSD_WS:+--ws=${GSD_WS##* }})
68
76
  if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
69
77
  ```
@@ -72,8 +72,12 @@ documents refreshed.
72
72
  Load codebase mapping context:
73
73
 
74
74
  ```bash
75
+ IFS= read -rd '' GSD_ARGS <<'GSD_ARGS_END' || true
76
+ $ARGUMENTS
77
+ GSD_ARGS_END
78
+ GSD_ARGS=${GSD_ARGS%$'\n'}
75
79
  _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}"; _gsd_at() { for _p; do if [ -f "$_p" ]; then GSD_TOOLS="$_p"; return 0; fi; done; return 1; }; _gsd_id_ok() { case "$("$1" runtime-identity --raw 2>/dev/null || true)" in '{"packageName":"@opengsd/gsd-core"'*'}') return 0;; *) return 1;; esac; }; _gsd_homes() { set -- "${CLAUDE_CONFIG_DIR:-$HOME/.claude}" "${ANTIGRAVITY_CONFIG_DIR:-$HOME/.gemini/antigravity}" "$HOME/.gemini/antigravity-ide" "$HOME/.gemini/antigravity-cli" "${AUGMENT_CONFIG_DIR:-$HOME/.augment}" "${CLINE_CONFIG_DIR:-$HOME/.cline}" "${CODEBUDDY_CONFIG_DIR:-$HOME/.codebuddy}" "${CODEX_HOME:-$HOME/.codex}" "${COPILOT_CONFIG_DIR:-${COPILOT_HOME:-$HOME/.copilot}}" "${CURSOR_CONFIG_DIR:-$HOME/.cursor}" "${HERMES_HOME:-$HOME/.hermes}" "${KILO_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/kilo}" "${KIMI_CONFIG_DIR:-$HOME/.config/agents}" "$HOME/.agents" "${KIMI_CODE_HOME:-$HOME/.kimi-code}" "${OPENCODE_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/opencode}" "${PI_CODING_AGENT_DIR:-$HOME/.pi/agent}" "${QWEN_CONFIG_DIR:-$HOME/.qwen}" "${TRAE_CONFIG_DIR:-$HOME/.trae}" "${WINDSURF_CONFIG_DIR:-$HOME/.codeium/windsurf}" "${ZCODE_CONFIG_DIR:-$HOME/.zcode}" "${GROK_AGENTS_HOME:-$HOME/.agents}"; for _h; do _gsd_at "$_h/gsd-core/bin/${_GSD_SHIM_NAME}" && return 0; done; return 1; }; if _gsd_at "${_GSD_RUNTIME_ROOT}/gsd-core/bin/${_GSD_SHIM_NAME}" "${_GSD_RUNTIME_ROOT}/.claude/gsd-core/bin/${_GSD_SHIM_NAME}" "${_GSD_RUNTIME_ROOT}/.codex/gsd-core/bin/${_GSD_SHIM_NAME}"; then gsd_run() { node "$GSD_TOOLS" "$@"; }; elif _gsd_homes; then gsd_run() { node "$GSD_TOOLS" "$@"; }; elif unset -f gsd_run; _G="$(command -v gsd_run)"; [ -n "$_G" ] && _gsd_id_ok "$_G"; then GSD_TOOLS="$_G"; gsd_run() { "$GSD_TOOLS" "$@"; }; else echo "ERROR: gsd-tools.cjs not found at $GSD_TOOLS and no identity-proving gsd_run is on PATH. Run: npx -y @opengsd/gsd-core@latest --claude --local" >&2; exit 1; fi; GSD_IDENTITY_STATUS=unverified; _gsd_id_ok gsd_run && GSD_IDENTITY_STATUS=ok; export GSD_IDENTITY_STATUS; [ "$GSD_IDENTITY_STATUS" = ok ] || echo "WARNING: \"$GSD_TOOLS\" did not prove it is @opengsd/gsd-core - it is either a different package or an @opengsd/gsd-core older than the runtime-identity verb. See docs/how-to/diagnose-a-foreign-gsd-tools.md" >&2; 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
76
- GSD_WS=$(echo " $ARGUMENTS" | sed -nE 's/.* --ws +([A-Za-z0-9][A-Za-z0-9._-]*).*/--ws \1/p' | head -n 1)
80
+ GSD_WS=$(echo " $GSD_ARGS" | sed -nE 's/.* --ws +([A-Za-z0-9][A-Za-z0-9._-]*).*/--ws \1/p' | head -n 1)
77
81
  INIT=$(gsd_run query init.map-codebase ${GSD_WS:+--ws=${GSD_WS##* }})
78
82
  if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
79
83
  AGENT_SKILLS_MAPPER=$(gsd_run query agent-skills gsd-codebase-mapper ${GSD_WS:+--ws=${GSD_WS##* }})
@@ -10,7 +10,11 @@ Designed for team onboarding — a new contributor can read the output and under
10
10
  ## Step 1: Resolve Version
11
11
 
12
12
  ```bash
13
- VERSION="$ARGUMENTS"
13
+ IFS= read -rd '' GSD_ARGS <<'GSD_ARGS_END' || true
14
+ $ARGUMENTS
15
+ GSD_ARGS_END
16
+ GSD_ARGS=${GSD_ARGS%$'\n'}
17
+ VERSION="$GSD_ARGS"
14
18
  ```
15
19
 
16
20
  If `$ARGUMENTS` is empty:
@@ -55,8 +59,12 @@ Read all files that exist. Missing files are fine — the summary adapts to what
55
59
  Find all phase directories:
56
60
 
57
61
  ```bash
62
+ IFS= read -rd '' GSD_ARGS <<'GSD_ARGS_END' || true
63
+ $ARGUMENTS
64
+ GSD_ARGS_END
65
+ GSD_ARGS=${GSD_ARGS%$'\n'}
58
66
  _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}"; _gsd_at() { for _p; do if [ -f "$_p" ]; then GSD_TOOLS="$_p"; return 0; fi; done; return 1; }; _gsd_id_ok() { case "$("$1" runtime-identity --raw 2>/dev/null || true)" in '{"packageName":"@opengsd/gsd-core"'*'}') return 0;; *) return 1;; esac; }; _gsd_homes() { set -- "${CLAUDE_CONFIG_DIR:-$HOME/.claude}" "${ANTIGRAVITY_CONFIG_DIR:-$HOME/.gemini/antigravity}" "$HOME/.gemini/antigravity-ide" "$HOME/.gemini/antigravity-cli" "${AUGMENT_CONFIG_DIR:-$HOME/.augment}" "${CLINE_CONFIG_DIR:-$HOME/.cline}" "${CODEBUDDY_CONFIG_DIR:-$HOME/.codebuddy}" "${CODEX_HOME:-$HOME/.codex}" "${COPILOT_CONFIG_DIR:-${COPILOT_HOME:-$HOME/.copilot}}" "${CURSOR_CONFIG_DIR:-$HOME/.cursor}" "${HERMES_HOME:-$HOME/.hermes}" "${KILO_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/kilo}" "${KIMI_CONFIG_DIR:-$HOME/.config/agents}" "$HOME/.agents" "${KIMI_CODE_HOME:-$HOME/.kimi-code}" "${OPENCODE_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/opencode}" "${PI_CODING_AGENT_DIR:-$HOME/.pi/agent}" "${QWEN_CONFIG_DIR:-$HOME/.qwen}" "${TRAE_CONFIG_DIR:-$HOME/.trae}" "${WINDSURF_CONFIG_DIR:-$HOME/.codeium/windsurf}" "${ZCODE_CONFIG_DIR:-$HOME/.zcode}" "${GROK_AGENTS_HOME:-$HOME/.agents}"; for _h; do _gsd_at "$_h/gsd-core/bin/${_GSD_SHIM_NAME}" && return 0; done; return 1; }; if _gsd_at "${_GSD_RUNTIME_ROOT}/gsd-core/bin/${_GSD_SHIM_NAME}" "${_GSD_RUNTIME_ROOT}/.claude/gsd-core/bin/${_GSD_SHIM_NAME}" "${_GSD_RUNTIME_ROOT}/.codex/gsd-core/bin/${_GSD_SHIM_NAME}"; then gsd_run() { node "$GSD_TOOLS" "$@"; }; elif _gsd_homes; then gsd_run() { node "$GSD_TOOLS" "$@"; }; elif unset -f gsd_run; _G="$(command -v gsd_run)"; [ -n "$_G" ] && _gsd_id_ok "$_G"; then GSD_TOOLS="$_G"; gsd_run() { "$GSD_TOOLS" "$@"; }; else echo "ERROR: gsd-tools.cjs not found at $GSD_TOOLS and no identity-proving gsd_run is on PATH. Run: npx -y @opengsd/gsd-core@latest --claude --local" >&2; exit 1; fi; GSD_IDENTITY_STATUS=unverified; _gsd_id_ok gsd_run && GSD_IDENTITY_STATUS=ok; export GSD_IDENTITY_STATUS; [ "$GSD_IDENTITY_STATUS" = ok ] || echo "WARNING: \"$GSD_TOOLS\" did not prove it is @opengsd/gsd-core - it is either a different package or an @opengsd/gsd-core older than the runtime-identity verb. See docs/how-to/diagnose-a-foreign-gsd-tools.md" >&2; 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
59
- GSD_WS=$(echo " $ARGUMENTS" | sed -nE 's/.* --ws +([A-Za-z0-9][A-Za-z0-9._-]*).*/--ws \1/p' | head -n 1)
67
+ GSD_WS=$(echo " $GSD_ARGS" | sed -nE 's/.* --ws +([A-Za-z0-9][A-Za-z0-9._-]*).*/--ws \1/p' | head -n 1)
60
68
  gsd_run query init.progress ${GSD_WS:+--ws=${GSD_WS##* }}
61
69
  ```
62
70
 
@@ -30,10 +30,14 @@ Parse `$ARGUMENTS` before doing anything else:
30
30
  Parse `GSD_WS` and `MILESTONE_ARG` using the established idiom (see `verify-work.md`):
31
31
 
32
32
  ```bash
33
+ IFS= read -rd '' GSD_ARGS <<'GSD_ARGS_END' || true
34
+ $ARGUMENTS
35
+ GSD_ARGS_END
36
+ GSD_ARGS=${GSD_ARGS%$'\n'}
33
37
  _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}"; _gsd_at() { for _p; do if [ -f "$_p" ]; then GSD_TOOLS="$_p"; return 0; fi; done; return 1; }; _gsd_id_ok() { case "$("$1" runtime-identity --raw 2>/dev/null || true)" in '{"packageName":"@opengsd/gsd-core"'*'}') return 0;; *) return 1;; esac; }; _gsd_homes() { set -- "${CLAUDE_CONFIG_DIR:-$HOME/.claude}" "${ANTIGRAVITY_CONFIG_DIR:-$HOME/.gemini/antigravity}" "$HOME/.gemini/antigravity-ide" "$HOME/.gemini/antigravity-cli" "${AUGMENT_CONFIG_DIR:-$HOME/.augment}" "${CLINE_CONFIG_DIR:-$HOME/.cline}" "${CODEBUDDY_CONFIG_DIR:-$HOME/.codebuddy}" "${CODEX_HOME:-$HOME/.codex}" "${COPILOT_CONFIG_DIR:-${COPILOT_HOME:-$HOME/.copilot}}" "${CURSOR_CONFIG_DIR:-$HOME/.cursor}" "${HERMES_HOME:-$HOME/.hermes}" "${KILO_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/kilo}" "${KIMI_CONFIG_DIR:-$HOME/.config/agents}" "$HOME/.agents" "${KIMI_CODE_HOME:-$HOME/.kimi-code}" "${OPENCODE_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/opencode}" "${PI_CODING_AGENT_DIR:-$HOME/.pi/agent}" "${QWEN_CONFIG_DIR:-$HOME/.qwen}" "${TRAE_CONFIG_DIR:-$HOME/.trae}" "${WINDSURF_CONFIG_DIR:-$HOME/.codeium/windsurf}" "${ZCODE_CONFIG_DIR:-$HOME/.zcode}" "${GROK_AGENTS_HOME:-$HOME/.agents}"; for _h; do _gsd_at "$_h/gsd-core/bin/${_GSD_SHIM_NAME}" && return 0; done; return 1; }; if _gsd_at "${_GSD_RUNTIME_ROOT}/gsd-core/bin/${_GSD_SHIM_NAME}" "${_GSD_RUNTIME_ROOT}/.claude/gsd-core/bin/${_GSD_SHIM_NAME}" "${_GSD_RUNTIME_ROOT}/.codex/gsd-core/bin/${_GSD_SHIM_NAME}"; then gsd_run() { node "$GSD_TOOLS" "$@"; }; elif _gsd_homes; then gsd_run() { node "$GSD_TOOLS" "$@"; }; elif unset -f gsd_run; _G="$(command -v gsd_run)"; [ -n "$_G" ] && _gsd_id_ok "$_G"; then GSD_TOOLS="$_G"; gsd_run() { "$GSD_TOOLS" "$@"; }; else echo "ERROR: gsd-tools.cjs not found at $GSD_TOOLS and no identity-proving gsd_run is on PATH. Run: npx -y @opengsd/gsd-core@latest --claude --local" >&2; exit 1; fi; GSD_IDENTITY_STATUS=unverified; _gsd_id_ok gsd_run && GSD_IDENTITY_STATUS=ok; export GSD_IDENTITY_STATUS; [ "$GSD_IDENTITY_STATUS" = ok ] || echo "WARNING: \"$GSD_TOOLS\" did not prove it is @opengsd/gsd-core - it is either a different package or an @opengsd/gsd-core older than the runtime-identity verb. See docs/how-to/diagnose-a-foreign-gsd-tools.md" >&2; 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
34
38
  GSD_WS=""
35
- echo "$ARGUMENTS" | grep -qE -- '--ws[[:space:]]+[A-Za-z0-9._-]+' && GSD_WS=$(echo "$ARGUMENTS" | grep -oE -- '--ws[[:space:]]+[A-Za-z0-9._-]+')
36
- MILESTONE_ARG=$(echo "$ARGUMENTS" | sed -E 's/--ws[[:space:]]+[A-Za-z0-9._-]+//g' | xargs)
39
+ echo "$GSD_ARGS" | grep -qE -- '--ws[[:space:]]+[A-Za-z0-9._-]+' && GSD_WS=$(echo "$GSD_ARGS" | grep -oE -- '--ws[[:space:]]+[A-Za-z0-9._-]+')
40
+ MILESTONE_ARG=$(echo "$GSD_ARGS" | sed -E 's/--ws[[:space:]]+[A-Za-z0-9._-]+//g' | xargs)
37
41
  # #4456: persist GSD_WS to a file so later steps' bash fences (each a
38
42
  # separate shell) can forward it — the same cross-fence problem Step 5/6
39
43
  # already solve for OUTGOING_MILESTONE via .gsd-outgoing-milestone.
@@ -296,7 +300,11 @@ gsd_run query commit "docs: start milestone v[X.Y] [Name]" --files "$PROJECT_PAT
296
300
  ## 7. Load Context and Resolve Models
297
301
 
298
302
  ```bash
299
- RESET_PHASE_NUMBERS_PARAM=""; if [[ "$ARGUMENTS" =~ (^|[[:space:]])--reset-phase-numbers([[:space:]]|$) ]]; then RESET_PHASE_NUMBERS_PARAM="--reset-phase-numbers"; fi
303
+ IFS= read -rd '' GSD_ARGS <<'GSD_ARGS_END' || true
304
+ $ARGUMENTS
305
+ GSD_ARGS_END
306
+ GSD_ARGS=${GSD_ARGS%$'\n'}
307
+ RESET_PHASE_NUMBERS_PARAM=""; if [[ "$GSD_ARGS" =~ (^|[[:space:]])--reset-phase-numbers([[:space:]]|$) ]]; then RESET_PHASE_NUMBERS_PARAM="--reset-phase-numbers"; fi
300
308
  GSD_WS_ARG=$(cat .planning/.gsd-ws-arg 2>/dev/null || true)
301
309
  INIT=$(gsd_run query init.new-milestone $RESET_PHASE_NUMBERS_PARAM ${GSD_WS_ARG:+--ws=${GSD_WS_ARG##* }})
302
310
  if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
@@ -435,10 +443,10 @@ Commit after writing.
435
443
 
436
444
  > **ORCHESTRATOR RULE — CODEX RUNTIME**: After calling Agent() above, 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.
437
445
 
438
- **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`:
446
+ **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. The restriction is not always fabricated: Claude Code refuses a subagent's `Write` to a few exact basenames — `SUMMARY.md` among them — with `Subagents should return findings as text, not write report files` (observed on Claude Code 2.1.301), and the synthesizer is told to return the full document inline when its `Write` hits that error; the refusal is real, not fabricated. It depends on the exact basename (`SUMMARY.md`, `REPORT.md`, `FINDINGS.md`, `ANALYSIS.md`, case-insensitive; a prefixed name such as `01-01-SUMMARY.md` and other agents' files write fine), so do not tell other agents to avoid `Write`. Either cause lands in step 2. 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 either cause deterministically before spawning `gsd-roadmapper`:
439
447
 
440
448
  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.
441
- 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.`
449
+ 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 synthesizer returned the document inline (the #222 false-refusal, or the runtime's real refusal of the name `SUMMARY.md`): 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.`
442
450
  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.
443
451
 
444
452
  This guarantees `gsd-roadmapper` (which lists SUMMARY.md as required reading) never runs against a missing or truncated SUMMARY.md.
@@ -30,8 +30,12 @@ If `section_manifest` is `null` or `"auto-mode-detection"` is in its `included`
30
30
  **MANDATORY FIRST STEP — Execute these checks before ANY user interaction:**
31
31
 
32
32
  ```bash
33
+ IFS= read -rd '' GSD_ARGS <<'GSD_ARGS_END' || true
34
+ $ARGUMENTS
35
+ GSD_ARGS_END
36
+ GSD_ARGS=${GSD_ARGS%$'\n'}
33
37
  _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}"; _gsd_at() { for _p; do if [ -f "$_p" ]; then GSD_TOOLS="$_p"; return 0; fi; done; return 1; }; _gsd_id_ok() { case "$("$1" runtime-identity --raw 2>/dev/null || true)" in '{"packageName":"@opengsd/gsd-core"'*'}') return 0;; *) return 1;; esac; }; _gsd_homes() { set -- "${CLAUDE_CONFIG_DIR:-$HOME/.claude}" "${ANTIGRAVITY_CONFIG_DIR:-$HOME/.gemini/antigravity}" "$HOME/.gemini/antigravity-ide" "$HOME/.gemini/antigravity-cli" "${AUGMENT_CONFIG_DIR:-$HOME/.augment}" "${CLINE_CONFIG_DIR:-$HOME/.cline}" "${CODEBUDDY_CONFIG_DIR:-$HOME/.codebuddy}" "${CODEX_HOME:-$HOME/.codex}" "${COPILOT_CONFIG_DIR:-${COPILOT_HOME:-$HOME/.copilot}}" "${CURSOR_CONFIG_DIR:-$HOME/.cursor}" "${HERMES_HOME:-$HOME/.hermes}" "${KILO_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/kilo}" "${KIMI_CONFIG_DIR:-$HOME/.config/agents}" "$HOME/.agents" "${KIMI_CODE_HOME:-$HOME/.kimi-code}" "${OPENCODE_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/opencode}" "${PI_CODING_AGENT_DIR:-$HOME/.pi/agent}" "${QWEN_CONFIG_DIR:-$HOME/.qwen}" "${TRAE_CONFIG_DIR:-$HOME/.trae}" "${WINDSURF_CONFIG_DIR:-$HOME/.codeium/windsurf}" "${ZCODE_CONFIG_DIR:-$HOME/.zcode}" "${GROK_AGENTS_HOME:-$HOME/.agents}"; for _h; do _gsd_at "$_h/gsd-core/bin/${_GSD_SHIM_NAME}" && return 0; done; return 1; }; if _gsd_at "${_GSD_RUNTIME_ROOT}/gsd-core/bin/${_GSD_SHIM_NAME}" "${_GSD_RUNTIME_ROOT}/.claude/gsd-core/bin/${_GSD_SHIM_NAME}" "${_GSD_RUNTIME_ROOT}/.codex/gsd-core/bin/${_GSD_SHIM_NAME}"; then gsd_run() { node "$GSD_TOOLS" "$@"; }; elif _gsd_homes; then gsd_run() { node "$GSD_TOOLS" "$@"; }; elif unset -f gsd_run; _G="$(command -v gsd_run)"; [ -n "$_G" ] && _gsd_id_ok "$_G"; then GSD_TOOLS="$_G"; gsd_run() { "$GSD_TOOLS" "$@"; }; else echo "ERROR: gsd-tools.cjs not found at $GSD_TOOLS and no identity-proving gsd_run is on PATH. Run: npx -y @opengsd/gsd-core@latest --claude --local" >&2; exit 1; fi; GSD_IDENTITY_STATUS=unverified; _gsd_id_ok gsd_run && GSD_IDENTITY_STATUS=ok; export GSD_IDENTITY_STATUS; [ "$GSD_IDENTITY_STATUS" = ok ] || echo "WARNING: \"$GSD_TOOLS\" did not prove it is @opengsd/gsd-core - it is either a different package or an @opengsd/gsd-core older than the runtime-identity verb. See docs/how-to/diagnose-a-foreign-gsd-tools.md" >&2; 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
34
- AUTO_PARAM=""; if [[ "$ARGUMENTS" =~ (^|[[:space:]])--auto([[:space:]]|$) ]]; then AUTO_PARAM="--auto"; fi
38
+ AUTO_PARAM=""; if [[ "$GSD_ARGS" =~ (^|[[:space:]])--auto([[:space:]]|$) ]]; then AUTO_PARAM="--auto"; fi
35
39
  INIT=$(gsd_run query init.new-project $AUTO_PARAM)
36
40
  if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
37
41
  AGENT_SKILLS_RESEARCHER=$(gsd_run query agent-skills gsd-project-researcher)
@@ -299,10 +303,10 @@ gsd_run query commit "docs: initialize project" --files .planning/PROJECT.md
299
303
 
300
304
  **If auto mode:** Skip — config was collected in Step 2a. Proceed to Step 5.5.
301
305
 
302
- **Check for global defaults** at `~/.gsd/defaults.json`. If the file exists, read and display its contents before asking:
306
+ **Check for global defaults** at `${GSD_HOME:-$HOME}/.gsd/defaults.json` (`~/.gsd/defaults.json` unless `GSD_HOME` is set). If the file exists, read and display its contents before asking:
303
307
 
304
308
  ```bash
305
- DEFAULTS_RAW=$(cat ~/.gsd/defaults.json 2>/dev/null)
309
+ DEFAULTS_RAW=$(cat "${GSD_HOME:-$HOME}/.gsd/defaults.json" 2>/dev/null)
306
310
  ```
307
311
 
308
312
  Format the JSON into human-readable bullets using these label mappings:
@@ -757,10 +761,10 @@ Commit after writing.
757
761
  <!-- gsd:protected -->
758
762
  > **ORCHESTRATOR RULE — CODEX RUNTIME**: After calling Agent() above, 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.
759
763
 
760
- **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`:
764
+ **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. The restriction is not always fabricated: Claude Code refuses a subagent's `Write` to a few exact basenames — `SUMMARY.md` among them — with `Subagents should return findings as text, not write report files` (observed on Claude Code 2.1.301), and the synthesizer is told to return the full document inline when its `Write` hits that error; the refusal is real, not fabricated. It depends on the exact basename (`SUMMARY.md`, `REPORT.md`, `FINDINGS.md`, `ANALYSIS.md`, case-insensitive; a prefixed name such as `01-01-SUMMARY.md` and other agents' files write fine), so do not tell other agents to avoid `Write`. Either cause lands in step 2. 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 either cause deterministically before spawning `gsd-roadmapper`:
761
765
 
762
766
  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.
763
- 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.`
767
+ 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 synthesizer returned the document inline (the #222 false-refusal, or the runtime's real refusal of the name `SUMMARY.md`): 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.`
764
768
  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.
765
769
 
766
770
  This guarantees `gsd-roadmapper` (which lists SUMMARY.md as required reading) never runs against a missing or truncated SUMMARY.md.
@@ -271,8 +271,12 @@ If STATE.md shows paused_at:
271
271
  Parse the arguments passed to this workflow to detect the plan strategy and build convergence pass-through args:
272
272
 
273
273
  ```bash
274
+ IFS= read -rd '' GSD_ARGS <<'GSD_ARGS_END' || true
275
+ $ARGUMENTS
276
+ GSD_ARGS_END
277
+ GSD_ARGS=${GSD_ARGS%$'\n'}
274
278
  PLAN_STRATEGY="local"
275
- if echo "$ARGUMENTS" | grep -qE '(^|[[:space:]])\-\-(converge|cross-ai)([[:space:]]|$)'; then
279
+ if echo "$GSD_ARGS" | grep -qE '(^|[[:space:]])\-\-(converge|cross-ai)([[:space:]]|$)'; then
276
280
  PLAN_STRATEGY="converge"
277
281
  fi
278
282
 
@@ -280,14 +284,14 @@ CONVERGENCE_ARGS=""
280
284
  # Lane flags derived from the declared roster (#2800/#2272); --all and --text are convergence
281
285
  # controls, not reviewer lanes, so they stay literal.
282
286
  for REVIEW_FLAG in $(gsd_run review-lane flags) --all --text; do
283
- if echo "$ARGUMENTS" | grep -qE "(^|[[:space:]])${REVIEW_FLAG}([[:space:]]|$)"; then
287
+ if echo "$GSD_ARGS" | grep -qE "(^|[[:space:]])${REVIEW_FLAG}([[:space:]]|$)"; then
284
288
  CONVERGENCE_ARGS="${CONVERGENCE_ARGS} ${REVIEW_FLAG}"
285
289
  fi
286
290
  done
287
291
 
288
292
  MAX_CYCLES_ARG=""
289
- if echo "$ARGUMENTS" | grep -qE '\-\-max-cycles\s+[0-9]+'; then
290
- MAX_CYCLES_ARG=$(echo "$ARGUMENTS" | grep -oE '\-\-max-cycles\s+[0-9]+' | awk '{print $2}')
293
+ if echo "$GSD_ARGS" | grep -qE '\-\-max-cycles\s+[0-9]+'; then
294
+ MAX_CYCLES_ARG=$(echo "$GSD_ARGS" | grep -oE '\-\-max-cycles\s+[0-9]+' | awk '{print $2}')
291
295
  CONVERGENCE_ARGS="${CONVERGENCE_ARGS} --max-cycles ${MAX_CYCLES_ARG}"
292
296
  fi
293
297
  ```
@@ -229,7 +229,7 @@ timestamp=$(gsd_run query current-timestamp full --raw)
229
229
 
230
230
  <step name="commit">
231
231
  ```bash
232
- gsd_run query commit "wip: [context-name] paused at [X]/[Y]" --files [handoff-path] .planning/HANDOFF.json
232
+ gsd_run query commit "docs(pause): [context-name] paused at [X]/[Y]" --files [handoff-path] .planning/HANDOFF.json
233
233
  ```
234
234
  </step>
235
235
 
@@ -246,7 +246,7 @@ Current state:
246
246
  - Task: [X] of [Y]
247
247
  - Status: [in_progress/blocked]
248
248
  - Blockers: [count] ({human_actions_pending count} need human action)
249
- - Committed as WIP
249
+ - Committed handoff
250
250
 
251
251
  To resume: /gsd:resume-work
252
252
 
@@ -260,6 +260,6 @@ To resume: /gsd:resume-work
260
260
  - [ ] .continue-here.md created at correct path for detected context
261
261
  - [ ] Required Reading, Anti-Patterns, and Infrastructure State sections filled
262
262
  - [ ] Pre-Execution Critique section filled if pausing between design and execution
263
- - [ ] Committed as WIP
263
+ - [ ] Committed handoff
264
264
  - [ ] User knows location and how to resume
265
265
  </success_criteria>
@@ -0,0 +1,70 @@
1
+ # Auto-Advance Check (plan-phase step 15)
2
+
3
+ This file is Read, not textually substituted: wherever a snippet below shows `$ARGUMENTS`, write the parent command's original argument string there (#4772).
4
+
5
+ Check for auto-advance trigger using values already loaded in step 1:
6
+
7
+ 1. Parse `--auto` and `--chain` flags from $ARGUMENTS
8
+ 2. Use `auto_chain_active` and `auto_advance` from the INIT JSON parsed in step 1 — **do not issue additional `config-get` calls for these values** (they are already present in the init output). Issuing redundant `config-get` calls for values already in INIT can cause infinite read loops on some runtimes.
9
+ 3. **Sync chain flag with intent** — if user invoked manually (no `--auto` and no `--chain`), clear the ephemeral chain flag from any previous interrupted `--auto` chain. This does NOT touch `workflow.auto_advance` (the user's persistent settings preference):
10
+ ```bash
11
+ _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}"; _gsd_at() { for _p; do if [ -f "$_p" ]; then GSD_TOOLS="$_p"; return 0; fi; done; return 1; }; _gsd_id_ok() { case "$("$1" runtime-identity --raw 2>/dev/null || true)" in '{"packageName":"@opengsd/gsd-core"'*'}') return 0;; *) return 1;; esac; }; _gsd_homes() { set -- "${CLAUDE_CONFIG_DIR:-$HOME/.claude}" "${ANTIGRAVITY_CONFIG_DIR:-$HOME/.gemini/antigravity}" "$HOME/.gemini/antigravity-ide" "$HOME/.gemini/antigravity-cli" "${AUGMENT_CONFIG_DIR:-$HOME/.augment}" "${CLINE_CONFIG_DIR:-$HOME/.cline}" "${CODEBUDDY_CONFIG_DIR:-$HOME/.codebuddy}" "${CODEX_HOME:-$HOME/.codex}" "${COPILOT_CONFIG_DIR:-${COPILOT_HOME:-$HOME/.copilot}}" "${CURSOR_CONFIG_DIR:-$HOME/.cursor}" "${HERMES_HOME:-$HOME/.hermes}" "${KILO_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/kilo}" "${KIMI_CONFIG_DIR:-$HOME/.config/agents}" "$HOME/.agents" "${KIMI_CODE_HOME:-$HOME/.kimi-code}" "${OPENCODE_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/opencode}" "${PI_CODING_AGENT_DIR:-$HOME/.pi/agent}" "${QWEN_CONFIG_DIR:-$HOME/.qwen}" "${TRAE_CONFIG_DIR:-$HOME/.trae}" "${WINDSURF_CONFIG_DIR:-$HOME/.codeium/windsurf}" "${ZCODE_CONFIG_DIR:-$HOME/.zcode}" "${GROK_AGENTS_HOME:-$HOME/.agents}"; for _h; do _gsd_at "$_h/gsd-core/bin/${_GSD_SHIM_NAME}" && return 0; done; return 1; }; if _gsd_at "${_GSD_RUNTIME_ROOT}/gsd-core/bin/${_GSD_SHIM_NAME}" "${_GSD_RUNTIME_ROOT}/.claude/gsd-core/bin/${_GSD_SHIM_NAME}" "${_GSD_RUNTIME_ROOT}/.codex/gsd-core/bin/${_GSD_SHIM_NAME}"; then gsd_run() { node "$GSD_TOOLS" "$@"; }; elif _gsd_homes; then gsd_run() { node "$GSD_TOOLS" "$@"; }; elif unset -f gsd_run; _G="$(command -v gsd_run)"; [ -n "$_G" ] && _gsd_id_ok "$_G"; then GSD_TOOLS="$_G"; gsd_run() { "$GSD_TOOLS" "$@"; }; else echo "ERROR: gsd-tools.cjs not found at $GSD_TOOLS and no identity-proving gsd_run is on PATH. Run: npx -y @opengsd/gsd-core@latest --claude --local" >&2; exit 1; fi; GSD_IDENTITY_STATUS=unverified; _gsd_id_ok gsd_run && GSD_IDENTITY_STATUS=ok; export GSD_IDENTITY_STATUS; [ "$GSD_IDENTITY_STATUS" = ok ] || echo "WARNING: \"$GSD_TOOLS\" did not prove it is @opengsd/gsd-core - it is either a different package or an @opengsd/gsd-core older than the runtime-identity verb. See docs/how-to/diagnose-a-foreign-gsd-tools.md" >&2; 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
12
+ IFS= read -rd '' GSD_ARGS <<'GSD_ARGS_END' || true
13
+ $ARGUMENTS
14
+ GSD_ARGS_END
15
+ GSD_ARGS=${GSD_ARGS%$'\n'}
16
+ if [[ ! "$GSD_ARGS" =~ --auto ]] && [[ ! "$GSD_ARGS" =~ --chain ]]; then
17
+ gsd_run query config-set workflow._auto_chain_active false || true
18
+ fi
19
+ ```
20
+
21
+ Set local variables from INIT (parsed once in step 1):
22
+ - `AUTO_CHAIN` = `auto_chain_active` from INIT JSON (boolean, default false)
23
+ - `AUTO_CFG` = `auto_advance` from INIT JSON (boolean, default false)
24
+
25
+ **If `--auto` or `--chain` flag present AND `AUTO_CHAIN` is not true:** Persist chain flag to config (handles direct invocation without prior discuss-phase):
26
+ ```bash
27
+ IFS= read -rd '' GSD_ARGS <<'GSD_ARGS_END' || true
28
+ $ARGUMENTS
29
+ GSD_ARGS_END
30
+ GSD_ARGS=${GSD_ARGS%$'\n'}
31
+ if ([[ "$GSD_ARGS" =~ --auto ]] || [[ "$GSD_ARGS" =~ --chain ]]) && [[ "$AUTO_CHAIN" != "true" ]]; then
32
+ gsd_run query config-set workflow._auto_chain_active true
33
+ fi
34
+ ```
35
+
36
+ **If `--auto` or `--chain` flag present OR `AUTO_CHAIN` is true OR `AUTO_CFG` is true:**
37
+
38
+ Display banner:
39
+ ```
40
+ ### GSD ► AUTO-ADVANCING TO EXECUTE
41
+
42
+ Plans ready. Launching execute-phase...
43
+ ```
44
+
45
+ Launch execute-phase using the Skill tool to avoid nested Task sessions (which cause runtime freezes due to deep agent nesting):
46
+ ```
47
+ Skill(skill="gsd-execute-phase", args="${PHASE} --auto --no-transition ${GSD_WS}")
48
+ ```
49
+
50
+ The `--no-transition` flag tells execute-phase to return status after verification instead of chaining further. This keeps the auto-advance chain flat — each phase runs at the same nesting level rather than spawning deeper Task agents.
51
+
52
+ **Handle execute-phase return:**
53
+ - **PHASE COMPLETE** → Display final summary:
54
+ ```
55
+ ### GSD ► PHASE ${PHASE} COMPLETE ✓
56
+
57
+ Auto-advance pipeline finished.
58
+
59
+ Next: /gsd:discuss-phase ${NEXT_PHASE} --auto ${GSD_WS}
60
+ ```
61
+ - **GAPS FOUND / VERIFICATION FAILED** → Display result, stop chain:
62
+ ```
63
+ Auto-advance stopped: Execution needs review.
64
+
65
+ Review the output above and continue manually:
66
+ /gsd:execute-phase ${PHASE} ${GSD_WS}
67
+ ```
68
+
69
+ **If neither `--auto` nor config enabled:**
70
+ Route to `<offer_next>` (existing behavior).
@@ -122,8 +122,12 @@ path regardless of `CHUNKED_PARALLEL` — there is nothing to batch.
122
122
  plans are overwritten, not skipped (#2762). Unchanged from before this change, applied per entry
123
123
  before dispatch rather than immediately before each individual spawn:
124
124
  ```bash
125
+ IFS= read -rd '' GSD_ARGS <<'GSD_ARGS_END' || true
126
+ $ARGUMENTS
127
+ GSD_ARGS_END
128
+ GSD_ARGS=${GSD_ARGS%$'\n'}
125
129
  PLAN_FILE="${PHASE_DIR}/${plan_id}-PLAN.md"
126
- if [[ -f "$PLAN_FILE" ]] && head -1 "$PLAN_FILE" | grep -q '^---' && [[ "$ARGUMENTS" != *"--reviews"* ]]; then
130
+ if [[ -f "$PLAN_FILE" ]] && head -1 "$PLAN_FILE" | grep -q '^---' && [[ "$GSD_ARGS" != *"--reviews"* ]]; then
127
131
  : # resume safety — skip this plan, remove from the batch's runnable set — NOT under --reviews (replan)
128
132
  fi
129
133
  ```
@@ -5,13 +5,17 @@ The init JSON includes `phase_status` — one of `Pending | Planned | In Progres
5
5
  Parse `phase_status` from the init JSON, then:
6
6
 
7
7
  ```bash
8
+ IFS= read -rd '' GSD_ARGS <<'GSD_ARGS_END' || true
9
+ $ARGUMENTS
10
+ GSD_ARGS_END
11
+ GSD_ARGS=${GSD_ARGS%$'\n'}
8
12
  FORCE_REPLAN=false
9
- if [[ "$ARGUMENTS" =~ (^|[[:space:]])--force([[:space:]]|$) ]]; then
13
+ if [[ "$GSD_ARGS" =~ (^|[[:space:]])--force([[:space:]]|$) ]]; then
10
14
  FORCE_REPLAN=true
11
15
  fi
12
16
 
13
17
  if [ "${phase_status}" = "Complete" ]; then
14
- if [[ "$ARGUMENTS" =~ (^|[[:space:]])--reviews([[:space:]]|$) ]]; then
18
+ if [[ "$GSD_ARGS" =~ (^|[[:space:]])--reviews([[:space:]]|$) ]]; then
15
19
  # --reviews on a closed phase is never legitimate — concerns belong in a
16
20
  # new phase or issue against the closed phase's commits.
17
21
  cat <<EOF >&2