@opengsd/gsd-core 1.8.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 (174) 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 +31 -1
  4. package/agents/gsd-code-fixer.md +1 -1
  5. package/agents/gsd-codebase-mapper.md +1 -1
  6. package/agents/gsd-debug-session-manager.md +36 -0
  7. package/agents/gsd-executor.md +20 -7
  8. package/agents/gsd-intel-updater.md +3 -3
  9. package/agents/gsd-phase-researcher.md +4 -2
  10. package/agents/gsd-plan-checker.md +20 -0
  11. package/agents/gsd-planner.md +15 -23
  12. package/agents/gsd-project-researcher.md +2 -2
  13. package/agents/gsd-ui-auditor.md +0 -40
  14. package/bin/install.js +186 -55
  15. package/commands/gsd/plan-review-convergence.md +5 -1
  16. package/gsd-core/bin/gsd-tools.cjs +849 -2
  17. package/gsd-core/bin/lib/api-coverage.cjs +22 -8
  18. package/gsd-core/bin/lib/audit.cjs +8 -8
  19. package/gsd-core/bin/lib/capability-consent.cjs +40 -1
  20. package/gsd-core/bin/lib/capability-lifecycle.cjs +58 -0
  21. package/gsd-core/bin/lib/capability-loader.cjs +23 -1
  22. package/gsd-core/bin/lib/capability-registry.cjs +1353 -132
  23. package/gsd-core/bin/lib/capability-trust.cjs +468 -33
  24. package/gsd-core/bin/lib/capability-validator.cjs +882 -6
  25. package/gsd-core/bin/lib/check-command-router.cjs +12 -2
  26. package/gsd-core/bin/lib/cjs-command-router-adapter.cjs +15 -0
  27. package/gsd-core/bin/lib/claude-orchestration-command-router.cjs +102 -12
  28. package/gsd-core/bin/lib/claude-orchestration.cjs +125 -22
  29. package/gsd-core/bin/lib/commands.cjs +246 -18
  30. package/gsd-core/bin/lib/config-loader.cjs +200 -28
  31. package/gsd-core/bin/lib/config.cjs +90 -5
  32. package/gsd-core/bin/lib/estimate-cli.cjs +336 -0
  33. package/gsd-core/bin/lib/frontmatter.cjs +125 -15
  34. package/gsd-core/bin/lib/host-integration.cjs +215 -8
  35. package/gsd-core/bin/lib/init.cjs +44 -19
  36. package/gsd-core/bin/lib/install-engine.cjs +1 -0
  37. package/gsd-core/bin/lib/milestone.cjs +5 -5
  38. package/gsd-core/bin/lib/model-catalog.cjs +51 -1
  39. package/gsd-core/bin/lib/observability/logger.cjs +7 -2
  40. package/gsd-core/bin/lib/phase-command-router.cjs +10 -1
  41. package/gsd-core/bin/lib/phase-estimation.cjs +398 -0
  42. package/gsd-core/bin/lib/phase-id.cjs +278 -5
  43. package/gsd-core/bin/lib/phase.cjs +57 -5
  44. package/gsd-core/bin/lib/plan-drift-guard.cjs +1 -1
  45. package/gsd-core/bin/lib/plan-scan.cjs +1 -1
  46. package/gsd-core/bin/lib/planning-workspace.cjs +9 -2
  47. package/gsd-core/bin/lib/profile-output.cjs +34 -8
  48. package/gsd-core/bin/lib/review-lane-descriptor.cjs +927 -0
  49. package/gsd-core/bin/lib/review-lane-invocation.cjs +348 -0
  50. package/gsd-core/bin/lib/review-lane-runner.cjs +594 -0
  51. package/gsd-core/bin/lib/review-reviewer-selection.cjs +114 -32
  52. package/gsd-core/bin/lib/roadmap-parser.cjs +54 -6
  53. package/gsd-core/bin/lib/roadmap.cjs +10 -4
  54. package/gsd-core/bin/lib/runtime-artifact-conversion.cjs +31 -4
  55. package/gsd-core/bin/lib/runtime-artifact-layout.cjs +1 -1
  56. package/gsd-core/bin/lib/runtime-hooks-surface.cjs +140 -0
  57. package/gsd-core/bin/lib/runtime-name-policy.cjs +15 -2
  58. package/gsd-core/bin/lib/smart-entry.cjs +1 -1
  59. package/gsd-core/bin/lib/state-document.cjs +164 -20
  60. package/gsd-core/bin/lib/state-transition.cjs +28 -10
  61. package/gsd-core/bin/lib/state.cjs +141 -21
  62. package/gsd-core/bin/lib/uat-predicate.cjs +6 -4
  63. package/gsd-core/bin/lib/uat.cjs +9 -7
  64. package/gsd-core/bin/lib/ui-consideration-probe.cjs +2 -2
  65. package/gsd-core/bin/lib/unusable-input.cjs +216 -0
  66. package/gsd-core/bin/lib/validate.cjs +32 -0
  67. package/gsd-core/bin/lib/verification.cjs +51 -14
  68. package/gsd-core/bin/lib/verify.cjs +128 -20
  69. package/gsd-core/bin/lib/worktree-safety.cjs +360 -15
  70. package/gsd-core/bin/shared/config-defaults.manifest.json +1 -0
  71. package/gsd-core/bin/shared/config-schema.manifest.json +1 -13
  72. package/gsd-core/bin/shared/model-catalog.json +5 -0
  73. package/gsd-core/bin/shared/runtime-aliases.manifest.json +5 -0
  74. package/gsd-core/references/context-budget.md +40 -0
  75. package/gsd-core/references/gate-prompts.md +6 -3
  76. package/gsd-core/references/model-profile-resolution.md +64 -13
  77. package/gsd-core/references/offer-next.md +88 -0
  78. package/gsd-core/references/planning-config.md +2 -1
  79. package/gsd-core/references/reviewer-instances.md +28 -21
  80. package/gsd-core/references/runtime-aware-dispatch.md +42 -0
  81. package/gsd-core/references/ui-consideration-probe.md +2 -2
  82. package/gsd-core/references/worktree-branch-check.md +4 -4
  83. package/gsd-core/templates/summary-minimal.md +4 -0
  84. package/gsd-core/templates/summary-standard.md +4 -0
  85. package/gsd-core/templates/summary.md +7 -0
  86. package/gsd-core/workflows/ai-integration-phase.md +4 -4
  87. package/gsd-core/workflows/audit-fix.md +4 -0
  88. package/gsd-core/workflows/audit-milestone.md +8 -0
  89. package/gsd-core/workflows/autonomous.md +19 -15
  90. package/gsd-core/workflows/check-todos.md +2 -2
  91. package/gsd-core/workflows/code-review-fix.md +14 -6
  92. package/gsd-core/workflows/code-review.md +76 -19
  93. package/gsd-core/workflows/debug.md +10 -2
  94. package/gsd-core/workflows/diagnose-issues.md +4 -0
  95. package/gsd-core/workflows/discuss-phase/modes/advisor.md +2 -4
  96. package/gsd-core/workflows/discuss-phase/modes/auto.md +0 -6
  97. package/gsd-core/workflows/discuss-phase-assumptions.md +15 -9
  98. package/gsd-core/workflows/discuss-phase.md +2 -2
  99. package/gsd-core/workflows/docs-update.md +8 -0
  100. package/gsd-core/workflows/eval-review.md +1 -1
  101. package/gsd-core/workflows/execute-phase/steps/codebase-drift-gate.md +4 -0
  102. package/gsd-core/workflows/execute-phase/steps/executor-isolation-dispatch.md +160 -0
  103. package/gsd-core/workflows/execute-phase.md +85 -115
  104. package/gsd-core/workflows/execute-plan.md +5 -4
  105. package/gsd-core/workflows/explore.md +4 -0
  106. package/gsd-core/workflows/extract-learnings.md +21 -0
  107. package/gsd-core/workflows/help/modes/full.md +3 -3
  108. package/gsd-core/workflows/import.md +4 -1
  109. package/gsd-core/workflows/ingest-docs.md +4 -0
  110. package/gsd-core/workflows/map-codebase.md +13 -6
  111. package/gsd-core/workflows/new-milestone.md +10 -2
  112. package/gsd-core/workflows/new-project.md +11 -4
  113. package/gsd-core/workflows/next.md +5 -2
  114. package/gsd-core/workflows/plan-phase.md +42 -46
  115. package/gsd-core/workflows/plan-review-convergence.md +18 -14
  116. package/gsd-core/workflows/progress.md +1 -1
  117. package/gsd-core/workflows/quick.md +14 -3
  118. package/gsd-core/workflows/review.md +146 -575
  119. package/gsd-core/workflows/scan.md +9 -1
  120. package/gsd-core/workflows/secure-phase.md +10 -2
  121. package/gsd-core/workflows/ship.md +41 -11
  122. package/gsd-core/workflows/smart-entry.md +1 -1
  123. package/gsd-core/workflows/ui-phase.md +8 -1
  124. package/gsd-core/workflows/ui-review.md +8 -1
  125. package/gsd-core/workflows/update.md +104 -5
  126. package/gsd-core/workflows/validate-phase.md +10 -2
  127. package/gsd-core/workflows/verify-work.md +8 -1
  128. package/hooks/dist/gsd-cursor-session-start.js +6 -2
  129. package/hooks/dist/gsd-cursor-stop.js +6 -2
  130. package/hooks/dist/gsd-cursor-subagent-start.js +6 -2
  131. package/hooks/dist/gsd-graphify-update.sh +9 -0
  132. package/hooks/dist/gsd-phase-boundary.sh +14 -2
  133. package/hooks/dist/gsd-prompt-guard.js +101 -2
  134. package/hooks/dist/gsd-read-guard.js +100 -2
  135. package/hooks/dist/gsd-read-injection-scanner.js +109 -2
  136. package/hooks/dist/gsd-statusline.js +9 -6
  137. package/hooks/dist/gsd-workflow-guard.js +110 -6
  138. package/hooks/dist/gsd-worktree-path-guard.js +132 -8
  139. package/hooks/dist/lib/cursor-workspace.js +74 -0
  140. package/hooks/gsd-cursor-session-start.js +6 -2
  141. package/hooks/gsd-cursor-stop.js +6 -2
  142. package/hooks/gsd-cursor-subagent-start.js +6 -2
  143. package/hooks/gsd-graphify-update.sh +9 -0
  144. package/hooks/gsd-phase-boundary.sh +14 -2
  145. package/hooks/gsd-prompt-guard.js +101 -2
  146. package/hooks/gsd-read-guard.js +100 -2
  147. package/hooks/gsd-read-injection-scanner.js +109 -2
  148. package/hooks/gsd-statusline.js +9 -6
  149. package/hooks/gsd-workflow-guard.js +110 -6
  150. package/hooks/gsd-worktree-path-guard.js +132 -8
  151. package/hooks/lib/cursor-workspace.js +74 -0
  152. package/package.json +7 -7
  153. package/pi/gsd.cjs +26 -1
  154. package/scripts/check-coverage-gate.cjs +51 -0
  155. package/scripts/check-glossary-refs.cjs +24 -0
  156. package/scripts/ci-test-scope.cjs +67 -17
  157. package/scripts/gen-adr-index.cjs +6 -4
  158. package/scripts/gen-capability-matrix.cjs +26 -2
  159. package/scripts/gen-capability-registry.cjs +132 -34
  160. package/scripts/gen-emitted-baseline.cjs +145 -0
  161. package/scripts/lint-compiled-artifact-sync.cjs +146 -0
  162. package/scripts/lint-emitted-drift-ack.cjs +149 -0
  163. package/scripts/lint-fix-has-regression-test.cjs +131 -0
  164. package/scripts/lint-resolution-provenance.cjs +9 -0
  165. package/scripts/mutation-matrix.cjs +4 -0
  166. package/scripts/prompt-injection-scan.sh +6 -0
  167. package/scripts/registry-schema.cjs +57 -8
  168. package/scripts/release-notes/conventional-title.cjs +19 -1
  169. package/scripts/release-notes/format-github-release-notes.cjs +7 -3
  170. package/scripts/workflow-size.cjs +16 -8
  171. package/skills/gsd-plan-review-convergence/SKILL.md +5 -1
  172. package/vscode/package.json +1 -1
  173. package/scripts/gen-golden-install-parity-zcode.cjs +0 -77
  174. package/scripts/update-size-baseline.cjs +0 -68
@@ -9,7 +9,7 @@
9
9
  {
10
10
  "name": "gsd-core",
11
11
  "description": "GSD Core is a meta-prompting, context engineering, and spec-driven development system for AI coding agents.",
12
- "version": "1.8.0",
12
+ "version": "1.9.0",
13
13
  "source": "./",
14
14
  "author": {
15
15
  "name": "open-gsd",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "gsd-core",
3
3
  "displayName": "GSD Core",
4
- "version": "1.8.0",
4
+ "version": "1.9.0",
5
5
  "description": "GSD Core is a meta-prompting, context engineering, and spec-driven development system for AI coding agents.",
6
6
  "author": {
7
7
  "name": "open-gsd",
@@ -239,6 +239,32 @@ function runHook(hookFile, payload, opts = {}) {
239
239
  return { stdout, exitCode, timedOut: result.signal === "SIGTERM" };
240
240
  }
241
241
 
242
+ /**
243
+ * In-process check for whether context-usage warnings are disabled in project
244
+ * config. Mirrors the exact semantics of the same check inside
245
+ * hooks/gsd-context-monitor.js (introduced by #1073): an explicit
246
+ * `config.hooks.context_warnings === false` disables them; a missing or
247
+ * unparseable .planning/config.json keeps them enabled (the default).
248
+ *
249
+ * #2697: hoisting this check in-process lets the adapter SKIP the context-monitor
250
+ * spawn entirely when the user has opted out, instead of paying a full Node boot
251
+ * inside the child only to read the boolean and exit. Missing/unparseable config
252
+ * MUST behave identically to the hook (enabled) so the default path is unchanged.
253
+ *
254
+ * @param {string} cwd project working directory (the plugin's currentCwd)
255
+ * @returns {boolean} true when context warnings are explicitly disabled
256
+ */
257
+ function contextWarningsDisabled(cwd) {
258
+ try {
259
+ const configPath = path.join(cwd, '.planning', 'config.json');
260
+ const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
261
+ return config.hooks?.context_warnings === false;
262
+ } catch {
263
+ // Missing or unparseable config → proceed with defaults (context warnings enabled).
264
+ return false;
265
+ }
266
+ }
267
+
242
268
  // ---------------------------------------------------------------------------
243
269
  // Hook output translation → OpenCode semantics
244
270
  // ---------------------------------------------------------------------------
@@ -587,7 +613,11 @@ const GsdCorePlugin = async ({ directory } = {}) => {
587
613
 
588
614
  // gsd-context-monitor.js — context usage warnings (Bash/Edit/Write/Task/...)
589
615
  // Only meaningful when a session_id is tracked (writes metrics sentinel).
590
- if (currentSessionId) {
616
+ // #2697: skip the subprocess spawn entirely when context warnings are
617
+ // explicitly disabled in project config — the hook would exit early anyway,
618
+ // so hoisting the check in-process avoids paying a Node boot per tool call.
619
+ // Missing/unparseable config = enabled (default), so the spawn still runs.
620
+ if (currentSessionId && !contextWarningsDisabled(cwd)) {
591
621
  const payload = {
592
622
  hook_event_name: "PostToolUse",
593
623
  tool_name: claudeTool,
@@ -456,7 +456,7 @@ For each finding in sorted order:
456
456
 
457
457
  **If verification passed:**
458
458
 
459
- Use `gsd-tools query commit` with conventional format (message first, then every staged file path):
459
+ Use `gsd_run query commit` with conventional format (message first, then every staged file path):
460
460
  ```bash
461
461
  _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
462
462
  gsd_run query commit \
@@ -175,7 +175,7 @@ Write document(s) to `.planning/codebase/` using the templates below.
175
175
  **Document naming:** UPPERCASE.md (e.g., STACK.md, ARCHITECTURE.md)
176
176
 
177
177
  **Template filling:**
178
- 1. Replace `[YYYY-MM-DD]` with the date provided in your prompt (the `Today's date:` line). NEVER guess or infer the date — always use the exact date from the prompt.
178
+ 1. Set the `**Analysis Date:**` line, the `*... analysis: ...*` footer, and any `<!-- refreshed: ... -->` header to the date provided in your prompt (the `Today's date:` line), overwriting whatever date is already there. NEVER guess or infer the date — always use the exact date from the prompt.
179
179
  2. Replace `[Placeholder text]` with findings from exploration
180
180
  3. If something is not found, use "Not detected" or "Not applicable"
181
181
  4. Always include file paths with backticks
@@ -310,6 +310,41 @@ If user selects 3: proceed to Step 4 with fix = "not applied (guardrail rejected
310
310
 
311
311
  Read the resolved (or current) debug file to extract final Resolution values.
312
312
 
313
+ **Commit before returning a terminal summary (#2568).** This agent owns the terminal path —
314
+ it applies fixes, archives to `resolved/`, and returns the summary — but carried no commit
315
+ step, so `commit_docs` was never consulted on the normal `/gsd:debug` flow and session docs
316
+ were left untracked. Do this for **both** terminal shapes below, and **NOT** for
317
+ `CONTINUE_REQUIRED` above: that shape is non-terminal, and committing there would strand a
318
+ half-finished session looking done, exactly as fabricating a terminal summary would.
319
+ `CHECKPOINT REACHED` (Step 3d) likewise does not commit — it pauses for user input and loops
320
+ back to Step 3.
321
+
322
+ 1. **In-session fix code.** If a fix was applied during this session and its code changes are
323
+ still uncommitted, commit them first. Stage **specific files only** — the files the fix
324
+ touched. Do this rather than `git add -A`, which would sweep unrelated working-tree
325
+ changes into a debug commit. Guard on staged content: `gsd-debugger.md`'s
326
+ `archive_session` step may already have committed this fix on the confirmed-checkpoint
327
+ path, and a bare `git commit` with nothing staged exits non-zero and would abort this
328
+ step before the summary is returned:
329
+ ```bash
330
+ git add <files the fix touched>
331
+ git diff --cached --quiet || git commit -m "fix: {brief description}"
332
+ ```
333
+ 2. **Session doc.** Commit via the CLI, which already gates on `commit_docs` and returns
334
+ `skipped_commit_docs_false` when disabled — call it unconditionally rather than
335
+ re-checking the config here, so the policy lives in one place. `query commit` treats an
336
+ empty diff as `nothing_to_commit` and exits 0, so a second call after
337
+ `archive_session` already committed the doc is a safe no-op. The canonical `gsd_run` preamble is
338
+ established once in Step 2 and is the single definition this agent carries (repo
339
+ invariant: exactly one preamble per agent file, before its first call):
340
+ ```bash
341
+ # resolved session — path spelled literally; this agent receives `slug` and
342
+ # `debug_file_path`, NOT a `debug_dir` variable (see <session_parameters>).
343
+ gsd_run query commit "docs(debug): resolve {slug} session" --files .planning/debug/resolved/{slug}.md
344
+ # abandoned session (checkpoint retained for `/gsd:debug continue {slug}`)
345
+ gsd_run query commit "docs(debug): checkpoint {slug} session" --files {debug_file_path}
346
+ ```
347
+
313
348
  Return compact summary (terminal — investigation resolved):
314
349
 
315
350
  ```markdown
@@ -349,5 +384,6 @@ If the session was abandoned by user choice, return (terminal — user stopped):
349
384
  - [ ] TDD gate applied when tdd_mode=true and ROOT CAUSE FOUND
350
385
  - [ ] Loop continues until DEBUG COMPLETE, ABANDONED, or user stops
351
386
  - [ ] Non-terminal `CONTINUE_REQUIRED` (not a fabricated terminal summary) returned when the manager's own turn/context budget is exhausted mid-investigation
387
+ - [ ] Session doc (and any uncommitted fix code from this session) committed before a terminal summary, respecting `commit_docs` — and NOT committed on the non-terminal `CONTINUE_REQUIRED` path
352
388
  - [ ] Compact summary returned (at most 2K tokens)
353
389
  </success_criteria>
@@ -495,11 +495,11 @@ if [ -f .git ]; then # worktree
495
495
  echo "DO NOT use 'git update-ref' to rewind the protected branch — surface as blocker (#2924)." >&2
496
496
  exit 1
497
497
  fi
498
- # Positive allow-list: HEAD must be on the canonical Claude Code worktree-agent
499
- # branch namespace (`worktree-agent-<id>`). This catches feature/* and any other
500
- # arbitrary branch that the deny-list would silently allow (#2924).
501
- if ! echo "$ACTUAL_BRANCH" | grep -Eq '^worktree-agent-[A-Za-z0-9._/-]+$'; then
502
- echo "FATAL: refusing to commit — worktree HEAD '$ACTUAL_BRANCH' is not in the worktree-agent-* namespace." >&2
498
+ # Positive allow-list: HEAD must be on a per-agent branch (`agent-<id>` or
499
+ # legacy `worktree-agent-<id>`). This catches feature/* and any other
500
+ # arbitrary branch that the deny-list would silently allow (#2924, #1995).
501
+ if ! echo "$ACTUAL_BRANCH" | grep -Eq '^(worktree-)?agent-[A-Za-z0-9._/-]+$'; then
502
+ echo "FATAL: refusing to commit — worktree HEAD '$ACTUAL_BRANCH' is not in the agent-* / worktree-agent-* namespace." >&2
503
503
  echo "Agent commits must live on per-agent branches; surface as blocker (#2924)." >&2
504
504
  exit 1
505
505
  fi
@@ -638,7 +638,16 @@ This file is the canonical output of this step. The orchestrator reads `.plannin
638
638
 
639
639
  **Use template:** @~/.claude/gsd-core/templates/summary.md
640
640
 
641
- **Frontmatter:** phase, plan, subsystem, tags, dependency graph (requires/provides/affects), tech-stack (added/patterns), key-files (created/modified), decisions, metrics (duration, completed date), status (`status: complete` — required so the audit-open scanner recognises the summary as done).
641
+ **Frontmatter:** phase, plan, subsystem, tags, dependency graph (requires/provides/affects), tech-stack (added/patterns), key-files (created/modified), decisions, metrics (duration, completed date), status (`status: complete` — required so the audit-open scanner recognises the summary as done), and `actuals` (#2632).
642
+
643
+ **`actuals` (required when the plan carried an `estimate`):** record what the phase ACTUALLY cost, on the SAME scale the estimate used — `estimateTokens` (chars/4) over the realized diff, NOT a harness token count. Mixing scales measures the measurement methods, not the miss.
644
+ ```yaml
645
+ actuals:
646
+ tokens: 74000 # chars/4 over the files you actually changed
647
+ tasks: 5 # tasks completed
648
+ commits: 7 # commits made
649
+ ```
650
+ These pair with the plan's `estimate` to calibrate future estimates (ADR-2629). Do not round to look closer to the estimate — a flattering number corrupts every later projection.
642
651
 
643
652
  **Title:** `# Phase [X] Plan [Y]: [Name] Summary`
644
653
 
@@ -780,7 +789,7 @@ gsd_run query commit "docs({phase}-{plan}): complete [plan-name] plan" --files \
780
789
  Separate from per-task commits — captures execution results only.
781
790
 
782
791
  **Handling the SDK return envelope (#3678):** `gsd-tools query commit` returns
783
- one of three shapes:
792
+ one of these shapes:
784
793
 
785
794
  - `{committed: true, hash, reason: 'committed'}` — commit succeeded; record
786
795
  the hash in the completion format.
@@ -793,6 +802,10 @@ one of three shapes:
793
802
  success path.** Record "skipped (.planning gitignored)" and move on.
794
803
  - `{committed: false, reason: 'nothing_to_commit' | 'commit_failed', ...}` —
795
804
  no-op / genuine failure; surface in the completion notes.
805
+ - `{committed: false, reason: 'staging_failed' | 'staging_timeout', file, error}` —
806
+ `git add` itself failed (#2608), e.g. an unwritable index. Nothing committed,
807
+ index rolled back. Surface `file` + `error` (git's stderr); do not retry — a
808
+ retry hits the same cause.
796
809
 
797
810
  **Do not fall back to raw `git add` / `git commit` / `git add -f`** when the
798
811
  SDK returns `skipped: true`. The SDK's skip is the user's deliberate choice
@@ -123,7 +123,7 @@ All JSON files include a `_meta` object with `updated_at` (ISO timestamp) and `v
123
123
  }
124
124
  ```
125
125
 
126
- **exports constraint:** Array of ACTUAL exported symbol names extracted from `module.exports` or `export` statements. MUST be real identifiers (e.g., `"configLoad"`, `"stateUpdate"`), NOT descriptions (e.g., `"config operations"`). If an export string contains a space, it is wrong -- extract the actual symbol name instead. Use `gsd-tools intel extract-exports <file>` to get accurate exports.
126
+ **exports constraint:** Array of ACTUAL exported symbol names extracted from `module.exports` or `export` statements. MUST be real identifiers (e.g., `"configLoad"`, `"stateUpdate"`), NOT descriptions (e.g., `"config operations"`). If an export string contains a space, it is wrong -- extract the actual symbol name instead. Use `gsd_run intel extract-exports <file>` to get accurate exports.
127
127
 
128
128
  Types: `entry-point`, `module`, `config`, `test`, `script`, `type-def`, `style`, `template`, `data`.
129
129
 
@@ -255,7 +255,7 @@ gsd_run intel patch-meta .planning/intel/arch-decisions.json
255
255
 
256
256
  ### Step 6.5: Self-Check
257
257
 
258
- Run: `gsd-tools intel validate`
258
+ Run: `gsd_run intel validate`
259
259
 
260
260
  Review the output:
261
261
 
@@ -267,7 +267,7 @@ This step is MANDATORY -- do not skip it.
267
267
 
268
268
  ### Step 7: Snapshot
269
269
 
270
- Run: `gsd-tools intel snapshot`
270
+ Run: `gsd_run intel snapshot`
271
271
 
272
272
  This writes `.last-refresh.json` with accurate timestamps and hashes. Do NOT write `.last-refresh.json` manually.
273
273
  </execution_flow>
@@ -32,6 +32,8 @@ Spawned by `/gsd:plan-phase` (integrated) or `/gsd:plan-phase --research-phase <
32
32
 
33
33
  **Package name provenance rule:** A package name discovered via WebSearch, training data, or any non-authoritative source must be tagged `[ASSUMED]` regardless of whether `npm view` confirms it exists on the registry. Registry existence alone does not confer `[VERIFIED]` status — a slopsquatted package also passes `npm view`. Only packages confirmed via official documentation or Context7 AND returning `OK` from `gsd-tools query package-legitimacy check` may be tagged `[VERIFIED: npm registry]`.
34
34
 
35
+ **In-repo value provenance rule:** A claim about an in-repo *discrete value* — an enum, a schema or type union, an error code, a status constant, or a filesystem path — may be tagged `[VERIFIED: …]` only if you opened the source-of-truth file with `Read` **this session**. A codebase `grep` is not sufficient on its own: it confirms a string occurs, not that you read the definition. Cite the path **and line range** (`[VERIFIED: src/types/order.ts:14-22]`), and quote the values **verbatim** in RESEARCH.md beside the claim — paraphrase is forbidden. The quote is what makes the tag checkable — a citation with no quote beside it does not earn `[VERIFIED]`, however precise the line range looks. Every value appearing in a code example or skeleton must also appear in that verbatim quote; a value that does not is `[ASSUMED]`. For a filesystem path, cite the line in the script that creates it, not the location you expect it to occupy. Training memory and a web search are not substitutes for reading the file — a discrete value that merely looks right fails at the executor's `parse()`/typecheck, the most expensive place to discover it.
36
+
35
37
  Claims tagged `[ASSUMED]` signal to the planner and discuss-phase that the information needs user confirmation before becoming a locked decision. Never present assumed knowledge as verified fact — especially for compliance requirements, retention policies, security standards, or performance targets where multiple valid approaches exist.
36
38
  </role>
37
39
 
@@ -136,7 +138,7 @@ For each item where `fetch` is present, invoke the MCP tool matching `fetch.prov
136
138
  | `exa` | `mcp__exa__web_search_exa` with `fetch.query` |
137
139
  | `tavily` | `mcp__tavily__search` with `fetch.query` |
138
140
  | `perplexity` | `mcp__perplexity__*` (use the appropriate perplexity MCP tool for the query) |
139
- | `brave` | `gsd-tools query websearch "<fetch.query>"` (Brave-backed) or built-in `WebSearch` |
141
+ | `brave` | `gsd_run query websearch "<fetch.query>"` (Brave-backed) or built-in `WebSearch` |
140
142
  | `firecrawl` | `mcp__firecrawl__scrape` with url (scrape kind) or `mcp__firecrawl__search` |
141
143
  | `websearch` | built-in `WebSearch` tool |
142
144
  | `webfetch` | built-in `WebFetch` tool |
@@ -707,7 +709,7 @@ docker info 2>/dev/null | head -3
707
709
 
708
710
  ## Step 3: Execute Research Protocol
709
711
 
710
- For each domain, use the `<tool_strategy>` seam (Steps A–D): build questions JSON, call `gsd-tools query research-plan`, run the indicated provider per item, then cache each digest. Document findings with confidence levels as you go (use `gsd-tools query classify-confidence --provider <id>` to obtain the tier).
712
+ For each domain, use the `<tool_strategy>` seam (Steps A–D): build questions JSON, call `gsd_run query research-plan`, run the indicated provider per item, then cache each digest. Document findings with confidence levels as you go (use `gsd_run query classify-confidence --provider <id>` to obtain the tier).
711
713
 
712
714
  ## Step 4: Validation Architecture Research (if nyquist_validation enabled)
713
715
 
@@ -252,6 +252,19 @@ issue:
252
252
  1. Count tasks per plan
253
253
  2. Estimate files modified per plan
254
254
  3. Check against thresholds
255
+ 4. **Smart-zone estimate check (#2631, ADR-2629).** For each plan carrying an `estimate` block, run the
256
+ `estimate-check --calibrated` verb against its `estimate.tokens` (the `--calibrated` flag is required —
257
+ the plan's figure already has the factor applied, and omitting it would square the correction) (invoked in Step 1 below, after the launcher
258
+ preamble). The verb reads `workflow.smart_zone_tokens` and applies the project's calibration. Report
259
+ one line per plan: plan id, estimated tokens, the budget, and — when `over_budget` is true — the
260
+ returned `recommendation`, which names how many slices the phase should become.
261
+
262
+ **Over budget is a WARNING, never a blocker** (ADR-2629 Decision 5). Recommend re-slicing into a tracer
263
+ plus expansion slices; never fail the check on it. Report `estimate.confidence` alongside: `low` means
264
+ fewer than 3 completed phases carry actuals, so the figure is not yet calibrated for this project — say
265
+ so rather than presenting it as precise, and weigh the task/file thresholds above more heavily.
266
+
267
+ A plan with no `estimate` block is not a defect; the field is optional and additive.
255
268
 
256
269
  **Thresholds:**
257
270
  | Metric | Target | Warning | Blocker |
@@ -706,6 +719,13 @@ gsd_run query phase.list-plans "$phase_number"
706
719
  gsd_run query phase.list-artifacts "$phase_number" --type research
707
720
  gsd_run query roadmap.get-phase "$phase_number"
708
721
  gsd_run query phase.list-artifacts "$phase_number" --type summary
722
+
723
+ # Smart-zone estimate check (#2631) — advisory, never fails the check.
724
+ for plan in "${phase_dir:-$PHASE_DIR}"/*-PLAN.md; do
725
+ [ -f "$plan" ] || continue # unmatched glob leaves the literal pattern — skip it
726
+ EST=$(sed -n '/^estimate:/,/^[a-z_]*:/p' "$plan" | grep -o 'tokens: *[0-9]*' | head -1 | grep -o '[0-9]*')
727
+ [ -n "$EST" ] && gsd_run query estimate-check --tokens "$EST" --calibrated 2>/dev/null || true
728
+ done
709
729
  ```
710
730
 
711
731
  **Extract:** Phase goal, requirements (decompose goal), locked decisions, deferred ideas.
@@ -288,30 +288,15 @@ See @~/.claude/gsd-core/references/planner-guidance.md for dependency graph buil
288
288
 
289
289
  <scope_estimation>
290
290
 
291
- ## Context Budget Rules
291
+ ## Sizing and the Estimate Block
292
292
 
293
- Plans should complete within ~50% context (not 80%). No context anxiety, quality maintained start to finish, room for unexpected complexity.
293
+ Full rules: @~/.claude/gsd-core/references/context-budget.md (Phase Sizing). Read before sizing.
294
294
 
295
- **Each plan: 2-3 tasks maximum.**
296
-
297
- | Context Weight | Tasks/Plan | Context/Task | Total |
298
- |----------------|------------|--------------|-------|
299
- | Light (CRUD, config) | 3 | ~10-15% | ~30-45% |
300
- | Medium (auth, payments) | 2 | ~20-30% | ~40-50% |
301
- | Heavy (migrations, multi-subsystem) | 1-2 | ~30-40% | ~30-50% |
302
-
303
- ## Split Signals
304
-
305
- **ALWAYS split if:**
306
- - More than 3 tasks
307
- - Multiple subsystems (DB + API + UI = separate plans)
308
- - Any task with >5 file modifications
309
- - Checkpoint + implementation in same plan
310
- - Discovery + implementation in same plan
311
-
312
- **CONSIDER splitting:** >5 files total, natural semantic boundaries, context cost estimate exceeds 40% for a single plan. See `<planner_authority_limits>` for prohibited split reasons.
313
-
314
- See @~/.claude/gsd-core/references/planner-guidance.md for Granularity Calibration table (Coarse/Standard/Fine plans-per-phase).
295
+ - **2-3 tasks per plan.** **ALWAYS split if:** >3 tasks, multiple subsystems, or any task touching >5 files.
296
+ - **Emit `estimate`**: run `estimate-calibration`; `tokens` = raw projection x factor, `raw_tokens` = that
297
+ projection before the factor (calibration measures actual/raw), `confidence` verbatim — derived from
298
+ sample count, never self-rated.
299
+ - **Over the smart-zone budget?** Re-slice: tracer + expansion slices. Advisory, never a block.
315
300
 
316
301
  </scope_estimation>
317
302
 
@@ -331,6 +316,12 @@ autonomous: true # false if plan has checkpoints
331
316
  requirements: [] # REQUIRED — Requirement IDs from ROADMAP this plan addresses. MUST NOT be empty.
332
317
  user_setup: [] # Human-required setup (omit if empty)
333
318
 
319
+ estimate: # Projected execution cost (see Estimate Emission)
320
+ tokens: 60000 # calibrated projection
321
+ raw_tokens: 30000 # pre-factor projection
322
+ tasks: 3 # task count the projection assumes
323
+ confidence: low # low | med | high — DERIVED from sample count, never self-rated
324
+
334
325
  must_haves:
335
326
  truths: [] # Observable behaviors
336
327
  artifacts: [] # Files that must exist
@@ -412,6 +403,7 @@ Create `.planning/phases/XX-name/{padded_phase}-{plan}-SUMMARY.md` when done
412
403
  | `autonomous` | Yes | `true` if no checkpoints |
413
404
  | `requirements` | Yes | **MUST** list requirement IDs from ROADMAP. Every roadmap requirement ID MUST appear in at least one plan. |
414
405
  | `user_setup` | No | Human-required setup items |
406
+ | `estimate` | No | Projected cost `{tokens, tasks, confidence}`. See Estimate Emission. |
415
407
  | `must_haves` | Yes | Goal-backward verification criteria |
416
408
 
417
409
  Wave numbers are pre-computed during planning. Execute-phase reads `wave` directly from frontmatter.
@@ -734,7 +726,7 @@ Read the most recent milestone retrospective and cross-milestone trends. Extract
734
726
  </step>
735
727
 
736
728
  <step name="inject_global_learnings">
737
- If `features.global_learnings` is `true`: run `gsd-tools query learnings.query --tag <tag> --limit 5` once per tag from PLAN.md frontmatter `tags` (or use the single most specific keyword). The handler matches one `--tag` at a time. Prefix matches with `[Prior learning from <project>]` as weak priors. Project-local decisions take precedence. Skip silently if disabled or no matches.
729
+ If `features.global_learnings` is `true`: run `gsd_run query learnings.query --tag <tag> --limit 5` once per tag from PLAN.md frontmatter `tags` (or use the single most specific keyword). The handler matches one `--tag` at a time. Prefix matches with `[Prior learning from <project>]` as weak priors. Project-local decisions take precedence. Skip silently if disabled or no matches.
738
730
  </step>
739
731
 
740
732
  <step name="gather_phase_context">
@@ -102,7 +102,7 @@ For each item where `fetch` is present, invoke the MCP tool matching `fetch.prov
102
102
  | `exa` | `mcp__exa__web_search_exa` with `fetch.query` |
103
103
  | `tavily` | `mcp__tavily__search` with `fetch.query` |
104
104
  | `perplexity` | `mcp__perplexity__*` (use the appropriate perplexity MCP tool for the query) |
105
- | `brave` | `gsd-tools query websearch "<fetch.query>"` (Brave-backed) or built-in `WebSearch` |
105
+ | `brave` | `gsd_run query websearch "<fetch.query>"` (Brave-backed) or built-in `WebSearch` |
106
106
  | `firecrawl` | `mcp__firecrawl__scrape` with url (scrape kind) or `mcp__firecrawl__search` |
107
107
  | `websearch` | built-in `WebSearch` tool |
108
108
  | `webfetch` | built-in `WebFetch` tool |
@@ -490,7 +490,7 @@ Orchestrator provides: project name/description, research mode, project context,
490
490
 
491
491
  ## Step 3: Execute Research
492
492
 
493
- For each domain, use the `<tool_strategy>` seam (Steps A–D): build questions JSON, call `gsd-tools query research-plan`, run the indicated provider per item, then cache each digest. Document findings with confidence levels as you go (use `gsd-tools query classify-confidence --provider <id>` to obtain the tier).
493
+ For each domain, use the `<tool_strategy>` seam (Steps A–D): build questions JSON, call `gsd_run query research-plan`, run the indicated provider per item, then cache each digest. Document findings with confidence levels as you go (use `gsd_run query classify-confidence --provider <id>` to obtain the tier).
494
494
 
495
495
  ## Step 4: Quality Check
496
496
 
@@ -104,46 +104,6 @@ This gate runs unconditionally on every audit. The .gitignore ensures screenshot
104
104
 
105
105
  </gitignore_gate>
106
106
 
107
- <playwright_mcp_approach>
108
-
109
- ## Automated Screenshot Capture via Playwright-MCP (preferred when available)
110
-
111
- Before attempting the CLI screenshot approach, check whether `mcp__playwright__*`
112
- tools are available in this session. If they are, use them instead of the CLI approach:
113
-
114
- ```
115
- # Preferred: Playwright-MCP automated verification
116
- # 1. Navigate to the component URL
117
- mcp__playwright__navigate(url="http://localhost:3000")
118
-
119
- # 2. Take desktop screenshot
120
- mcp__playwright__screenshot(name="desktop", width=1440, height=900)
121
-
122
- # 3. Take mobile screenshot
123
- mcp__playwright__screenshot(name="mobile", width=375, height=812)
124
-
125
- # 4. For specific components listed in UI-SPEC.md, navigate to each
126
- # component route and capture targeted screenshots for comparison
127
- # against the spec's stated dimensions, colors, and layout.
128
-
129
- # 5. Compare screenshots against UI-SPEC.md requirements:
130
- # - Dimensions: Is component X width 70vw as specified?
131
- # - Color: Is the accent color applied only on declared elements?
132
- # - Layout: Are spacing values within the declared spacing scale?
133
- # Report any visual discrepancies as automated findings.
134
- ```
135
-
136
- **When Playwright-MCP is available:**
137
- - Use it for all screenshot capture (skip the CLI approach below)
138
- - Each UI checkpoint from UI-SPEC.md can be verified automatically
139
- - Discrepancies are reported as pillar findings with screenshot evidence
140
- - Items requiring subjective judgment are flagged as `needs_human_review: true`
141
-
142
- **When Playwright-MCP is NOT available:** fall back to the CLI screenshot approach
143
- below. Behavior is unchanged from the standard code-only audit path.
144
-
145
- </playwright_mcp_approach>
146
-
147
107
  <screenshot_approach>
148
108
 
149
109
  ## Screenshot Capture (CLI only — no MCP, no persistent browser)