@opengsd/gsd-core 1.14.0 → 1.16.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 (551) 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 +85 -5
  4. package/README.ja-JP.md +3 -3
  5. package/README.ko-KR.md +3 -3
  6. package/README.pt-BR.md +3 -3
  7. package/README.zh-CN.md +3 -3
  8. package/agents/gsd-code-fixer.compact.md +7 -6
  9. package/agents/gsd-code-fixer.md +9 -8
  10. package/agents/gsd-code-reviewer.compact.md +5 -3
  11. package/agents/gsd-code-reviewer.md +8 -6
  12. package/agents/gsd-debug-session-manager.compact.md +17 -2
  13. package/agents/gsd-debug-session-manager.md +17 -2
  14. package/agents/gsd-debugger.md +3 -3
  15. package/agents/gsd-eval-auditor.compact.md +1 -1
  16. package/agents/gsd-eval-auditor.md +1 -1
  17. package/agents/gsd-executor.md +17 -12
  18. package/agents/gsd-intel-updater.compact.md +1 -1
  19. package/agents/gsd-intel-updater.md +1 -1
  20. package/agents/gsd-mempalace-curator.md +2 -2
  21. package/agents/gsd-phase-researcher.md +19 -11
  22. package/agents/gsd-plan-checker.md +15 -9
  23. package/agents/gsd-planner.md +15 -11
  24. package/agents/gsd-project-researcher.compact.md +1 -1
  25. package/agents/gsd-project-researcher.md +1 -1
  26. package/agents/gsd-research-synthesizer.compact.md +1 -1
  27. package/agents/gsd-research-synthesizer.md +1 -1
  28. package/agents/gsd-ui-auditor.compact.md +21 -30
  29. package/agents/gsd-ui-auditor.md +166 -37
  30. package/agents/gsd-ui-researcher.compact.md +1 -1
  31. package/agents/gsd-ui-researcher.md +1 -1
  32. package/agents/gsd-verifier.md +37 -14
  33. package/bin/install.js +764 -287
  34. package/commands/gsd/add-tests.md +6 -1
  35. package/commands/gsd/ai-integration-phase.md +6 -1
  36. package/commands/gsd/audit-fix.md +5 -0
  37. package/commands/gsd/audit-milestone.md +6 -1
  38. package/commands/gsd/autonomous.md +7 -2
  39. package/commands/gsd/capture.md +9 -5
  40. package/commands/gsd/code-review.md +7 -2
  41. package/commands/gsd/complete-milestone.md +4 -0
  42. package/commands/gsd/config.md +7 -3
  43. package/commands/gsd/debug.md +11 -7
  44. package/commands/gsd/discuss-phase.md +7 -3
  45. package/commands/gsd/docs-update.md +12 -7
  46. package/commands/gsd/eval-review.md +6 -1
  47. package/commands/gsd/execute-phase.md +12 -7
  48. package/commands/gsd/extract-learnings.md +5 -0
  49. package/commands/gsd/fast.md +4 -0
  50. package/commands/gsd/forensics.md +5 -1
  51. package/commands/gsd/graphify.md +10 -6
  52. package/commands/gsd/health.md +5 -0
  53. package/commands/gsd/help.md +7 -2
  54. package/commands/gsd/import.md +7 -3
  55. package/commands/gsd/inbox.md +5 -0
  56. package/commands/gsd/ingest-docs.md +5 -1
  57. package/commands/gsd/manager.md +6 -1
  58. package/commands/gsd/map-codebase.md +7 -3
  59. package/commands/gsd/mempalace-capture.md +12 -4
  60. package/commands/gsd/mempalace-recall.md +5 -1
  61. package/commands/gsd/milestone-summary.md +5 -1
  62. package/commands/gsd/mvp-phase.md +8 -3
  63. package/commands/gsd/new-milestone.md +6 -1
  64. package/commands/gsd/new-project.md +5 -0
  65. package/commands/gsd/next.md +6 -1
  66. package/commands/gsd/ns-context.md +4 -0
  67. package/commands/gsd/ns-ideate.md +4 -0
  68. package/commands/gsd/ns-manage.md +4 -0
  69. package/commands/gsd/ns-project.md +4 -0
  70. package/commands/gsd/ns-review.md +4 -0
  71. package/commands/gsd/ns-workflow.md +4 -0
  72. package/commands/gsd/onboard.md +6 -1
  73. package/commands/gsd/pause-work.md +5 -1
  74. package/commands/gsd/phase.md +8 -4
  75. package/commands/gsd/plan-phase.md +6 -1
  76. package/commands/gsd/plan-review-convergence.md +11 -7
  77. package/commands/gsd/pr-branch.md +4 -0
  78. package/commands/gsd/profile-user.md +5 -1
  79. package/commands/gsd/progress.md +7 -2
  80. package/commands/gsd/quick-batch.md +21 -9
  81. package/commands/gsd/quick.md +12 -7
  82. package/commands/gsd/review.md +7 -4
  83. package/commands/gsd/secure-phase.md +6 -1
  84. package/commands/gsd/ship.md +5 -0
  85. package/commands/gsd/sketch.md +7 -2
  86. package/commands/gsd/spec-phase.md +5 -1
  87. package/commands/gsd/spike.md +8 -3
  88. package/commands/gsd/surface.md +5 -1
  89. package/commands/gsd/thread.md +4 -0
  90. package/commands/gsd/ui-phase.md +6 -1
  91. package/commands/gsd/ui-review.md +6 -1
  92. package/commands/gsd/ultraplan-phase.md +5 -1
  93. package/commands/gsd/undo.md +5 -1
  94. package/commands/gsd/update.md +6 -2
  95. package/commands/gsd/validate-phase.md +6 -1
  96. package/commands/gsd/verify-work.md +6 -1
  97. package/commands/gsd/workspace.md +7 -3
  98. package/gsd-core/bin/gsd-tools.cjs +477 -78
  99. package/gsd-core/bin/lib/active-workstream-store.cjs +15 -0
  100. package/gsd-core/bin/lib/adr-parser.cjs +3 -1
  101. package/gsd-core/bin/lib/agent-install-check.cjs +4 -1
  102. package/gsd-core/bin/lib/audit.cjs +144 -42
  103. package/gsd-core/bin/lib/broken-windows.cjs +13 -13
  104. package/gsd-core/bin/lib/capability-activation.cjs +9 -4
  105. package/gsd-core/bin/lib/capability-registry.cjs +197 -222
  106. package/gsd-core/bin/lib/capability-validator.cjs +16 -1
  107. package/gsd-core/bin/lib/check-auto-mode.cjs +35 -0
  108. package/gsd-core/bin/lib/check-command-router.cjs +164 -1625
  109. package/gsd-core/bin/lib/cjs-command-router-adapter.cjs +13 -2
  110. package/gsd-core/bin/lib/cli-exit.cjs +12 -0
  111. package/gsd-core/bin/lib/codex-agent-toml.cjs +32 -33
  112. package/gsd-core/bin/lib/command-aliases.cjs +7 -0
  113. package/gsd-core/bin/lib/command-routing-hub.cjs +48 -1
  114. package/gsd-core/bin/lib/commands.cjs +343 -207
  115. package/gsd-core/bin/lib/complexity-trigger.cjs +8 -7
  116. package/gsd-core/bin/lib/config-loader.cjs +65 -4
  117. package/gsd-core/bin/lib/config.cjs +76 -19
  118. package/gsd-core/bin/lib/core-utils.cjs +6 -1
  119. package/gsd-core/bin/lib/coverage.cjs +4 -8
  120. package/gsd-core/bin/lib/decision-coverage-support.cjs +259 -0
  121. package/gsd-core/bin/lib/decisions.cjs +30 -14
  122. package/gsd-core/bin/lib/drift.cjs +177 -42
  123. package/gsd-core/bin/lib/frontmatter-fence.cjs +90 -0
  124. package/gsd-core/bin/lib/frontmatter-splice.cjs +494 -0
  125. package/gsd-core/bin/lib/frontmatter.cjs +426 -234
  126. package/gsd-core/bin/lib/gap-checker.cjs +72 -29
  127. package/gsd-core/bin/lib/gate-api-coverage-verify-pre.cjs +381 -0
  128. package/gsd-core/bin/lib/gate-args.cjs +53 -0
  129. package/gsd-core/bin/lib/gate-codebase-drift.cjs +285 -0
  130. package/gsd-core/bin/lib/gate-config.cjs +46 -0
  131. package/gsd-core/bin/lib/gate-context-drift.cjs +141 -0
  132. package/gsd-core/bin/lib/gate-decision-coverage-plan.cjs +169 -0
  133. package/gsd-core/bin/lib/gate-decision-coverage-verify.cjs +126 -0
  134. package/gsd-core/bin/lib/gate-evaluation-scope.cjs +555 -0
  135. package/gsd-core/bin/lib/gate-evidence.cjs +138 -0
  136. package/gsd-core/bin/lib/gate-exit.cjs +27 -0
  137. package/gsd-core/bin/lib/gate-gap-analysis-plan-post.cjs +61 -0
  138. package/gsd-core/bin/lib/gate-phase-context.cjs +170 -0
  139. package/gsd-core/bin/lib/gate-predicate-evaluator.cjs +1 -1
  140. package/gsd-core/bin/lib/gate-predicate.cjs +165 -0
  141. package/gsd-core/bin/lib/gate-prohibition-enforcement.cjs +94 -0
  142. package/gsd-core/bin/lib/gate-schema-drift.cjs +165 -0
  143. package/gsd-core/bin/lib/gate-tdd-red-evidence.cjs +100 -0
  144. package/gsd-core/bin/lib/gate-tdd-review-checkpoint.cjs +182 -0
  145. package/gsd-core/bin/lib/gate-ui-plan.cjs +86 -0
  146. package/gsd-core/bin/lib/gate-ui-safety.cjs +80 -0
  147. package/gsd-core/bin/lib/gate-verdict.cjs +64 -0
  148. package/gsd-core/bin/lib/gate-verify-command-paths.cjs +78 -0
  149. package/gsd-core/bin/lib/gate-verify-failure-directions.cjs +41 -0
  150. package/gsd-core/bin/lib/graphify.cjs +10 -2
  151. package/gsd-core/bin/lib/health-diagnostic-rules/phase-structure.cjs +43 -47
  152. package/gsd-core/bin/lib/health-diagnostic.cjs +45 -8
  153. package/gsd-core/bin/lib/host-runtime-detection.cjs +9 -0
  154. package/gsd-core/bin/lib/init.cjs +364 -132
  155. package/gsd-core/bin/lib/install-engine.cjs +30 -33
  156. package/gsd-core/bin/lib/install-profiles.cjs +7 -4
  157. package/gsd-core/bin/lib/installer-migrations.cjs +8 -1
  158. package/gsd-core/bin/lib/io.cjs +122 -3
  159. package/gsd-core/bin/lib/loop-resolver.cjs +95 -0
  160. package/gsd-core/bin/lib/markdown-sectionizer.cjs +75 -1
  161. package/gsd-core/bin/lib/milestone.cjs +37 -6
  162. package/gsd-core/bin/lib/model-resolver.cjs +171 -62
  163. package/gsd-core/bin/lib/observability/event.cjs +1 -1
  164. package/gsd-core/bin/lib/observability/logger.cjs +46 -1
  165. package/gsd-core/bin/lib/pattern.cjs +10 -0
  166. package/gsd-core/bin/lib/phase-command-router.cjs +20 -5
  167. package/gsd-core/bin/lib/phase-estimation.cjs +5 -4
  168. package/gsd-core/bin/lib/phase-id-card.cjs +32 -0
  169. package/gsd-core/bin/lib/phase-id-display.cjs +78 -0
  170. package/gsd-core/bin/lib/phase-id.cjs +110 -8
  171. package/gsd-core/bin/lib/phase-lifecycle.cjs +9 -2
  172. package/gsd-core/bin/lib/phase-locator.cjs +29 -10
  173. package/gsd-core/bin/lib/phase-status.cjs +360 -0
  174. package/gsd-core/bin/lib/phase.cjs +489 -88
  175. package/gsd-core/bin/lib/plan-document.cjs +142 -20
  176. package/gsd-core/bin/lib/plan-drift-guard.cjs +5 -0
  177. package/gsd-core/bin/lib/planning-document.cjs +692 -0
  178. package/gsd-core/bin/lib/planning-inspect.cjs +60 -9
  179. package/gsd-core/bin/lib/planning-snapshot.cjs +18 -0
  180. package/gsd-core/bin/lib/planning-workspace.cjs +83 -55
  181. package/gsd-core/bin/lib/pr-branch-patterns.cjs +57 -0
  182. package/gsd-core/bin/lib/pristine-baseline.cjs +10 -0
  183. package/gsd-core/bin/lib/probe-core.cjs +7 -1
  184. package/gsd-core/bin/lib/profile-output.cjs +6 -3
  185. package/gsd-core/bin/lib/prohibition-enforcement.cjs +0 -55
  186. package/gsd-core/bin/lib/project-root.cjs +41 -2
  187. package/gsd-core/bin/lib/quick-batch-command-router.cjs +35 -9
  188. package/gsd-core/bin/lib/quick-batch-dispatch.cjs +11 -8
  189. package/gsd-core/bin/lib/real-home-guard.cjs +9 -1
  190. package/gsd-core/bin/lib/report-parser.cjs +269 -0
  191. package/gsd-core/bin/lib/review-lane-descriptor.cjs +10 -30
  192. package/gsd-core/bin/lib/review-reviewer-selection.cjs +2 -2
  193. package/gsd-core/bin/lib/roadmap-command-router.cjs +25 -19
  194. package/gsd-core/bin/lib/roadmap-parser.cjs +242 -15
  195. package/gsd-core/bin/lib/roadmap-upgrade.cjs +1653 -65
  196. package/gsd-core/bin/lib/roadmap.cjs +405 -88
  197. package/gsd-core/bin/lib/runtime-artifact-conversion.cjs +373 -187
  198. package/gsd-core/bin/lib/runtime-artifact-install-plan.cjs +5 -2
  199. package/gsd-core/bin/lib/runtime-artifact-layout.cjs +57 -1
  200. package/gsd-core/bin/lib/runtime-homes.cjs +14 -7
  201. package/gsd-core/bin/lib/runtime-hooks-surface.cjs +522 -624
  202. package/gsd-core/bin/lib/runtime-name-policy.cjs +246 -21
  203. package/gsd-core/bin/lib/runtime-slash.cjs +47 -30
  204. package/gsd-core/bin/lib/shell-command-projection.cjs +47 -8
  205. package/gsd-core/bin/lib/smart-entry.cjs +19 -3
  206. package/gsd-core/bin/lib/stale-bake-guard.cjs +32 -48
  207. package/gsd-core/bin/lib/state-contract.cjs +15 -18
  208. package/gsd-core/bin/lib/state-document.cjs +100 -22
  209. package/gsd-core/bin/lib/state-transition.cjs +39 -2
  210. package/gsd-core/bin/lib/state.cjs +256 -105
  211. package/gsd-core/bin/lib/surface.cjs +19 -2
  212. package/gsd-core/bin/lib/tdd-red-evidence.cjs +48 -79
  213. package/gsd-core/bin/lib/uat-predicate.cjs +359 -38
  214. package/gsd-core/bin/lib/uat.cjs +432 -7
  215. package/gsd-core/bin/lib/ui-consideration-probe.cjs +15 -2
  216. package/gsd-core/bin/lib/ui-frontend-evidence.cjs +167 -40
  217. package/gsd-core/bin/lib/undo-commit-selection.cjs +131 -0
  218. package/gsd-core/bin/lib/vendor/README.md +31 -9
  219. package/gsd-core/bin/lib/vendor/saxes.cjs +1934 -0
  220. package/gsd-core/bin/lib/vendor/saxes.cjs.LICENSE.txt +92 -0
  221. package/gsd-core/bin/lib/vendor/tap-parser.cjs +8927 -0
  222. package/gsd-core/bin/lib/vendor/tap-parser.cjs.LICENSE.txt +152 -0
  223. package/gsd-core/bin/lib/verification-command-router.cjs +2 -1
  224. package/gsd-core/bin/lib/verification.cjs +1378 -274
  225. package/gsd-core/bin/lib/verify-command-grounding.cjs +46 -2
  226. package/gsd-core/bin/lib/verify-command-router.cjs +18 -7
  227. package/gsd-core/bin/lib/verify.cjs +357 -531
  228. package/gsd-core/bin/lib/workstream-inventory-builder.cjs +14 -6
  229. package/gsd-core/bin/lib/workstream-inventory.cjs +31 -21
  230. package/gsd-core/bin/lib/workstream-name-policy.cjs +31 -1
  231. package/gsd-core/bin/lib/workstream.cjs +11 -2
  232. package/gsd-core/bin/lib/worktree-base-ref.cjs +482 -73
  233. package/gsd-core/bin/lib/worktree-safety.cjs +784 -51
  234. package/gsd-core/bin/shared/config-defaults.manifest.json +8 -0
  235. package/gsd-core/bin/shared/config-schema.manifest.json +5 -0
  236. package/gsd-core/references/autonomous-smart-discuss.md +2 -1
  237. package/gsd-core/references/autonomous-ui-design-contract.md +3 -3
  238. package/gsd-core/references/checkpoints.md +5 -3
  239. package/gsd-core/references/edge-probe-fixtures/01-round-half-even/expected-coverage.json +28 -3
  240. package/gsd-core/references/edge-probe-fixtures/02-merge-intervals/expected-coverage.json +37 -4
  241. package/gsd-core/references/edge-probe-fixtures/03-truncate-graphemes/expected-coverage.json +28 -3
  242. package/gsd-core/references/edge-probe-fixtures/04-money-rounding/expected-coverage.json +28 -3
  243. package/gsd-core/references/edge-probe-fixtures/05-list-dedupe/expected-coverage.json +37 -4
  244. package/gsd-core/references/edge-probe-fixtures/06-resolved-mixed/expected-coverage.json +37 -4
  245. package/gsd-core/references/edge-probe.md +195 -21
  246. package/gsd-core/references/execute-mvp-tdd.md +5 -10
  247. package/gsd-core/references/execute-phase-between-wave-reset.md +10 -6
  248. package/gsd-core/references/execute-phase-response-language.md +1 -1
  249. package/gsd-core/references/execute-phase-wave-guard.md +22 -11
  250. package/gsd-core/references/gsd-run-resolver.md +1 -1
  251. package/gsd-core/references/loop-hook-dispatch.md +7 -1
  252. package/gsd-core/references/model-profiles.md +1 -1
  253. package/gsd-core/references/offer-next.md +1 -1
  254. package/gsd-core/references/phase-argument-parsing.md +9 -7
  255. package/gsd-core/references/phase-id-convention.md +28 -0
  256. package/gsd-core/references/planner-gap-closure.md +2 -0
  257. package/gsd-core/references/planner-load-graph-context.md +24 -13
  258. package/gsd-core/references/planner-verify-command-grounding.md +14 -0
  259. package/gsd-core/references/planning-config.md +12 -3
  260. package/gsd-core/references/spidr-splitting.md +1 -1
  261. package/gsd-core/references/tdd.md +37 -8
  262. package/gsd-core/references/ui-consideration-probe.md +10 -5
  263. package/gsd-core/references/verifier-phase-gates.md +5 -2
  264. package/gsd-core/references/verify-command-path-resolvability.md +10 -2
  265. package/gsd-core/references/verify-mvp-mode.md +2 -2
  266. package/gsd-core/references/workstream-flag.md +33 -3
  267. package/gsd-core/references/worktree-path-safety.md +321 -0
  268. package/gsd-core/templates/README.md +1 -1
  269. package/gsd-core/templates/UAT.md +17 -1
  270. package/gsd-core/templates/config.json +2 -11
  271. package/gsd-core/templates/verification-report.md +1 -1
  272. package/gsd-core/workflows/_runtime-launcher.snippet.sh +1 -1
  273. package/gsd-core/workflows/add-backlog.md +1 -1
  274. package/gsd-core/workflows/add-phase.md +8 -7
  275. package/gsd-core/workflows/add-tests.md +4 -3
  276. package/gsd-core/workflows/add-todo.md +6 -5
  277. package/gsd-core/workflows/ai-integration-phase.md +13 -4
  278. package/gsd-core/workflows/audit-fix.md +1 -1
  279. package/gsd-core/workflows/audit-milestone.md +4 -3
  280. package/gsd-core/workflows/audit-uat.md +1 -1
  281. package/gsd-core/workflows/autonomous/steps/converge-fail-fast.md +9 -18
  282. package/gsd-core/workflows/autonomous.md +43 -23
  283. package/gsd-core/workflows/check-todos.md +7 -6
  284. package/gsd-core/workflows/cleanup.md +2 -2
  285. package/gsd-core/workflows/code-review/steps/dispatch-fix.md +4 -3
  286. package/gsd-core/workflows/code-review/steps/structural-pre-pass.md +20 -13
  287. package/gsd-core/workflows/code-review-fix.md +112 -25
  288. package/gsd-core/workflows/code-review.md +146 -135
  289. package/gsd-core/workflows/complete-milestone/detail/elaboration.md +4 -3
  290. package/gsd-core/workflows/complete-milestone.md +13 -8
  291. package/gsd-core/workflows/debug.md +32 -7
  292. package/gsd-core/workflows/diagnose-issues.md +3 -2
  293. package/gsd-core/workflows/discuss-phase/modes/advisor.md +1 -1
  294. package/gsd-core/workflows/discuss-phase/modes/chain.md +1 -1
  295. package/gsd-core/workflows/discuss-phase-assumptions.md +4 -3
  296. package/gsd-core/workflows/discuss-phase.md +4 -3
  297. package/gsd-core/workflows/do.md +2 -2
  298. package/gsd-core/workflows/docs-update.md +6 -5
  299. package/gsd-core/workflows/edit-phase.md +4 -3
  300. package/gsd-core/workflows/eval-review.md +14 -5
  301. package/gsd-core/workflows/execute-phase/detail/elaboration.md +2 -2
  302. package/gsd-core/workflows/execute-phase/steps/code-review-disposition.md +1019 -0
  303. package/gsd-core/workflows/execute-phase/steps/codebase-drift-gate.md +15 -4
  304. package/gsd-core/workflows/execute-phase/steps/completion-reconciliation.md +10 -7
  305. package/gsd-core/workflows/execute-phase/steps/executor-isolation-dispatch.md +37 -3
  306. package/gsd-core/workflows/execute-phase/steps/gap-closure-artifacts.md +3 -1
  307. package/gsd-core/workflows/execute-phase/steps/partial-wave.md +2 -2
  308. package/gsd-core/workflows/execute-phase/steps/per-plan-executor-routing.md +1 -1
  309. package/gsd-core/workflows/execute-phase/steps/per-plan-worktree-gate.md +1 -1
  310. package/gsd-core/workflows/execute-phase/steps/post-merge-gate.md +46 -9
  311. package/gsd-core/workflows/execute-phase/steps/protected-branch.md +1 -1
  312. package/gsd-core/workflows/execute-phase/steps/ready-wave-gate.md +37 -0
  313. package/gsd-core/workflows/execute-phase/steps/regression-gate-run.md +1 -1
  314. package/gsd-core/workflows/execute-phase/steps/regression-gate.md +2 -0
  315. package/gsd-core/workflows/execute-phase/steps/tdd-applicability-resolution.md +1 -1
  316. package/gsd-core/workflows/execute-phase/steps/threat-id-gate.md +28 -0
  317. package/gsd-core/workflows/execute-phase/steps/verify-phase-goal.md +187 -0
  318. package/gsd-core/workflows/execute-phase/steps/wave-post-gate-hooks.md +2 -3
  319. package/gsd-core/workflows/execute-phase/steps/worktree-base-check.md +25 -0
  320. package/gsd-core/workflows/execute-phase.md +96 -178
  321. package/gsd-core/workflows/execute-plan.md +18 -23
  322. package/gsd-core/workflows/explore.md +4 -4
  323. package/gsd-core/workflows/extract-learnings.md +4 -2
  324. package/gsd-core/workflows/fast.md +1 -1
  325. package/gsd-core/workflows/forensics.md +1 -1
  326. package/gsd-core/workflows/graduation.md +1 -1
  327. package/gsd-core/workflows/health.md +3 -2
  328. package/gsd-core/workflows/help/modes/full.compact.md +3 -3
  329. package/gsd-core/workflows/help/modes/full.md +5 -5
  330. package/gsd-core/workflows/help/modes/topic.md +15 -5
  331. package/gsd-core/workflows/import.md +4 -3
  332. package/gsd-core/workflows/inbox.md +2 -2
  333. package/gsd-core/workflows/ingest-docs.md +3 -3
  334. package/gsd-core/workflows/insert-phase.md +4 -3
  335. package/gsd-core/workflows/list-seeds.md +1 -1
  336. package/gsd-core/workflows/list-workspaces.md +1 -1
  337. package/gsd-core/workflows/manager.md +6 -4
  338. package/gsd-core/workflows/map-codebase.md +5 -4
  339. package/gsd-core/workflows/milestone-summary.md +3 -2
  340. package/gsd-core/workflows/mvp-phase.md +14 -14
  341. package/gsd-core/workflows/new-milestone.md +11 -11
  342. package/gsd-core/workflows/new-project/steps/auto-mode-config.md +3 -3
  343. package/gsd-core/workflows/new-project/steps/codebase-map-offer.md +1 -1
  344. package/gsd-core/workflows/new-project.md +7 -7
  345. package/gsd-core/workflows/new-workspace.md +2 -2
  346. package/gsd-core/workflows/next.md +1 -1
  347. package/gsd-core/workflows/note.md +1 -1
  348. package/gsd-core/workflows/onboard.md +1 -1
  349. package/gsd-core/workflows/pause-work.md +2 -2
  350. package/gsd-core/workflows/plan-phase/detail/elaboration.md +1 -1
  351. package/gsd-core/workflows/plan-phase/steps/chunked-planning-mode.md +17 -5
  352. package/gsd-core/workflows/plan-phase/steps/closed-phase-gate.md +1 -1
  353. package/gsd-core/workflows/plan-phase/steps/prd-express-path.md +1 -1
  354. package/gsd-core/workflows/plan-phase/steps/stall-detection-helpers.md +23 -5
  355. package/gsd-core/workflows/plan-phase.md +50 -24
  356. package/gsd-core/workflows/plan-review-convergence.md +21 -5
  357. package/gsd-core/workflows/plant-seed.md +62 -20
  358. package/gsd-core/workflows/pr-branch.md +113 -13
  359. package/gsd-core/workflows/profile-user.md +2 -2
  360. package/gsd-core/workflows/progress.md +19 -49
  361. package/gsd-core/workflows/quick/steps/plan-checker-loop.md +27 -0
  362. package/gsd-core/workflows/quick/steps/quick-verification.md +4 -4
  363. package/gsd-core/workflows/quick/steps/worktree-pre-dispatch-commit.md +30 -11
  364. package/gsd-core/workflows/quick-batch/steps/batch-init.md +1 -1
  365. package/gsd-core/workflows/quick-batch/steps/completion.md +1 -1
  366. package/gsd-core/workflows/quick-batch/steps/merge-wave.md +1 -1
  367. package/gsd-core/workflows/quick-batch/steps/planner-wave.md +1 -1
  368. package/gsd-core/workflows/quick-batch/steps/research-phase.md +1 -1
  369. package/gsd-core/workflows/quick-batch/steps/resume-mode.md +1 -1
  370. package/gsd-core/workflows/quick-batch/steps/verification-wave.md +9 -3
  371. package/gsd-core/workflows/quick-batch/steps/worktree-dispatch.md +1 -1
  372. package/gsd-core/workflows/quick-batch.md +15 -10
  373. package/gsd-core/workflows/quick.md +62 -39
  374. package/gsd-core/workflows/reapply-patches.md +9 -3
  375. package/gsd-core/workflows/remove-phase.md +3 -2
  376. package/gsd-core/workflows/remove-workspace.md +2 -2
  377. package/gsd-core/workflows/resume-project.md +3 -2
  378. package/gsd-core/workflows/review.md +33 -17
  379. package/gsd-core/workflows/scan.md +3 -2
  380. package/gsd-core/workflows/secure-phase.md +13 -13
  381. package/gsd-core/workflows/settings-advanced.md +30 -10
  382. package/gsd-core/workflows/settings-integrations.md +2 -3
  383. package/gsd-core/workflows/settings.md +4 -4
  384. package/gsd-core/workflows/ship.md +14 -13
  385. package/gsd-core/workflows/sketch-wrap-up.md +1 -1
  386. package/gsd-core/workflows/sketch.md +1 -1
  387. package/gsd-core/workflows/smart-entry.md +2 -2
  388. package/gsd-core/workflows/spec-phase.md +15 -5
  389. package/gsd-core/workflows/spike-wrap-up.md +1 -1
  390. package/gsd-core/workflows/spike.md +1 -1
  391. package/gsd-core/workflows/stats.md +1 -1
  392. package/gsd-core/workflows/sync-skills.md +5 -5
  393. package/gsd-core/workflows/thread.md +2 -2
  394. package/gsd-core/workflows/transition.md +13 -23
  395. package/gsd-core/workflows/ui-phase.md +48 -11
  396. package/gsd-core/workflows/ui-review.md +21 -6
  397. package/gsd-core/workflows/ultraplan-phase.md +3 -2
  398. package/gsd-core/workflows/undo.md +339 -20
  399. package/gsd-core/workflows/update.md +7 -7
  400. package/gsd-core/workflows/validate-phase.md +12 -13
  401. package/gsd-core/workflows/verify-work/detail/elaboration.md +43 -3
  402. package/gsd-core/workflows/verify-work/steps/automated-ui-verification.md +1 -1
  403. package/gsd-core/workflows/verify-work/steps/mvp-uat-framing.md +5 -3
  404. package/gsd-core/workflows/verify-work.md +129 -55
  405. package/hooks/dist/gsd-agent-isolation-guard.js +32 -0
  406. package/hooks/dist/gsd-check-update-worker.js +8 -0
  407. package/hooks/dist/gsd-check-update.js +8 -0
  408. package/hooks/dist/gsd-context-monitor.js +31 -8
  409. package/hooks/dist/gsd-cursor-subagent-start.js +8 -0
  410. package/hooks/dist/gsd-secret-read-guard.js +161 -4
  411. package/hooks/dist/gsd-statusline.js +85 -20
  412. package/hooks/dist/gsd-update-banner.js +8 -0
  413. package/hooks/dist/gsd-validate-commit.sh +63 -4
  414. package/hooks/dist/gsd-windsurf-pre-write.js +11 -2
  415. package/hooks/dist/gsd-workflow-guard.js +5 -4
  416. package/hooks/dist/gsd-worktree-path-guard.js +6 -2
  417. package/hooks/dist/lib/cli-exit.js +12 -0
  418. package/hooks/dist/lib/git-probe.js +17 -1
  419. package/hooks/dist/lib/isolation-sentinel.js +2 -2
  420. package/hooks/gsd-agent-isolation-guard.js +32 -0
  421. package/hooks/gsd-check-update-worker.js +8 -0
  422. package/hooks/gsd-check-update.js +8 -0
  423. package/hooks/gsd-context-monitor.js +31 -8
  424. package/hooks/gsd-cursor-subagent-start.js +8 -0
  425. package/hooks/gsd-secret-read-guard.js +161 -4
  426. package/hooks/gsd-statusline.js +85 -20
  427. package/hooks/gsd-update-banner.js +8 -0
  428. package/hooks/gsd-validate-commit.sh +63 -4
  429. package/hooks/gsd-windsurf-pre-write.js +11 -2
  430. package/hooks/gsd-workflow-guard.js +5 -4
  431. package/hooks/gsd-worktree-path-guard.js +6 -2
  432. package/hooks/hooks.json +5 -5
  433. package/hooks/lib/cli-exit.js +12 -0
  434. package/hooks/lib/git-probe.js +17 -1
  435. package/hooks/lib/isolation-sentinel.js +2 -2
  436. package/package.json +22 -4
  437. package/scripts/build-hooks.js +15 -6
  438. package/scripts/changeset/parse.cjs +52 -4
  439. package/scripts/check-contract-drift.cjs +127 -11
  440. package/scripts/ci-timeout-report.cjs +770 -4
  441. package/scripts/command-contract-helpers.cjs +15 -8
  442. package/scripts/docs-guard-registry.cjs +34 -0
  443. package/scripts/gen-features.cjs +13 -8
  444. package/scripts/gen-hooks-cli-exit.cjs +12 -28
  445. package/scripts/gen-loop-host-contract.cjs +79 -1
  446. package/scripts/gen-platform-conformance-tier.cjs +187 -1
  447. package/scripts/gen-plugin-skills.cjs +87 -1
  448. package/scripts/gen-research-agents.cjs +24 -31
  449. package/scripts/gen-scripts-cli-exit.cjs +30 -3
  450. package/scripts/gen-test-timings.cjs +32 -7
  451. package/scripts/lib/cli-exit.cjs +12 -0
  452. package/scripts/lib/macos-conformance-tier.generated.cjs +34 -2
  453. package/scripts/lib/ndjson-reporter.cjs +31 -5
  454. package/scripts/lib/platform-conformance-tier.generated.cjs +45 -5
  455. package/scripts/lib/registration-ledger-preload.cjs +155 -0
  456. package/scripts/lib/vendor-bundle.cjs +59 -0
  457. package/scripts/lib/vendor-licenses/saxes-6.0.0.txt +64 -0
  458. package/scripts/lint-allow-test-rule-refs.effective-ceiling.json +1 -1
  459. package/scripts/lint-allow-test-rule-refs.unverified-ceiling.json +1 -1
  460. package/scripts/lint-completion-predicate-drift.cjs +18 -19
  461. package/scripts/lint-descriptions.cjs +7 -3
  462. package/scripts/lint-docs-guard-registration.exempt-baseline.cjs +38 -1
  463. package/scripts/lint-eslint-glob-coverage.allowlist.json +20 -0
  464. package/scripts/lint-frontmatter-fence-drift.cjs +313 -0
  465. package/scripts/lint-frontmatter-scalar-broad-grep.cjs +122 -16
  466. package/scripts/lint-phase-arg-assignment.cjs +257 -0
  467. package/scripts/lint-phase-enumeration-drift.cjs +12 -8
  468. package/scripts/lint-phase-id-drift.cjs +319 -5
  469. package/scripts/lint-planning-document-positive-control.cjs +329 -0
  470. package/scripts/lint-pr-branch-pattern-drift.cjs +148 -0
  471. package/scripts/lint-response-language-coverage.cjs +3 -0
  472. package/scripts/lint-retired-runtime-name.cjs +619 -0
  473. package/scripts/lint-skill-deps.cjs +7 -3
  474. package/scripts/lint-state-write-path-drift.cjs +93 -0
  475. package/scripts/lint-test-file-count.allowlist.json +38 -9
  476. package/scripts/lint-test-file-count.cjs +34 -1
  477. package/scripts/lint-vendored-deps.cjs +41 -5
  478. package/scripts/lint-workflow-shellcheck-baseline.json +25 -10
  479. package/scripts/mutation-matrix.cjs +50 -5
  480. package/scripts/prompt-injection-scan.sh +4 -0
  481. package/scripts/release-tarball-smoke.cjs +194 -1
  482. package/scripts/require-issue-link-policy.cjs +6 -2
  483. package/scripts/sync-runtime-launcher.cjs +184 -2
  484. package/scripts/verify-npm-publish.cjs +76 -20
  485. package/skills/gsd-add-tests/SKILL.md +6 -1
  486. package/skills/gsd-ai-integration-phase/SKILL.md +6 -1
  487. package/skills/gsd-audit-fix/SKILL.md +5 -0
  488. package/skills/gsd-audit-milestone/SKILL.md +6 -1
  489. package/skills/gsd-autonomous/SKILL.md +7 -2
  490. package/skills/gsd-capture/SKILL.md +9 -5
  491. package/skills/gsd-code-review/SKILL.md +7 -2
  492. package/skills/gsd-complete-milestone/SKILL.md +4 -0
  493. package/skills/gsd-config/SKILL.md +8 -4
  494. package/skills/gsd-debug/SKILL.md +11 -7
  495. package/skills/gsd-discuss-phase/SKILL.md +7 -3
  496. package/skills/gsd-docs-update/SKILL.md +12 -7
  497. package/skills/gsd-eval-review/SKILL.md +6 -1
  498. package/skills/gsd-execute-phase/SKILL.md +12 -7
  499. package/skills/gsd-extract-learnings/SKILL.md +5 -0
  500. package/skills/gsd-fast/SKILL.md +4 -0
  501. package/skills/gsd-forensics/SKILL.md +5 -1
  502. package/skills/gsd-graphify/SKILL.md +10 -6
  503. package/skills/gsd-health/SKILL.md +5 -0
  504. package/skills/gsd-help/SKILL.md +7 -2
  505. package/skills/gsd-import/SKILL.md +7 -3
  506. package/skills/gsd-inbox/SKILL.md +5 -0
  507. package/skills/gsd-ingest-docs/SKILL.md +5 -1
  508. package/skills/gsd-manager/SKILL.md +6 -1
  509. package/skills/gsd-map-codebase/SKILL.md +7 -3
  510. package/skills/gsd-mempalace-capture/SKILL.md +12 -4
  511. package/skills/gsd-mempalace-recall/SKILL.md +5 -1
  512. package/skills/gsd-milestone-summary/SKILL.md +5 -1
  513. package/skills/gsd-mvp-phase/SKILL.md +8 -3
  514. package/skills/gsd-new-milestone/SKILL.md +6 -1
  515. package/skills/gsd-new-project/SKILL.md +5 -0
  516. package/skills/gsd-next/SKILL.md +6 -1
  517. package/skills/gsd-ns-context/SKILL.md +4 -0
  518. package/skills/gsd-ns-ideate/SKILL.md +4 -0
  519. package/skills/gsd-ns-manage/SKILL.md +4 -0
  520. package/skills/gsd-ns-project/SKILL.md +4 -0
  521. package/skills/gsd-ns-review/SKILL.md +4 -0
  522. package/skills/gsd-ns-workflow/SKILL.md +4 -0
  523. package/skills/gsd-onboard/SKILL.md +6 -1
  524. package/skills/gsd-pause-work/SKILL.md +5 -1
  525. package/skills/gsd-phase/SKILL.md +8 -4
  526. package/skills/gsd-plan-phase/SKILL.md +6 -1
  527. package/skills/gsd-plan-review-convergence/SKILL.md +10 -6
  528. package/skills/gsd-pr-branch/SKILL.md +4 -0
  529. package/skills/gsd-profile-user/SKILL.md +5 -1
  530. package/skills/gsd-progress/SKILL.md +7 -2
  531. package/skills/gsd-quick/SKILL.md +16 -10
  532. package/skills/gsd-quick-batch/SKILL.md +21 -9
  533. package/skills/gsd-review/SKILL.md +7 -4
  534. package/skills/gsd-review-backlog/SKILL.md +3 -2
  535. package/skills/gsd-secure-phase/SKILL.md +6 -1
  536. package/skills/gsd-ship/SKILL.md +5 -0
  537. package/skills/gsd-sketch/SKILL.md +7 -2
  538. package/skills/gsd-spec-phase/SKILL.md +5 -1
  539. package/skills/gsd-spike/SKILL.md +8 -3
  540. package/skills/gsd-surface/SKILL.md +5 -1
  541. package/skills/gsd-thread/SKILL.md +4 -0
  542. package/skills/gsd-ui-phase/SKILL.md +6 -1
  543. package/skills/gsd-ui-review/SKILL.md +6 -1
  544. package/skills/gsd-ultraplan-phase/SKILL.md +5 -1
  545. package/skills/gsd-undo/SKILL.md +5 -1
  546. package/skills/gsd-update/SKILL.md +6 -2
  547. package/skills/gsd-validate-phase/SKILL.md +6 -1
  548. package/skills/gsd-verify-work/SKILL.md +6 -1
  549. package/skills/gsd-workspace/SKILL.md +7 -3
  550. package/skills/gsd-workstreams/SKILL.md +6 -6
  551. package/vscode/package.json +1 -1
@@ -3,7 +3,9 @@
3
3
  * Complexity-triggered refactor extension point — analyzer, evaluator, and
4
4
  * baseline persistence (issue #1953).
5
5
  *
6
- * LEAF MODULE — imports ONLY: node:fs, node:path. No other src/ imports.
6
+ * LEAF MODULE — imports ONLY: node:fs, node:path, and the zero-import leaf
7
+ * frontmatter-fence.cjs (the one frontmatter fence owner, read by parseProposal). No other
8
+ * src/ imports.
7
9
  *
8
10
  * Pipeline: analyzeSource (decision-point complexity per function, via
9
11
  * stripLiterals to blank comments/string/regex content while preserving
@@ -49,6 +51,7 @@ exports.readBaseline = readBaseline;
49
51
  exports.writeBaseline = writeBaseline;
50
52
  const node_fs_1 = __importDefault(require("node:fs"));
51
53
  const node_path_1 = __importDefault(require("node:path"));
54
+ const frontmatter_fence_cjs_1 = require("./frontmatter-fence.cjs");
52
55
  // ─── Constants ─────────────────────────────────────────────────────────────
53
56
  exports.BASELINE_FILE_NAME = 'complexity-baseline.json'; // under .planning/
54
57
  exports.PROPOSAL_SUFFIX = '-REFACTOR.md'; // ${PHASE_DIR}/${PADDED}-REFACTOR.md
@@ -1018,13 +1021,11 @@ function renderProposal(p) {
1018
1021
  */
1019
1022
  function parseProposal(text) {
1020
1023
  try {
1021
- if (!text.startsWith('---\n') && !text.startsWith('---\r\n'))
1024
+ // The block is the one the one fence owner finds (`locateFrontmatterFence`).
1025
+ const fence = (0, frontmatter_fence_cjs_1.locateFrontmatterFence)(text);
1026
+ if (!fence?.closed)
1022
1027
  return null;
1023
- const headerEnd = text.startsWith('---\r\n') ? 5 : 4;
1024
- const closeIdx = text.indexOf('\n---', headerEnd);
1025
- if (closeIdx === -1)
1026
- return null;
1027
- const yamlBody = text.slice(headerEnd, closeIdx);
1028
+ const yamlBody = text.slice(fence.openEnd, fence.bodyEnd);
1028
1029
  const fm = {};
1029
1030
  for (const rawLine of yamlBody.split(/\r?\n/)) {
1030
1031
  const line = rawLine.replace(/\r$/, '');
@@ -28,6 +28,9 @@ const node_fs_1 = __importDefault(require("node:fs"));
28
28
  const node_os_1 = __importDefault(require("node:os"));
29
29
  const node_path_1 = __importDefault(require("node:path"));
30
30
  const shell_command_projection_cjs_1 = require("./shell-command-projection.cjs");
31
+ // #4717: runtime-identity fill — env rung + per-install marker rung.
32
+ const runtime_slash_cjs_1 = require("./runtime-slash.cjs");
33
+ const runtime_name_policy_cjs_1 = require("./runtime-name-policy.cjs");
31
34
  // eslint-disable-next-line @typescript-eslint/no-require-imports
32
35
  const planningWorkspace = require("./planning-workspace.cjs");
33
36
  const { planningDir, planningRoot } = planningWorkspace;
@@ -150,8 +153,21 @@ const CONFIG_DEFAULTS = {
150
153
  research_before_questions: _getNestedConfigDefault('workflow', 'research_before_questions'), // #3894
151
154
  smart_zone_tokens: _getNestedConfigDefault('workflow', 'smart_zone_tokens'),
152
155
  inline_plan_threshold: _getNestedConfigDefault('workflow', 'inline_plan_threshold'), // #3801
156
+ planner_stall_detection_enabled: _getNestedConfigDefault('planner', 'stall_detection_enabled'),
153
157
  max_prompt_tokens: _getNestedConfigDefault('review', 'max_prompt_tokens'),
154
158
  };
159
+ /**
160
+ * Resolve the planner watchdog policy from hand-edited configuration.
161
+ * Only a real JSON boolean may override the default; strings/numbers/null
162
+ * fail safe to the manifest-owned default-on behavior (#4570).
163
+ */
164
+ function resolvePlannerStallDetectionEnabled(value) {
165
+ if (typeof value === 'boolean')
166
+ return value;
167
+ // A missing or skewed manifest must never convert an absent override into
168
+ // permission to disable the watchdog. The documented contract is default-on.
169
+ return true;
170
+ }
155
171
  /**
156
172
  * Deep-merge two plain config objects. `overlay` wins on key conflict.
157
173
  * Explicit `null` in overlay overrides base (null means "unset this key").
@@ -601,7 +617,7 @@ function _warnUnusableConfig(fault) {
601
617
  * cannot dirty the working tree; the ~30 callers that omit it keep persisting, so
602
618
  * a legacy config is still migrated exactly once by ordinary use.
603
619
  */
604
- function loadConfigResolved(cwd, options = {}) {
620
+ function loadConfigResolvedInternal(cwd, options = {}) {
605
621
  // Opt-OUT, not opt-in: omitting the option must preserve the historical
606
622
  // write-back for every existing caller.
607
623
  const persist = options['persist'] !== false;
@@ -614,7 +630,7 @@ function loadConfigResolved(cwd, options = {}) {
614
630
  : (options['workstreamContext'] && Object.prototype.hasOwnProperty.call(options['workstreamContext'], 'ws'))
615
631
  ? options['workstreamContext']['ws']
616
632
  : (process.env['GSD_WORKSTREAM'] || null);
617
- const ws = typeof activeWorkstream === 'string' ? activeWorkstream : (activeWorkstream === null ? null : null);
633
+ const ws = typeof activeWorkstream === 'string' ? activeWorkstream.trim() || null : null;
618
634
  // wsRequested: true when caller explicitly requested a non-empty workstream.
619
635
  // Used for source labeling (Fix 4) and early absent-dir intercept (Fix 2).
620
636
  const wsRequested = ws != null && ws !== '';
@@ -858,6 +874,7 @@ function loadConfigResolved(cwd, options = {}) {
858
874
  phase_naming: get('phase_naming') ?? defaults.phase_naming,
859
875
  project_code: get('project_code') ?? defaults.project_code,
860
876
  subagent_timeout: get('subagent_timeout', { section: 'workflow', field: 'subagent_timeout' }) ?? defaults.subagent_timeout,
877
+ planner_stall_detection_enabled: resolvePlannerStallDetectionEnabled(getNested('planner', 'stall_detection_enabled')),
861
878
  model_overrides: (parsed['model_overrides']) || null,
862
879
  agent_tools: (parsed['agent_tools']) || null,
863
880
  models: (parsed['models']) || null,
@@ -959,7 +976,7 @@ function loadConfigResolved(cwd, options = {}) {
959
976
  // `workstream: null` still wins the `hasOwnProperty` check at the top of this
960
977
  // function, so spreading cannot let `workstreamContext` reintroduce a workstream.
961
978
  if (wsRequested && rootParsed) {
962
- const fb = loadConfigResolved(cwd, { ...options, workstream: null });
979
+ const fb = loadConfigResolvedInternal(cwd, { ...options, workstream: null });
963
980
  return fallback({ config: fb.config, source: 'root', degraded: true });
964
981
  }
965
982
  // Branch B, C, D, E
@@ -967,7 +984,7 @@ function loadConfigResolved(cwd, options = {}) {
967
984
  if (rootParsed) {
968
985
  // Branch B: workstream requested but ws config.json absent; root config present.
969
986
  // (Only reached when wsRequested is false — e.g. ws='' with .planning/workstreams//config.json)
970
- const fb = loadConfigResolved(cwd, { ...options, workstream: null });
987
+ const fb = loadConfigResolvedInternal(cwd, { ...options, workstream: null });
971
988
  return fallback({ config: fb.config, source: 'root', degraded: true });
972
989
  }
973
990
  // Branch C: .planning/ exists but no config.json and no root config — federated/builtin defaults
@@ -1016,6 +1033,7 @@ function loadConfigResolved(cwd, options = {}) {
1016
1033
  resolve_model_ids: (globalDefaults['resolve_model_ids']) ?? defaults.resolve_model_ids,
1017
1034
  context_window: (globalDefaults['context_window']) ?? defaults.context_window,
1018
1035
  subagent_timeout: (globalDefaults['subagent_timeout']) ?? defaults.subagent_timeout,
1036
+ planner_stall_detection_enabled: resolvePlannerStallDetectionEnabled(globalDefaults['planner']?.['stall_detection_enabled']),
1019
1037
  model_overrides: (globalDefaults['model_overrides']) || null,
1020
1038
  models: (globalDefaults['models']) || null,
1021
1039
  granularity: (globalDefaults['granularity']) !== undefined ? globalDefaults['granularity'] : null,
@@ -1054,6 +1072,48 @@ function loadConfigResolved(cwd, options = {}) {
1054
1072
  }
1055
1073
  }
1056
1074
  }
1075
+ /**
1076
+ * #4717 — fill an empty `runtime` from the environment, then the per-install
1077
+ * marker. writeNonClaudeDefaults stamps `runtime` into the SHARED
1078
+ * ~/.gsd/defaults.json with whichever non-Claude runtime installed first, so
1079
+ * direct readers of config.runtime saw another runtime's identity (or
1080
+ * nothing) on a multi-runtime machine. Copy-on-write: the builtin-defaults
1081
+ * branch returns a shared object, so never assign into it. An explicit
1082
+ * config.runtime is never overridden.
1083
+ */
1084
+ function fillRuntimeIdentity(resolved) {
1085
+ const cfg = resolved?.config;
1086
+ if (!cfg)
1087
+ return resolved;
1088
+ const runtime = (0, runtime_name_policy_cjs_1.resolveRuntimeNameFromCandidates)(process.env['GSD_RUNTIME'], (0, runtime_slash_cjs_1.readInstallRuntimeMarker)());
1089
+ // Only a runtime the name policy can canonicalize is an identity. Unknown
1090
+ // tokens pass THROUGH resolveRuntimeNameFromCandidates (future-runtime
1091
+ // tolerance) and must not be materialized into config.runtime, where ~30
1092
+ // consumers would read them — fail safe to no identity (#4717 review).
1093
+ const canonicalRuntime = runtime ? (0, runtime_name_policy_cjs_1.canonicalizeRuntimeName)(runtime) : null;
1094
+ if (!canonicalRuntime)
1095
+ return resolved;
1096
+ // Rung 1 — empty runtime: materialize THIS install's identity (env, then
1097
+ // the per-install marker). An explicit runtime is never overridden.
1098
+ if (!cfg['runtime']) {
1099
+ return { ...resolved, config: { ...cfg, runtime: canonicalRuntime } };
1100
+ }
1101
+ // Rung 2 (#4717 stamped-defaults leg): the global-defaults branch forwards
1102
+ // the SHARED ~/.gsd/defaults.json's runtime verbatim — whichever non-Claude
1103
+ // runtime installed FIRST stamped that machine-wide file, and every other
1104
+ // runtime's resolution inherited its identity (the issue's second failure
1105
+ // shape). When THIS install carries its own identity (GSD_RUNTIME or the
1106
+ // marker), the stamp — not the operator — is speaking: correct it. Project
1107
+ // and workstream configs are explicit operator intent and are never touched;
1108
+ // with no install identity of its own the stamped value stays (status quo).
1109
+ if (resolved.source === 'global-defaults') {
1110
+ return { ...resolved, config: { ...cfg, runtime: canonicalRuntime } };
1111
+ }
1112
+ return resolved;
1113
+ }
1114
+ function loadConfigResolved(cwd, options = {}) {
1115
+ return fillRuntimeIdentity(loadConfigResolvedInternal(cwd, options));
1116
+ }
1057
1117
  /**
1058
1118
  * loadConfig — backwards-compatible config loading, now a thin wrapper over loadConfigResolved.
1059
1119
  * Returns the config object only; for provenance metadata use loadConfigResolved.
@@ -1072,6 +1132,7 @@ module.exports = {
1072
1132
  _getNestedConfigDefault,
1073
1133
  _getConfigValue,
1074
1134
  _getConfigNested,
1135
+ resolvePlannerStallDetectionEnabled,
1075
1136
  _deepMergeConfig,
1076
1137
  _warnedUnknownConfigKeys,
1077
1138
  _warnedShadowedGlobalKeys,
@@ -20,11 +20,11 @@ const cliExitMod = require("./cli-exit.cjs");
20
20
  const { ExitError } = cliExitMod;
21
21
  // eslint-disable-next-line @typescript-eslint/no-require-imports
22
22
  const configLoader = require("./config-loader.cjs");
23
- const { CONFIG_DEFAULTS } = configLoader;
23
+ const { CONFIG_DEFAULTS, resolvePlannerStallDetectionEnabled } = configLoader;
24
24
  const shell_command_projection_cjs_1 = require("./shell-command-projection.cjs");
25
25
  // eslint-disable-next-line @typescript-eslint/no-require-imports
26
26
  const planningWorkspace = require("./planning-workspace.cjs");
27
- const { planningDir, planningRoot, withPlanningLock } = planningWorkspace;
27
+ const { planningDir, planningRoot, resolveEnvWorkstream, withPlanningLock } = planningWorkspace;
28
28
  // eslint-disable-next-line @typescript-eslint/no-require-imports
29
29
  const modelProfiles = require("./model-profiles.cjs");
30
30
  const { VALID_PROFILES, getAgentToModelMapForProfile, formatAgentToModelMapAsTable } = modelProfiles;
@@ -66,6 +66,14 @@ const SHIP_PR_BODY_TEMPLATE_TOKENS = new Set([
66
66
  'padded_phase',
67
67
  ]);
68
68
  const SHIP_PR_BODY_SOURCE_RE = /^(ROADMAP|PLAN|SUMMARY|VERIFICATION|STATE|REQUIREMENTS|CONTEXT)\.md\s+##\s+[^\r\n#][^\r\n]*$/;
69
+ // ADR-612 PR-5: configuration accepts every convention the runtime can read.
70
+ // Keep this distinct from roadmap-upgrade's supported target set: sequential
71
+ // is valid project configuration but is not a migration destination.
72
+ const VALID_PHASE_ID_CONVENTIONS = Object.freeze([
73
+ 'sequential',
74
+ 'milestone-prefixed',
75
+ 'bracket',
76
+ ]);
69
77
  /**
70
78
  * Schema-level defaults for well-known config keys.
71
79
  * When a key is absent from config.json and no --default flag was supplied,
@@ -75,6 +83,7 @@ const SCHEMA_DEFAULTS = {
75
83
  'context_window': 200000,
76
84
  'executor.stall_detect_interval_minutes': 5,
77
85
  'executor.stall_threshold_minutes': 10,
86
+ 'planner.stall_detection_enabled': CONFIG_DEFAULTS.planner_stall_detection_enabled,
78
87
  'planner.stall_detect_interval_minutes': 5,
79
88
  'planner.stall_threshold_minutes': 10,
80
89
  'git.create_tag': true,
@@ -119,6 +128,19 @@ const SCHEMA_DEFAULTS = {
119
128
  // WARNING_THRESHOLD/CRITICAL_THRESHOLD so the copies cannot drift.
120
129
  'hooks.context_warning_threshold': 35,
121
130
  'hooks.context_critical_threshold': 25,
131
+ // #4974: gates.* confirmation toggles — an absent key must resolve to the
132
+ // documented default (true) rather than "Key not found", matching
133
+ // config-defaults.manifest.json's `gates` block. Literal here (like
134
+ // git.create_tag above) rather than derived from config-loader.cjs's flat
135
+ // CONFIG_DEFAULTS: that flat projection is enumerated 1:1 against
136
+ // gsd-core/references/planning-config.md by
137
+ // tests/config-field-docs.test.cjs, and these 3 keys are internal workflow
138
+ // wiring, not part of that public flat-key surface. Only the 3 keys
139
+ // actually read by workflow conditions are registered — see
140
+ // gsd-core/bin/shared/config-schema.manifest.json.
141
+ 'gates.execute_next_plan': true,
142
+ 'gates.confirm_transition': true,
143
+ 'gates.confirm_milestone_scope': true,
122
144
  };
123
145
  /**
124
146
  * Resolve a schema-level default for an absent key (#2256). Checks the legacy
@@ -152,12 +174,15 @@ function resolveSchemaDefault(cwd, kp) {
152
174
  * Centralizing emission here means masking can't be missed at a call site.
153
175
  */
154
176
  function emitResolvedDefault(kp, value, raw) {
177
+ const resolvedValue = kp === 'planner.stall_detection_enabled'
178
+ ? resolvePlannerStallDetectionEnabled(value)
179
+ : value;
155
180
  if ((0, secrets_cjs_1.isSecretKey)(kp)) {
156
- const masked = (0, secrets_cjs_1.maskSecret)(value);
181
+ const masked = (0, secrets_cjs_1.maskSecret)(resolvedValue);
157
182
  output(masked, raw, masked);
158
183
  return;
159
184
  }
160
- output(value, raw, String(value));
185
+ output(resolvedValue, raw, String(resolvedValue));
161
186
  }
162
187
  // ─── Validation helpers ───────────────────────────────────────────────────────
163
188
  function validateKnownConfigKeyPath(keyPath) {
@@ -252,7 +277,8 @@ function validateShipPrBodySections(value) {
252
277
  *
253
278
  * Merges (increasing priority):
254
279
  * 1. Hardcoded defaults — every key that loadConfig() resolves, plus mode/granularity
255
- * 2. User-level defaults from ~/.gsd/defaults.json (if present)
280
+ * 2. User-level defaults from $GSD_HOME/.gsd/defaults.json (if present;
281
+ * GSD_HOME defaults to the home directory, as in the config loader)
256
282
  * 3. userChoices — the settings the user explicitly selected during /gsd:new-project
257
283
  *
258
284
  * Uses the canonical `git` namespace for branching keys (consistent with VALID_CONFIG_KEYS
@@ -263,24 +289,27 @@ function validateShipPrBodySections(value) {
263
289
  */
264
290
  function buildNewProjectConfig(userChoices) {
265
291
  const choices = userChoices || {};
266
- const homedir = node_os_1.default.homedir();
292
+ // #4976: the GSD-owned store resolves exactly as the config loader resolves
293
+ // it (`GSD_HOME || homedir()`), so the defaults.json seeding this project is
294
+ // the one the loader and its #3532 shadow warning read in the same run.
295
+ const gsdHome = process.env['GSD_HOME'] || node_os_1.default.homedir();
267
296
  // Detect API key availability
268
- const braveKeyFile = node_path_1.default.join(homedir, '.gsd', 'brave_api_key');
297
+ const braveKeyFile = node_path_1.default.join(gsdHome, '.gsd', 'brave_api_key');
269
298
  const hasBraveSearch = !!(process.env['BRAVE_API_KEY'] || node_fs_1.default.existsSync(braveKeyFile));
270
- const firecrawlKeyFile = node_path_1.default.join(homedir, '.gsd', 'firecrawl_api_key');
299
+ const firecrawlKeyFile = node_path_1.default.join(gsdHome, '.gsd', 'firecrawl_api_key');
271
300
  const hasFirecrawl = !!(process.env['FIRECRAWL_API_KEY'] || node_fs_1.default.existsSync(firecrawlKeyFile));
272
- const exaKeyFile = node_path_1.default.join(homedir, '.gsd', 'exa_api_key');
301
+ const exaKeyFile = node_path_1.default.join(gsdHome, '.gsd', 'exa_api_key');
273
302
  const hasExaSearch = !!(process.env['EXA_API_KEY'] || node_fs_1.default.existsSync(exaKeyFile));
274
- const tavilyKeyFile = node_path_1.default.join(homedir, '.gsd', 'tavily_api_key');
303
+ const tavilyKeyFile = node_path_1.default.join(gsdHome, '.gsd', 'tavily_api_key');
275
304
  const hasTavilySearch = !!(process.env['TAVILY_API_KEY'] || node_fs_1.default.existsSync(tavilyKeyFile));
276
- const refKeyFile = node_path_1.default.join(homedir, '.gsd', 'ref_api_key');
305
+ const refKeyFile = node_path_1.default.join(gsdHome, '.gsd', 'ref_api_key');
277
306
  const hasRefSearch = !!(process.env['REF_API_KEY'] || node_fs_1.default.existsSync(refKeyFile));
278
- const perplexityKeyFile = node_path_1.default.join(homedir, '.gsd', 'perplexity_api_key');
307
+ const perplexityKeyFile = node_path_1.default.join(gsdHome, '.gsd', 'perplexity_api_key');
279
308
  const hasPerplexity = !!(process.env['PERPLEXITY_API_KEY'] || node_fs_1.default.existsSync(perplexityKeyFile));
280
- const jinaKeyFile = node_path_1.default.join(homedir, '.gsd', 'jina_api_key');
309
+ const jinaKeyFile = node_path_1.default.join(gsdHome, '.gsd', 'jina_api_key');
281
310
  const hasJina = !!(process.env['JINA_API_KEY'] || node_fs_1.default.existsSync(jinaKeyFile));
282
- // Load user-level defaults from ~/.gsd/defaults.json if available
283
- const globalDefaultsPath = node_path_1.default.join(homedir, '.gsd', 'defaults.json');
311
+ // Load user-level defaults from $GSD_HOME/.gsd/defaults.json if available
312
+ const globalDefaultsPath = node_path_1.default.join(gsdHome, '.gsd', 'defaults.json');
284
313
  let userDefaults = {};
285
314
  try {
286
315
  if (node_fs_1.default.existsSync(globalDefaultsPath)) {
@@ -422,7 +451,7 @@ function buildNewProjectConfig(userChoices) {
422
451
  *
423
452
  * Accepts user-chosen settings as a JSON string (the keys the user explicitly
424
453
  * configured during /gsd:new-project). All remaining keys are filled from
425
- * hardcoded defaults and optional ~/.gsd/defaults.json.
454
+ * hardcoded defaults and optional $GSD_HOME/.gsd/defaults.json.
426
455
  *
427
456
  * Idempotent: if config.json already exists, returns { created: false }.
428
457
  */
@@ -542,7 +571,7 @@ function _setNestedValue(config, keyPath, parsedValue) {
542
571
  }
543
572
  /**
544
573
  * Deletes a value from the config object, allowing nested values via dot
545
- * notation (e.g., "review.models.gemini"). Mirrors `_setNestedValue`'s
574
+ * notation (e.g., "review.models.codex"). Mirrors `_setNestedValue`'s
546
575
  * prototype-pollution guard on every path segment (including intermediates).
547
576
  *
548
577
  * Unlike `_setNestedValue`, this NEVER creates missing intermediate objects —
@@ -806,6 +835,16 @@ function cmdConfigSet(cwd, keyPath, value, raw, options = {}) {
806
835
  const VALID_CONTEXT_VALUES = ['dev', 'research', 'review'];
807
836
  if (kp === 'context')
808
837
  assertEnumValue(parsedValue, val, VALID_CONTEXT_VALUES, 'context value');
838
+ // #4974: `mode` was never enum-validated — `config-set mode custom` (or any
839
+ // other string) silently succeeded, even though only "interactive" and
840
+ // "yolo" are documented/read values (gsd-core/references/planning-config.md,
841
+ // docs/CONFIGURATION.md, pinned by tests/config-field-docs.test.cjs).
842
+ const VALID_MODE_VALUES = ['interactive', 'yolo'];
843
+ if (kp === 'mode')
844
+ assertEnumValue(parsedValue, val, VALID_MODE_VALUES, 'mode');
845
+ if (kp === 'phase_id_convention') {
846
+ assertEnumValue(parsedValue, val, VALID_PHASE_ID_CONVENTIONS, 'phase_id_convention');
847
+ }
809
848
  // Codebase drift detector (#2003)
810
849
  const VALID_DRIFT_ACTIONS = ['warn', 'auto-remap'];
811
850
  if (kp === 'workflow.drift_action')
@@ -853,6 +892,20 @@ function cmdConfigSet(cwd, keyPath, value, raw, options = {}) {
853
892
  error(`Invalid workflow.agent_hint_routing '${val}'. Must be a boolean (true or false).`);
854
893
  }
855
894
  }
895
+ // Planner watchdog opt-out (#4570) — only a real boolean may change the
896
+ // default-on policy. In particular, string "false" must not disable it.
897
+ if (kp === 'planner.stall_detection_enabled') {
898
+ if (typeof parsedValue !== 'boolean') {
899
+ error(`Invalid planner.stall_detection_enabled '${val}'. Must be a boolean (true or false).`);
900
+ }
901
+ }
902
+ // Dispatch audit-trail opt-in (#4975) — boolean only. The live seams honour
903
+ // only a real `true`, so any other stored value would be silently ignored.
904
+ if (kp === 'audit.enabled') {
905
+ if (typeof parsedValue !== 'boolean') {
906
+ error(`Invalid audit.enabled '${val}'. Must be a boolean (true or false).`);
907
+ }
908
+ }
856
909
  // #3086 — git.create_tag: boolean only
857
910
  if (kp === 'git.create_tag') {
858
911
  if (typeof parsedValue !== 'boolean') {
@@ -1161,6 +1214,9 @@ function cmdConfigGet(cwd, keyPath, raw, defaultValue) {
1161
1214
  }
1162
1215
  error(`Key not found: ${kp}`, ERROR_REASON.CONFIG_KEY_NOT_FOUND);
1163
1216
  }
1217
+ if (kp === 'planner.stall_detection_enabled') {
1218
+ current = resolvePlannerStallDetectionEnabled(current);
1219
+ }
1164
1220
  // Never echo plaintext for sensitive keys via config-get. Plaintext lives
1165
1221
  // in config.json on disk; the CLI surface always shows the masked form.
1166
1222
  if ((0, secrets_cjs_1.isSecretKey)(kp)) {
@@ -1190,7 +1246,7 @@ function resolveFromRootConfig(cwd, kp) {
1190
1246
  // diverges from planningRoot without a workstream and loadConfigResolved does NOT
1191
1247
  // inherit root — matching the runtime's own `if (ws)` gate keeps the two surfaces
1192
1248
  // from diverging on the project-scoped (non-workstream) case.
1193
- if (!process.env['GSD_WORKSTREAM'])
1249
+ if (!resolveEnvWorkstream())
1194
1250
  return { found: false, value: undefined };
1195
1251
  const root = planningRoot(cwd);
1196
1252
  const rootConfigPath = node_path_1.default.join(root, 'config.json');
@@ -1297,7 +1353,7 @@ function cmdConfigPath(cwd, _raw, workstreamContext = null) {
1297
1353
  * (caller uses `await` which is safe on a sync return value).
1298
1354
  */
1299
1355
  function cmdMigrateConfig(cwd, raw) {
1300
- const ws = process.env['GSD_WORKSTREAM'] || null;
1356
+ const ws = resolveEnvWorkstream();
1301
1357
  // #3749: resolve the migration target through the project-aware resolver so
1302
1358
  // GSD_PROJECT scopes the write; migrateOnDisk itself cannot (see its
1303
1359
  // configPathOverride note).
@@ -1345,6 +1401,7 @@ function cmdMigrateConfig(cwd, raw) {
1345
1401
  }
1346
1402
  module.exports = {
1347
1403
  VALID_CONFIG_KEYS,
1404
+ VALID_PHASE_ID_CONVENTIONS,
1348
1405
  cmdConfigEnsureSection,
1349
1406
  cmdConfigSet,
1350
1407
  cmdConfigGet,
@@ -15,6 +15,7 @@
15
15
  * - node:fs / node:path (stdlib)
16
16
  * - ./phase-id.cjs (comparePhaseNum, used by readSubdirectories)
17
17
  * - ./planning-workspace.cjs (findContextMdIn, used by getPhaseFileStats)
18
+ * - ./frontmatter-fence.cjs (locateFrontmatterFence, used by extractOneLinerFromBody)
18
19
  *
19
20
  * #3883 (ADR-3473 §8.3): two of this module's cyclic partners require
20
21
  * generateSlugInternal, the canonical slug formula:
@@ -37,6 +38,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
37
38
  };
38
39
  const node_fs_1 = __importDefault(require("node:fs"));
39
40
  const node_path_1 = __importDefault(require("node:path"));
41
+ // frontmatter-fence.cjs is a leaf module (no imports), so this adds no cycle.
42
+ const frontmatter_fence_cjs_1 = require("./frontmatter-fence.cjs");
40
43
  // eslint-disable-next-line @typescript-eslint/no-require-imports
41
44
  const phaseIdModule = require("./phase-id.cjs");
42
45
  // eslint-disable-next-line @typescript-eslint/no-require-imports
@@ -139,7 +142,9 @@ function extractOneLinerFromBody(content) {
139
142
  if (!content)
140
143
  return null;
141
144
  const normalized = content.replace(/\r\n/g, '\n').replace(/\r/g, '\n');
142
- const body = normalized.replace(/^---\r?\n[\s\S]*?\r?\n---\r?\n*/, '');
145
+ // The body starts after the block the one fence owner finds, and the blank lines after it.
146
+ const fence = (0, frontmatter_fence_cjs_1.locateFrontmatterFence)(normalized);
147
+ const body = fence?.closed ? normalized.slice(fence.closingFenceEnd).replace(/^\n+/, '') : normalized;
143
148
  // #3170: anchor to a summary-shaped heading (Summary / Overview /
144
149
  // Accomplishments) so an incidental first heading (a rule list, task
145
150
  // breakdown, deviation note) does not contribute its first bold run as the
@@ -34,6 +34,7 @@ const { output, error } = io;
34
34
  const coreUtils = require("./core-utils.cjs");
35
35
  const { toPosixPath } = coreUtils;
36
36
  const security_cjs_1 = require("./security.cjs");
37
+ const frontmatter_fence_cjs_1 = require("./frontmatter-fence.cjs");
37
38
  // ─── Frozen typed-IR surface ────────────────────────────────────────────────
38
39
  const MODE = Object.freeze({
39
40
  COVERAGE: 'coverage',
@@ -186,15 +187,10 @@ function setKey(obj, key, value) {
186
187
  obj[key] = value;
187
188
  }
188
189
  // ─── Frontmatter region helpers ──────────────────────────────────────────────
190
+ /** The closed frontmatter block's YAML text, as the one fence owner finds it, or null. */
189
191
  function getFrontmatterYaml(content) {
190
- const headerEnd = content.startsWith('---\r\n') ? 5 : content.startsWith('---\n') ? 4 : -1;
191
- if (headerEnd === -1)
192
- return null;
193
- const closingLineStart = content.indexOf('\n---', headerEnd);
194
- if (closingLineStart === -1)
195
- return null;
196
- const yamlEnd = content[closingLineStart - 1] === '\r' ? closingLineStart - 1 : closingLineStart;
197
- return content.slice(headerEnd, yamlEnd);
192
+ const fence = (0, frontmatter_fence_cjs_1.locateFrontmatterFence)(content);
193
+ return fence?.closed ? content.slice(fence.openEnd, fence.bodyEnd) : null;
198
194
  }
199
195
  /**
200
196
  * Locate and parse the top-level `coverage:` block from a SUMMARY document.