@opengsd/gsd-core 1.13.0 → 1.15.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 (441) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/README.ja-JP.md +3 -3
  4. package/README.ko-KR.md +3 -3
  5. package/README.pt-BR.md +3 -3
  6. package/README.zh-CN.md +3 -3
  7. package/agents/gsd-advisor-researcher.compact.md +85 -0
  8. package/agents/gsd-ai-researcher.compact.md +96 -0
  9. package/agents/gsd-assumptions-analyzer.compact.md +81 -0
  10. package/agents/gsd-code-fixer.compact.md +459 -0
  11. package/agents/gsd-code-fixer.md +9 -8
  12. package/agents/gsd-code-reviewer.compact.md +269 -0
  13. package/agents/gsd-code-reviewer.md +15 -3
  14. package/agents/gsd-codebase-mapper.compact.md +760 -0
  15. package/agents/gsd-debug-session-manager.compact.md +360 -0
  16. package/agents/gsd-debug-session-manager.md +17 -2
  17. package/agents/gsd-debugger.md +2 -2
  18. package/agents/gsd-doc-classifier.compact.md +192 -0
  19. package/agents/gsd-doc-synthesizer.compact.md +200 -0
  20. package/agents/gsd-doc-verifier.compact.md +143 -0
  21. package/agents/gsd-doc-writer.compact.md +440 -0
  22. package/agents/gsd-dom-verifier.compact.md +138 -0
  23. package/agents/gsd-domain-researcher.compact.md +141 -0
  24. package/agents/gsd-eval-auditor.compact.md +160 -0
  25. package/agents/gsd-eval-auditor.md +1 -1
  26. package/agents/gsd-eval-planner.compact.md +137 -0
  27. package/agents/gsd-executor.md +13 -8
  28. package/agents/gsd-framework-selector.compact.md +82 -0
  29. package/agents/gsd-integration-checker.compact.md +245 -0
  30. package/agents/gsd-intel-updater.compact.md +226 -0
  31. package/agents/gsd-intel-updater.md +1 -1
  32. package/agents/gsd-mempalace-curator.compact.md +45 -0
  33. package/agents/gsd-nyquist-auditor.compact.md +179 -0
  34. package/agents/gsd-pattern-mapper.compact.md +275 -0
  35. package/agents/gsd-phase-researcher.md +19 -11
  36. package/agents/gsd-plan-checker.md +8 -7
  37. package/agents/gsd-planner.md +12 -8
  38. package/agents/gsd-project-researcher.compact.md +587 -0
  39. package/agents/gsd-project-researcher.md +1 -1
  40. package/agents/gsd-research-synthesizer.compact.md +212 -0
  41. package/agents/gsd-research-synthesizer.md +1 -1
  42. package/agents/gsd-roadmapper.compact.md +454 -0
  43. package/agents/gsd-roadmapper.md +13 -0
  44. package/agents/gsd-security-auditor.compact.md +162 -0
  45. package/agents/gsd-ui-auditor.compact.md +404 -0
  46. package/agents/gsd-ui-auditor.md +155 -17
  47. package/agents/gsd-ui-checker.compact.md +277 -0
  48. package/agents/gsd-ui-researcher.compact.md +282 -0
  49. package/agents/gsd-ui-researcher.md +1 -1
  50. package/agents/gsd-user-profiler.compact.md +108 -0
  51. package/agents/gsd-verifier.md +10 -9
  52. package/bin/install.js +848 -163
  53. package/commands/gsd/autonomous.md +2 -2
  54. package/commands/gsd/capture.md +1 -1
  55. package/commands/gsd/cleanup.md +1 -0
  56. package/commands/gsd/code-review.md +2 -1
  57. package/commands/gsd/complete-milestone.md +1 -0
  58. package/commands/gsd/config.md +1 -0
  59. package/commands/gsd/debug.md +1 -0
  60. package/commands/gsd/graphify.md +1 -0
  61. package/commands/gsd/health.md +1 -0
  62. package/commands/gsd/mempalace-capture.md +8 -3
  63. package/commands/gsd/mempalace-recall.md +1 -0
  64. package/commands/gsd/new-milestone.md +1 -0
  65. package/commands/gsd/new-project.md +1 -0
  66. package/commands/gsd/next.md +1 -0
  67. package/commands/gsd/pause-work.md +1 -0
  68. package/commands/gsd/phase.md +1 -0
  69. package/commands/gsd/plan-review-convergence.md +6 -6
  70. package/commands/gsd/pr-branch.md +1 -0
  71. package/commands/gsd/progress.md +1 -1
  72. package/commands/gsd/quick-batch.md +1 -1
  73. package/commands/gsd/resume-work.md +1 -0
  74. package/commands/gsd/review-backlog.md +1 -0
  75. package/commands/gsd/review.md +2 -3
  76. package/commands/gsd/settings.md +2 -1
  77. package/commands/gsd/stats.md +1 -0
  78. package/commands/gsd/thread.md +1 -0
  79. package/commands/gsd/workspace.md +1 -0
  80. package/commands/gsd/workstreams.md +1 -0
  81. package/gsd-core/bin/check-latest-version.cjs +8 -3
  82. package/gsd-core/bin/gsd-tools.cjs +672 -146
  83. package/gsd-core/bin/lib/adr-parser.cjs +4 -2
  84. package/gsd-core/bin/lib/artifacts.cjs +2 -1
  85. package/gsd-core/bin/lib/audit.cjs +119 -34
  86. package/gsd-core/bin/lib/broken-windows.cjs +168 -49
  87. package/gsd-core/bin/lib/capability-lifecycle.cjs +10 -6
  88. package/gsd-core/bin/lib/capability-loader.cjs +135 -1
  89. package/gsd-core/bin/lib/capability-registry.cjs +96 -189
  90. package/gsd-core/bin/lib/capability-source.cjs +19 -2
  91. package/gsd-core/bin/lib/capability-validator.cjs +14 -2
  92. package/gsd-core/bin/lib/check-command-router.cjs +213 -49
  93. package/gsd-core/bin/lib/code-review-depth.cjs +2 -2
  94. package/gsd-core/bin/lib/codex-agent-toml.cjs +21 -25
  95. package/gsd-core/bin/lib/commands.cjs +823 -112
  96. package/gsd-core/bin/lib/config-loader.cjs +66 -4
  97. package/gsd-core/bin/lib/config.cjs +186 -45
  98. package/gsd-core/bin/lib/coverage.cjs +1 -1
  99. package/gsd-core/bin/lib/decisions.cjs +164 -45
  100. package/gsd-core/bin/lib/external-descriptor-trust.cjs +29 -14
  101. package/gsd-core/bin/lib/frontmatter.cjs +13 -0
  102. package/gsd-core/bin/lib/graphify.cjs +10 -2
  103. package/gsd-core/bin/lib/gsd2-import.cjs +1 -2
  104. package/gsd-core/bin/lib/health-diagnostic-rules/state-consistency.cjs +12 -1
  105. package/gsd-core/bin/lib/health-diagnostic-rules/worktree-health.cjs +1 -1
  106. package/gsd-core/bin/lib/host-runtime-detection.cjs +9 -0
  107. package/gsd-core/bin/lib/init.cjs +614 -86
  108. package/gsd-core/bin/lib/install-engine.cjs +29 -3
  109. package/gsd-core/bin/lib/install-profiles.cjs +14 -0
  110. package/gsd-core/bin/lib/installer-migrations.cjs +41 -5
  111. package/gsd-core/bin/lib/loop-resolver.cjs +50 -31
  112. package/gsd-core/bin/lib/mcp-catalog.cjs +2 -2
  113. package/gsd-core/bin/lib/milestone.cjs +37 -13
  114. package/gsd-core/bin/lib/model-resolver.cjs +253 -53
  115. package/gsd-core/bin/lib/phase-command-router.cjs +16 -2
  116. package/gsd-core/bin/lib/phase-id-card.cjs +32 -0
  117. package/gsd-core/bin/lib/phase-id-display.cjs +78 -0
  118. package/gsd-core/bin/lib/phase-id.cjs +268 -27
  119. package/gsd-core/bin/lib/phase-lifecycle.cjs +61 -0
  120. package/gsd-core/bin/lib/phase-locator.cjs +29 -10
  121. package/gsd-core/bin/lib/phase.cjs +393 -88
  122. package/gsd-core/bin/lib/plan-document.cjs +49 -1
  123. package/gsd-core/bin/lib/planning-document.cjs +459 -0
  124. package/gsd-core/bin/lib/planning-inspect.cjs +52 -19
  125. package/gsd-core/bin/lib/planning-snapshot.cjs +61 -12
  126. package/gsd-core/bin/lib/planning-workspace.cjs +57 -3
  127. package/gsd-core/bin/lib/pr-branch-patterns.cjs +57 -0
  128. package/gsd-core/bin/lib/pristine-baseline.cjs +182 -0
  129. package/gsd-core/bin/lib/probe-core.cjs +7 -1
  130. package/gsd-core/bin/lib/prohibition-enforcement.cjs +91 -4
  131. package/gsd-core/bin/lib/project-root.cjs +41 -2
  132. package/gsd-core/bin/lib/quick-batch.cjs +1 -1
  133. package/gsd-core/bin/lib/refactor-trigger-command-router.cjs +61 -2
  134. package/gsd-core/bin/lib/research-store.cjs +11 -12
  135. package/gsd-core/bin/lib/review-lane-descriptor.cjs +10 -30
  136. package/gsd-core/bin/lib/review-lane-invocation.cjs +23 -0
  137. package/gsd-core/bin/lib/review-reviewer-selection.cjs +2 -2
  138. package/gsd-core/bin/lib/reviewer-step-dispatch.cjs +337 -0
  139. package/gsd-core/bin/lib/roadmap-command-router.cjs +12 -4
  140. package/gsd-core/bin/lib/roadmap-parser.cjs +219 -18
  141. package/gsd-core/bin/lib/roadmap-upgrade.cjs +1539 -13
  142. package/gsd-core/bin/lib/roadmap.cjs +356 -42
  143. package/gsd-core/bin/lib/runtime-artifact-conversion.cjs +310 -41
  144. package/gsd-core/bin/lib/runtime-artifact-install-plan.cjs +15 -4
  145. package/gsd-core/bin/lib/runtime-artifact-layout.cjs +13 -5
  146. package/gsd-core/bin/lib/runtime-homes.cjs +4 -0
  147. package/gsd-core/bin/lib/runtime-hooks-surface.cjs +408 -37
  148. package/gsd-core/bin/lib/runtime-name-policy.cjs +111 -1
  149. package/gsd-core/bin/lib/security.cjs +126 -7
  150. package/gsd-core/bin/lib/shell-command-projection.cjs +10 -6
  151. package/gsd-core/bin/lib/state-document.cjs +130 -28
  152. package/gsd-core/bin/lib/state-md-schema.cjs +21 -14
  153. package/gsd-core/bin/lib/state-transition.cjs +181 -30
  154. package/gsd-core/bin/lib/state.cjs +265 -27
  155. package/gsd-core/bin/lib/surface.cjs +77 -3
  156. package/gsd-core/bin/lib/task-command-router.cjs +12 -6
  157. package/gsd-core/bin/lib/tdd-red-evidence.cjs +78 -5
  158. package/gsd-core/bin/lib/uat-predicate.cjs +47 -4
  159. package/gsd-core/bin/lib/uat.cjs +9 -1
  160. package/gsd-core/bin/lib/ui-consideration-probe.cjs +15 -2
  161. package/gsd-core/bin/lib/ui-frontend-evidence.cjs +100 -9
  162. package/gsd-core/bin/lib/undo-commit-selection.cjs +131 -0
  163. package/gsd-core/bin/lib/update-context.cjs +30 -24
  164. package/gsd-core/bin/lib/vendor/js-yaml.cjs +11 -3
  165. package/gsd-core/bin/lib/verification.cjs +315 -30
  166. package/gsd-core/bin/lib/verify-command-grounding.cjs +47 -3
  167. package/gsd-core/bin/lib/verify.cjs +320 -48
  168. package/gsd-core/bin/lib/workstream-inventory.cjs +1 -0
  169. package/gsd-core/bin/lib/worktree-base-ref.cjs +482 -73
  170. package/gsd-core/bin/lib/worktree-safety.cjs +797 -58
  171. package/gsd-core/bin/shared/config-defaults.manifest.json +4 -0
  172. package/gsd-core/bin/shared/config-schema.manifest.json +6 -0
  173. package/gsd-core/bin/verify-reapply-patches.cjs +439 -80
  174. package/gsd-core/references/checkpoints.md +5 -3
  175. package/gsd-core/references/compact-content-gate.md +66 -0
  176. package/gsd-core/references/edge-probe-fixtures/01-round-half-even/expected-coverage.json +28 -3
  177. package/gsd-core/references/edge-probe-fixtures/02-merge-intervals/expected-coverage.json +37 -4
  178. package/gsd-core/references/edge-probe-fixtures/03-truncate-graphemes/expected-coverage.json +28 -3
  179. package/gsd-core/references/edge-probe-fixtures/04-money-rounding/expected-coverage.json +28 -3
  180. package/gsd-core/references/edge-probe-fixtures/05-list-dedupe/expected-coverage.json +37 -4
  181. package/gsd-core/references/edge-probe-fixtures/06-resolved-mixed/expected-coverage.json +37 -4
  182. package/gsd-core/references/edge-probe.md +195 -21
  183. package/gsd-core/references/execute-phase-between-wave-reset.md +7 -6
  184. package/gsd-core/references/execute-phase-wave-guard.md +22 -11
  185. package/gsd-core/references/gsd-run-resolver.md +1 -1
  186. package/gsd-core/references/loop-hook-dispatch.md +18 -0
  187. package/gsd-core/references/model-profiles.md +13 -4
  188. package/gsd-core/references/phase-argument-parsing.md +9 -7
  189. package/gsd-core/references/phase-id-convention.md +28 -0
  190. package/gsd-core/references/planner-gap-closure.md +2 -0
  191. package/gsd-core/references/planner-load-graph-context.md +24 -13
  192. package/gsd-core/references/planner-verify-command-grounding.md +14 -0
  193. package/gsd-core/references/planning-config.md +14 -2
  194. package/gsd-core/references/tdd.md +30 -4
  195. package/gsd-core/references/thinking-models-planning.md +18 -2
  196. package/gsd-core/references/ui-consideration-probe.md +10 -5
  197. package/gsd-core/references/verification-patterns.md +17 -4
  198. package/gsd-core/references/verify-command-path-resolvability.md +10 -2
  199. package/gsd-core/references/worktree-path-safety.md +433 -2
  200. package/gsd-core/templates/README.md +7 -1
  201. package/gsd-core/templates/state.md +6 -3
  202. package/gsd-core/templates/summary.compact.md +212 -0
  203. package/gsd-core/templates/user-setup.compact.md +199 -0
  204. package/gsd-core/templates/user-setup.md +0 -9
  205. package/gsd-core/templates/verification-report.md +1 -1
  206. package/gsd-core/workflows/_runtime-launcher.snippet.sh +1 -1
  207. package/gsd-core/workflows/add-backlog.md +1 -1
  208. package/gsd-core/workflows/add-phase.md +1 -1
  209. package/gsd-core/workflows/add-tests.md +2 -2
  210. package/gsd-core/workflows/add-todo.md +6 -5
  211. package/gsd-core/workflows/ai-integration-phase.md +11 -3
  212. package/gsd-core/workflows/audit-fix.md +1 -1
  213. package/gsd-core/workflows/audit-milestone.md +1 -1
  214. package/gsd-core/workflows/audit-uat.md +1 -1
  215. package/gsd-core/workflows/autonomous/steps/converge-fail-fast.md +9 -18
  216. package/gsd-core/workflows/autonomous.md +29 -16
  217. package/gsd-core/workflows/check-todos.md +6 -4
  218. package/gsd-core/workflows/cleanup.md +5 -3
  219. package/gsd-core/workflows/code-review/steps/dispatch-fix.md +4 -3
  220. package/gsd-core/workflows/code-review/steps/structural-pre-pass.md +8 -1
  221. package/gsd-core/workflows/code-review-fix.md +108 -22
  222. package/gsd-core/workflows/code-review.md +216 -73
  223. package/gsd-core/workflows/complete-milestone/detail/elaboration.md +274 -0
  224. package/gsd-core/workflows/complete-milestone.md +41 -264
  225. package/gsd-core/workflows/debug.md +3 -3
  226. package/gsd-core/workflows/diagnose-issues.md +1 -1
  227. package/gsd-core/workflows/discuss-phase/modes/advisor.md +1 -1
  228. package/gsd-core/workflows/discuss-phase/modes/chain.md +1 -1
  229. package/gsd-core/workflows/discuss-phase-assumptions.md +1 -1
  230. package/gsd-core/workflows/discuss-phase.md +1 -1
  231. package/gsd-core/workflows/do.md +2 -2
  232. package/gsd-core/workflows/docs-update/detail/elaboration.md +179 -0
  233. package/gsd-core/workflows/docs-update.md +17 -158
  234. package/gsd-core/workflows/edit-phase.md +1 -1
  235. package/gsd-core/workflows/eval-review.md +10 -3
  236. package/gsd-core/workflows/execute-phase/detail/elaboration.md +124 -0
  237. package/gsd-core/workflows/execute-phase/steps/code-review-disposition.md +1017 -0
  238. package/gsd-core/workflows/execute-phase/steps/codebase-drift-gate.md +19 -4
  239. package/gsd-core/workflows/execute-phase/steps/completion-reconciliation.md +56 -0
  240. package/gsd-core/workflows/execute-phase/steps/executor-isolation-dispatch.md +43 -4
  241. package/gsd-core/workflows/execute-phase/steps/executor-progress-policy.md +43 -0
  242. package/gsd-core/workflows/execute-phase/steps/gap-closure-artifacts.md +1 -1
  243. package/gsd-core/workflows/execute-phase/steps/partial-wave.md +1 -1
  244. package/gsd-core/workflows/execute-phase/steps/per-plan-executor-routing.md +1 -1
  245. package/gsd-core/workflows/execute-phase/steps/per-plan-worktree-gate.md +1 -1
  246. package/gsd-core/workflows/execute-phase/steps/post-merge-gate.md +46 -9
  247. package/gsd-core/workflows/execute-phase/steps/protected-branch.md +1 -1
  248. package/gsd-core/workflows/execute-phase/steps/ready-wave-gate.md +37 -0
  249. package/gsd-core/workflows/execute-phase/steps/regression-gate-run.md +1 -1
  250. package/gsd-core/workflows/execute-phase/steps/sequential-root-pin.md +35 -0
  251. package/gsd-core/workflows/execute-phase/steps/stale-reverification.md +24 -0
  252. package/gsd-core/workflows/execute-phase/steps/tdd-applicability-resolution.md +1 -1
  253. package/gsd-core/workflows/execute-phase/steps/threat-id-gate.md +28 -0
  254. package/gsd-core/workflows/execute-phase/steps/wave-post-gate-hooks.md +1 -1
  255. package/gsd-core/workflows/execute-phase/steps/worktree-base-check.md +25 -0
  256. package/gsd-core/workflows/execute-phase.md +83 -172
  257. package/gsd-core/workflows/execute-plan.md +24 -10
  258. package/gsd-core/workflows/explore.md +3 -3
  259. package/gsd-core/workflows/extract-learnings.md +2 -1
  260. package/gsd-core/workflows/fast.md +1 -1
  261. package/gsd-core/workflows/forensics.md +1 -1
  262. package/gsd-core/workflows/graduation.md +1 -1
  263. package/gsd-core/workflows/health.md +2 -2
  264. package/gsd-core/workflows/help/modes/full.compact.md +398 -0
  265. package/gsd-core/workflows/help/modes/full.md +5 -5
  266. package/gsd-core/workflows/help/modes/topic.md +15 -5
  267. package/gsd-core/workflows/help.md +1 -1
  268. package/gsd-core/workflows/import.md +2 -2
  269. package/gsd-core/workflows/inbox.md +2 -2
  270. package/gsd-core/workflows/ingest-docs.md +3 -3
  271. package/gsd-core/workflows/insert-phase.md +1 -1
  272. package/gsd-core/workflows/list-seeds.md +1 -1
  273. package/gsd-core/workflows/list-workspaces.md +1 -1
  274. package/gsd-core/workflows/manager.md +2 -2
  275. package/gsd-core/workflows/map-codebase.md +52 -5
  276. package/gsd-core/workflows/milestone-summary.md +1 -1
  277. package/gsd-core/workflows/mvp-phase.md +1 -1
  278. package/gsd-core/workflows/new-milestone.md +56 -14
  279. package/gsd-core/workflows/new-project/detail/elaboration.md +216 -0
  280. package/gsd-core/workflows/new-project/steps/auto-mode-config.md +3 -3
  281. package/gsd-core/workflows/new-project/steps/codebase-map-offer.md +1 -1
  282. package/gsd-core/workflows/new-project.md +39 -209
  283. package/gsd-core/workflows/new-workspace.md +2 -2
  284. package/gsd-core/workflows/next.md +1 -1
  285. package/gsd-core/workflows/note.md +1 -1
  286. package/gsd-core/workflows/onboard.md +1 -1
  287. package/gsd-core/workflows/pause-work.md +1 -1
  288. package/gsd-core/workflows/plan-phase/detail/elaboration.md +209 -0
  289. package/gsd-core/workflows/plan-phase/steps/chunked-planning-mode.md +17 -5
  290. package/gsd-core/workflows/plan-phase/steps/prd-express-path.md +1 -1
  291. package/gsd-core/workflows/plan-phase/steps/stall-detection-helpers.md +23 -5
  292. package/gsd-core/workflows/plan-phase.md +45 -187
  293. package/gsd-core/workflows/plan-review-convergence.md +21 -5
  294. package/gsd-core/workflows/plant-seed.md +62 -20
  295. package/gsd-core/workflows/pr-branch.md +132 -20
  296. package/gsd-core/workflows/profile-user.md +2 -2
  297. package/gsd-core/workflows/progress.md +1 -1
  298. package/gsd-core/workflows/quick/steps/plan-checker-loop.md +25 -0
  299. package/gsd-core/workflows/quick/steps/quick-verification.md +1 -1
  300. package/gsd-core/workflows/quick/steps/worktree-pre-dispatch-commit.md +1 -1
  301. package/gsd-core/workflows/quick-batch/steps/batch-init.md +1 -1
  302. package/gsd-core/workflows/quick-batch/steps/completion.md +1 -1
  303. package/gsd-core/workflows/quick-batch/steps/merge-wave.md +1 -1
  304. package/gsd-core/workflows/quick-batch/steps/planner-wave.md +1 -1
  305. package/gsd-core/workflows/quick-batch/steps/research-phase.md +1 -1
  306. package/gsd-core/workflows/quick-batch/steps/resume-mode.md +1 -1
  307. package/gsd-core/workflows/quick-batch/steps/verification-wave.md +1 -1
  308. package/gsd-core/workflows/quick-batch/steps/worktree-dispatch.md +1 -1
  309. package/gsd-core/workflows/quick-batch.md +1 -1
  310. package/gsd-core/workflows/quick.md +29 -10
  311. package/gsd-core/workflows/reapply-patches.md +86 -6
  312. package/gsd-core/workflows/remove-phase.md +1 -1
  313. package/gsd-core/workflows/remove-workspace.md +2 -2
  314. package/gsd-core/workflows/resume-project.md +1 -1
  315. package/gsd-core/workflows/review.md +31 -16
  316. package/gsd-core/workflows/scan.md +1 -1
  317. package/gsd-core/workflows/secure-phase.md +3 -2
  318. package/gsd-core/workflows/settings-advanced.md +30 -10
  319. package/gsd-core/workflows/settings-integrations.md +2 -3
  320. package/gsd-core/workflows/settings.md +22 -9
  321. package/gsd-core/workflows/ship.md +3 -2
  322. package/gsd-core/workflows/sketch-wrap-up.md +1 -1
  323. package/gsd-core/workflows/sketch.md +1 -1
  324. package/gsd-core/workflows/smart-entry.md +2 -2
  325. package/gsd-core/workflows/spec-phase.md +15 -5
  326. package/gsd-core/workflows/spike-wrap-up.md +1 -1
  327. package/gsd-core/workflows/spike.md +1 -1
  328. package/gsd-core/workflows/stats.md +1 -1
  329. package/gsd-core/workflows/sync-skills.md +5 -5
  330. package/gsd-core/workflows/thread.md +1 -1
  331. package/gsd-core/workflows/transition.md +1 -1
  332. package/gsd-core/workflows/ui-phase.md +44 -8
  333. package/gsd-core/workflows/ui-review.md +18 -4
  334. package/gsd-core/workflows/ultraplan-phase.md +1 -1
  335. package/gsd-core/workflows/undo.md +339 -20
  336. package/gsd-core/workflows/update.md +14 -12
  337. package/gsd-core/workflows/validate-phase.md +3 -2
  338. package/gsd-core/workflows/verify-work/detail/elaboration.md +230 -0
  339. package/gsd-core/workflows/verify-work/steps/automated-ui-verification.md +1 -1
  340. package/gsd-core/workflows/verify-work/steps/mvp-uat-framing.md +1 -1
  341. package/gsd-core/workflows/verify-work.md +101 -196
  342. package/hooks/dist/gsd-agent-isolation-guard.js +66 -16
  343. package/hooks/dist/gsd-context-monitor.js +88 -15
  344. package/hooks/dist/gsd-cursor-subagent-start.js +34 -14
  345. package/hooks/dist/gsd-secret-read-guard.js +71 -19
  346. package/hooks/dist/gsd-statusline.js +81 -20
  347. package/hooks/dist/gsd-validate-commit.sh +97 -8
  348. package/hooks/dist/gsd-worktree-path-guard.js +25 -14
  349. package/hooks/dist/gsd-write-guard.js +46 -1
  350. package/hooks/dist/lib/dispatch-identity.js +187 -0
  351. package/hooks/dist/lib/filename-classification.js +64 -0
  352. package/hooks/dist/lib/isolation-deny-reason.js +53 -1
  353. package/hooks/dist/lib/isolation-sentinel.js +58 -19
  354. package/hooks/gsd-agent-isolation-guard.js +66 -16
  355. package/hooks/gsd-context-monitor.js +88 -15
  356. package/hooks/gsd-cursor-subagent-start.js +34 -14
  357. package/hooks/gsd-secret-read-guard.js +71 -19
  358. package/hooks/gsd-statusline.js +81 -20
  359. package/hooks/gsd-validate-commit.sh +97 -8
  360. package/hooks/gsd-worktree-path-guard.js +25 -14
  361. package/hooks/gsd-write-guard.js +46 -1
  362. package/hooks/lib/dispatch-identity.js +187 -0
  363. package/hooks/lib/filename-classification.js +64 -0
  364. package/hooks/lib/isolation-deny-reason.js +53 -1
  365. package/hooks/lib/isolation-sentinel.js +58 -19
  366. package/package.json +11 -6
  367. package/scripts/benchmark-compact-content-variants.cjs +298 -0
  368. package/scripts/benchmark-compact-content.cjs +368 -0
  369. package/scripts/build-hooks.js +15 -6
  370. package/scripts/check-contract-drift.cjs +131 -12
  371. package/scripts/check-env.cjs +36 -8
  372. package/scripts/check-glossary-refs.cjs +25 -21
  373. package/scripts/ci-next-health.cjs +271 -0
  374. package/scripts/ci-prepare-test-scope.cjs +7 -7
  375. package/scripts/ci-test-scope.cjs +126 -20
  376. package/scripts/ci-timeout-report.cjs +1 -1
  377. package/scripts/command-contract-helpers.cjs +3 -0
  378. package/scripts/diff-touches-shipped-paths.cjs +1 -1
  379. package/scripts/docs-guard-registry.cjs +35 -2
  380. package/scripts/gen-adr-index.cjs +8 -2
  381. package/scripts/gen-inventory-manifest.cjs +12 -0
  382. package/scripts/gen-loop-host-contract.cjs +69 -0
  383. package/scripts/gen-platform-conformance-tier.cjs +557 -0
  384. package/scripts/lib/drift-scan.cjs +1 -1
  385. package/scripts/lib/macos-conformance-tier.generated.cjs +224 -0
  386. package/scripts/lib/ndjson-reporter.cjs +3 -2
  387. package/scripts/lib/npm-version-check-diagnosis.cjs +59 -0
  388. package/scripts/lib/platform-conformance-tier.generated.cjs +287 -0
  389. package/scripts/lib/suite-detection.cjs +32 -0
  390. package/scripts/lint-allowed-tools-parity.cjs +221 -0
  391. package/scripts/lint-docs-guard-registration.exempt-baseline.cjs +47 -3
  392. package/scripts/lint-phase-arg-assignment.cjs +257 -0
  393. package/scripts/lint-phase-id-drift.cjs +623 -13
  394. package/scripts/lint-pr-branch-pattern-drift.cjs +148 -0
  395. package/scripts/lint-response-language-coverage.cjs +9 -3
  396. package/scripts/lint-retired-runtime-name.cjs +619 -0
  397. package/scripts/lint-source-test-name-collision.cjs +1 -1
  398. package/scripts/lint-state-write-path-drift.cjs +93 -0
  399. package/scripts/lint-test-file-count.allowlist.json +29 -9
  400. package/scripts/lint-vendored-deps.cjs +128 -17
  401. package/scripts/lint-workflow-shellcheck-baseline.json +100 -0
  402. package/scripts/prompt-injection-scan.sh +18 -0
  403. package/scripts/release-tarball-smoke.cjs +194 -1
  404. package/scripts/workflow-size.cjs +139 -0
  405. package/skills/gsd-autonomous/SKILL.md +2 -2
  406. package/skills/gsd-capture/SKILL.md +1 -1
  407. package/skills/gsd-cleanup/SKILL.md +1 -0
  408. package/skills/gsd-code-review/SKILL.md +2 -1
  409. package/skills/gsd-complete-milestone/SKILL.md +1 -0
  410. package/skills/gsd-config/SKILL.md +1 -0
  411. package/skills/gsd-debug/SKILL.md +1 -0
  412. package/skills/gsd-graphify/SKILL.md +1 -0
  413. package/skills/gsd-health/SKILL.md +1 -0
  414. package/skills/gsd-mempalace-capture/SKILL.md +8 -3
  415. package/skills/gsd-mempalace-recall/SKILL.md +1 -0
  416. package/skills/gsd-new-milestone/SKILL.md +1 -0
  417. package/skills/gsd-new-project/SKILL.md +1 -0
  418. package/skills/gsd-next/SKILL.md +1 -0
  419. package/skills/gsd-pause-work/SKILL.md +1 -0
  420. package/skills/gsd-phase/SKILL.md +1 -0
  421. package/skills/gsd-plan-review-convergence/SKILL.md +5 -5
  422. package/skills/gsd-pr-branch/SKILL.md +1 -0
  423. package/skills/gsd-progress/SKILL.md +1 -1
  424. package/skills/gsd-quick-batch/SKILL.md +1 -1
  425. package/skills/gsd-resume-work/SKILL.md +1 -0
  426. package/skills/gsd-review/SKILL.md +2 -3
  427. package/skills/gsd-review-backlog/SKILL.md +1 -0
  428. package/skills/gsd-settings/SKILL.md +2 -1
  429. package/skills/gsd-stats/SKILL.md +1 -0
  430. package/skills/gsd-thread/SKILL.md +1 -0
  431. package/skills/gsd-workspace/SKILL.md +1 -0
  432. package/skills/gsd-workstreams/SKILL.md +1 -0
  433. package/vscode/package.json +1 -1
  434. package/gsd-core/templates/claude-md.md +0 -145
  435. package/gsd-core/templates/codebase/concerns.md +0 -310
  436. package/gsd-core/templates/codebase/conventions.md +0 -307
  437. package/gsd-core/templates/codebase/integrations.md +0 -280
  438. package/gsd-core/templates/codebase/structure.md +0 -285
  439. package/gsd-core/templates/codebase/testing.md +0 -480
  440. package/gsd-core/templates/debug-subagent-prompt.md +0 -91
  441. package/gsd-core/templates/discovery.md +0 -146
@@ -1,10 +1,10 @@
1
1
  0.5. **Inter-wave worktree base re-check (wave N+1 guard — #1369):**
2
2
 
3
3
  After Wave N merges and tracking commits advance orchestrator HEAD, Claude Code's
4
- `isolation="worktree"` still forks new worktrees from `origin/HEAD` (the "fresh" base),
5
- not the live HEAD. This means Wave N+1 worktrees would be created from the stale
6
- pre-Wave-N base, causing the `worktree_branch_check` guard inside each executor to halt
7
- immediately with a base-mismatch fatal.
4
+ `isolation="worktree"` forks new worktrees from `origin/HEAD` (the "fresh" base) unless
5
+ `worktree.baseRef:"head"` is set — not the live HEAD. Without the setting, Wave N+1
6
+ worktrees would be created from the stale pre-Wave-N base, causing the
7
+ `worktree_branch_check` guard inside each executor to halt with a base-mismatch fatal.
8
8
 
9
9
  **Run this check at the start of every wave when `USE_WORKTREES != "false"` and
10
10
  `ISOLATION = "harness-worktree"`** (#2652 — the harness caches the fork base, so this is a
@@ -30,10 +30,21 @@
30
30
  this check and may re-enable worktree isolation once `origin/HEAD` matches HEAD again
31
31
  (e.g. via `git fetch` or a push that advances it).
32
32
 
33
- **Why `worktree.baseRef:"head"` does not avoid this degrade (#48, #3659):** the runtime
34
- harness does not read project-settings `baseRef` — an isolated dispatch always forks from
35
- `origin/HEAD` regardless of the setting, so the check compares against the real fork base
36
- and degrades whenever HEAD has diverged. Parallel worktrees return once HEAD is
37
- merged/pushed so `origin/HEAD` matches it. The setting still restores parallel execution
38
- on runtimes where GSD itself creates the worktrees (orchestrator-managed isolation:
39
- Codex, OpenCode, Kimi, Kimi Code). See #683 for the base-ref configuration detail.
33
+ **How `worktree.baseRef:"head"` interacts with this degrade (#3659, #4588):** with the
34
+ setting in place the check trusts it and does not compare — the worktree creator forks from the
35
+ orchestrator HEAD (GSD's own `git worktree add` by construction; the Claude Code harness as
36
+ measured from all three settings layers, #4588; Cursor unmeasured), so outside the two
37
+ exceptions below this guard only fires when the setting
38
+ is absent and HEAD has diverged from `origin/HEAD`. Parallel worktrees then return once HEAD
39
+ is merged/pushed so `origin/HEAD` matches it, or once the setting is applied. The exceptions
40
+ (#4588): a supplied `--observed-fork-base` is compared against HEAD instead of trusted, in
41
+ both modes; and on a harness-created run with no observation, a Claude Code `WorktreeCreate`
42
+ hook in any of those settings files — or one of them that does not parse, so a hook cannot be
43
+ ruled out — withholds the trust: the hook creates the worktree without applying the setting,
44
+ so the check compares against `origin/HEAD` anyway and a mismatch degrades with
45
+ `baseref-head-bypassed-by-hook`. The #4868 prior-worktree observation does not lift that
46
+ degrade: a worktree at HEAD records nothing about which creator left it there, so one the
47
+ plain harness created before the hook was configured reads the same as one the hook created
48
+ (#4881). On a hook host only `--observed-fork-base` restores a trusted verdict. The exit-42
49
+ guard in each executor remains the backstop on a host that does not honor the setting.
50
+ See #683 for the base-ref configuration detail.
@@ -4,5 +4,5 @@ Use this bootstrap block when a workflow must call `gsd-tools` from the active w
4
4
  Keep this resolver centralized; workflows should reference this file instead of copying the shell probe.
5
5
 
6
6
  ```bash
7
- _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; }; 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 unset -f gsd_run; _G="$(command -v gsd_run)"; then GSD_TOOLS="$_G"; gsd_run() { "$GSD_TOOLS" "$@"; }; elif _gsd_at "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/gsd-core/bin/${_GSD_SHIM_NAME}" "${HERMES_HOME:-$HOME/.hermes}/gsd-core/bin/${_GSD_SHIM_NAME}" "${CURSOR_CONFIG_DIR:-$HOME/.cursor}/gsd-core/bin/${_GSD_SHIM_NAME}" "${CODEX_HOME:-$HOME/.codex}/gsd-core/bin/${_GSD_SHIM_NAME}" "${GEMINI_CONFIG_DIR:-$HOME/.gemini}/gsd-core/bin/${_GSD_SHIM_NAME}" "${COPILOT_CONFIG_DIR:-$HOME/.copilot}/gsd-core/bin/${_GSD_SHIM_NAME}" "${WINDSURF_CONFIG_DIR:-$HOME/.codeium/windsurf}/gsd-core/bin/${_GSD_SHIM_NAME}" "${AUGMENT_CONFIG_DIR:-$HOME/.augment}/gsd-core/bin/${_GSD_SHIM_NAME}" "${TRAE_CONFIG_DIR:-$HOME/.trae}/gsd-core/bin/${_GSD_SHIM_NAME}" "${QWEN_CONFIG_DIR:-$HOME/.qwen}/gsd-core/bin/${_GSD_SHIM_NAME}" "${CODEBUDDY_CONFIG_DIR:-$HOME/.codebuddy}/gsd-core/bin/${_GSD_SHIM_NAME}" "${CLINE_CONFIG_DIR:-$HOME/.cline}/gsd-core/bin/${_GSD_SHIM_NAME}" "${GROK_AGENTS_HOME:-$HOME/.agents}/gsd-core/bin/${_GSD_SHIM_NAME}" "${ANTIGRAVITY_CONFIG_DIR:-$HOME/.gemini/antigravity}/gsd-core/bin/${_GSD_SHIM_NAME}" "${OPENCODE_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/opencode}/gsd-core/bin/${_GSD_SHIM_NAME}" "${KILO_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/kilo}/gsd-core/bin/${_GSD_SHIM_NAME}"; then gsd_run() { node "$GSD_TOOLS" "$@"; }; else echo "ERROR: gsd-tools.cjs not found at $GSD_TOOLS and gsd_run is not on PATH. Run: npx -y @opengsd/gsd-core@latest --claude --local" >&2; exit 1; fi; GSD_IDENTITY_STATUS=unverified; case "$(gsd_run runtime-identity --raw 2>/dev/null || true)" in '{"packageName":"@opengsd/gsd-core"'*'}') GSD_IDENTITY_STATUS=ok;; esac; 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
7
+ _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() { _gsd_at "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/gsd-core/bin/${_GSD_SHIM_NAME}" "${HERMES_HOME:-$HOME/.hermes}/gsd-core/bin/${_GSD_SHIM_NAME}" "${CURSOR_CONFIG_DIR:-$HOME/.cursor}/gsd-core/bin/${_GSD_SHIM_NAME}" "${CODEX_HOME:-$HOME/.codex}/gsd-core/bin/${_GSD_SHIM_NAME}" "${GEMINI_CONFIG_DIR:-$HOME/.gemini}/gsd-core/bin/${_GSD_SHIM_NAME}" "${COPILOT_CONFIG_DIR:-$HOME/.copilot}/gsd-core/bin/${_GSD_SHIM_NAME}" "${WINDSURF_CONFIG_DIR:-$HOME/.codeium/windsurf}/gsd-core/bin/${_GSD_SHIM_NAME}" "${AUGMENT_CONFIG_DIR:-$HOME/.augment}/gsd-core/bin/${_GSD_SHIM_NAME}" "${TRAE_CONFIG_DIR:-$HOME/.trae}/gsd-core/bin/${_GSD_SHIM_NAME}" "${QWEN_CONFIG_DIR:-$HOME/.qwen}/gsd-core/bin/${_GSD_SHIM_NAME}" "${CODEBUDDY_CONFIG_DIR:-$HOME/.codebuddy}/gsd-core/bin/${_GSD_SHIM_NAME}" "${CLINE_CONFIG_DIR:-$HOME/.cline}/gsd-core/bin/${_GSD_SHIM_NAME}" "${GROK_AGENTS_HOME:-$HOME/.agents}/gsd-core/bin/${_GSD_SHIM_NAME}" "${ANTIGRAVITY_CONFIG_DIR:-$HOME/.gemini/antigravity}/gsd-core/bin/${_GSD_SHIM_NAME}" "${OPENCODE_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/opencode}/gsd-core/bin/${_GSD_SHIM_NAME}" "${KILO_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/kilo}/gsd-core/bin/${_GSD_SHIM_NAME}"; }; 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
8
8
  ```
@@ -57,6 +57,24 @@ Dispatch the referenced unit. Exactly one of `ref.skill`, `ref.agent`, or `ref.c
57
57
 
58
58
  Wait for the result before continuing to the next hook or the next step.
59
59
 
60
+ **`supportsReviewerLanes` (optional, boolean).** A `step` entry may carry
61
+ `supportsReviewerLanes: true` alongside `ref` (#4209). A workflow opts a step into external
62
+ reviewer-lane dispatch by calling `gsd_run review-lane dispatch-step --cap-id <capId> --point
63
+ <point> --explicit <slugs> ...` — `dispatch-step` resolves its OWN active hook for `<point>` (via
64
+ `resolveActiveHooksForPoint`, the same in-process resolver `loop render-hooks` itself calls) and
65
+ checks whether `<capId>`'s hook carries this field before proceeding; the workflow does not
66
+ resolve or gate on the trait itself, only passes the two flags naming which step it is. When the
67
+ trait reads exactly `true`, `dispatch-step` routes through `dispatchReviewerLanes`, the one
68
+ interpreter in `src/reviewer-step-dispatch.cts` that reuses the existing reviewer-lane selection,
69
+ planning, and invocation machinery, so any explicitly selected reviewer lane also reviews the
70
+ same scope. Absent or `false` is inert: `dispatch-step` itself is a no-op (a non-boolean value is
71
+ rejected by `capability-validator.cjs` at load time, so it never reaches `dispatch-step` at all).
72
+ This is the only place a step opts into reviewer-lane support: a capability beyond `code-review`
73
+ reuses it by declaring the same trait on its own step and calling `dispatch-step` with
74
+ `--cap-id`/`--point`, with zero bespoke TRAIT-RESOLUTION code of its own. The workflow still owns
75
+ matching its own CLI flags against the reviewer-lane roster and assembling the evidence block
76
+ handed to its consolidator — those are NOT part of what this trait makes reusable.
77
+
60
78
  A `step` is **advisory by construction**: it never blocks or redirects the host workflow —
61
79
  that is what a `gate` is for. Each dispatch is best-effort; on error record a warning and
62
80
  continue, honoring `onError`.
@@ -58,6 +58,10 @@ Model profiles control which Claude model each GSD agent uses. This allows balan
58
58
  3. **Profile table** — the per-agent column from the active `model_profile`
59
59
  4. **Runtime default** — when nothing else applies
60
60
 
61
+ Steps 2–4 select the *tier*; a `model_profile_overrides.<runtime>.<tier>` entry then
62
+ maps that tier to a concrete model (#4192 — honored on the claude runtime as well, so
63
+ pinning composes with tiering instead of replacing it).
64
+
61
65
  ### Why two layers above the profile?
62
66
 
63
67
  - **Profile** is a global tier strategy (everyone runs balanced).
@@ -96,7 +100,7 @@ The three layers compose: `models` defaults a phase, `model_overrides` carves an
96
100
  - **Required when using non-Anthropic providers** (OpenRouter, local models, etc.) — otherwise GSD may call Anthropic models directly, incurring unexpected costs
97
101
  - Use when: you want GSD to follow your currently selected runtime model
98
102
 
99
- ## Using Non-Claude Runtimes (Codex, OpenCode, Gemini CLI, Kilo)
103
+ ## Using Non-Claude Runtimes (Codex, OpenCode, Antigravity CLI, Kilo)
100
104
 
101
105
  When installed for a non-Claude runtime, the GSD installer sets `resolve_model_ids: "omit"` in `~/.gsd/defaults.json`. This returns an empty model parameter for all agents, so each agent uses the runtime's default model. No manual setup is needed.
102
106
 
@@ -215,8 +219,11 @@ is (highest → lowest):
215
219
  (see §Dynamic Routing — escalation steps tier up per attempt counter)
216
220
  4. If no dynamic_routing match, check models[phase_type] for a phase-type tier
217
221
  (see §Per-Phase-Type Model Map for the agent → phase-type mapping)
218
- 5. If no phase-type slot, look up agent in profile table
219
- 6. Pass model parameter to Task call
222
+ 5. Check model_profile_overrides.<runtime>.<tier> for a per-tier model override
223
+ (honored on the claude runtime too — #4192; verbatim unless it maps to the
224
+ current tier alias)
225
+ 6. If no phase-type slot, look up agent in profile table
226
+ 7. Pass model parameter to Task call
220
227
  ```
221
228
 
222
229
  `model` and `effort` resolve through different mechanisms at different
@@ -246,7 +253,9 @@ Override specific agents without changing the entire profile:
246
253
  }
247
254
  ```
248
255
 
249
- Overrides take precedence over the profile. Valid values: `opus`, `sonnet`, `haiku`, `inherit`, or any fully-qualified model ID (e.g., `"o3"`, `"openai/o3"`, `"google/gemini-2.5-pro"`).
256
+ Overrides take precedence over the profile. Valid values: `opus`, `sonnet`, `haiku`, `fable`, `inherit`, or any fully-qualified model ID (e.g., `"o3"`, `"openai/o3"`, `"google/gemini-2.5-pro"`). `fable` is a Claude Code Agent-tool alias, not a GSD profile tier — it has no column in the profile table above.
257
+
258
+ On the Claude runtime, fully-qualified Claude model IDs are honored as explicit generation pins (#4192): an ID that names the current tier default (e.g. `"claude-sonnet-5"`) resolves to its tier alias — the same model in the form the Agent tool always accepts — while any other ID (e.g. `"claude-opus-4-7"`) resolves verbatim, with a warn-once stderr note that setups accepting only tier aliases will not honor a full ID. To pin a generation for a whole tier rather than one agent, set `model_profile_overrides.claude.<tier>` (see docs/CONFIGURATION.md — Runtime-Aware Profiles).
250
259
 
251
260
  ## Switching Profiles
252
261
 
@@ -27,16 +27,18 @@ Returns JSON with:
27
27
 
28
28
  ## Manual Normalization (Legacy)
29
29
 
30
- Zero-pad integer phases to 2 digits. Preserve decimal suffixes.
30
+ Zero-pad the leading integer to 2 digits. Preserve a letter suffix and any dotted
31
+ segments — the canonical grammar in `src/phase-id.cts` (`normalizePhaseName`):
32
+ `8 → 08`, `2.1 → 02.1`, `3A → 03A`, `23.1.2 → 23.1.2`.
31
33
 
32
34
  ```bash
33
35
  # Normalize phase number
34
- if [[ "$PHASE" =~ ^[0-9]+$ ]]; then
35
- # Integer: 8 → 08
36
- PHASE=$(printf "%02d" "$PHASE")
37
- elif [[ "$PHASE" =~ ^([0-9]+)\.([0-9]+)$ ]]; then
38
- # Decimal: 2.1 → 02.1
39
- PHASE=$(printf "%02d.%s" "${BASH_REMATCH[1]}" "${BASH_REMATCH[2]}")
36
+ # #4748: one branch for the whole canonical token — digits, optional [A-Z],
37
+ # dotted segments. Pad through $((10#…)) so an already-padded `08` is not read
38
+ # as octal by printf; anything non-canonical passes through untouched.
39
+ if [[ "$PHASE" =~ ^([0-9]+)([A-Z]?)((\.[0-9]+)*)$ ]]; then
40
+ PHASE_INT=${BASH_REMATCH[1]}
41
+ PHASE=$(printf "%02d" "$((10#$PHASE_INT))")${BASH_REMATCH[2]}${BASH_REMATCH[3]}
40
42
  fi
41
43
  ```
42
44
 
@@ -0,0 +1,28 @@
1
+ # Bracket phase-ID convention
2
+
3
+ The bracket convention is opt-in through `phase_id_convention: "bracket"`.
4
+ Its compact grammar card below is generated from `src/phase-id-card.cts`; edit
5
+ that module, not this block.
6
+
7
+ <!-- PHASE-ID-CARD:START -->
8
+ ```text
9
+ [GSD.02] 05.03-01
10
+ │ │ │ │ │
11
+ │ │ │ │ └── plan 01
12
+ │ │ │ └────── subphase 03
13
+ │ │ └───────── phase 05
14
+ │ └───────────── milestone 02
15
+ └───────────────── project GSD
16
+
17
+ milestone = bracket integer; dots = phase-levels; one hyphen = plan; no 'Phase' word, no vX.Y
18
+ ```
19
+ <!-- PHASE-ID-CARD:END -->
20
+
21
+ The display form is `[PROJECT.MM] PP[.SS][-LL]`: the bracket carries the
22
+ project and milestone, dots join phase levels, and the single hyphen introduces
23
+ the optional plan. A phase directory encodes the same identity without brackets:
24
+ `PROJECT.MM-PP[.SS]-slug/`.
25
+
26
+ Human-facing bracket surfaces omit both the literal `Phase` label and the
27
+ legacy `vX.Y` milestone marker. Repositories using the unset, `sequential`, or
28
+ `milestone-prefixed` conventions retain their existing display forms.
@@ -60,3 +60,5 @@ autonomous: true
60
60
  gap_closure: true # Flag for tracking
61
61
  ---
62
62
  ```
63
+
64
+ **9. Number threat IDs after the phase's existing registers** (#4683): when `security_enforcement` is on, read the `<threat_model>` blocks of the phase's existing PLAN files and continue after their highest `T-{phase}-NN` — do not renumber from `T-{phase}-01`. Every ID already names a specific threat in an earlier plan; reusing it makes `SECURITY.md` rows and `VALIDATION.md`'s Threat Ref column ambiguous. `T-{phase}-SC` is reserved and every plan keeps it. The execute-phase init reports any cross-plan duplicates and hard-stops on them (`threat_id_duplicates`), so a collision surfaces here as a failed plan check.
@@ -2,35 +2,46 @@
2
2
 
3
3
  > Loaded by `gsd-planner` at the `load_graph_context` step.
4
4
 
5
- Check for knowledge graph:
6
-
7
- ```bash
8
- ls .planning/graphs/graph.json 2>/dev/null
9
- ```
10
-
11
- If graph.json exists, check freshness:
5
+ Check for a knowledge graph and read its freshness in one call. `status` resolves the
6
+ graph through `graphify.graph_path`, so it is also the presence gate — a bare
7
+ `ls` of the default location misses an umbrella graph shared across sibling repos:
12
8
 
13
9
  ```bash
14
10
  _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 command -v gsd-tools >/dev/null 2>&1; then GSD_TOOLS="$(command -v gsd-tools)"; gsd_run() { "$GSD_TOOLS" "$@"; }; elif [ -f "$HOME/.claude/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="$HOME/.claude/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; 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
15
11
  gsd_run graphify status
16
12
  ```
17
13
 
14
+ If `exists` is `false`, continue without graph context — skip the rest of this step.
15
+
18
16
  If the status response has `stale: true`, note for later: "Graph is {age_hours}h old -- treat semantic relationships as approximate." Include this annotation inline with any graph context injected below.
19
17
 
20
- Query the graph for phase-relevant dependency context (single query per D-06):
18
+ The same response carries `graph_path` — the resolved graph location. Substitute it for `<graph>` below. `graph_path` comes from `graphify.graph_path` in `.planning/config.json`, a config surface already trusted elsewhere; if it ever carried attacker-controlled content, the literal double-quoted substitution below would need escaping.
19
+
20
+ Query the graph for phase-relevant dependency context (single query per D-06). Prefer the `graphify` CLI when it is on PATH; fall back to the built-in reader otherwise:
21
21
 
22
22
  ```bash
23
- gsd_run graphify query "<phase-goal-keyword>" --budget 2000
23
+ if command -v graphify >/dev/null 2>&1; then
24
+ graphify query "<phase-goal-keyword>" --graph "<graph>" --budget 2000
25
+ graphify affected "<phase-goal-keyword>" --graph "<graph>" --depth 2
26
+ else
27
+ gsd_run graphify query "<phase-goal-keyword>" --budget 2000
28
+ fi
24
29
  ```
25
30
 
26
- Use the keyword that best captures the phase goal. Examples:
27
- - Phase "User Authentication" -> query term "auth"
31
+ Why the CLI is preferred: it ranks seeds (IDF weighting, fuzzy matching) and applies context filters before traversal, where the built-in reader seeds by case-insensitive substring over label and description — so a term like "auth" seeds equally on `author` and `authorize` — and then expands a fixed two hops. `affected` answers "which subsystems may be affected by changes in this phase" directly, by reverse traversal; it has no built-in equivalent, so the fallback path runs the query alone.
32
+
33
+ The two paths return **different shapes**: the CLI emits prose, the built-in emits JSON with per-edge confidence tiers and `budget_met`/`budget_estimate`. `--budget` caps rendered output on the CLI and estimated payload bytes in the built-in — same flag name, different unit. Read whichever you get; do not assume a stable shape and do not paste raw output into PLAN.md.
34
+
35
+ Use the keyword that best captures the phase goal. Prefer the full domain word over a
36
+ prefix of it — on the fallback path a prefix is matched as a substring, so "auth" also
37
+ seeds on `author` and `authoring`. Examples:
38
+ - Phase "User Authentication" -> query term "authentication"
28
39
  - Phase "Payment Integration" -> query term "payment"
29
40
  - Phase "Database Migration" -> query term "migration"
30
41
 
31
- If the query returns nodes and edges, incorporate as dependency context for planning:
42
+ If the query returns related nodes, incorporate as dependency context for planning:
32
43
  - Which modules/files are semantically related to this phase's domain
33
44
  - Which subsystems may be affected by changes in this phase
34
45
  - Cross-document relationships that inform task ordering and wave structure
35
46
 
36
- If no results or graph.json absent, continue without graph context.
47
+ If nothing comes back, continue without graph context.
@@ -15,3 +15,17 @@ command, must hold the matching `package.json`/`Makefile`. `npm --prefix <dir> r
15
15
  preferred over `cd <dir> && npm run <script>` — it does not depend on the executor's cwd. If
16
16
  `prior_verify_commands` is empty and you cannot ground a path, say so in the plan instead of
17
17
  guessing one.
18
+
19
+ **Root-relative, never absolute (#4767).** The paths in your prompt's `<required_reading>` are
20
+ absolute on purpose — a subagent's cwd may differ from the orchestrator's (#2376). That rule
21
+ covers prompt *inputs* only. Every path in the plan *body* — `<files>`, `<verify>`, `<automated>`,
22
+ task actions — is repo-root-relative, and every `<automated>` command assumes cwd at the checkout
23
+ root. An absolute path copied from the prompt into `<automated>` pins the command to the
24
+ orchestrator's checkout; under worktree isolation the executor's checkout is a different
25
+ directory, so the command `cd`s into the main tree, finds it, runs, and **passes against code the
26
+ worktree changed and the main tree did not**. The path probe reports such a target as
27
+ `outside_root` (a warning), but only when the target is outside the *orchestrator's* root — an
28
+ absolute path *inside* it is exactly the shape that passes the probe and still misfires under
29
+ isolation. The authoring rule is the fix; the probe is the backstop. It binds `prior_verify_commands`
30
+ too: a harvested command that carries an absolute path is re-rooted before reuse, never copied
31
+ verbatim — it "worked" in a run that may have been verifying the wrong checkout.
@@ -40,6 +40,7 @@ Configuration options for `.planning/` directory behavior.
40
40
  | `git.quick_branch_template` | `null` | Optional branch template for quick-task runs |
41
41
  | `workflow.use_worktrees` | `true` | Whether executor agents run in isolated git worktrees. Set to `false` to disable worktrees — agents execute sequentially on the main working tree instead. Recommended for solo developers or when worktree merges cause issues. Note: if your branch is ahead of `origin/HEAD` (a diverged milestone or feature branch), GSD auto-degrades to sequential and prints a warning; set `worktree.baseRef:"head"` in `.claude/settings.local.json` to restore parallel execution. See the branch-divergence note below. |
42
42
  | `workflow.subagent_timeout` | `300000` | Timeout in milliseconds for parallel subagent tasks (e.g. codebase mapping). Increase for large codebases or slower models. Default: 300000 (5 minutes). |
43
+ | `planner.stall_detection_enabled` | `true` | Default-on bounded stall detection for planner and plan-checker agents. Set to `false` to await runtime-native completion without watchdog polling; this gives up bounded automatic recovery if the completion handoff is lost. _Loader projection:_ `planner_stall_detection_enabled`. |
43
44
  | `workflow.inline_plan_threshold` | `2` | Plans with this many tasks or fewer execute inline (Pattern C) instead of spawning a subagent. Avoids ~14K token spawn overhead for small plans. Set to `0` to always spawn subagents. |
44
45
  | `workflow.test_command` | `null` | Custom shell command run as the regression/test gate by execute-phase, audit-fix, and post-merge-gate. When unset, GSD auto-detects (Makefile / package.json / Cargo.toml / go.mod / pyproject.toml). Example: `npm test`. |
45
46
  | `workflow.build_command` | `null` | Custom shell command run as the build gate by the post-merge gate. When unset, the build step is skipped/auto-detected. Example: `npm run build`. |
@@ -266,7 +267,7 @@ Generated from `CONFIG_DEFAULTS` (configuration.cjs) and `VALID_CONFIG_KEYS` (co
266
267
  | `context_window` | number | `200000` | `200000`, `1000000` | Context window size; set `1000000` for 1M-context models |
267
268
  | `resolve_model_ids` | boolean\|string | `false` | `false`, `true`, `"omit"` | Map model aliases to full Claude IDs; `"omit"` returns empty string |
268
269
  | `context` | string\|null | `null` | `"dev"`, `"research"`, `"review"` | Execution context profile that adjusts agent behavior: `"dev"` for development tasks, `"research"` for investigation/exploration, `"review"` for code review workflows |
269
- | `review.models.<cli>` | string\|null | `null` | Any model ID string | Per-CLI model override for /gsd:review (e.g., `review.models.gemini`). Falls back to CLI default when null. |
270
+ | `review.models.<cli>` | string\|null | `null` | Any model ID string | Per-CLI model override for /gsd:review (e.g., `review.models.codex`). Falls back to CLI default when null. |
270
271
  | `review.max_prompt_tokens` | number\|null | `null` | Any positive integer, or `null` | Central, cross-lane default cap (in estimated tokens) on the assembled review prompt; `null` means no trim. A per-lane `review.max_prompt_tokens_per_reviewer.<slug>` value overrides it for that lane: `-1` means unset (inherits this global default), `0` means "do not trim that lane" (not unset — it is an explicit, standing opt-out). _Alias:_ `max_prompt_tokens` is the flat-key form used in `CONFIG_DEFAULTS`; `review.max_prompt_tokens` is the canonical namespaced form. |
271
272
 
272
273
  ### Workflow Fields
@@ -289,6 +290,7 @@ Set via `workflow.*` namespace in config.json (e.g., `"workflow": { "research":
289
290
  | `workflow.ui_phase` | boolean | `true` | `true`, `false` | Generate UI-SPEC.md for frontend phases |
290
291
  | `workflow.ui_safety_gate` | boolean | `true` | `true`, `false` | Require safety gate approval for UI changes |
291
292
  | `workflow.text_mode` | boolean | `false` | `true`, `false` | Use plain-text numbered lists instead of AskUserQuestion menus |
293
+ | `workflow.compact_content` | boolean | `false` | `true`, `false` | Compact content mode (#4139, ADR-4139) — per-project boolean selecting terser payloads. Six workflows branch on it via spine+detail: `plan-phase` (#4402, pilot), `execute-phase`, `docs-update`, `new-project`, `verify-work`, `complete-milestone` (#4405). The rest of the eager-window corpus was reviewed and recorded as not worth splitting (`docs/PARTITION-RULES.md`). Lazily-`Read` workflow fragments and `gsd-core/templates/**` templates use a `.compact.md` sibling instead (#4406, `gsd-core/references/compact-content-gate.md` § "Streams 1b and 4") — wired today for `help --full` and the sequential-execution `SUMMARY.md`/`USER-SETUP.md` reads. Agent-skill payloads (#4407, § "Stream 2") use the same `.compact.md` sibling shape, resolved in code by the `gsd_run query agent-skills` CLI seam rather than prose, for the non-Claude persona fallback only |
292
294
  | `workflow.research_before_questions` | boolean | `false` | `true`, `false` | Run research before interactive questions in discuss phase (also honored on the `/gsd:quick` path, #3894). _Alias:_ `research_before_questions` is the flat-key form used in `CONFIG_DEFAULTS`; `workflow.research_before_questions` is the canonical namespaced form. |
293
295
  | `workflow.discuss_mode` | string | `"discuss"` | `"discuss"`, `"assumptions"` | Default mode for discuss-phase: `"discuss"` runs interactive questioning; `"assumptions"` analyzes codebase and surfaces assumptions instead |
294
296
  | `workflow.skip_discuss` | boolean | `false` | `true`, `false` | Skip discuss phase entirely |
@@ -312,6 +314,14 @@ Set via `workflow.*` namespace in config.json (e.g., `"workflow": { "research":
312
314
  | `workflow.security_block_on` | string | `"high"` | `"critical"`, `"high"`, `"medium"`, `"low"`, `"none"` | Minimum threat severity that blocks phase advancement. The auditor counts only open threats at or above this severity toward the blocking gate (SECURITY.md `threats_open`); `none` disables severity blocking. |
313
315
  | `workflow.post_planning_gaps` | boolean | `true` | `true`, `false` | Post-planning gap report (#2493). After plans are generated, scans REQUIREMENTS.md and CONTEXT.md `<decisions>` against all PLAN.md files and emits a unified `Source \| Item \| Status` table. Non-blocking. Set to `false` to skip Step 13e of plan-phase. _Alias:_ `post_planning_gaps` is the flat-key form used in `CONFIG_DEFAULTS`; `workflow.post_planning_gaps` is the canonical namespaced form. |
314
316
 
317
+ ### Planner Fields
318
+
319
+ Set via the `planner.*` namespace. These settings affect only planner/plan-checker waits; executor stall controls are independent.
320
+
321
+ | Key | Type | Default | Allowed Values | Description |
322
+ |-----|------|---------|----------------|-------------|
323
+ | `planner.stall_detection_enabled` | boolean | `true` | `true`, `false` | Default-on bounded stall detection for the standard planner, chunked outline/per-plan planners, plan-checker, and revision planner. `false` skips `gsd_stall_watch` polling but still awaits and consumes the real runtime-native agent result. It gives up bounded automatic recovery if the runtime loses the completion handoff. _Loader projection:_ `planner_stall_detection_enabled`. |
324
+
315
325
  ### Ship Fields
316
326
 
317
327
  Set via `ship.*` namespace in config.json. These fields affect `/gsd:ship` PRD-style pull request body composition only.
@@ -360,6 +370,8 @@ Set via `hooks.*` namespace (e.g., `"hooks": { "context_warnings": true }`).
360
370
  | Key | Type | Default | Allowed Values | Description |
361
371
  |-----|------|---------|----------------|-------------|
362
372
  | `hooks.context_warnings` | boolean | `true` | `true`, `false` | Show warnings when context budget is exceeded |
373
+ | `hooks.context_warning_threshold` | number | `35` | Greater than 0 and at most 100, and strictly greater than `hooks.context_critical_threshold`. `config-set` refuses 0: nothing is below it, so no critical value could satisfy the pair | Percent of context window REMAINING at or below which the monitor emits CONTEXT WARNING. An out-of-domain value falls back **per key**; both keys revert to their defaults only when the RESOLVED pair violates `critical < warning`. Read from the root project config — a workstream-scoped `config-set` does not reach this hook. Inert on a runtime with no context-monitor hook installed, Codex among them (#2586); see [context-monitor.md](../../docs/context-monitor.md) (#4285) |
374
+ | `hooks.context_critical_threshold` | number | `25` | At least 0 and less than 100, and strictly less than `hooks.context_warning_threshold`. `config-set` refuses 100: nothing is above it, so no warning value could satisfy the pair | Percent of context window REMAINING at or below which the monitor escalates to CONTEXT CRITICAL. Setting only one of the pair is checked against the other's default, so tune both when moving either past the other. Same root-config scope, and the same installed-monitor prerequisite, as the key above (#4285) |
363
375
 
364
376
  ### Learnings Fields
365
377
 
@@ -428,7 +440,7 @@ Several config fields affect each other or trigger special behavior:
428
440
 
429
441
  8. **`sub_repos` auto-sync** -- On every config load, GSD scans for child directories with `.git` and updates the `sub_repos` array if the filesystem has changed. Legacy `multiRepo: true` is automatically migrated to a detected `sub_repos` array.
430
442
 
431
- 9. **`workflow.use_worktrees` and branch divergence** -- When `use_worktrees` is `true` (default), executor worktrees are forked from `origin/HEAD` -- by the host's own harness on `dispatch.isolation: harness-worktree` runtimes (Claude Code, Cursor), or by GSD itself on `orchestrator-worktree` runtimes (Codex, OpenCode, Kimi, Kimi Code). The divergence behavior below is identical either way, because the fork base is a property of the repository rather than of whoever creates the worktree. If your current branch has commits that `origin/HEAD` does not (for example an unmerged milestone or feature branch), GSD automatically degrades to sequential execution for that run and prints a one-line `⚠ Worktree base mismatch` warning. To restore parallel execution permanently, set `worktree.baseRef:"head"` in `.claude/settings.local.json` (run `gsd_run worktree set-baseref`). This makes the harness fork worktrees from the live HEAD instead of `origin/HEAD`. Both fresh installs and upgrades of GSD Core set this automatically (no-clobber) when `use_worktrees` is enabled; you can also run the command manually at any time. Setting `workflow.use_worktrees: false` is the alternative if worktrees are not needed at all. On a runtime whose declared `dispatch.isolation` is `none`, an explicit `true` is a config the execution workflows fail closed on; `/gsd:health` reports it as warning `W025` and `/gsd:settings` offers to repair it (#2486).
443
+ 9. **`workflow.use_worktrees` and branch divergence** -- When `use_worktrees` is `true` (default) and `worktree.baseRef` is unset, executor worktrees are forked from `origin/HEAD` -- by the host's own harness on `dispatch.isolation: harness-worktree` runtimes (Claude Code, Cursor), or by GSD itself on `orchestrator-worktree` runtimes (Codex, OpenCode, Kimi, Kimi Code). The divergence behavior below is identical either way, because the fork base is a property of the repository rather than of whoever creates the worktree. If your current branch has commits that `origin/HEAD` does not (for example an unmerged milestone or feature branch), GSD automatically degrades to sequential execution for that run and prints a one-line `⚠ Worktree base mismatch` warning. To restore parallel execution permanently, set `worktree.baseRef:"head"` in `.claude/settings.local.json` (run `gsd_run worktree set-baseref`). GSD-created worktrees then fork from the live HEAD instead of `origin/HEAD` by construction, and the Claude Code harness does the same as measured from every settings layer (#4588; Cursor has not been measured — its exit-42 spawn-time guard is the backstop). A configured Claude Code `WorktreeCreate` hook is the exception: it creates the worktree without applying the setting, so GSD keeps comparing against `origin/HEAD` on such a host (#4588). A prior harness worktree at the current HEAD does not lift that comparison — it records no creator, so one left there before the hook was configured would read as evidence for the hook; pass `--observed-fork-base` for a trusted verdict (#4881). Both fresh installs and upgrades of GSD Core set this automatically (no-clobber) when `use_worktrees` is enabled; you can also run the command manually at any time. Setting `workflow.use_worktrees: false` is the alternative if worktrees are not needed at all. On a runtime whose declared `dispatch.isolation` is `none`, an explicit `true` is a config the execution workflows fail closed on; `/gsd:health` reports it as warning `W025` and `/gsd:settings` offers to repair it (#2486).
432
444
 
433
445
  ---
434
446
 
@@ -178,10 +178,32 @@ cargo test # Rust
178
178
  ```
179
179
 
180
180
  **5. Create first test file:**
181
- Follow project conventions for test location:
182
- - `*.test.ts` / `*.spec.ts` next to source
181
+ Follow project conventions for test location. The RED-commit gate
182
+ (`workflows/execute-phase.md`) recognises the patterns below at any depth, repo root
183
+ included. Note the gate's pathspec is deliberately **wider than the project types the
184
+ detection step above enumerates** — it costs nothing to recognise a convention the
185
+ onboarding flow does not yet auto-detect, and a project using one should not have its
186
+ RED commits go unseen:
187
+ - `*.test.*` / `*.spec.*` next to source — JS/TS and anything sharing the convention
183
188
  - `__tests__/` directory
184
189
  - `tests/` directory at root
190
+ - `*_test.go` — Go
191
+ - `test_*.py` / `*_test.py` — Python (in addition to `tests/`)
192
+ - `*_test.exs` — Elixir
193
+ - `*_spec.rb` / `*_test.rb` — Ruby
194
+
195
+ **Cost of the broad pathspec (#4379).** `*.spec.*` can match a non-test file that happens to carry
196
+ the word — `api.spec.json`, `openapi.spec.yaml` — which lets the RED gate pass on a commit touching
197
+ only that. This is not new: the previous `**/*.spec.*` already matched those at any nested path, so
198
+ dropping the `**/` prefix only extends the same false-positive class to the repo root. It is
199
+ accepted rather than narrowed, because narrowing it is a behaviour change to the
200
+ currently-supported case and not part of making other languages visible.
201
+
202
+ **Known gap — Rust (#4379).** `#[test]` conventionally lives inside the implementation file, so a
203
+ Rust RED commit touches `src/*.rs` and no path-based gate can distinguish it from ordinary source.
204
+ Widening the pathspec to cover it would match all source and make the gate meaningless. `cargo test`
205
+ works; the RED-*commit* gate cannot see it, so a Rust project using `workflow.tdd_mode` should
206
+ expect the gate to trip.
185
207
 
186
208
  Framework setup is a one-time cost included in the first TDD plan's RED phase.
187
209
  </framework_setup>
@@ -273,8 +295,12 @@ When `workflow.tdd_mode` is enabled in config, the RED/GREEN/REFACTOR gate seque
273
295
  After completing a `type: tdd` plan, the executor validates the git log:
274
296
  ```bash
275
297
  # The commit protocol promises no zero-padding for ${PHASE}/${PLAN} — strip both and
276
- # match the commit-scope position anchored (#4003).
277
- PHASE_N=$((10#${PHASE})); PLAN_N=$((10#${PLAN}))
298
+ # match the commit-scope position anchored (#4003). #4619: PHASE may be decimal/
299
+ # N-segment; zero-strip only the leading integer segment, escape the rest.
300
+ # #4748: it may also carry a letter suffix (03A), so split at the first non-digit.
301
+ PHASE_INT=${PHASE%%[!0-9]*}; PHASE_REST=${PHASE#"$PHASE_INT"}
302
+ PHASE_N="$((10#$PHASE_INT))${PHASE_REST//./\\.}"
303
+ PLAN_N=$((10#${PLAN}))
278
304
  # Check for RED gate commit
279
305
  git log --oneline -E --grep="^test\((0*${PHASE_N})-(0*${PLAN_N})\):" | head -1
280
306
  # Check for GREEN gate commit
@@ -34,13 +34,29 @@ For each significant decision in this plan, ask what undoing it would cost three
34
34
 
35
35
  This is the reasoning step that produces the rating. The taxonomy itself, the emission rules, and the anti-patterns live in @~/.claude/gsd-core/references/planner-reversibility.md — do not maintain a second classification here.
36
36
 
37
- ## 5. Curse of Knowledge Counter
37
+ ## 5. Occam's Razor
38
+
39
+ **Counters:** Plans that prescribe avoidable dependencies, abstractions, files, or speculative flexibility before execution begins.
40
+
41
+ This check complements the planner's RESEARCH.md `dont_hand_roll` guidance and the plan checker's Dimension 12 (Pattern Compliance): those sources identify capabilities and established patterns, while this check orders otherwise sufficient implementation choices. The executor applies the related check later in `thinking-models-execution.md`, after the plan has already selected an approach.
42
+
43
+ After preserving locked user decisions and complete requirement coverage, choose the first option that is demonstrably sufficient for the task's `<done>` condition:
44
+
45
+ 1. Existing project behavior, helper, or established pattern
46
+ 2. Standard-library capability
47
+ 3. Native platform capability
48
+ 4. Already-installed dependency
49
+ 5. Minimum new implementation
50
+
51
+ This ordering is a sufficiency check, not permission to make the task smaller. It must never reduce requested scope or override locked user decisions, requirement coverage, security, validation, accessibility, error handling, or verification. The planner uses it when choosing implementation actions; the plan checker flags a new abstraction or dependency only when a higher rung is demonstrably sufficient.
52
+
53
+ ## 6. Curse of Knowledge Counter
38
54
 
39
55
  **Counters:** Plan-to-executor ambiguity from compressed instructions.
40
56
 
41
57
  For each `<action>` step, re-read it as if you have NEVER seen this codebase. Is every noun unambiguous (which file? which function? which endpoint?)? Is every verb specific (add WHERE? modify HOW?)? If a step could be interpreted two ways, rewrite it. Include file paths, function names, and expected behavior in every action step.
42
58
 
43
- ## 6. Base Rate Neglect Counter
59
+ ## 7. Base Rate Neglect Counter
44
60
 
45
61
  **Counters:** Planners ignoring low-confidence research caveats.
46
62
 
@@ -15,11 +15,16 @@ here. Forcing them into a closed compiled taxonomy is the wrong model.
15
15
 
16
16
  ## Inputs
17
17
 
18
- A list of UI elements, each a `{ id, text, elements? }` record where `text` is the
19
- researcher-authored description and `elements` is an optional author-supplied override of the
20
- element classification. The six element kinds are: `form`, `list-collection`, `nav`, `media`,
21
- `interactive-control`, `static-content`. When `elements` is absent, a heuristic classifier
22
- proposes kinds from the prose (propose-then-confirm) — the author may correct the kind.
18
+ A list of UI elements, each a `{ id, text, text_en?, elements? }` record where `text` is the
19
+ researcher-authored description, `elements` is an optional author-supplied override of the
20
+ element classification, and `text_en` is an optional English translation of `text`
21
+ (#4657). The element cues are English word-boundary patterns, so a non-English `text` (a
22
+ project running with `response_language` set) classifies to zero kinds unless `text_en`
23
+ carries a faithful English rendering — engine input, never user-facing output; `text`
24
+ itself keeps the UI-SPEC's own language and is never translated. The six element kinds are:
25
+ `form`, `list-collection`, `nav`, `media`, `interactive-control`, `static-content`. When
26
+ `elements` is absent, a heuristic classifier proposes kinds from the prose
27
+ (`text_en ?? text`, propose-then-confirm) — the author may correct the kind.
23
28
 
24
29
  ## Taxonomy (8 categories)
25
30
 
@@ -309,14 +309,17 @@ grep -r "$hook_name()" src/ --include="*.tsx" --include="*.ts" | grep -v "$hook_
309
309
  # .env file exists
310
310
  [ -f ".env" ] || [ -f ".env.local" ]
311
311
 
312
- # Required variable is defined
313
- grep -E "^$VAR_NAME=" .env .env.local 2>/dev/null
312
+ # Required variable is defined (in the environment: dotenv/direnv/the framework has loaded it)
313
+ printenv "$VAR_NAME" >/dev/null
314
314
  ```
315
315
 
316
316
  **Substantive check:**
317
317
  ```bash
318
- # Variable has actual value (not placeholder)
319
- grep -E "^$VAR_NAME=.+" .env .env.local 2>/dev/null | grep -v "your-.*-here|xxx|placeholder|TODO" -i
318
+ # Variable has an actual value (not a placeholder) -- tests the shape, never prints the value;
319
+ # exit 0 = real value, exit 1 = missing or placeholder (case-insensitive)
320
+ v=$(printenv "$VAR_NAME"); case "$(printf %s "$v" | tr '[:upper:]' '[:lower:]')" in
321
+ ""|*your-*-here*|*xxx*|*placeholder*|*todo*) exit 1;;
322
+ esac
320
323
 
321
324
  # Value looks valid for type:
322
325
  # - URLs should start with http
@@ -324,6 +327,16 @@ grep -E "^$VAR_NAME=.+" .env .env.local 2>/dev/null | grep -v "your-.*-here|xxx|
324
327
  # - Booleans should be true/false
325
328
  ```
326
329
 
330
+ When the variable is not present in the agent's own environment (a framework that loads
331
+ `.env.local` itself at runtime does not export it to the shell that runs these checks),
332
+ ask the user to confirm it is set rather than reading `.env` directly. Variable NAMES can
333
+ still be checked against `.env.example`, which the secret-read guard exempts from its
334
+ protected-file patterns.
335
+
336
+ One guard-matching note worth knowing when auditing docs for `.env` mentions: the guard
337
+ treats a grep PATTERN whose last path segment is a secret file name as a file operand, so
338
+ `grep -n "\.env" file.md` is denied while `grep -n "\.env\b" file.md` is allowed.
339
+
327
340
  **Stub patterns specific to env:**
328
341
  ```bash
329
342
  # RED FLAGS - These are stubs:
@@ -11,8 +11,9 @@ checker flagged a bad `cd ../../frontend` (correct), then prescribed two success
11
11
  replacement paths — the second citing a `package.json` that did not exist. Consume the
12
12
  deterministic probe result, never re-derive it yourself.
13
13
 
14
- `gsd-core/workflows/plan-phase.md` already runs the probe **before** spawning this checker and
15
- interpolates the result into the verification prompt as `{VERIFY_PATHS}`, inside a
14
+ `gsd-core/workflows/plan-phase.md` — and, since #4767, quick mode's
15
+ `quick/steps/plan-checker-loop.md` (via `--dir`) — already runs the probe **before** spawning this
16
+ checker and interpolates the result into the verification prompt as `{VERIFY_PATHS}`, inside a
16
17
  `<verify_command_path_probe>` block. This dimension reads that already-supplied JSON — it never
17
18
  invokes `gsd_run check verify-command-paths` itself. If `{VERIFY_PATHS}` is absent from the
18
19
  prompt, treat this dimension as silent (nothing to check) rather than trying to run the probe.
@@ -37,6 +38,13 @@ Rules:
37
38
  a finding.** Say nothing.
38
39
  - `unresolvable` means the probe could not ground the path (a variable, glob, substitution, or
39
40
  `~`). That is a WARNING, never a BLOCKER — and never a licence to guess the literal path.
41
+ - `outside_root` covers two shapes: a bare ancestor climb (`cd ../..`) and an **absolute target
42
+ outside the project root** (#4767). Both are ambiguous across worktrees; the absolute one is
43
+ pinned to a single checkout, so under worktree isolation it runs against the wrong tree and
44
+ passes. Report it as a WARNING with the target verbatim. Note the probe's root is the
45
+ *orchestrator's*: an absolute path inside it passes here and still misfires under isolation,
46
+ which is why the planner's path-form rule (root-relative, cwd at the checkout root) is the fix
47
+ and this probe the backstop.
40
48
  - A non-empty `readError` means the probe **could not look**. Report that as a WARNING in its
41
49
  own words; it is not a clean bill of health.
42
50
  - `MISSING …` sentinels are Dimension 8's business — this dimension stays silent on them.