@opengsd/gsd-core 1.15.0 → 1.17.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 (505) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -2
  3. package/.opencode/plugins/gsd-core.js +336 -6
  4. package/.opencode/plugins/gsd-statusline/tui.tsx +55 -0
  5. package/GEMINI.md +1 -1
  6. package/agents/gsd-code-fixer.compact.md +1 -1
  7. package/agents/gsd-code-fixer.md +1 -1
  8. package/agents/gsd-code-reviewer.compact.md +5 -3
  9. package/agents/gsd-code-reviewer.md +8 -6
  10. package/agents/gsd-debug-session-manager.compact.md +7 -1
  11. package/agents/gsd-debug-session-manager.md +7 -1
  12. package/agents/gsd-debugger.md +2 -2
  13. package/agents/gsd-eval-auditor.compact.md +1 -1
  14. package/agents/gsd-eval-auditor.md +1 -1
  15. package/agents/gsd-executor.md +4 -4
  16. package/agents/gsd-intel-updater.compact.md +1 -1
  17. package/agents/gsd-intel-updater.md +1 -1
  18. package/agents/gsd-mempalace-curator.md +2 -2
  19. package/agents/gsd-phase-researcher.md +1 -1
  20. package/agents/gsd-plan-checker.md +7 -2
  21. package/agents/gsd-planner.md +3 -3
  22. package/agents/gsd-project-researcher.compact.md +1 -1
  23. package/agents/gsd-project-researcher.md +1 -1
  24. package/agents/gsd-research-synthesizer.compact.md +1 -1
  25. package/agents/gsd-research-synthesizer.md +1 -1
  26. package/agents/gsd-ui-auditor.compact.md +21 -30
  27. package/agents/gsd-ui-auditor.md +42 -51
  28. package/agents/gsd-ui-researcher.compact.md +1 -1
  29. package/agents/gsd-ui-researcher.md +1 -1
  30. package/agents/gsd-verifier.md +31 -9
  31. package/bin/gsd-mcp-server.js +3 -1
  32. package/bin/install.js +487 -290
  33. package/commands/gsd/add-tests.md +6 -1
  34. package/commands/gsd/ai-integration-phase.md +6 -1
  35. package/commands/gsd/audit-fix.md +5 -0
  36. package/commands/gsd/audit-milestone.md +6 -1
  37. package/commands/gsd/autonomous.md +5 -0
  38. package/commands/gsd/capture.md +8 -4
  39. package/commands/gsd/code-review.md +7 -2
  40. package/commands/gsd/complete-milestone.md +4 -0
  41. package/commands/gsd/config.md +7 -3
  42. package/commands/gsd/debug.md +11 -7
  43. package/commands/gsd/discuss-phase.md +7 -3
  44. package/commands/gsd/docs-update.md +12 -7
  45. package/commands/gsd/eval-review.md +6 -1
  46. package/commands/gsd/execute-phase.md +12 -7
  47. package/commands/gsd/extract-learnings.md +5 -0
  48. package/commands/gsd/fast.md +4 -0
  49. package/commands/gsd/forensics.md +5 -1
  50. package/commands/gsd/graphify.md +10 -6
  51. package/commands/gsd/health.md +5 -0
  52. package/commands/gsd/help.md +7 -2
  53. package/commands/gsd/import.md +7 -3
  54. package/commands/gsd/inbox.md +5 -0
  55. package/commands/gsd/ingest-docs.md +5 -1
  56. package/commands/gsd/manager.md +6 -1
  57. package/commands/gsd/map-codebase.md +7 -3
  58. package/commands/gsd/mempalace-capture.md +5 -1
  59. package/commands/gsd/mempalace-recall.md +5 -1
  60. package/commands/gsd/milestone-summary.md +5 -1
  61. package/commands/gsd/mvp-phase.md +8 -3
  62. package/commands/gsd/new-milestone.md +6 -1
  63. package/commands/gsd/new-project.md +5 -0
  64. package/commands/gsd/next.md +6 -1
  65. package/commands/gsd/ns-context.md +4 -0
  66. package/commands/gsd/ns-ideate.md +4 -0
  67. package/commands/gsd/ns-manage.md +4 -0
  68. package/commands/gsd/ns-project.md +4 -0
  69. package/commands/gsd/ns-review.md +4 -0
  70. package/commands/gsd/ns-workflow.md +4 -0
  71. package/commands/gsd/onboard.md +6 -1
  72. package/commands/gsd/pause-work.md +5 -1
  73. package/commands/gsd/phase.md +8 -4
  74. package/commands/gsd/plan-phase.md +6 -1
  75. package/commands/gsd/plan-review-convergence.md +5 -1
  76. package/commands/gsd/pr-branch.md +4 -0
  77. package/commands/gsd/profile-user.md +5 -1
  78. package/commands/gsd/progress.md +6 -1
  79. package/commands/gsd/quick-batch.md +20 -8
  80. package/commands/gsd/quick.md +12 -7
  81. package/commands/gsd/review.md +5 -1
  82. package/commands/gsd/secure-phase.md +6 -1
  83. package/commands/gsd/ship.md +5 -0
  84. package/commands/gsd/sketch.md +7 -2
  85. package/commands/gsd/spec-phase.md +5 -1
  86. package/commands/gsd/spike.md +8 -3
  87. package/commands/gsd/surface.md +5 -1
  88. package/commands/gsd/thread.md +4 -0
  89. package/commands/gsd/ui-phase.md +6 -1
  90. package/commands/gsd/ui-review.md +6 -1
  91. package/commands/gsd/ultraplan-phase.md +5 -1
  92. package/commands/gsd/undo.md +5 -1
  93. package/commands/gsd/update.md +6 -2
  94. package/commands/gsd/validate-phase.md +6 -1
  95. package/commands/gsd/verify-work.md +6 -1
  96. package/commands/gsd/workspace.md +7 -3
  97. package/gsd-core/bin/gsd-tools.cjs +159 -58
  98. package/gsd-core/bin/lib/active-workstream-store.cjs +15 -0
  99. package/gsd-core/bin/lib/adr-parser.cjs +37 -5
  100. package/gsd-core/bin/lib/agent-install-check.cjs +4 -1
  101. package/gsd-core/bin/lib/audit.cjs +78 -44
  102. package/gsd-core/bin/lib/broken-windows.cjs +13 -13
  103. package/gsd-core/bin/lib/capability-activation.cjs +9 -4
  104. package/gsd-core/bin/lib/capability-registry.cjs +249 -117
  105. package/gsd-core/bin/lib/capability-validator.cjs +18 -1
  106. package/gsd-core/bin/lib/capability-writer.cjs +2 -1
  107. package/gsd-core/bin/lib/check-auto-mode.cjs +35 -0
  108. package/gsd-core/bin/lib/check-command-router.cjs +164 -1712
  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 +11 -8
  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 +201 -178
  115. package/gsd-core/bin/lib/complexity-trigger.cjs +8 -7
  116. package/gsd-core/bin/lib/config.cjs +43 -12
  117. package/gsd-core/bin/lib/core-utils.cjs +6 -1
  118. package/gsd-core/bin/lib/coverage.cjs +4 -8
  119. package/gsd-core/bin/lib/decision-coverage-support.cjs +259 -0
  120. package/gsd-core/bin/lib/drift.cjs +177 -42
  121. package/gsd-core/bin/lib/frontmatter-fence.cjs +90 -0
  122. package/gsd-core/bin/lib/frontmatter-splice.cjs +494 -0
  123. package/gsd-core/bin/lib/frontmatter.cjs +413 -234
  124. package/gsd-core/bin/lib/gap-checker.cjs +72 -29
  125. package/gsd-core/bin/lib/gate-api-coverage-verify-pre.cjs +381 -0
  126. package/gsd-core/bin/lib/gate-args.cjs +53 -0
  127. package/gsd-core/bin/lib/gate-codebase-drift.cjs +285 -0
  128. package/gsd-core/bin/lib/gate-config.cjs +46 -0
  129. package/gsd-core/bin/lib/gate-context-drift.cjs +142 -0
  130. package/gsd-core/bin/lib/gate-decision-coverage-plan.cjs +169 -0
  131. package/gsd-core/bin/lib/gate-decision-coverage-verify.cjs +126 -0
  132. package/gsd-core/bin/lib/gate-evaluation-scope.cjs +555 -0
  133. package/gsd-core/bin/lib/gate-evidence.cjs +138 -0
  134. package/gsd-core/bin/lib/gate-exit.cjs +27 -0
  135. package/gsd-core/bin/lib/gate-gap-analysis-plan-post.cjs +61 -0
  136. package/gsd-core/bin/lib/gate-phase-context.cjs +170 -0
  137. package/gsd-core/bin/lib/gate-predicate-evaluator.cjs +1 -1
  138. package/gsd-core/bin/lib/gate-predicate.cjs +165 -0
  139. package/gsd-core/bin/lib/gate-prohibition-enforcement.cjs +94 -0
  140. package/gsd-core/bin/lib/gate-schema-drift.cjs +165 -0
  141. package/gsd-core/bin/lib/gate-tdd-red-evidence.cjs +100 -0
  142. package/gsd-core/bin/lib/gate-tdd-review-checkpoint.cjs +182 -0
  143. package/gsd-core/bin/lib/gate-ui-plan.cjs +86 -0
  144. package/gsd-core/bin/lib/gate-ui-safety.cjs +81 -0
  145. package/gsd-core/bin/lib/gate-verdict.cjs +64 -0
  146. package/gsd-core/bin/lib/gate-verify-command-paths.cjs +78 -0
  147. package/gsd-core/bin/lib/gate-verify-failure-directions.cjs +41 -0
  148. package/gsd-core/bin/lib/graphify.cjs +3 -2
  149. package/gsd-core/bin/lib/health-diagnostic-rules/phase-structure.cjs +43 -47
  150. package/gsd-core/bin/lib/health-diagnostic.cjs +45 -8
  151. package/gsd-core/bin/lib/init.cjs +194 -108
  152. package/gsd-core/bin/lib/install-engine.cjs +30 -35
  153. package/gsd-core/bin/lib/install-profiles.cjs +7 -4
  154. package/gsd-core/bin/lib/install-shadow-report.cjs +12 -0
  155. package/gsd-core/bin/lib/installer-migrations/011-opencode-mcp-no-prompts.cjs +99 -0
  156. package/gsd-core/bin/lib/installer-migrations.cjs +54 -1
  157. package/gsd-core/bin/lib/io.cjs +122 -3
  158. package/gsd-core/bin/lib/jsonc-edit.cjs +418 -0
  159. package/gsd-core/bin/lib/loop-host-contract.cjs +2 -1
  160. package/gsd-core/bin/lib/loop-resolver.cjs +95 -0
  161. package/gsd-core/bin/lib/markdown-sectionizer.cjs +75 -1
  162. package/gsd-core/bin/lib/mcp-server.cjs +5 -1
  163. package/gsd-core/bin/lib/milestone.cjs +19 -1
  164. package/gsd-core/bin/lib/model-resolver.cjs +18 -18
  165. package/gsd-core/bin/lib/observability/event.cjs +1 -1
  166. package/gsd-core/bin/lib/observability/logger.cjs +46 -1
  167. package/gsd-core/bin/lib/opencode-mcp-entry.cjs +39 -0
  168. package/gsd-core/bin/lib/opencode-version.cjs +486 -0
  169. package/gsd-core/bin/lib/pattern.cjs +10 -0
  170. package/gsd-core/bin/lib/phase-command-router.cjs +11 -4
  171. package/gsd-core/bin/lib/phase-estimation.cjs +5 -4
  172. package/gsd-core/bin/lib/phase-id.cjs +1 -1
  173. package/gsd-core/bin/lib/phase-lifecycle.cjs +9 -2
  174. package/gsd-core/bin/lib/phase-status.cjs +360 -0
  175. package/gsd-core/bin/lib/phase.cjs +301 -80
  176. package/gsd-core/bin/lib/plan-document.cjs +93 -19
  177. package/gsd-core/bin/lib/plan-drift-guard.cjs +5 -0
  178. package/gsd-core/bin/lib/planning-document.cjs +273 -40
  179. package/gsd-core/bin/lib/planning-inspect.cjs +42 -8
  180. package/gsd-core/bin/lib/planning-snapshot.cjs +18 -0
  181. package/gsd-core/bin/lib/planning-workspace.cjs +76 -53
  182. package/gsd-core/bin/lib/pristine-baseline.cjs +10 -0
  183. package/gsd-core/bin/lib/profile-output.cjs +6 -3
  184. package/gsd-core/bin/lib/prohibition-enforcement.cjs +0 -55
  185. package/gsd-core/bin/lib/quick-batch-command-router.cjs +35 -9
  186. package/gsd-core/bin/lib/quick-batch-dispatch.cjs +13 -9
  187. package/gsd-core/bin/lib/real-home-guard.cjs +9 -1
  188. package/gsd-core/bin/lib/report-parser.cjs +269 -0
  189. package/gsd-core/bin/lib/roadmap-command-router.cjs +13 -15
  190. package/gsd-core/bin/lib/roadmap-parser.cjs +82 -15
  191. package/gsd-core/bin/lib/roadmap-upgrade.cjs +127 -65
  192. package/gsd-core/bin/lib/roadmap.cjs +169 -72
  193. package/gsd-core/bin/lib/runtime-artifact-conversion.cjs +186 -161
  194. package/gsd-core/bin/lib/runtime-artifact-install-plan.cjs +2 -1
  195. package/gsd-core/bin/lib/runtime-artifact-layout.cjs +57 -1
  196. package/gsd-core/bin/lib/runtime-homes.cjs +13 -10
  197. package/gsd-core/bin/lib/runtime-hooks-surface.cjs +365 -594
  198. package/gsd-core/bin/lib/runtime-name-policy.cjs +142 -27
  199. package/gsd-core/bin/lib/runtime-slash.cjs +60 -30
  200. package/gsd-core/bin/lib/shell-command-projection.cjs +37 -2
  201. package/gsd-core/bin/lib/smart-entry.cjs +111 -56
  202. package/gsd-core/bin/lib/stale-bake-guard.cjs +32 -48
  203. package/gsd-core/bin/lib/state-contract.cjs +15 -18
  204. package/gsd-core/bin/lib/state-document.cjs +100 -22
  205. package/gsd-core/bin/lib/state-transition.cjs +67 -9
  206. package/gsd-core/bin/lib/state.cjs +668 -171
  207. package/gsd-core/bin/lib/surface.cjs +2 -1
  208. package/gsd-core/bin/lib/tdd-red-evidence.cjs +48 -152
  209. package/gsd-core/bin/lib/uat-predicate.cjs +313 -35
  210. package/gsd-core/bin/lib/uat.cjs +424 -7
  211. package/gsd-core/bin/lib/ui-frontend-evidence.cjs +94 -58
  212. package/gsd-core/bin/lib/update-context.cjs +18 -1
  213. package/gsd-core/bin/lib/vendor/README.md +31 -9
  214. package/gsd-core/bin/lib/vendor/saxes.cjs +1934 -0
  215. package/gsd-core/bin/lib/vendor/saxes.cjs.LICENSE.txt +92 -0
  216. package/gsd-core/bin/lib/vendor/tap-parser.cjs +8927 -0
  217. package/gsd-core/bin/lib/vendor/tap-parser.cjs.LICENSE.txt +152 -0
  218. package/gsd-core/bin/lib/verification-command-router.cjs +2 -1
  219. package/gsd-core/bin/lib/verification.cjs +1265 -324
  220. package/gsd-core/bin/lib/verify-command-router.cjs +18 -7
  221. package/gsd-core/bin/lib/verify.cjs +286 -567
  222. package/gsd-core/bin/lib/workstream-inventory-builder.cjs +14 -6
  223. package/gsd-core/bin/lib/workstream-inventory.cjs +31 -21
  224. package/gsd-core/bin/lib/workstream-name-policy.cjs +31 -1
  225. package/gsd-core/bin/lib/workstream.cjs +11 -2
  226. package/gsd-core/bin/shared/config-defaults.manifest.json +5 -0
  227. package/gsd-core/bin/shared/config-schema.manifest.json +4 -0
  228. package/gsd-core/references/autonomous-smart-discuss.md +2 -1
  229. package/gsd-core/references/autonomous-ui-design-contract.md +3 -3
  230. package/gsd-core/references/execute-mvp-tdd.md +5 -10
  231. package/gsd-core/references/execute-phase-between-wave-reset.md +3 -0
  232. package/gsd-core/references/execute-phase-response-language.md +1 -1
  233. package/gsd-core/references/gsd-run-resolver.md +1 -1
  234. package/gsd-core/references/loop-hook-dispatch.md +7 -1
  235. package/gsd-core/references/offer-next.md +1 -1
  236. package/gsd-core/references/planning-config.md +1 -1
  237. package/gsd-core/references/spidr-splitting.md +1 -1
  238. package/gsd-core/references/tdd.md +10 -4
  239. package/gsd-core/references/verifier-phase-gates.md +5 -2
  240. package/gsd-core/references/verify-mvp-mode.md +2 -2
  241. package/gsd-core/references/workstream-flag.md +33 -3
  242. package/gsd-core/templates/README.md +1 -1
  243. package/gsd-core/templates/UAT.md +17 -1
  244. package/gsd-core/templates/config.json +2 -11
  245. package/gsd-core/templates/verification-report.md +1 -1
  246. package/gsd-core/workflows/_runtime-launcher.snippet.sh +1 -1
  247. package/gsd-core/workflows/add-backlog.md +1 -1
  248. package/gsd-core/workflows/add-phase.md +8 -7
  249. package/gsd-core/workflows/add-tests.md +3 -2
  250. package/gsd-core/workflows/add-todo.md +4 -3
  251. package/gsd-core/workflows/ai-integration-phase.md +3 -2
  252. package/gsd-core/workflows/audit-fix.md +1 -1
  253. package/gsd-core/workflows/audit-milestone.md +4 -3
  254. package/gsd-core/workflows/audit-uat.md +1 -1
  255. package/gsd-core/workflows/autonomous.md +28 -18
  256. package/gsd-core/workflows/check-todos.md +6 -5
  257. package/gsd-core/workflows/cleanup.md +1 -1
  258. package/gsd-core/workflows/code-review/steps/structural-pre-pass.md +20 -13
  259. package/gsd-core/workflows/code-review-fix.md +5 -4
  260. package/gsd-core/workflows/code-review.md +100 -91
  261. package/gsd-core/workflows/complete-milestone/detail/elaboration.md +4 -3
  262. package/gsd-core/workflows/complete-milestone.md +12 -7
  263. package/gsd-core/workflows/debug.md +30 -5
  264. package/gsd-core/workflows/diagnose-issues.md +3 -2
  265. package/gsd-core/workflows/discuss-phase/modes/advisor.md +1 -1
  266. package/gsd-core/workflows/discuss-phase/modes/chain.md +1 -1
  267. package/gsd-core/workflows/discuss-phase-assumptions.md +4 -3
  268. package/gsd-core/workflows/discuss-phase.md +4 -3
  269. package/gsd-core/workflows/do.md +1 -1
  270. package/gsd-core/workflows/docs-update.md +4 -3
  271. package/gsd-core/workflows/edit-phase.md +4 -3
  272. package/gsd-core/workflows/eval-review.md +5 -3
  273. package/gsd-core/workflows/execute-phase/detail/elaboration.md +1 -1
  274. package/gsd-core/workflows/execute-phase/steps/code-review-disposition.md +4 -2
  275. package/gsd-core/workflows/execute-phase/steps/codebase-drift-gate.md +15 -4
  276. package/gsd-core/workflows/execute-phase/steps/completion-reconciliation.md +10 -7
  277. package/gsd-core/workflows/execute-phase/steps/executor-isolation-dispatch.md +2 -2
  278. package/gsd-core/workflows/execute-phase/steps/gap-closure-artifacts.md +3 -1
  279. package/gsd-core/workflows/execute-phase/steps/partial-wave.md +2 -2
  280. package/gsd-core/workflows/execute-phase/steps/per-plan-executor-routing.md +1 -1
  281. package/gsd-core/workflows/execute-phase/steps/per-plan-worktree-gate.md +1 -1
  282. package/gsd-core/workflows/execute-phase/steps/post-merge-gate.md +1 -1
  283. package/gsd-core/workflows/execute-phase/steps/protected-branch.md +1 -1
  284. package/gsd-core/workflows/execute-phase/steps/regression-gate-run.md +1 -1
  285. package/gsd-core/workflows/execute-phase/steps/regression-gate.md +2 -0
  286. package/gsd-core/workflows/execute-phase/steps/tdd-applicability-resolution.md +1 -1
  287. package/gsd-core/workflows/execute-phase/steps/verify-phase-goal.md +187 -0
  288. package/gsd-core/workflows/execute-phase/steps/wave-post-gate-hooks.md +2 -3
  289. package/gsd-core/workflows/execute-phase.md +81 -171
  290. package/gsd-core/workflows/execute-plan.md +13 -19
  291. package/gsd-core/workflows/explore.md +2 -2
  292. package/gsd-core/workflows/extract-learnings.md +3 -2
  293. package/gsd-core/workflows/fast.md +1 -1
  294. package/gsd-core/workflows/forensics.md +1 -1
  295. package/gsd-core/workflows/graduation.md +1 -1
  296. package/gsd-core/workflows/health.md +2 -1
  297. package/gsd-core/workflows/import.md +3 -2
  298. package/gsd-core/workflows/inbox.md +1 -1
  299. package/gsd-core/workflows/ingest-docs.md +1 -1
  300. package/gsd-core/workflows/insert-phase.md +4 -3
  301. package/gsd-core/workflows/list-seeds.md +1 -1
  302. package/gsd-core/workflows/list-workspaces.md +1 -1
  303. package/gsd-core/workflows/manager.md +5 -3
  304. package/gsd-core/workflows/map-codebase.md +4 -3
  305. package/gsd-core/workflows/milestone-summary.md +3 -2
  306. package/gsd-core/workflows/mvp-phase.md +14 -14
  307. package/gsd-core/workflows/new-milestone.md +10 -10
  308. package/gsd-core/workflows/new-project/steps/auto-mode-config.md +1 -1
  309. package/gsd-core/workflows/new-project.md +1 -1
  310. package/gsd-core/workflows/new-workspace.md +1 -1
  311. package/gsd-core/workflows/next.md +1 -1
  312. package/gsd-core/workflows/pause-work.md +2 -2
  313. package/gsd-core/workflows/plan-phase/detail/elaboration.md +1 -1
  314. package/gsd-core/workflows/plan-phase/steps/chunked-planning-mode.md +1 -1
  315. package/gsd-core/workflows/plan-phase/steps/closed-phase-gate.md +1 -1
  316. package/gsd-core/workflows/plan-phase/steps/prd-express-path.md +1 -1
  317. package/gsd-core/workflows/plan-phase/steps/stall-detection-helpers.md +1 -1
  318. package/gsd-core/workflows/plan-phase.md +27 -18
  319. package/gsd-core/workflows/plan-review-convergence.md +1 -1
  320. package/gsd-core/workflows/plant-seed.md +1 -1
  321. package/gsd-core/workflows/pr-branch.md +1 -1
  322. package/gsd-core/workflows/profile-user.md +1 -1
  323. package/gsd-core/workflows/progress.md +19 -49
  324. package/gsd-core/workflows/quick/steps/plan-checker-loop.md +4 -2
  325. package/gsd-core/workflows/quick/steps/quick-verification.md +4 -4
  326. package/gsd-core/workflows/quick/steps/worktree-pre-dispatch-commit.md +30 -11
  327. package/gsd-core/workflows/quick-batch/steps/batch-init.md +1 -1
  328. package/gsd-core/workflows/quick-batch/steps/completion.md +1 -1
  329. package/gsd-core/workflows/quick-batch/steps/merge-wave.md +1 -1
  330. package/gsd-core/workflows/quick-batch/steps/planner-wave.md +1 -1
  331. package/gsd-core/workflows/quick-batch/steps/research-phase.md +1 -1
  332. package/gsd-core/workflows/quick-batch/steps/resume-mode.md +1 -1
  333. package/gsd-core/workflows/quick-batch/steps/verification-wave.md +9 -3
  334. package/gsd-core/workflows/quick-batch/steps/worktree-dispatch.md +1 -1
  335. package/gsd-core/workflows/quick-batch.md +15 -10
  336. package/gsd-core/workflows/quick.md +42 -31
  337. package/gsd-core/workflows/remove-phase.md +3 -2
  338. package/gsd-core/workflows/remove-workspace.md +1 -1
  339. package/gsd-core/workflows/resume-project.md +17 -12
  340. package/gsd-core/workflows/review.md +3 -2
  341. package/gsd-core/workflows/scan.md +3 -2
  342. package/gsd-core/workflows/secure-phase.md +11 -12
  343. package/gsd-core/workflows/settings-advanced.md +1 -1
  344. package/gsd-core/workflows/settings-integrations.md +1 -1
  345. package/gsd-core/workflows/settings.md +1 -1
  346. package/gsd-core/workflows/ship.md +12 -12
  347. package/gsd-core/workflows/sketch-wrap-up.md +1 -1
  348. package/gsd-core/workflows/sketch.md +1 -1
  349. package/gsd-core/workflows/smart-entry.md +1 -1
  350. package/gsd-core/workflows/spec-phase.md +1 -1
  351. package/gsd-core/workflows/spike-wrap-up.md +1 -1
  352. package/gsd-core/workflows/spike.md +1 -1
  353. package/gsd-core/workflows/stats.md +1 -1
  354. package/gsd-core/workflows/sync-skills.md +1 -1
  355. package/gsd-core/workflows/thread.md +2 -2
  356. package/gsd-core/workflows/transition.md +13 -23
  357. package/gsd-core/workflows/ui-phase.md +5 -4
  358. package/gsd-core/workflows/ui-review.md +4 -3
  359. package/gsd-core/workflows/ultraplan-phase.md +3 -2
  360. package/gsd-core/workflows/undo.md +1 -1
  361. package/gsd-core/workflows/validate-phase.md +10 -12
  362. package/gsd-core/workflows/verify-work/detail/elaboration.md +43 -3
  363. package/gsd-core/workflows/verify-work/steps/automated-ui-verification.md +1 -1
  364. package/gsd-core/workflows/verify-work/steps/mvp-uat-framing.md +5 -3
  365. package/gsd-core/workflows/verify-work.md +68 -59
  366. package/hooks/dist/gsd-agent-isolation-guard.js +8 -0
  367. package/hooks/dist/gsd-check-update-worker.js +8 -0
  368. package/hooks/dist/gsd-check-update.js +34 -20
  369. package/hooks/dist/gsd-context-monitor.js +45 -13
  370. package/hooks/dist/gsd-cursor-subagent-start.js +8 -0
  371. package/hooks/dist/gsd-secret-read-guard.js +263 -16
  372. package/hooks/dist/gsd-statusline.js +336 -29
  373. package/hooks/dist/gsd-update-banner.js +8 -0
  374. package/hooks/dist/gsd-windsurf-pre-write.js +11 -2
  375. package/hooks/dist/gsd-workflow-guard.js +5 -4
  376. package/hooks/dist/gsd-worktree-path-guard.js +6 -2
  377. package/hooks/dist/lib/cli-exit.js +12 -0
  378. package/hooks/dist/lib/git-probe.js +17 -1
  379. package/hooks/dist/lib/isolation-sentinel.js +2 -2
  380. package/hooks/gsd-agent-isolation-guard.js +8 -0
  381. package/hooks/gsd-check-update-worker.js +8 -0
  382. package/hooks/gsd-check-update.js +34 -20
  383. package/hooks/gsd-context-monitor.js +45 -13
  384. package/hooks/gsd-cursor-subagent-start.js +8 -0
  385. package/hooks/gsd-secret-read-guard.js +263 -16
  386. package/hooks/gsd-statusline.js +336 -29
  387. package/hooks/gsd-update-banner.js +8 -0
  388. package/hooks/gsd-windsurf-pre-write.js +11 -2
  389. package/hooks/gsd-workflow-guard.js +5 -4
  390. package/hooks/gsd-worktree-path-guard.js +6 -2
  391. package/hooks/hooks.json +5 -5
  392. package/hooks/lib/cli-exit.js +12 -0
  393. package/hooks/lib/git-probe.js +17 -1
  394. package/hooks/lib/isolation-sentinel.js +2 -2
  395. package/package.json +21 -4
  396. package/scripts/changeset/parse.cjs +52 -4
  397. package/scripts/ci-timeout-report.cjs +770 -4
  398. package/scripts/command-contract-helpers.cjs +12 -8
  399. package/scripts/docs-guard-registry.cjs +6 -0
  400. package/scripts/gen-capability-registry.cjs +7 -1
  401. package/scripts/gen-features.cjs +13 -8
  402. package/scripts/gen-hooks-cli-exit.cjs +12 -28
  403. package/scripts/gen-loop-host-contract.cjs +14 -2
  404. package/scripts/gen-platform-conformance-tier.cjs +187 -1
  405. package/scripts/gen-plugin-skills.cjs +87 -1
  406. package/scripts/gen-research-agents.cjs +24 -31
  407. package/scripts/gen-scripts-cli-exit.cjs +30 -3
  408. package/scripts/gen-test-timings.cjs +32 -7
  409. package/scripts/lib/cli-exit.cjs +12 -0
  410. package/scripts/lib/macos-conformance-tier.generated.cjs +24 -2
  411. package/scripts/lib/ndjson-reporter.cjs +28 -3
  412. package/scripts/lib/platform-conformance-tier.generated.cjs +44 -5
  413. package/scripts/lib/registration-ledger-preload.cjs +155 -0
  414. package/scripts/lib/vendor-bundle.cjs +59 -0
  415. package/scripts/lib/vendor-licenses/saxes-6.0.0.txt +64 -0
  416. package/scripts/lint-allow-test-rule-refs.effective-ceiling.json +1 -1
  417. package/scripts/lint-allow-test-rule-refs.unverified-ceiling.json +1 -1
  418. package/scripts/lint-completion-predicate-drift.cjs +18 -19
  419. package/scripts/lint-descriptions.cjs +7 -3
  420. package/scripts/lint-docs-guard-registration.exempt-baseline.cjs +10 -0
  421. package/scripts/lint-eslint-glob-coverage.allowlist.json +20 -0
  422. package/scripts/lint-frontmatter-fence-drift.cjs +313 -0
  423. package/scripts/lint-frontmatter-scalar-broad-grep.cjs +122 -16
  424. package/scripts/lint-phase-enumeration-drift.cjs +12 -8
  425. package/scripts/lint-phase-id-drift.cjs +29 -0
  426. package/scripts/lint-planning-document-positive-control.cjs +329 -0
  427. package/scripts/lint-response-language-coverage.cjs +3 -0
  428. package/scripts/lint-skill-deps.cjs +7 -3
  429. package/scripts/lint-test-file-count.allowlist.json +11 -1
  430. package/scripts/lint-test-file-count.cjs +34 -1
  431. package/scripts/lint-vendored-deps.cjs +41 -5
  432. package/scripts/lint-workflow-shellcheck-baseline.json +10 -10
  433. package/scripts/mutation-matrix.cjs +53 -6
  434. package/scripts/release-tarball-smoke.cjs +14 -7
  435. package/scripts/require-issue-link-policy.cjs +6 -2
  436. package/scripts/sync-runtime-launcher.cjs +184 -2
  437. package/scripts/verify-npm-publish.cjs +76 -20
  438. package/skills/gsd-add-tests/SKILL.md +6 -1
  439. package/skills/gsd-ai-integration-phase/SKILL.md +6 -1
  440. package/skills/gsd-audit-fix/SKILL.md +5 -0
  441. package/skills/gsd-audit-milestone/SKILL.md +6 -1
  442. package/skills/gsd-autonomous/SKILL.md +5 -0
  443. package/skills/gsd-capture/SKILL.md +8 -4
  444. package/skills/gsd-code-review/SKILL.md +7 -2
  445. package/skills/gsd-complete-milestone/SKILL.md +4 -0
  446. package/skills/gsd-config/SKILL.md +8 -4
  447. package/skills/gsd-debug/SKILL.md +11 -7
  448. package/skills/gsd-discuss-phase/SKILL.md +7 -3
  449. package/skills/gsd-docs-update/SKILL.md +12 -7
  450. package/skills/gsd-eval-review/SKILL.md +6 -1
  451. package/skills/gsd-execute-phase/SKILL.md +12 -7
  452. package/skills/gsd-extract-learnings/SKILL.md +5 -0
  453. package/skills/gsd-fast/SKILL.md +4 -0
  454. package/skills/gsd-forensics/SKILL.md +5 -1
  455. package/skills/gsd-graphify/SKILL.md +10 -6
  456. package/skills/gsd-health/SKILL.md +5 -0
  457. package/skills/gsd-help/SKILL.md +7 -2
  458. package/skills/gsd-import/SKILL.md +7 -3
  459. package/skills/gsd-inbox/SKILL.md +5 -0
  460. package/skills/gsd-ingest-docs/SKILL.md +5 -1
  461. package/skills/gsd-manager/SKILL.md +6 -1
  462. package/skills/gsd-map-codebase/SKILL.md +7 -3
  463. package/skills/gsd-mempalace-capture/SKILL.md +5 -1
  464. package/skills/gsd-mempalace-recall/SKILL.md +5 -1
  465. package/skills/gsd-milestone-summary/SKILL.md +5 -1
  466. package/skills/gsd-mvp-phase/SKILL.md +8 -3
  467. package/skills/gsd-new-milestone/SKILL.md +6 -1
  468. package/skills/gsd-new-project/SKILL.md +5 -0
  469. package/skills/gsd-next/SKILL.md +6 -1
  470. package/skills/gsd-ns-context/SKILL.md +4 -0
  471. package/skills/gsd-ns-ideate/SKILL.md +4 -0
  472. package/skills/gsd-ns-manage/SKILL.md +4 -0
  473. package/skills/gsd-ns-project/SKILL.md +4 -0
  474. package/skills/gsd-ns-review/SKILL.md +4 -0
  475. package/skills/gsd-ns-workflow/SKILL.md +4 -0
  476. package/skills/gsd-onboard/SKILL.md +6 -1
  477. package/skills/gsd-pause-work/SKILL.md +5 -1
  478. package/skills/gsd-phase/SKILL.md +8 -4
  479. package/skills/gsd-plan-phase/SKILL.md +6 -1
  480. package/skills/gsd-plan-review-convergence/SKILL.md +5 -1
  481. package/skills/gsd-pr-branch/SKILL.md +4 -0
  482. package/skills/gsd-profile-user/SKILL.md +5 -1
  483. package/skills/gsd-progress/SKILL.md +6 -1
  484. package/skills/gsd-quick/SKILL.md +16 -10
  485. package/skills/gsd-quick-batch/SKILL.md +20 -8
  486. package/skills/gsd-review/SKILL.md +5 -1
  487. package/skills/gsd-review-backlog/SKILL.md +3 -2
  488. package/skills/gsd-secure-phase/SKILL.md +6 -1
  489. package/skills/gsd-ship/SKILL.md +5 -0
  490. package/skills/gsd-sketch/SKILL.md +7 -2
  491. package/skills/gsd-spec-phase/SKILL.md +5 -1
  492. package/skills/gsd-spike/SKILL.md +8 -3
  493. package/skills/gsd-surface/SKILL.md +5 -1
  494. package/skills/gsd-thread/SKILL.md +4 -0
  495. package/skills/gsd-ui-phase/SKILL.md +6 -1
  496. package/skills/gsd-ui-review/SKILL.md +6 -1
  497. package/skills/gsd-ultraplan-phase/SKILL.md +5 -1
  498. package/skills/gsd-undo/SKILL.md +5 -1
  499. package/skills/gsd-update/SKILL.md +6 -2
  500. package/skills/gsd-validate-phase/SKILL.md +6 -1
  501. package/skills/gsd-verify-work/SKILL.md +6 -1
  502. package/skills/gsd-workspace/SKILL.md +7 -3
  503. package/skills/gsd-workstreams/SKILL.md +6 -6
  504. package/vscode/package.json +1 -1
  505. package/gsd-core/workflows/execute-phase/steps/stale-reverification.md +0 -24
@@ -43,6 +43,7 @@ const node_fs_1 = __importDefault(require("node:fs"));
43
43
  const node_path_1 = __importDefault(require("node:path"));
44
44
  const node_child_process_1 = require("node:child_process");
45
45
  const markdown_sectionizer_cjs_1 = require("./markdown-sectionizer.cjs");
46
+ const runtime_slash_cjs_1 = require("./runtime-slash.cjs");
46
47
  // #3696: the calendar-validity predicate moved to the STATE.md document module
47
48
  // so `state validate` can assert the same `last_activity` invariant this reader
48
49
  // already enforces (ADR-227). Two copies would let the two surfaces disagree
@@ -52,14 +53,17 @@ const ioMod = require("./io.cjs");
52
53
  const { output } = ioMod;
53
54
  // eslint-disable-next-line @typescript-eslint/no-require-imports
54
55
  const planningWorkspace = require("./planning-workspace.cjs");
55
- const { planningPaths } = planningWorkspace;
56
+ const { planningPaths, resolvePhaseIdConvention } = planningWorkspace;
56
57
  // eslint-disable-next-line @typescript-eslint/no-require-imports
57
58
  const frontmatter = require("./frontmatter.cjs");
58
- const { extractFrontmatter } = frontmatter;
59
+ const { extractFrontmatter, frontmatterBlock } = frontmatter;
59
60
  // eslint-disable-next-line @typescript-eslint/no-require-imports -- phase-lifecycle.cjs is an export= CommonJS module
60
61
  const phaseLifecycle = require("./phase-lifecycle.cjs");
61
62
  const { deriveProgressFromRoadmap } = phaseLifecycle;
62
63
  // eslint-disable-next-line @typescript-eslint/no-require-imports
64
+ const roadmapParser = require("./roadmap-parser.cjs");
65
+ const { extractCurrentMilestone, scanMilestonePhaseIds } = roadmapParser;
66
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
63
67
  const stateDocument = require("./state-document.cjs");
64
68
  const { stateFieldValue } = stateDocument;
65
69
  // eslint-disable-next-line @typescript-eslint/no-require-imports
@@ -71,6 +75,10 @@ const { readStateHeadFreshness } = stateMod;
71
75
  // eslint-disable-next-line @typescript-eslint/no-require-imports
72
76
  const unusableInput = require("./unusable-input.cjs");
73
77
  const { warnUnusableInput, UNUSABLE_REASON } = unusableInput;
78
+ // #5118: the verification-status owner's frontmatter-only report check.
79
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
80
+ const verificationMod = require("./verification.cjs");
81
+ const { findVerificationStatusError } = verificationMod;
74
82
  // ─── Constants ────────────────────────────────────────────────────────────────
75
83
  /**
76
84
  * Staleness threshold for idle-stranded detection. A clean tree whose last
@@ -285,11 +293,20 @@ function detectVerifyFailed(cwd, currentPhaseRaw) {
285
293
  catch {
286
294
  return false;
287
295
  }
296
+ // #5118: this phase's VERIFICATION report `status` is judged by its owner
297
+ // (src/verification.cts, the same frontmatter-only, containment-checked
298
+ // locator every reader shares) — an out-of-set value is the owner's hard
299
+ // error here as at every other reader, never a silent "not failed". The
300
+ // body `STATUS:` marker scan below is this probe's own signal.
301
+ const statusError = findVerificationStatusError([latestDir]);
302
+ if (statusError)
303
+ throw statusError;
288
304
  const candidates = files.filter((f) => /summary|verif(?:y|ication)|uat/i.test(f));
289
305
  for (const name of candidates) {
290
306
  let content = '';
307
+ const filePath = node_path_1.default.join(latestDir, name);
291
308
  try {
292
- content = node_fs_1.default.readFileSync(node_path_1.default.join(latestDir, name), 'utf-8');
309
+ content = node_fs_1.default.readFileSync(filePath, 'utf-8');
293
310
  }
294
311
  catch {
295
312
  continue;
@@ -311,7 +328,10 @@ function readStateFile(statePath) {
311
328
  return null;
312
329
  }
313
330
  const fm = extractFrontmatter(content, statePath);
314
- const body = content.replace(/^---[\s\S]*?---\s*/, '');
331
+ // The body starts after the block `extractFrontmatter` just read (the one fence owner), so a
332
+ // `---` inside a value, a BOM, or an adjacent empty block cannot cut it somewhere else.
333
+ const block = frontmatterBlock(content);
334
+ const body = block ? block.rest.replace(/^\s+/, '') : content;
315
335
  return { fm, body };
316
336
  }
317
337
  /** Collect the full signal set from disk for `cwd`. Exported for unit tests. */
@@ -336,6 +356,7 @@ function detectSignals(cwd, now = Date.now) {
336
356
  stale_activity: false,
337
357
  roadmap_total_phases: null,
338
358
  roadmap_completed_phases: null,
359
+ milestone_phases: [],
339
360
  // No STATE.md (or unreadable) → no stamp to compare. Unknown, not fresh.
340
361
  state_commits_behind: null,
341
362
  state_commit_stale: null,
@@ -409,12 +430,18 @@ function detectSignals(cwd, now = Date.now) {
409
430
  // Progress table — isComplete falls back to the legacy comparison in that case.
410
431
  let roadmapTotalPhases = null;
411
432
  let roadmapCompletedPhases = null;
433
+ let milestonePhases = [];
412
434
  if (hasRoadmap) {
413
435
  try {
414
436
  const roadmapContent = node_fs_1.default.readFileSync(paths.roadmap, 'utf8');
415
437
  const derived = deriveProgressFromRoadmap(roadmapContent);
416
438
  roadmapTotalPhases = derived.totalPhases;
417
439
  roadmapCompletedPhases = derived.completedPhases;
440
+ // #5228: the ordered phase list of the current milestone, from the same
441
+ // scan the milestone-scoped commands use.
442
+ milestonePhases = [
443
+ ...scanMilestonePhaseIds(extractCurrentMilestone(roadmapContent, cwd), resolvePhaseIdConvention(cwd)),
444
+ ].sort(comparePhaseNum);
418
445
  }
419
446
  catch {
420
447
  /* ROADMAP.md unreadable — leave null; isComplete falls back to legacy. */
@@ -441,6 +468,7 @@ function detectSignals(cwd, now = Date.now) {
441
468
  stale_activity: staleActivity,
442
469
  roadmap_total_phases: roadmapTotalPhases,
443
470
  roadmap_completed_phases: roadmapCompletedPhases,
471
+ milestone_phases: milestonePhases,
444
472
  state_commits_behind: freshness.commits_behind,
445
473
  state_commit_stale: freshness.commit_stale,
446
474
  };
@@ -472,10 +500,21 @@ function isComplete(s) {
472
500
  // Legacy path: STATE.md comparison. It only fires when ROADMAP.md is
473
501
  // absent or has no Progress table, and uses canonical phase-id ordering
474
502
  // so dotted phase ids are never coerced to JavaScript numbers.
475
- if (s.total_phases === null || s.current_phase === null)
476
- return false;
477
- if (comparePhaseNum(s.current_phase, s.total_phases) < 0)
503
+ if (s.current_phase === null)
478
504
  return false;
505
+ if (s.milestone_phases.length > 0) {
506
+ // #5228: compare against the milestone's LAST phase. The phase count is
507
+ // not a phase number once numbering continues from an earlier milestone.
508
+ const last = s.milestone_phases[s.milestone_phases.length - 1];
509
+ if (comparePhaseNum(s.current_phase, last) < 0)
510
+ return false;
511
+ }
512
+ else {
513
+ if (s.total_phases === null)
514
+ return false;
515
+ if (comparePhaseNum(s.current_phase, s.total_phases) < 0)
516
+ return false;
517
+ }
479
518
  }
480
519
  // Status regex: require milestone-level completion language. The pre-fix
481
520
  // regex matched any "shipped" / "done" substring (per-phase language).
@@ -542,52 +581,54 @@ function rec(id, label, command) {
542
581
  return action(id, label, command, true);
543
582
  }
544
583
  /** Per-situation ordered action list; recommended action first. */
545
- function actionsFor(situation, s) {
584
+ function actionsFor(situation, s, runtime = 'claude') {
585
+ // #4859: commands are printed verbatim, so name them the way this runtime registers them.
586
+ const cmd = (name) => (0, runtime_slash_cjs_1.formatGsdSlash)(name, runtime);
546
587
  const phaseN = s.current_phase ?? '';
547
588
  const execLabel = phaseN === '' ? 'Continue executing' : `Continue executing phase ${phaseN}`;
548
589
  switch (situation) {
549
590
  case 'no-project':
550
591
  return [
551
- rec('new-project', 'Start a new project', '/gsd:new-project'),
552
- action('map-codebase', 'Map an existing codebase', '/gsd:map-codebase'),
553
- action('quick', 'Quick task', '/gsd:quick'),
554
- action('help', 'Show help', '/gsd:help'),
592
+ rec('new-project', 'Start a new project', cmd('new-project')),
593
+ action('map-codebase', 'Map an existing codebase', cmd('map-codebase')),
594
+ action('quick', 'Quick task', cmd('quick')),
595
+ action('help', 'Show help', cmd('help')),
555
596
  ];
556
597
  case 'paused':
557
598
  return [
558
- rec('resume-work', 'Resume work', '/gsd:resume-work'),
559
- action('progress', 'Show progress', '/gsd:progress'),
560
- action('quick', 'Quick task', '/gsd:quick'),
561
- action('help', 'Show help', '/gsd:help'),
599
+ rec('resume-work', 'Resume work', cmd('resume-work')),
600
+ action('progress', 'Show progress', cmd('progress')),
601
+ action('quick', 'Quick task', cmd('quick')),
602
+ action('help', 'Show help', cmd('help')),
562
603
  ];
563
604
  case 'blocked':
564
605
  return [
565
- rec('debug', 'Debug the blocker', '/gsd:debug'),
566
- action('verify-work', 'Verify current work', '/gsd:verify-work'),
567
- action('capture', 'Capture a note', '/gsd:capture'),
568
- action('progress', 'Show progress', '/gsd:progress'),
606
+ rec('debug', 'Debug the blocker', cmd('debug')),
607
+ action('verify-work', 'Verify current work', cmd('verify-work')),
608
+ action('capture', 'Capture a note', cmd('capture')),
609
+ action('progress', 'Show progress', cmd('progress')),
569
610
  ];
570
611
  case 'verify-failed':
571
612
  return [
572
- rec('verify-work', 'Re-verify work', '/gsd:verify-work'),
573
- action('debug', 'Debug the failure', '/gsd:debug'),
574
- action('code-review', 'Review recent work', '/gsd:code-review'),
575
- action('progress', 'Show progress', '/gsd:progress'),
613
+ rec('verify-work', 'Re-verify work', cmd('verify-work')),
614
+ action('debug', 'Debug the failure', cmd('debug')),
615
+ action('code-review', 'Review recent work', cmd('code-review')),
616
+ action('progress', 'Show progress', cmd('progress')),
576
617
  ];
577
618
  case 'needs-first-phase':
578
619
  return [
579
- rec('discuss-phase', 'Discuss the first phase', '/gsd:discuss-phase'),
580
- action('plan-phase', 'Plan phase 1', '/gsd:plan-phase'),
581
- action('quick', 'Quick task', '/gsd:quick'),
582
- action('progress', 'Show progress', '/gsd:progress'),
620
+ rec('discuss-phase', 'Discuss the first phase', cmd('discuss-phase')),
621
+ action('plan-phase', 'Plan phase 1', cmd('plan-phase')),
622
+ action('quick', 'Quick task', cmd('quick')),
623
+ action('progress', 'Show progress', cmd('progress')),
583
624
  ];
584
625
  case 'planning':
585
626
  // Forward motion → delegate to the single gated engine (see 'executing').
586
627
  return [
587
- rec('progress-next', `Advance to the next step (plan phase ${phaseN || 1})`, '/gsd:progress --next'),
588
- action('plan-phase', `Plan phase ${phaseN || 1}`, '/gsd:plan-phase'),
589
- action('discuss-phase', 'Discuss before planning', '/gsd:discuss-phase'),
590
- action('progress', 'Show progress', '/gsd:progress'),
628
+ rec('progress-next', `Advance to the next step (plan phase ${phaseN || 1})`, cmd('progress --next')),
629
+ action('plan-phase', `Plan phase ${phaseN || 1}`, cmd('plan-phase')),
630
+ action('discuss-phase', 'Discuss before planning', cmd('discuss-phase')),
631
+ action('progress', 'Show progress', cmd('progress')),
591
632
  ];
592
633
  case 'executing':
593
634
  // In-project forward motion delegates to the single gated engine
@@ -596,40 +637,40 @@ function actionsFor(situation, s) {
596
637
  // /gsd:execute-phase here — that divergence is why the old flat /gsd-next
597
638
  // was removed (#3054). Direct execute stays as an explicit secondary choice.
598
639
  return [
599
- rec('progress-next', 'Advance to the next step', '/gsd:progress --next'),
600
- action('execute-phase', execLabel, '/gsd:execute-phase'),
601
- action('quick', 'Quick task', '/gsd:quick'),
602
- action('code-review', 'Review recent work', '/gsd:code-review'),
640
+ rec('progress-next', 'Advance to the next step', cmd('progress --next')),
641
+ action('execute-phase', execLabel, cmd('execute-phase')),
642
+ action('quick', 'Quick task', cmd('quick')),
643
+ action('code-review', 'Review recent work', cmd('code-review')),
603
644
  ];
604
645
  case 'verify-pending':
605
646
  // Forward motion → delegate to the single gated engine (see 'executing').
606
647
  return [
607
- rec('progress-next', 'Advance to the next step (verify)', '/gsd:progress --next'),
608
- action('verify-work', 'Verify work', '/gsd:verify-work'),
609
- action('code-review', 'Review recent work', '/gsd:code-review'),
610
- action('ship', 'Ship completed work', '/gsd:ship'),
648
+ rec('progress-next', 'Advance to the next step (verify)', cmd('progress --next')),
649
+ action('verify-work', 'Verify work', cmd('verify-work')),
650
+ action('code-review', 'Review recent work', cmd('code-review')),
651
+ action('ship', 'Ship completed work', cmd('ship')),
611
652
  ];
612
653
  case 'idle-stranded':
613
654
  return [
614
- rec('ship', 'Ship committed work', '/gsd:ship'),
615
- action('complete-milestone', 'Complete the milestone', '/gsd:complete-milestone'),
616
- action('progress', 'Show progress', '/gsd:progress'),
617
- action('capture', 'Capture a note', '/gsd:capture'),
655
+ rec('ship', 'Ship committed work', cmd('ship')),
656
+ action('complete-milestone', 'Complete the milestone', cmd('complete-milestone')),
657
+ action('progress', 'Show progress', cmd('progress')),
658
+ action('capture', 'Capture a note', cmd('capture')),
618
659
  ];
619
660
  case 'complete':
620
661
  return [
621
- rec('new-milestone', 'Start a new milestone', '/gsd:new-milestone'),
622
- action('extract-learnings', 'Extract learnings', '/gsd:extract-learnings'),
623
- action('quick', 'Quick task', '/gsd:quick'),
624
- action('progress', 'Show progress', '/gsd:progress'),
662
+ rec('new-milestone', 'Start a new milestone', cmd('new-milestone')),
663
+ action('extract-learnings', 'Extract learnings', cmd('extract-learnings')),
664
+ action('quick', 'Quick task', cmd('quick')),
665
+ action('progress', 'Show progress', cmd('progress')),
625
666
  ];
626
667
  case 'unknown':
627
668
  default:
628
669
  return [
629
- rec('progress', 'Show progress', '/gsd:progress'),
630
- action('progress-next', 'Advance to the next step', '/gsd:progress --next'),
631
- action('quick', 'Quick task', '/gsd:quick'),
632
- action('help', 'Show help', '/gsd:help'),
670
+ rec('progress', 'Show progress', cmd('progress')),
671
+ action('progress-next', 'Advance to the next step', cmd('progress --next')),
672
+ action('quick', 'Quick task', cmd('quick')),
673
+ action('help', 'Show help', cmd('help')),
633
674
  ];
634
675
  }
635
676
  }
@@ -647,7 +688,7 @@ function buildSummary(situation, s) {
647
688
  case 'needs-first-phase':
648
689
  return 'Project initialized — plan your first phase';
649
690
  case 'planning':
650
- return `Phase ${s.current_phase ?? '?'} of ${s.total_phases ?? '?'} — needs a plan`;
691
+ return `${phasePosition(s)} — needs a plan`;
651
692
  case 'executing':
652
693
  return progressLine('executing', s);
653
694
  case 'verify-pending':
@@ -661,10 +702,24 @@ function buildSummary(situation, s) {
661
702
  return 'Unsure of state — showing progress';
662
703
  }
663
704
  }
705
+ /**
706
+ * "Phase N of M" for the current phase. N is the phase's 1-based position in
707
+ * the current milestone's ordered phase list (#5228), so a milestone that
708
+ * continues the numbering of an earlier one (phases 9-17) reads "Phase 1 of 9",
709
+ * not "Phase 9 of 9". When the phase is not in that list (or the roadmap lists
710
+ * none) the STATE.md figures are printed as recorded.
711
+ */
712
+ function phasePosition(s) {
713
+ const current = s.current_phase;
714
+ const at = current === null ? -1 : s.milestone_phases.findIndex((id) => comparePhaseNum(id, current) === 0);
715
+ if (at >= 0)
716
+ return `Phase ${at + 1} of ${s.milestone_phases.length}`;
717
+ return `Phase ${s.current_phase ?? '?'} of ${s.total_phases ?? '?'}`;
718
+ }
664
719
  function progressLine(tail, s) {
665
720
  const parts = [];
666
721
  if (s.current_phase !== null && s.total_phases !== null) {
667
- parts.push(`Phase ${s.current_phase} of ${s.total_phases}`);
722
+ parts.push(phasePosition(s));
668
723
  }
669
724
  else if (s.current_phase !== null) {
670
725
  parts.push(`Phase ${s.current_phase}`);
@@ -683,7 +738,7 @@ function progressLine(tail, s) {
683
738
  function classifyProject(cwd, now = Date.now) {
684
739
  const signals = detectSignals(cwd, now);
685
740
  const situation = classify(signals);
686
- const actions = actionsFor(situation, signals);
741
+ const actions = actionsFor(situation, signals, (0, runtime_slash_cjs_1.resolveRuntime)(cwd));
687
742
  const recommended = actions.find((a) => a.recommended)?.id ?? 'progress';
688
743
  const summary = buildSummary(situation, signals);
689
744
  return { situation, recommended, summary, signals, actions };
@@ -702,6 +757,6 @@ function runSmartEntry(cwd, args, raw) {
702
757
  return;
703
758
  }
704
759
  // Human mode: a compact one-liner plus the recommended action.
705
- const human = `${result.summary}\nRecommended: ${result.recommended} → ${result.actions.find((a) => a.id === result.recommended)?.command ?? '/gsd:progress'}`;
760
+ const human = `${result.summary}\nRecommended: ${result.recommended} → ${result.actions.find((a) => a.id === result.recommended)?.command ?? (0, runtime_slash_cjs_1.runtimeCommand)(cwd, 'progress')}`;
706
761
  output(null, true, human);
707
762
  }
@@ -21,22 +21,23 @@
21
21
  const fs = require('fs');
22
22
  const path = require('path');
23
23
  const os = require('os');
24
+ const capabilityRegistry = require('./capability-registry.cjs');
25
+ const { hostBehaviorsFor } = require('./runtime-name-policy.cjs');
26
+ const { resolveConfigHomeFromDescriptor } = require('./runtime-homes.cjs');
27
+ const { resolveActiveRuntime } = require('./runtime-slash.cjs');
24
28
 
25
29
  /**
26
- * Runtimes whose agent config is static frontmatter/TOML baked at install time.
27
- * MUST stay in sync with the bake paths in bin/install.js. The parity test in
28
- * tests/stale-bake-guard.test.cjs asserts this matches the runtimes that
29
- * actually emit a baked model: line id #2256 (opencode), #49/#2256 (codex),
30
- * and #2093 (kilo).
30
+ * Runtimes whose agent config is static frontmatter/TOML baked at install time,
31
+ * DERIVED from the runtime descriptors (`hostBehaviors.bakesStaticAgentModel`,
32
+ * #5169) instead of a hand-kept list: line id #2256 (opencode), #49/#2256
33
+ * (codex), and #2093 (kilo) declare it, and a new baking runtime does too.
31
34
  */
32
- const STATIC_FRONTMATTER_RUNTIMES = Object.freeze(['codex', 'kilo', 'opencode']);
35
+ const STATIC_FRONTMATTER_RUNTIMES = Object.freeze(
36
+ Object.keys(capabilityRegistry.runtimes)
37
+ .filter((id) => hostBehaviorsFor(id).bakesStaticAgentModel === true)
38
+ .sort(),
39
+ );
33
40
 
34
- /** Per-runtime `gsd install` flag, for the remediation hint in the warning. */
35
- const INSTALL_FLAG_BY_RUNTIME = Object.freeze({
36
- codex: '--codex',
37
- opencode: '--opencode',
38
- kilo: '--kilo',
39
- });
40
41
 
41
42
  const _warnedKeys = new Set();
42
43
 
@@ -64,7 +65,7 @@ function formatStaleBakeWarning({ runtime, configPath, configMtimeMs, agentMtime
64
65
  const signal = detectStaleBake({ runtime, configMtimeMs, agentMtimeMs });
65
66
  if (!signal) return '';
66
67
  const configDate = new Date(configMtimeMs).toISOString();
67
- const installFlag = INSTALL_FLAG_BY_RUNTIME[runtime] || `--${runtime}`;
68
+ const installFlag = `--${runtime}`;
68
69
  return [
69
70
  `gsd: model config in ${configPath} changed since agents were last baked (${configDate}).`,
70
71
  ` Static-frontmatter runtime '${runtime}' ignores the new model_overrides`,
@@ -74,44 +75,27 @@ function formatStaleBakeWarning({ runtime, configPath, configMtimeMs, agentMtime
74
75
  }
75
76
 
76
77
  /**
77
- * Pure: resolve the active runtime id from a parsed config object.
78
- * Returns the runtime string, or `'claude'` when unset (the spawn-time default
79
- * for which the guard is a no-op).
78
+ * Resolve the active runtime id for the guard: the SAME chain every consumer of
79
+ * "which runtime is this install" reads — GSD_RUNTIME → config.runtime →
80
+ * per-install `.gsd-runtime` marker → `'claude'` (#5169, #4690). Returns
81
+ * `'claude'` when nothing is declared (the spawn-time default for which the
82
+ * guard is a no-op).
80
83
  */
81
- function resolveRuntimeFromConfig(config) {
82
- if (config && typeof config === 'object'
83
- && typeof config.runtime === 'string' && config.runtime) {
84
- return config.runtime;
85
- }
86
- return 'claude';
84
+ function resolveRuntimeFromConfig(config, env = process.env) {
85
+ return resolveActiveRuntime(config, env);
87
86
  }
88
87
 
89
88
  /**
90
- * Resolve the install root for a runtime's agent files, honoring the same env
91
- * vars the installer does (CODEX_HOME, OPENCODE_CONFIG_DIR, KILO_CONFIG_DIR).
92
- * Returns the absolute directory or `null` for unsupported runtimes.
89
+ * Resolve the install root for a runtime's agent files from the runtime
90
+ * descriptor's `configHome` (the same resolution the installer uses), then
91
+ * append `agents` — the installer writes agents to `<configHome>/agents`
92
+ * (plural; #2093). Returns the absolute directory or `null` for runtimes that
93
+ * do not bake a static agent model.
93
94
  */
94
95
  function resolveAgentDir(runtime, { env = process.env, homedir = os.homedir } = {}) {
95
- if (runtime === 'opencode') {
96
- const base = (env.OPENCODE_CONFIG_DIR && String(env.OPENCODE_CONFIG_DIR).trim()) || path.join(homedir(), '.config', 'opencode');
97
- // #2093 fix: the installer writes agents to `<base>/agents` (plural — see
98
- // bin/install.js's universal `agentsDest = path.join(targetDir, 'agents')`,
99
- // verified against a live `--opencode --global` install). The prior
100
- // singular `agent` never matched the real install output, so this guard's
101
- // `findOldestAgentMtime` always hit ENOENT and warnIfStaleBake was a
102
- // silent no-op for opencode in production — discovered while wiring the
103
- // parallel kilo entry below (same bake mechanism, #2093).
104
- return path.join(base, 'agents');
105
- }
106
- if (runtime === 'kilo') {
107
- const base = (env.KILO_CONFIG_DIR && String(env.KILO_CONFIG_DIR).trim()) || path.join(homedir(), '.config', 'kilo');
108
- return path.join(base, 'agents');
109
- }
110
- if (runtime === 'codex') {
111
- const base = (env.CODEX_HOME && String(env.CODEX_HOME).trim()) || path.join(homedir(), '.codex');
112
- return path.join(base, 'agents');
113
- }
114
- return null;
96
+ if (!STATIC_FRONTMATTER_RUNTIMES.includes(runtime)) return null;
97
+ const configHome = capabilityRegistry.runtimes[runtime].runtime.configHome;
98
+ return path.join(resolveConfigHomeFromDescriptor(configHome, { env, home: homedir() }), 'agents');
115
99
  }
116
100
 
117
101
  /**
@@ -168,8 +152,8 @@ function findOldestAgentMtime(runtime, { env = process.env, homedir = os.homedir
168
152
  for (const entry of entries) {
169
153
  if (!entry.isFile()) continue;
170
154
  if (!entry.name.startsWith('gsd-')) continue;
171
- const isAgentFile = ((runtime === 'opencode' || runtime === 'kilo') && entry.name.endsWith('.md'))
172
- || (runtime === 'codex' && (entry.name.endsWith('.toml') || entry.name.endsWith('.md')));
155
+ const bakedExts = hostBehaviorsFor(runtime).bakedAgentFileExtensions;
156
+ const isAgentFile = Array.isArray(bakedExts) && bakedExts.some((ext) => entry.name.endsWith(ext));
173
157
  if (!isAgentFile) continue;
174
158
  try {
175
159
  const st = fsStatSync(path.join(dir, entry.name));
@@ -209,7 +193,7 @@ function warnIfStaleBake(cwd, options = {}) {
209
193
  } = options;
210
194
  try {
211
195
  const resolvedConfig = config || _readRuntimeConfig(cwd, { fsStatSync });
212
- const runtime = resolveRuntimeFromConfig(resolvedConfig);
196
+ const runtime = resolveRuntimeFromConfig(resolvedConfig, env);
213
197
  if (!STATIC_FRONTMATTER_RUNTIMES.includes(runtime)) return false;
214
198
 
215
199
  const dedupKey = `${runtime}::${path.resolve(cwd || '.')}`;
@@ -73,6 +73,12 @@ exports.buildStateContract = buildStateContract;
73
73
  exports.publishStateContract = publishStateContract;
74
74
  const node_path_1 = __importDefault(require("node:path"));
75
75
  const node_fs_1 = __importDefault(require("node:fs"));
76
+ // #5060: `phase-status.cjs` is a LOAD-TIME LEAF — no top-level requires of
77
+ // its own (verification.cjs/plan-scan.cjs are required lazily, only inside
78
+ // `phaseStatus()`) — so importing it here at top level does not reopen the
79
+ // documented `state.cjs -> state-contract.cjs -> smart-entry.cjs -> state.cjs`
80
+ // require cycle the file header warns about.
81
+ const phase_status_cjs_1 = require("./phase-status.cjs");
76
82
  // ─── Public wire vocabulary ────────────────────────────────────────────────
77
83
  exports.STATE_CONTRACT_VERSION = '1.0.0';
78
84
  exports.STATE_CONTRACT_FLAVOR = 'core';
@@ -80,12 +86,14 @@ exports.STATE_CONTRACT_FLAVOR = 'core';
80
86
  exports.CONTRACT_KEY_ORDER = Object.freeze(['contract', 'flavor', 'milestone', 'phases', 'next', 'updated_at']);
81
87
  /** Key order of each emitted phase object — an observable, pinned by test. */
82
88
  exports.PHASE_KEY_ORDER = Object.freeze(['number', 'name', 'status']);
83
- /** Frozen three-value phase status vocabulary. Conservative in what we send (Postel's Law). */
84
- exports.PHASE_STATUS = Object.freeze({
85
- COMPLETE: 'complete',
86
- IN_PROGRESS: 'in_progress',
87
- PENDING: 'pending',
88
- });
89
+ /**
90
+ * Frozen three-value phase status vocabulary. Conservative in what we send
91
+ * (Postel's Law). #5060: identity-pinned to the Phase Status Module's own
92
+ * `WIRE_STATUS` — this is not a copy, it IS that frozen object, so
93
+ * `state-contract`'s `PHASE_STATUS` and `phase-status.cjs`'s `WIRE_STATUS`
94
+ * can never independently drift.
95
+ */
96
+ exports.PHASE_STATUS = phase_status_cjs_1.WIRE_STATUS;
89
97
  /** Frozen `publishStateContract` result reasons. */
90
98
  exports.PUBLISH_REASON = Object.freeze({
91
99
  PUBLISHED: 'published',
@@ -146,17 +154,6 @@ function buildMilestone(cwd) {
146
154
  }
147
155
  // ─── phases: Progress-table (primary) enumerator ───────────────────────────
148
156
  const PHASE_CELL_RE = /^(\d+(?:\.\d+)*)\s*[.:)–—-]?\s*(.*)$/;
149
- function statusFromProgressCell(raw) {
150
- const normalized = (raw ?? '').trim().toLowerCase().replace(/\s+/g, ' ');
151
- if (normalized === 'complete')
152
- return exports.PHASE_STATUS.COMPLETE;
153
- if (normalized === 'in progress')
154
- return exports.PHASE_STATUS.IN_PROGRESS;
155
- // Everything else — 'not started', 'deferred' (design row 12, lossy by
156
- // design), '', and any unrecognized word — folds to pending. An
157
- // unrecognized status must never reach the wire as a 4th value.
158
- return exports.PHASE_STATUS.PENDING;
159
- }
160
157
  function phasesFromProgressTable(table) {
161
158
  const { isSentinelPhaseId } = owners();
162
159
  const phases = [];
@@ -169,7 +166,7 @@ function phasesFromProgressTable(table) {
169
166
  const m = PHASE_CELL_RE.exec(cell);
170
167
  const number = m ? m[1] : cell;
171
168
  const name = m && m[2].trim().length > 0 ? m[2].trim() : null;
172
- phases.push({ number, name, status: statusFromProgressCell(row['Status']) });
169
+ phases.push({ number, name, status: (0, phase_status_cjs_1.parseRoadmapStatusCell)(row['Status']) });
173
170
  }
174
171
  return phases;
175
172
  }