@opengsd/gsd-core 1.15.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 (487) 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/agents/gsd-code-fixer.compact.md +1 -1
  5. package/agents/gsd-code-fixer.md +1 -1
  6. package/agents/gsd-code-reviewer.compact.md +5 -3
  7. package/agents/gsd-code-reviewer.md +8 -6
  8. package/agents/gsd-debug-session-manager.compact.md +1 -1
  9. package/agents/gsd-debug-session-manager.md +1 -1
  10. package/agents/gsd-debugger.md +2 -2
  11. package/agents/gsd-eval-auditor.compact.md +1 -1
  12. package/agents/gsd-eval-auditor.md +1 -1
  13. package/agents/gsd-executor.md +4 -4
  14. package/agents/gsd-intel-updater.compact.md +1 -1
  15. package/agents/gsd-intel-updater.md +1 -1
  16. package/agents/gsd-mempalace-curator.md +2 -2
  17. package/agents/gsd-phase-researcher.md +1 -1
  18. package/agents/gsd-plan-checker.md +7 -2
  19. package/agents/gsd-planner.md +3 -3
  20. package/agents/gsd-project-researcher.compact.md +1 -1
  21. package/agents/gsd-project-researcher.md +1 -1
  22. package/agents/gsd-research-synthesizer.compact.md +1 -1
  23. package/agents/gsd-research-synthesizer.md +1 -1
  24. package/agents/gsd-ui-auditor.compact.md +21 -30
  25. package/agents/gsd-ui-auditor.md +42 -51
  26. package/agents/gsd-ui-researcher.compact.md +1 -1
  27. package/agents/gsd-ui-researcher.md +1 -1
  28. package/agents/gsd-verifier.md +31 -9
  29. package/bin/install.js +126 -196
  30. package/commands/gsd/add-tests.md +6 -1
  31. package/commands/gsd/ai-integration-phase.md +6 -1
  32. package/commands/gsd/audit-fix.md +5 -0
  33. package/commands/gsd/audit-milestone.md +6 -1
  34. package/commands/gsd/autonomous.md +5 -0
  35. package/commands/gsd/capture.md +8 -4
  36. package/commands/gsd/code-review.md +7 -2
  37. package/commands/gsd/complete-milestone.md +4 -0
  38. package/commands/gsd/config.md +7 -3
  39. package/commands/gsd/debug.md +11 -7
  40. package/commands/gsd/discuss-phase.md +7 -3
  41. package/commands/gsd/docs-update.md +12 -7
  42. package/commands/gsd/eval-review.md +6 -1
  43. package/commands/gsd/execute-phase.md +12 -7
  44. package/commands/gsd/extract-learnings.md +5 -0
  45. package/commands/gsd/fast.md +4 -0
  46. package/commands/gsd/forensics.md +5 -1
  47. package/commands/gsd/graphify.md +10 -6
  48. package/commands/gsd/health.md +5 -0
  49. package/commands/gsd/help.md +7 -2
  50. package/commands/gsd/import.md +7 -3
  51. package/commands/gsd/inbox.md +5 -0
  52. package/commands/gsd/ingest-docs.md +5 -1
  53. package/commands/gsd/manager.md +6 -1
  54. package/commands/gsd/map-codebase.md +7 -3
  55. package/commands/gsd/mempalace-capture.md +5 -1
  56. package/commands/gsd/mempalace-recall.md +5 -1
  57. package/commands/gsd/milestone-summary.md +5 -1
  58. package/commands/gsd/mvp-phase.md +8 -3
  59. package/commands/gsd/new-milestone.md +6 -1
  60. package/commands/gsd/new-project.md +5 -0
  61. package/commands/gsd/next.md +6 -1
  62. package/commands/gsd/ns-context.md +4 -0
  63. package/commands/gsd/ns-ideate.md +4 -0
  64. package/commands/gsd/ns-manage.md +4 -0
  65. package/commands/gsd/ns-project.md +4 -0
  66. package/commands/gsd/ns-review.md +4 -0
  67. package/commands/gsd/ns-workflow.md +4 -0
  68. package/commands/gsd/onboard.md +6 -1
  69. package/commands/gsd/pause-work.md +5 -1
  70. package/commands/gsd/phase.md +8 -4
  71. package/commands/gsd/plan-phase.md +6 -1
  72. package/commands/gsd/plan-review-convergence.md +5 -1
  73. package/commands/gsd/pr-branch.md +4 -0
  74. package/commands/gsd/profile-user.md +5 -1
  75. package/commands/gsd/progress.md +6 -1
  76. package/commands/gsd/quick-batch.md +20 -8
  77. package/commands/gsd/quick.md +12 -7
  78. package/commands/gsd/review.md +5 -1
  79. package/commands/gsd/secure-phase.md +6 -1
  80. package/commands/gsd/ship.md +5 -0
  81. package/commands/gsd/sketch.md +7 -2
  82. package/commands/gsd/spec-phase.md +5 -1
  83. package/commands/gsd/spike.md +8 -3
  84. package/commands/gsd/surface.md +5 -1
  85. package/commands/gsd/thread.md +4 -0
  86. package/commands/gsd/ui-phase.md +6 -1
  87. package/commands/gsd/ui-review.md +6 -1
  88. package/commands/gsd/ultraplan-phase.md +5 -1
  89. package/commands/gsd/undo.md +5 -1
  90. package/commands/gsd/update.md +6 -2
  91. package/commands/gsd/validate-phase.md +6 -1
  92. package/commands/gsd/verify-work.md +6 -1
  93. package/commands/gsd/workspace.md +7 -3
  94. package/gsd-core/bin/gsd-tools.cjs +142 -56
  95. package/gsd-core/bin/lib/active-workstream-store.cjs +15 -0
  96. package/gsd-core/bin/lib/agent-install-check.cjs +4 -1
  97. package/gsd-core/bin/lib/audit.cjs +78 -44
  98. package/gsd-core/bin/lib/broken-windows.cjs +13 -13
  99. package/gsd-core/bin/lib/capability-activation.cjs +9 -4
  100. package/gsd-core/bin/lib/capability-registry.cjs +183 -103
  101. package/gsd-core/bin/lib/capability-validator.cjs +16 -0
  102. package/gsd-core/bin/lib/check-auto-mode.cjs +35 -0
  103. package/gsd-core/bin/lib/check-command-router.cjs +164 -1712
  104. package/gsd-core/bin/lib/cjs-command-router-adapter.cjs +13 -2
  105. package/gsd-core/bin/lib/cli-exit.cjs +12 -0
  106. package/gsd-core/bin/lib/codex-agent-toml.cjs +11 -8
  107. package/gsd-core/bin/lib/command-aliases.cjs +7 -0
  108. package/gsd-core/bin/lib/command-routing-hub.cjs +48 -1
  109. package/gsd-core/bin/lib/commands.cjs +173 -170
  110. package/gsd-core/bin/lib/complexity-trigger.cjs +8 -7
  111. package/gsd-core/bin/lib/config.cjs +43 -12
  112. package/gsd-core/bin/lib/core-utils.cjs +6 -1
  113. package/gsd-core/bin/lib/coverage.cjs +4 -8
  114. package/gsd-core/bin/lib/decision-coverage-support.cjs +259 -0
  115. package/gsd-core/bin/lib/drift.cjs +177 -42
  116. package/gsd-core/bin/lib/frontmatter-fence.cjs +90 -0
  117. package/gsd-core/bin/lib/frontmatter-splice.cjs +494 -0
  118. package/gsd-core/bin/lib/frontmatter.cjs +413 -234
  119. package/gsd-core/bin/lib/gap-checker.cjs +72 -29
  120. package/gsd-core/bin/lib/gate-api-coverage-verify-pre.cjs +381 -0
  121. package/gsd-core/bin/lib/gate-args.cjs +53 -0
  122. package/gsd-core/bin/lib/gate-codebase-drift.cjs +285 -0
  123. package/gsd-core/bin/lib/gate-config.cjs +46 -0
  124. package/gsd-core/bin/lib/gate-context-drift.cjs +141 -0
  125. package/gsd-core/bin/lib/gate-decision-coverage-plan.cjs +169 -0
  126. package/gsd-core/bin/lib/gate-decision-coverage-verify.cjs +126 -0
  127. package/gsd-core/bin/lib/gate-evaluation-scope.cjs +555 -0
  128. package/gsd-core/bin/lib/gate-evidence.cjs +138 -0
  129. package/gsd-core/bin/lib/gate-exit.cjs +27 -0
  130. package/gsd-core/bin/lib/gate-gap-analysis-plan-post.cjs +61 -0
  131. package/gsd-core/bin/lib/gate-phase-context.cjs +170 -0
  132. package/gsd-core/bin/lib/gate-predicate-evaluator.cjs +1 -1
  133. package/gsd-core/bin/lib/gate-predicate.cjs +165 -0
  134. package/gsd-core/bin/lib/gate-prohibition-enforcement.cjs +94 -0
  135. package/gsd-core/bin/lib/gate-schema-drift.cjs +165 -0
  136. package/gsd-core/bin/lib/gate-tdd-red-evidence.cjs +100 -0
  137. package/gsd-core/bin/lib/gate-tdd-review-checkpoint.cjs +182 -0
  138. package/gsd-core/bin/lib/gate-ui-plan.cjs +86 -0
  139. package/gsd-core/bin/lib/gate-ui-safety.cjs +80 -0
  140. package/gsd-core/bin/lib/gate-verdict.cjs +64 -0
  141. package/gsd-core/bin/lib/gate-verify-command-paths.cjs +78 -0
  142. package/gsd-core/bin/lib/gate-verify-failure-directions.cjs +41 -0
  143. package/gsd-core/bin/lib/health-diagnostic-rules/phase-structure.cjs +43 -47
  144. package/gsd-core/bin/lib/health-diagnostic.cjs +45 -8
  145. package/gsd-core/bin/lib/init.cjs +162 -96
  146. package/gsd-core/bin/lib/install-engine.cjs +19 -35
  147. package/gsd-core/bin/lib/install-profiles.cjs +7 -4
  148. package/gsd-core/bin/lib/io.cjs +122 -3
  149. package/gsd-core/bin/lib/loop-resolver.cjs +95 -0
  150. package/gsd-core/bin/lib/markdown-sectionizer.cjs +75 -1
  151. package/gsd-core/bin/lib/milestone.cjs +19 -1
  152. package/gsd-core/bin/lib/model-resolver.cjs +18 -18
  153. package/gsd-core/bin/lib/observability/event.cjs +1 -1
  154. package/gsd-core/bin/lib/observability/logger.cjs +46 -1
  155. package/gsd-core/bin/lib/pattern.cjs +10 -0
  156. package/gsd-core/bin/lib/phase-command-router.cjs +11 -4
  157. package/gsd-core/bin/lib/phase-estimation.cjs +5 -4
  158. package/gsd-core/bin/lib/phase-id.cjs +1 -1
  159. package/gsd-core/bin/lib/phase-lifecycle.cjs +9 -2
  160. package/gsd-core/bin/lib/phase-status.cjs +360 -0
  161. package/gsd-core/bin/lib/phase.cjs +280 -80
  162. package/gsd-core/bin/lib/plan-document.cjs +93 -19
  163. package/gsd-core/bin/lib/plan-drift-guard.cjs +5 -0
  164. package/gsd-core/bin/lib/planning-document.cjs +273 -40
  165. package/gsd-core/bin/lib/planning-inspect.cjs +42 -8
  166. package/gsd-core/bin/lib/planning-snapshot.cjs +18 -0
  167. package/gsd-core/bin/lib/planning-workspace.cjs +76 -53
  168. package/gsd-core/bin/lib/pristine-baseline.cjs +10 -0
  169. package/gsd-core/bin/lib/profile-output.cjs +6 -3
  170. package/gsd-core/bin/lib/prohibition-enforcement.cjs +0 -55
  171. package/gsd-core/bin/lib/quick-batch-command-router.cjs +35 -9
  172. package/gsd-core/bin/lib/quick-batch-dispatch.cjs +11 -8
  173. package/gsd-core/bin/lib/real-home-guard.cjs +9 -1
  174. package/gsd-core/bin/lib/report-parser.cjs +269 -0
  175. package/gsd-core/bin/lib/roadmap-command-router.cjs +13 -15
  176. package/gsd-core/bin/lib/roadmap-parser.cjs +82 -15
  177. package/gsd-core/bin/lib/roadmap-upgrade.cjs +127 -65
  178. package/gsd-core/bin/lib/roadmap.cjs +169 -72
  179. package/gsd-core/bin/lib/runtime-artifact-conversion.cjs +91 -157
  180. package/gsd-core/bin/lib/runtime-artifact-install-plan.cjs +2 -1
  181. package/gsd-core/bin/lib/runtime-artifact-layout.cjs +57 -1
  182. package/gsd-core/bin/lib/runtime-homes.cjs +13 -10
  183. package/gsd-core/bin/lib/runtime-hooks-surface.cjs +307 -591
  184. package/gsd-core/bin/lib/runtime-name-policy.cjs +142 -27
  185. package/gsd-core/bin/lib/runtime-slash.cjs +47 -30
  186. package/gsd-core/bin/lib/shell-command-projection.cjs +37 -2
  187. package/gsd-core/bin/lib/smart-entry.cjs +19 -3
  188. package/gsd-core/bin/lib/stale-bake-guard.cjs +32 -48
  189. package/gsd-core/bin/lib/state-contract.cjs +15 -18
  190. package/gsd-core/bin/lib/state-document.cjs +100 -22
  191. package/gsd-core/bin/lib/state.cjs +214 -105
  192. package/gsd-core/bin/lib/surface.cjs +2 -1
  193. package/gsd-core/bin/lib/tdd-red-evidence.cjs +48 -152
  194. package/gsd-core/bin/lib/uat-predicate.cjs +313 -35
  195. package/gsd-core/bin/lib/uat.cjs +424 -7
  196. package/gsd-core/bin/lib/ui-frontend-evidence.cjs +94 -58
  197. package/gsd-core/bin/lib/vendor/README.md +31 -9
  198. package/gsd-core/bin/lib/vendor/saxes.cjs +1934 -0
  199. package/gsd-core/bin/lib/vendor/saxes.cjs.LICENSE.txt +92 -0
  200. package/gsd-core/bin/lib/vendor/tap-parser.cjs +8927 -0
  201. package/gsd-core/bin/lib/vendor/tap-parser.cjs.LICENSE.txt +152 -0
  202. package/gsd-core/bin/lib/verification-command-router.cjs +2 -1
  203. package/gsd-core/bin/lib/verification.cjs +1165 -314
  204. package/gsd-core/bin/lib/verify-command-router.cjs +18 -7
  205. package/gsd-core/bin/lib/verify.cjs +286 -567
  206. package/gsd-core/bin/lib/workstream-inventory-builder.cjs +14 -6
  207. package/gsd-core/bin/lib/workstream-inventory.cjs +31 -21
  208. package/gsd-core/bin/lib/workstream-name-policy.cjs +31 -1
  209. package/gsd-core/bin/lib/workstream.cjs +11 -2
  210. package/gsd-core/bin/shared/config-defaults.manifest.json +5 -0
  211. package/gsd-core/bin/shared/config-schema.manifest.json +4 -0
  212. package/gsd-core/references/autonomous-smart-discuss.md +2 -1
  213. package/gsd-core/references/autonomous-ui-design-contract.md +3 -3
  214. package/gsd-core/references/execute-mvp-tdd.md +5 -10
  215. package/gsd-core/references/execute-phase-between-wave-reset.md +3 -0
  216. package/gsd-core/references/execute-phase-response-language.md +1 -1
  217. package/gsd-core/references/gsd-run-resolver.md +1 -1
  218. package/gsd-core/references/loop-hook-dispatch.md +7 -1
  219. package/gsd-core/references/offer-next.md +1 -1
  220. package/gsd-core/references/planning-config.md +1 -1
  221. package/gsd-core/references/spidr-splitting.md +1 -1
  222. package/gsd-core/references/tdd.md +10 -4
  223. package/gsd-core/references/verifier-phase-gates.md +5 -2
  224. package/gsd-core/references/verify-mvp-mode.md +2 -2
  225. package/gsd-core/references/workstream-flag.md +33 -3
  226. package/gsd-core/templates/README.md +1 -1
  227. package/gsd-core/templates/UAT.md +17 -1
  228. package/gsd-core/templates/config.json +2 -11
  229. package/gsd-core/templates/verification-report.md +1 -1
  230. package/gsd-core/workflows/_runtime-launcher.snippet.sh +1 -1
  231. package/gsd-core/workflows/add-backlog.md +1 -1
  232. package/gsd-core/workflows/add-phase.md +8 -7
  233. package/gsd-core/workflows/add-tests.md +3 -2
  234. package/gsd-core/workflows/add-todo.md +4 -3
  235. package/gsd-core/workflows/ai-integration-phase.md +3 -2
  236. package/gsd-core/workflows/audit-fix.md +1 -1
  237. package/gsd-core/workflows/audit-milestone.md +4 -3
  238. package/gsd-core/workflows/audit-uat.md +1 -1
  239. package/gsd-core/workflows/autonomous.md +28 -18
  240. package/gsd-core/workflows/check-todos.md +6 -5
  241. package/gsd-core/workflows/cleanup.md +1 -1
  242. package/gsd-core/workflows/code-review/steps/structural-pre-pass.md +20 -13
  243. package/gsd-core/workflows/code-review-fix.md +5 -4
  244. package/gsd-core/workflows/code-review.md +84 -90
  245. package/gsd-core/workflows/complete-milestone/detail/elaboration.md +4 -3
  246. package/gsd-core/workflows/complete-milestone.md +12 -7
  247. package/gsd-core/workflows/debug.md +30 -5
  248. package/gsd-core/workflows/diagnose-issues.md +3 -2
  249. package/gsd-core/workflows/discuss-phase/modes/advisor.md +1 -1
  250. package/gsd-core/workflows/discuss-phase/modes/chain.md +1 -1
  251. package/gsd-core/workflows/discuss-phase-assumptions.md +4 -3
  252. package/gsd-core/workflows/discuss-phase.md +4 -3
  253. package/gsd-core/workflows/do.md +1 -1
  254. package/gsd-core/workflows/docs-update.md +4 -3
  255. package/gsd-core/workflows/edit-phase.md +4 -3
  256. package/gsd-core/workflows/eval-review.md +5 -3
  257. package/gsd-core/workflows/execute-phase/detail/elaboration.md +1 -1
  258. package/gsd-core/workflows/execute-phase/steps/code-review-disposition.md +4 -2
  259. package/gsd-core/workflows/execute-phase/steps/codebase-drift-gate.md +15 -4
  260. package/gsd-core/workflows/execute-phase/steps/completion-reconciliation.md +10 -7
  261. package/gsd-core/workflows/execute-phase/steps/executor-isolation-dispatch.md +1 -1
  262. package/gsd-core/workflows/execute-phase/steps/gap-closure-artifacts.md +3 -1
  263. package/gsd-core/workflows/execute-phase/steps/partial-wave.md +2 -2
  264. package/gsd-core/workflows/execute-phase/steps/per-plan-executor-routing.md +1 -1
  265. package/gsd-core/workflows/execute-phase/steps/per-plan-worktree-gate.md +1 -1
  266. package/gsd-core/workflows/execute-phase/steps/post-merge-gate.md +1 -1
  267. package/gsd-core/workflows/execute-phase/steps/protected-branch.md +1 -1
  268. package/gsd-core/workflows/execute-phase/steps/regression-gate-run.md +1 -1
  269. package/gsd-core/workflows/execute-phase/steps/regression-gate.md +2 -0
  270. package/gsd-core/workflows/execute-phase/steps/tdd-applicability-resolution.md +1 -1
  271. package/gsd-core/workflows/execute-phase/steps/verify-phase-goal.md +187 -0
  272. package/gsd-core/workflows/execute-phase/steps/wave-post-gate-hooks.md +2 -3
  273. package/gsd-core/workflows/execute-phase.md +78 -170
  274. package/gsd-core/workflows/execute-plan.md +13 -19
  275. package/gsd-core/workflows/explore.md +2 -2
  276. package/gsd-core/workflows/extract-learnings.md +3 -2
  277. package/gsd-core/workflows/fast.md +1 -1
  278. package/gsd-core/workflows/forensics.md +1 -1
  279. package/gsd-core/workflows/graduation.md +1 -1
  280. package/gsd-core/workflows/health.md +2 -1
  281. package/gsd-core/workflows/import.md +3 -2
  282. package/gsd-core/workflows/inbox.md +1 -1
  283. package/gsd-core/workflows/ingest-docs.md +1 -1
  284. package/gsd-core/workflows/insert-phase.md +4 -3
  285. package/gsd-core/workflows/list-seeds.md +1 -1
  286. package/gsd-core/workflows/list-workspaces.md +1 -1
  287. package/gsd-core/workflows/manager.md +5 -3
  288. package/gsd-core/workflows/map-codebase.md +4 -3
  289. package/gsd-core/workflows/milestone-summary.md +3 -2
  290. package/gsd-core/workflows/mvp-phase.md +14 -14
  291. package/gsd-core/workflows/new-milestone.md +10 -10
  292. package/gsd-core/workflows/new-project/steps/auto-mode-config.md +1 -1
  293. package/gsd-core/workflows/new-project.md +1 -1
  294. package/gsd-core/workflows/new-workspace.md +1 -1
  295. package/gsd-core/workflows/next.md +1 -1
  296. package/gsd-core/workflows/pause-work.md +2 -2
  297. package/gsd-core/workflows/plan-phase/detail/elaboration.md +1 -1
  298. package/gsd-core/workflows/plan-phase/steps/chunked-planning-mode.md +1 -1
  299. package/gsd-core/workflows/plan-phase/steps/closed-phase-gate.md +1 -1
  300. package/gsd-core/workflows/plan-phase/steps/prd-express-path.md +1 -1
  301. package/gsd-core/workflows/plan-phase/steps/stall-detection-helpers.md +1 -1
  302. package/gsd-core/workflows/plan-phase.md +27 -18
  303. package/gsd-core/workflows/plan-review-convergence.md +1 -1
  304. package/gsd-core/workflows/plant-seed.md +1 -1
  305. package/gsd-core/workflows/pr-branch.md +1 -1
  306. package/gsd-core/workflows/profile-user.md +1 -1
  307. package/gsd-core/workflows/progress.md +19 -49
  308. package/gsd-core/workflows/quick/steps/plan-checker-loop.md +4 -2
  309. package/gsd-core/workflows/quick/steps/quick-verification.md +4 -4
  310. package/gsd-core/workflows/quick/steps/worktree-pre-dispatch-commit.md +30 -11
  311. package/gsd-core/workflows/quick-batch/steps/batch-init.md +1 -1
  312. package/gsd-core/workflows/quick-batch/steps/completion.md +1 -1
  313. package/gsd-core/workflows/quick-batch/steps/merge-wave.md +1 -1
  314. package/gsd-core/workflows/quick-batch/steps/planner-wave.md +1 -1
  315. package/gsd-core/workflows/quick-batch/steps/research-phase.md +1 -1
  316. package/gsd-core/workflows/quick-batch/steps/resume-mode.md +1 -1
  317. package/gsd-core/workflows/quick-batch/steps/verification-wave.md +9 -3
  318. package/gsd-core/workflows/quick-batch/steps/worktree-dispatch.md +1 -1
  319. package/gsd-core/workflows/quick-batch.md +15 -10
  320. package/gsd-core/workflows/quick.md +42 -31
  321. package/gsd-core/workflows/remove-phase.md +3 -2
  322. package/gsd-core/workflows/remove-workspace.md +1 -1
  323. package/gsd-core/workflows/resume-project.md +3 -2
  324. package/gsd-core/workflows/review.md +3 -2
  325. package/gsd-core/workflows/scan.md +3 -2
  326. package/gsd-core/workflows/secure-phase.md +11 -12
  327. package/gsd-core/workflows/settings-advanced.md +1 -1
  328. package/gsd-core/workflows/settings-integrations.md +1 -1
  329. package/gsd-core/workflows/settings.md +1 -1
  330. package/gsd-core/workflows/ship.md +12 -12
  331. package/gsd-core/workflows/sketch-wrap-up.md +1 -1
  332. package/gsd-core/workflows/sketch.md +1 -1
  333. package/gsd-core/workflows/smart-entry.md +1 -1
  334. package/gsd-core/workflows/spec-phase.md +1 -1
  335. package/gsd-core/workflows/spike-wrap-up.md +1 -1
  336. package/gsd-core/workflows/spike.md +1 -1
  337. package/gsd-core/workflows/stats.md +1 -1
  338. package/gsd-core/workflows/sync-skills.md +1 -1
  339. package/gsd-core/workflows/thread.md +2 -2
  340. package/gsd-core/workflows/transition.md +13 -23
  341. package/gsd-core/workflows/ui-phase.md +5 -4
  342. package/gsd-core/workflows/ui-review.md +4 -3
  343. package/gsd-core/workflows/ultraplan-phase.md +3 -2
  344. package/gsd-core/workflows/undo.md +1 -1
  345. package/gsd-core/workflows/validate-phase.md +10 -12
  346. package/gsd-core/workflows/verify-work/detail/elaboration.md +43 -3
  347. package/gsd-core/workflows/verify-work/steps/automated-ui-verification.md +1 -1
  348. package/gsd-core/workflows/verify-work/steps/mvp-uat-framing.md +5 -3
  349. package/gsd-core/workflows/verify-work.md +68 -59
  350. package/hooks/dist/gsd-agent-isolation-guard.js +8 -0
  351. package/hooks/dist/gsd-check-update-worker.js +8 -0
  352. package/hooks/dist/gsd-check-update.js +8 -0
  353. package/hooks/dist/gsd-context-monitor.js +31 -8
  354. package/hooks/dist/gsd-cursor-subagent-start.js +8 -0
  355. package/hooks/dist/gsd-secret-read-guard.js +147 -16
  356. package/hooks/dist/gsd-statusline.js +15 -7
  357. package/hooks/dist/gsd-update-banner.js +8 -0
  358. package/hooks/dist/gsd-windsurf-pre-write.js +11 -2
  359. package/hooks/dist/gsd-workflow-guard.js +5 -4
  360. package/hooks/dist/gsd-worktree-path-guard.js +6 -2
  361. package/hooks/dist/lib/cli-exit.js +12 -0
  362. package/hooks/dist/lib/git-probe.js +17 -1
  363. package/hooks/dist/lib/isolation-sentinel.js +2 -2
  364. package/hooks/gsd-agent-isolation-guard.js +8 -0
  365. package/hooks/gsd-check-update-worker.js +8 -0
  366. package/hooks/gsd-check-update.js +8 -0
  367. package/hooks/gsd-context-monitor.js +31 -8
  368. package/hooks/gsd-cursor-subagent-start.js +8 -0
  369. package/hooks/gsd-secret-read-guard.js +147 -16
  370. package/hooks/gsd-statusline.js +15 -7
  371. package/hooks/gsd-update-banner.js +8 -0
  372. package/hooks/gsd-windsurf-pre-write.js +11 -2
  373. package/hooks/gsd-workflow-guard.js +5 -4
  374. package/hooks/gsd-worktree-path-guard.js +6 -2
  375. package/hooks/hooks.json +5 -5
  376. package/hooks/lib/cli-exit.js +12 -0
  377. package/hooks/lib/git-probe.js +17 -1
  378. package/hooks/lib/isolation-sentinel.js +2 -2
  379. package/package.json +21 -4
  380. package/scripts/changeset/parse.cjs +52 -4
  381. package/scripts/ci-timeout-report.cjs +770 -4
  382. package/scripts/command-contract-helpers.cjs +12 -8
  383. package/scripts/docs-guard-registry.cjs +6 -0
  384. package/scripts/gen-features.cjs +13 -8
  385. package/scripts/gen-hooks-cli-exit.cjs +12 -28
  386. package/scripts/gen-loop-host-contract.cjs +10 -1
  387. package/scripts/gen-platform-conformance-tier.cjs +187 -1
  388. package/scripts/gen-plugin-skills.cjs +87 -1
  389. package/scripts/gen-research-agents.cjs +24 -31
  390. package/scripts/gen-scripts-cli-exit.cjs +30 -3
  391. package/scripts/gen-test-timings.cjs +32 -7
  392. package/scripts/lib/cli-exit.cjs +12 -0
  393. package/scripts/lib/macos-conformance-tier.generated.cjs +20 -2
  394. package/scripts/lib/ndjson-reporter.cjs +28 -3
  395. package/scripts/lib/platform-conformance-tier.generated.cjs +34 -5
  396. package/scripts/lib/registration-ledger-preload.cjs +155 -0
  397. package/scripts/lib/vendor-bundle.cjs +59 -0
  398. package/scripts/lib/vendor-licenses/saxes-6.0.0.txt +64 -0
  399. package/scripts/lint-allow-test-rule-refs.effective-ceiling.json +1 -1
  400. package/scripts/lint-allow-test-rule-refs.unverified-ceiling.json +1 -1
  401. package/scripts/lint-completion-predicate-drift.cjs +18 -19
  402. package/scripts/lint-descriptions.cjs +7 -3
  403. package/scripts/lint-docs-guard-registration.exempt-baseline.cjs +10 -0
  404. package/scripts/lint-eslint-glob-coverage.allowlist.json +20 -0
  405. package/scripts/lint-frontmatter-fence-drift.cjs +313 -0
  406. package/scripts/lint-frontmatter-scalar-broad-grep.cjs +122 -16
  407. package/scripts/lint-phase-enumeration-drift.cjs +12 -8
  408. package/scripts/lint-phase-id-drift.cjs +29 -0
  409. package/scripts/lint-planning-document-positive-control.cjs +329 -0
  410. package/scripts/lint-response-language-coverage.cjs +3 -0
  411. package/scripts/lint-skill-deps.cjs +7 -3
  412. package/scripts/lint-test-file-count.allowlist.json +11 -1
  413. package/scripts/lint-test-file-count.cjs +34 -1
  414. package/scripts/lint-vendored-deps.cjs +41 -5
  415. package/scripts/lint-workflow-shellcheck-baseline.json +10 -10
  416. package/scripts/mutation-matrix.cjs +50 -5
  417. package/scripts/require-issue-link-policy.cjs +6 -2
  418. package/scripts/sync-runtime-launcher.cjs +184 -2
  419. package/scripts/verify-npm-publish.cjs +76 -20
  420. package/skills/gsd-add-tests/SKILL.md +6 -1
  421. package/skills/gsd-ai-integration-phase/SKILL.md +6 -1
  422. package/skills/gsd-audit-fix/SKILL.md +5 -0
  423. package/skills/gsd-audit-milestone/SKILL.md +6 -1
  424. package/skills/gsd-autonomous/SKILL.md +5 -0
  425. package/skills/gsd-capture/SKILL.md +8 -4
  426. package/skills/gsd-code-review/SKILL.md +7 -2
  427. package/skills/gsd-complete-milestone/SKILL.md +4 -0
  428. package/skills/gsd-config/SKILL.md +8 -4
  429. package/skills/gsd-debug/SKILL.md +11 -7
  430. package/skills/gsd-discuss-phase/SKILL.md +7 -3
  431. package/skills/gsd-docs-update/SKILL.md +12 -7
  432. package/skills/gsd-eval-review/SKILL.md +6 -1
  433. package/skills/gsd-execute-phase/SKILL.md +12 -7
  434. package/skills/gsd-extract-learnings/SKILL.md +5 -0
  435. package/skills/gsd-fast/SKILL.md +4 -0
  436. package/skills/gsd-forensics/SKILL.md +5 -1
  437. package/skills/gsd-graphify/SKILL.md +10 -6
  438. package/skills/gsd-health/SKILL.md +5 -0
  439. package/skills/gsd-help/SKILL.md +7 -2
  440. package/skills/gsd-import/SKILL.md +7 -3
  441. package/skills/gsd-inbox/SKILL.md +5 -0
  442. package/skills/gsd-ingest-docs/SKILL.md +5 -1
  443. package/skills/gsd-manager/SKILL.md +6 -1
  444. package/skills/gsd-map-codebase/SKILL.md +7 -3
  445. package/skills/gsd-mempalace-capture/SKILL.md +5 -1
  446. package/skills/gsd-mempalace-recall/SKILL.md +5 -1
  447. package/skills/gsd-milestone-summary/SKILL.md +5 -1
  448. package/skills/gsd-mvp-phase/SKILL.md +8 -3
  449. package/skills/gsd-new-milestone/SKILL.md +6 -1
  450. package/skills/gsd-new-project/SKILL.md +5 -0
  451. package/skills/gsd-next/SKILL.md +6 -1
  452. package/skills/gsd-ns-context/SKILL.md +4 -0
  453. package/skills/gsd-ns-ideate/SKILL.md +4 -0
  454. package/skills/gsd-ns-manage/SKILL.md +4 -0
  455. package/skills/gsd-ns-project/SKILL.md +4 -0
  456. package/skills/gsd-ns-review/SKILL.md +4 -0
  457. package/skills/gsd-ns-workflow/SKILL.md +4 -0
  458. package/skills/gsd-onboard/SKILL.md +6 -1
  459. package/skills/gsd-pause-work/SKILL.md +5 -1
  460. package/skills/gsd-phase/SKILL.md +8 -4
  461. package/skills/gsd-plan-phase/SKILL.md +6 -1
  462. package/skills/gsd-plan-review-convergence/SKILL.md +5 -1
  463. package/skills/gsd-pr-branch/SKILL.md +4 -0
  464. package/skills/gsd-profile-user/SKILL.md +5 -1
  465. package/skills/gsd-progress/SKILL.md +6 -1
  466. package/skills/gsd-quick/SKILL.md +16 -10
  467. package/skills/gsd-quick-batch/SKILL.md +20 -8
  468. package/skills/gsd-review/SKILL.md +5 -1
  469. package/skills/gsd-review-backlog/SKILL.md +3 -2
  470. package/skills/gsd-secure-phase/SKILL.md +6 -1
  471. package/skills/gsd-ship/SKILL.md +5 -0
  472. package/skills/gsd-sketch/SKILL.md +7 -2
  473. package/skills/gsd-spec-phase/SKILL.md +5 -1
  474. package/skills/gsd-spike/SKILL.md +8 -3
  475. package/skills/gsd-surface/SKILL.md +5 -1
  476. package/skills/gsd-thread/SKILL.md +4 -0
  477. package/skills/gsd-ui-phase/SKILL.md +6 -1
  478. package/skills/gsd-ui-review/SKILL.md +6 -1
  479. package/skills/gsd-ultraplan-phase/SKILL.md +5 -1
  480. package/skills/gsd-undo/SKILL.md +5 -1
  481. package/skills/gsd-update/SKILL.md +6 -2
  482. package/skills/gsd-validate-phase/SKILL.md +6 -1
  483. package/skills/gsd-verify-work/SKILL.md +6 -1
  484. package/skills/gsd-workspace/SKILL.md +7 -3
  485. package/skills/gsd-workstreams/SKILL.md +6 -6
  486. package/vscode/package.json +1 -1
  487. package/gsd-core/workflows/execute-phase/steps/stale-reverification.md +0 -24
@@ -46,14 +46,19 @@ const planDocument = require("./plan-document.cjs");
46
46
  const state_document_cjs_1 = require("./state-document.cjs");
47
47
  const runtime_slash_cjs_1 = require("./runtime-slash.cjs");
48
48
  const host_runtime_detection_cjs_1 = require("./host-runtime-detection.cjs");
49
- // eslint-disable-next-line @typescript-eslint/no-require-imports -- commands.cjs is an export= CommonJS module
50
- const commandsMod = require("./commands.cjs");
51
49
  const security_cjs_1 = require("./security.cjs");
52
50
  const runtime_homes_cjs_1 = require("./runtime-homes.cjs");
53
51
  // eslint-disable-next-line @typescript-eslint/no-require-imports -- frontmatter.cjs is an export= CommonJS module
54
52
  const frontmatterMod = require("./frontmatter.cjs");
55
53
  // eslint-disable-next-line @typescript-eslint/no-require-imports -- verification.cjs is an export= CommonJS module
56
54
  const verificationMod = require("./verification.cjs");
55
+ // #5060: Phase Status Module — the single owner of "what state is phase P
56
+ // in?" (ADR-5057 §1/§2). Replaces this file's own determinePhaseStatus/
57
+ // projectCompletionStatus derivations, and cmdInitMilestoneOp's
58
+ // summary-count-only completion check (the former listPhaseSummaryFiles
59
+ // helper, since removed). listPhasePlanFiles (below) is unrelated — it backs
60
+ // only the STATE.md disk-plan-count validation, not a completion verdict.
61
+ const phase_status_cjs_1 = require("./phase-status.cjs");
57
62
  // eslint-disable-next-line @typescript-eslint/no-require-imports -- uat-predicate.cjs is an export= CommonJS module
58
63
  const uatPredicateMod = require("./uat-predicate.cjs");
59
64
  // eslint-disable-next-line @typescript-eslint/no-require-imports -- agent-install-check.cjs is an export= CommonJS module
@@ -91,10 +96,9 @@ const { getRoadmapPhaseInternal, getMilestoneInfo, stripShippedMilestones, extra
91
96
  const { pathExistsInternal, generateSlugInternal, toPosixPath } = coreUtils;
92
97
  const { comparePhaseNum, normalizePhaseName, stripProjectCodePrefix, PHASE_NUMBER_TOKEN_SOURCE, PHASE_DEP_REF_SOURCE, isForeignPrefixedPhaseQuery, isSentinelPhaseId, extractPhaseToken, scopeToPhase, renderPhaseBranchName, parsePhaseId, renderPhaseId, phaseHeadingPrefixSrcFor, PHASE_HEADING_BASELINE, buildPhaseHeadingScanRegex, } = phaseId;
93
98
  const { pruneOrphanedWorktrees } = worktreeSafety;
94
- const { planningPaths, planningDir, planningRoot, todosDir, listAvailableWorkstreams, peekActiveWorkstream, resolveEnvWorkstream, diagnoseUnresolvedActiveWorkstream, describeUnresolvedWorkstreamReason, findContextMdIn, resolvePhaseIdConvention, } = planningWorkspace;
95
- const { determinePhaseStatus } = commandsMod;
96
- const { extractFrontmatter } = frontmatterMod;
97
- const { isPhaseComplete, resolveVerificationFile, resolveUatFile } = verificationMod;
99
+ const { planningPaths, planningDir, planningRoot, todosDir, listAvailableWorkstreams, peekActiveWorkstream, resolveEnvWorkstream, diagnoseUnresolvedActiveWorkstream, describeUnresolvedWorkstreamReason, findContextMdIn, resolvePhaseIdConvention, worktreesOptedOut, } = planningWorkspace;
100
+ const { extractFrontmatter, frontmatterBlock } = frontmatterMod;
101
+ const { isPhaseComplete, resolveVerificationFile, resolveUatFile, VERIFICATION_STATUS, VerificationStatusError } = verificationMod;
98
102
  const { evaluateUatPassed } = uatPredicateMod;
99
103
  const { resolveLoopHooks } = loopResolverMod;
100
104
  const { loadRegistry } = capabilityLoaderMod;
@@ -186,20 +190,10 @@ function applyRoadmapFallback(phaseInfo, roadmapPhase, buildFallback) {
186
190
  }
187
191
  return phaseInfo;
188
192
  }
189
- function listPhaseSummaryFiles(phaseDir) {
190
- return scanPhasePlans(phaseDir)['summaryFiles'];
191
- }
192
193
  function listPhasePlanFiles(phaseDir) {
193
194
  return scanPhasePlans(phaseDir)['planFiles'];
194
195
  }
195
- function projectCompletionStatus(implementationComplete, phaseComplete) {
196
- if (phaseComplete)
197
- return 'complete';
198
- if (implementationComplete)
199
- return 'executed';
200
- return 'incomplete';
201
- }
202
- function buildPhaseCompletionProjection(cwd, phaseNumber, phaseDir, planCount, summaryCount, slashRuntime) {
196
+ function buildPhaseCompletionProjection(cwd, phaseNumber, phaseDir, planCount, summaryCount, slashRuntime, convention) {
203
197
  // ADR-3180 §7.4 (issue #3186) / DO-NOT-MIGRATE exemption
204
198
  // (scripts/lint-completion-predicate-drift.cjs FUNCTION_SCOPED_EXEMPTIONS,
205
199
  // declared deviation): `implementation_complete` answers "are the plans
@@ -219,20 +213,35 @@ function buildPhaseCompletionProjection(cwd, phaseNumber, phaseDir, planCount, s
219
213
  // #2617: the router still owns both the message content and the runtime
220
214
  // projection; init passes the phase number it already knows (its phaseDir
221
215
  // is unresolved in some branches, where the router could not derive one).
222
- const completionResult = isPhaseComplete(phaseFullDir, { runtime: slashRuntime, phaseNumber });
216
+ const completionResult = isPhaseComplete(phaseFullDir, { runtime: slashRuntime, phaseNumber, convention });
217
+ // #5118: the owner carried an out-of-set report status in its result
218
+ // (`statusError`, `verification.status: null`); an init bundle is never
219
+ // assembled over a report the owner refused — the carried error is raised
220
+ // here and every `init *` surface built on this projection fails with the
221
+ // error's own reason (the CLI entry seam), printing nothing.
222
+ if (completionResult.value.statusError)
223
+ throw completionResult.value.statusError;
223
224
  const verificationStatus = completionResult.value.verification;
224
225
  const projectedVerificationStatus = verificationStatus.status;
225
226
  const projectedVerificationAction = verificationStatus.next_action;
226
- const verificationPassed = projectedVerificationStatus === 'passed';
227
+ const verificationPassed = projectedVerificationStatus === VERIFICATION_STATUS.PASSED;
227
228
  const phaseComplete = completionResult.value.complete;
228
229
  return {
229
230
  implementation_complete: implementationComplete,
230
231
  verification_status: projectedVerificationStatus,
231
232
  verification_passed: verificationPassed,
232
233
  phase_complete: phaseComplete,
233
- completion_status: projectCompletionStatus(implementationComplete, phaseComplete),
234
+ // #5060: Phase Status Module — the single owner of "what state is phase P
235
+ // in?" (ADR-5057 §1/§2).
236
+ completion_status: (0, phase_status_cjs_1.toCompletionStatus)((0, phase_status_cjs_1.phaseStatusFromFacts)({
237
+ planCount,
238
+ summaryCount,
239
+ complete: phaseComplete,
240
+ verificationStatus: projectedVerificationStatus,
241
+ })),
234
242
  verification_next_action: projectedVerificationAction,
235
243
  verification_next_command: verificationStatus.next_command,
244
+ verification_route: verificationStatus.route,
236
245
  // #3057 B3: readVerificationStatus's result carries this flag when its
237
246
  // internal staleness check could not run to completion.
238
247
  verification_stale_check_indeterminate: 'staleCheckIndeterminate' in verificationStatus
@@ -479,7 +488,8 @@ function detectHasPriorPhases(cwd, phaseInfo) {
479
488
  * `false` — strict `=== true`, never coerced, mirrors `detectHasPriorPhases`'s
480
489
  * degrade-to-false discipline. `keyPath` is always a fixed literal supplied
481
490
  * by this module, never attacker/user input, so a plain bracket traversal
482
- * carries no prototype hazard here.
491
+ * carries no prototype hazard here. Only for keys whose default is OFF — a
492
+ * default-ON key read here silently inverts its unset value (#4977).
483
493
  */
484
494
  function readConfigJsonBoolean(cwd, keyPath) {
485
495
  try {
@@ -727,7 +737,13 @@ function buildSectionManifestField(cwd, phaseInfo, options, workflow, overrides
727
737
  flags,
728
738
  phaseNumber,
729
739
  hasPriorPhases: detectHasPriorPhases(cwd, phaseInfo),
730
- worktreesEnabled: readConfigJsonBoolean(cwd, ['workflow', 'use_worktrees']),
740
+ // #4977: `workflow.use_worktrees` defaults ON, so this fact must come from
741
+ // the #3972 owner `query dispatch-isolation` and the isolation guard
742
+ // already share — not `readConfigJsonBoolean`, whose absent ⇒ false
743
+ // polarity (right for the opt-in keys around it) excluded the quick
744
+ // pre-dispatch plan commit while the executor was still dispatched
745
+ // isolated. The ladder also brings root→workstream inheritance along.
746
+ worktreesEnabled: !worktreesOptedOut(cwd),
731
747
  phaseMvpMode: detectPhaseMvpMode(cwd, phaseNumber),
732
748
  needsCodebaseMap: overrides.needsCodebaseMap,
733
749
  chunkedMode,
@@ -1075,8 +1091,10 @@ function cmdInitPlanPhase(cwd, phase, raw, options = {}) {
1075
1091
  phase_slug: phaseInfo?.['phase_slug'] || null,
1076
1092
  padded_phase: phaseNumberPlan ? normalizePhaseName(phaseNumberPlan) : null,
1077
1093
  phase_req_ids,
1094
+ // #5060: Phase Status Module — the single owner of "what state is phase P
1095
+ // in?" (ADR-5057 §1/§2).
1078
1096
  phase_status: phaseDirPlan
1079
- ? determinePhaseStatus(phaseInfo?.['plans']?.length || 0, phaseInfo?.['summaries']?.length || 0, node_path_1.default.join(cwd, phaseDirPlan), 'Pending')
1097
+ ? (0, phase_status_cjs_1.toDisplayLabel)((0, phase_status_cjs_1.phaseStatus)(node_path_1.default.join(cwd, phaseDirPlan), { convention: resolvePhaseIdConvention(cwd) }).value.status, { pendingWord: 'Pending' })
1080
1098
  : 'Pending',
1081
1099
  has_research: phaseInfo?.['has_research'] || false,
1082
1100
  has_context: phaseInfo?.['has_context'] || false,
@@ -1273,12 +1291,15 @@ function buildInitCompletenessFields(cwd) {
1273
1291
  }
1274
1292
  function cmdInitNewProject(cwd, raw, options = {}) {
1275
1293
  const config = loadConfig(cwd);
1276
- const homedir = node_os_1.default.homedir();
1277
- const braveKeyFile = node_path_1.default.join(homedir, '.gsd', 'brave_api_key');
1294
+ // #4976: probe the GSD-owned store the config loader resolves
1295
+ // (`GSD_HOME || homedir()`), so these flags agree with config-new-project's
1296
+ // key probes in the same /gsd-new-project run.
1297
+ const gsdHome = process.env['GSD_HOME'] || node_os_1.default.homedir();
1298
+ const braveKeyFile = node_path_1.default.join(gsdHome, '.gsd', 'brave_api_key');
1278
1299
  const hasBraveSearch = !!(process.env['BRAVE_API_KEY'] || node_fs_1.default.existsSync(braveKeyFile));
1279
- const firecrawlKeyFile = node_path_1.default.join(homedir, '.gsd', 'firecrawl_api_key');
1300
+ const firecrawlKeyFile = node_path_1.default.join(gsdHome, '.gsd', 'firecrawl_api_key');
1280
1301
  const hasFirecrawl = !!(process.env['FIRECRAWL_API_KEY'] || node_fs_1.default.existsSync(firecrawlKeyFile));
1281
- const exaKeyFile = node_path_1.default.join(homedir, '.gsd', 'exa_api_key');
1302
+ const exaKeyFile = node_path_1.default.join(gsdHome, '.gsd', 'exa_api_key');
1282
1303
  const hasExaSearch = !!(process.env['EXA_API_KEY'] || node_fs_1.default.existsSync(exaKeyFile));
1283
1304
  const hasCode = hasCodeFilesInternal(cwd);
1284
1305
  const hasPackageFile = hasPackageFileInternal(cwd);
@@ -1638,9 +1659,21 @@ function cmdInitVerifyWork(cwd, phase, raw) {
1638
1659
  };
1639
1660
  });
1640
1661
  const phaseDir = phaseInfo?.['directory'] || null;
1641
- const planCount = phaseInfo?.['plans']?.length || 0;
1642
- const summaryCount = phaseInfo?.['summaries']?.length || 0;
1643
- const completion = buildPhaseCompletionProjection(cwd, phaseInfo?.['phase_number'] || phase, phaseDir, planCount, summaryCount, _slashRuntime);
1662
+ // #5060: Phase Status Module — matched counts from the §7.5 owner
1663
+ // (scanPhasePlans via phaseStatus), not phaseInfo's raw plans/summaries
1664
+ // arrays, so this projection's counts agree with buildPhaseCompletionProjection's
1665
+ // own isPhaseComplete call below (see the convention thread there).
1666
+ const verifyWorkConvention = resolvePhaseIdConvention(cwd);
1667
+ const verifyWorkPs = phaseDir
1668
+ ? (0, phase_status_cjs_1.phaseStatus)(node_path_1.default.join(cwd, phaseDir), { convention: verifyWorkConvention })
1669
+ : null;
1670
+ const planCount = verifyWorkPs
1671
+ ? verifyWorkPs.value.planCount
1672
+ : phaseInfo?.['plans']?.length || 0;
1673
+ const summaryCount = verifyWorkPs
1674
+ ? verifyWorkPs.value.summaryCount
1675
+ : phaseInfo?.['summaries']?.length || 0;
1676
+ const completion = buildPhaseCompletionProjection(cwd, phaseInfo?.['phase_number'] || phase, phaseDir, planCount, summaryCount, _slashRuntime, verifyWorkConvention);
1644
1677
  const uatReport = phaseDir
1645
1678
  ? evaluateUatPassed(node_path_1.default.join(cwd, phaseDir), {
1646
1679
  policy: { requireVerification: true },
@@ -2314,6 +2347,12 @@ function cmdInitTodos(cwd, area, raw) {
2314
2347
  function cmdInitMilestoneOp(cwd, raw) {
2315
2348
  const config = loadConfig(cwd);
2316
2349
  const milestone = milestoneRecord(cwd);
2350
+ // #5060: Phase Status Module — the single owner of "what state is phase P
2351
+ // in?" (ADR-5057 §1/§2). A phase counts as completed only when the ladder
2352
+ // itself says COMPLETE, not "has any *-SUMMARY.md" (a counts-only verdict
2353
+ // that bypasses isPhaseComplete and disagrees with every other completion
2354
+ // consumer on a stale `passed` report).
2355
+ const milestoneOpConvention = resolvePhaseIdConvention(cwd);
2317
2356
  let phaseCount = 0;
2318
2357
  let completedPhases = 0;
2319
2358
  const phasesDir = node_path_1.default.join(planningDir(cwd), 'phases');
@@ -2325,7 +2364,7 @@ function cmdInitMilestoneOp(cwd, raw) {
2325
2364
  // #1729: `(?:\s*\([^)\n]{0,200}\))?` tolerates a pre-colon ( ) tag, owned by
2326
2365
  // buildPhaseHeadingScanRegex (phase-id.cts) so this scan also recognizes
2327
2366
  // bracket-convention headings instead of hand-rolling a literal `Phase\s+`.
2328
- const { regex: phasePattern, phaseNumGroup } = buildPhaseHeadingScanRegex(PHASE_HEADING_BASELINE.ANY_BRACKET, resolvePhaseIdConvention(cwd));
2367
+ const { regex: phasePattern, phaseNumGroup } = buildPhaseHeadingScanRegex(PHASE_HEADING_BASELINE.ANY_BRACKET, milestoneOpConvention);
2329
2368
  let m;
2330
2369
  while ((m = phasePattern.exec(currentSection)) !== null) {
2331
2370
  // #3185: canonical sentinel predicate (SENTINEL_RANGES [0,999]) — this was a local 999-only literal that admitted Phase 0.
@@ -2366,8 +2405,8 @@ function cmdInitMilestoneOp(cwd, raw) {
2366
2405
  if (!dirName)
2367
2406
  continue;
2368
2407
  try {
2369
- const hasSummary = listPhaseSummaryFiles(node_path_1.default.join(phasesDir, dirName)).length > 0;
2370
- if (hasSummary)
2408
+ const isComplete = (0, phase_status_cjs_1.phaseStatus)(node_path_1.default.join(phasesDir, dirName), { convention: milestoneOpConvention }).value.status === phase_status_cjs_1.PHASE_STATUS.COMPLETE;
2409
+ if (isComplete)
2371
2410
  completedPhases++;
2372
2411
  }
2373
2412
  catch {
@@ -2386,8 +2425,8 @@ function cmdInitMilestoneOp(cwd, raw) {
2386
2425
  phaseCount = dirs.length;
2387
2426
  for (const dir of dirs) {
2388
2427
  try {
2389
- const hasSummary = listPhaseSummaryFiles(node_path_1.default.join(phasesDir, dir)).length > 0;
2390
- if (hasSummary)
2428
+ const isComplete = (0, phase_status_cjs_1.phaseStatus)(node_path_1.default.join(phasesDir, dir), { convention: milestoneOpConvention }).value.status === phase_status_cjs_1.PHASE_STATUS.COMPLETE;
2429
+ if (isComplete)
2391
2430
  completedPhases++;
2392
2431
  }
2393
2432
  catch {
@@ -2493,11 +2532,23 @@ function cmdInitManager(cwd, raw) {
2493
2532
  // getMilestonePhaseFilter window check (which also never excluded
2494
2533
  // sentinels, unlike the owner).
2495
2534
  const _checkboxStates = new Map();
2496
- const _cbPattern = new RegExp(`-\\s*\\[(x| )\\]\\s*.*${phaseHeadingPrefix}(${PHASE_NUMBER_TOKEN_SOURCE})[:\\s]`, 'gi');
2535
+ // #4982: anchored (`^`, `m`) so the phase label must be the FIRST thing
2536
+ // after the checkbox (tolerating only an optional `**` bold marker) —
2537
+ // the prior unanchored `\s*.*` let the greedy `.*` bind to the LAST
2538
+ // "Phase N" mentioned anywhere in the line's prose instead of the line's
2539
+ // own phase. First-match-wins (`if (!_checkboxStates.has(...))` below)
2540
+ // additionally guards against a later anchored line (e.g. a per-plan
2541
+ // sub-entry self-titled "Phase N ...") overwriting an already-recorded
2542
+ // phase's own (first) checkbox — anchoring alone does not fully close
2543
+ // that "last-match-wins" composition defect.
2544
+ const _cbPattern = new RegExp(`^[ \\t]*-[ \\t]*\\[(x| )\\][ \\t]*(?:\\*\\*)?${phaseHeadingPrefix}(${PHASE_NUMBER_TOKEN_SOURCE})[:\\s]`, 'gim');
2497
2545
  let _cbMatch;
2498
2546
  while ((_cbMatch = _cbPattern.exec(content)) !== null) {
2499
2547
  const phaseGroup = capturesBracketId ? 3 : 2;
2500
- _checkboxStates.set(_cbMatch[phaseGroup], _cbMatch[1].toLowerCase() === 'x');
2548
+ const _cbKey = _cbMatch[phaseGroup];
2549
+ if (!_checkboxStates.has(_cbKey)) {
2550
+ _checkboxStates.set(_cbKey, _cbMatch[1].toLowerCase() === 'x');
2551
+ }
2501
2552
  }
2502
2553
  // #1729: `(?:\s*\([^)\n]{0,200}\))?` tolerates a pre-colon ( ) tag (literal mirror of OPTIONAL_PHASE_TAG_SOURCE).
2503
2554
  const phasePattern = new RegExp(`#{2,4}\\s*${phaseHeadingPrefix}(${PHASE_NUMBER_TOKEN_SOURCE})(?:\\s*\\([^)\\n]{0,200}\\))?\\s*:\\s*([^\\n]+)`, 'gi');
@@ -2529,7 +2580,7 @@ function cmdInitManager(cwd, raw) {
2529
2580
  const goal = roadmapParser.extractPhaseFieldMultiline(section, 'Goal');
2530
2581
  const dependsMatch = section.match(/\*\*Depends on(?::\*\*|\*\*:)\s*([^\n]+)/i);
2531
2582
  const depends_on = dependsMatch ? dependsMatch[1].trim() : null;
2532
- let diskStatus = 'no_directory';
2583
+ let diskStatus = phase_status_cjs_1.DISK_STATUS.NO_DIRECTORY;
2533
2584
  let planCount = 0;
2534
2585
  let summaryCount = 0;
2535
2586
  let hasContext = false;
@@ -2539,7 +2590,7 @@ function cmdInitManager(cwd, raw) {
2539
2590
  // #4014 (epic #3473 B4-unreadable): default COMPLETE — no directory at
2540
2591
  // all (dirMatch not found) is a genuine, not-unreadable answer.
2541
2592
  let contextScope = SCOPE.COMPLETE;
2542
- let completion = buildPhaseCompletionProjection(cwd, phaseNum, null, planCount, summaryCount, _slashRuntime);
2593
+ let completion = buildPhaseCompletionProjection(cwd, phaseNum, null, planCount, summaryCount, _slashRuntime, phaseIdConvention);
2543
2594
  try {
2544
2595
  // #4801: resolve through the canonical locator instead of a private
2545
2596
  // current-milestone-only scan. findPhaseInternal searches the live
@@ -2570,8 +2621,11 @@ function cmdInitManager(cwd, raw) {
2570
2621
  // only, the failure control-flow is untouched.
2571
2622
  contextScope = findContextMdIn(fullDir).scope;
2572
2623
  const phaseFiles = node_fs_1.default.readdirSync(fullDir);
2573
- planCount = listPhasePlanFiles(fullDir).length;
2574
- summaryCount = listPhaseSummaryFiles(fullDir).length;
2624
+ // #5060: Phase Status Module — the single owner of "what state is
2625
+ // phase P in?" (ADR-5057 §1/§2).
2626
+ const ps = (0, phase_status_cjs_1.phaseStatus)(fullDir, { convention: phaseIdConvention });
2627
+ planCount = ps.value.planCount;
2628
+ summaryCount = ps.value.summaryCount;
2575
2629
  // #3511-class: scope the raw listing to THIS phase's own artifacts
2576
2630
  // before the hasContext/hasResearch predicates run, so a stray
2577
2631
  // cross-phase `-CONTEXT.md`/`-RESEARCH.md` sitting in this directory
@@ -2579,21 +2633,8 @@ function cmdInitManager(cwd, raw) {
2579
2633
  const scopedFiles = scopeToPhase(phaseFiles, dirMatch);
2580
2634
  hasContext = findContextMdIn(scopedFiles) !== null;
2581
2635
  hasResearch = scopedFiles.some((f) => f.endsWith('-RESEARCH.md') || f === 'RESEARCH.md');
2582
- completion = buildPhaseCompletionProjection(cwd, phaseNum, phaseDirRel, planCount, summaryCount, _slashRuntime);
2583
- if (completion.phase_complete)
2584
- diskStatus = 'complete';
2585
- else if (completion.implementation_complete)
2586
- diskStatus = 'executed';
2587
- else if (summaryCount > 0)
2588
- diskStatus = 'partial';
2589
- else if (planCount > 0)
2590
- diskStatus = 'planned';
2591
- else if (hasResearch)
2592
- diskStatus = 'researched';
2593
- else if (hasContext)
2594
- diskStatus = 'discussed';
2595
- else
2596
- diskStatus = 'empty';
2636
+ completion = buildPhaseCompletionProjection(cwd, phaseNum, phaseDirRel, planCount, summaryCount, _slashRuntime, phaseIdConvention);
2637
+ diskStatus = (0, phase_status_cjs_1.toDiskStatus)(ps.value.status, { hasResearch, hasContext });
2597
2638
  const nowMs = clock_cjs_1.realClock.now();
2598
2639
  let newestMtime = 0;
2599
2640
  for (const f of phaseFiles) {
@@ -2751,7 +2792,7 @@ function cmdInitManager(cwd, raw) {
2751
2792
  }
2752
2793
  for (const phase of phases) {
2753
2794
  phase['is_next_to_discuss'] =
2754
- (phase['disk_status'] === 'empty' || phase['disk_status'] === 'no_directory') &&
2795
+ (phase['disk_status'] === phase_status_cjs_1.DISK_STATUS.EMPTY || phase['disk_status'] === phase_status_cjs_1.DISK_STATUS.NO_DIRECTORY) &&
2755
2796
  phase['deps_satisfied'];
2756
2797
  }
2757
2798
  let waitingSignal = null;
@@ -2773,12 +2814,12 @@ function cmdInitManager(cwd, raw) {
2773
2814
  }
2774
2815
  const recommendedActions = [];
2775
2816
  for (const phase of phases) {
2776
- if (phase['disk_status'] === 'complete')
2817
+ if (phase['disk_status'] === phase_status_cjs_1.DISK_STATUS.COMPLETE)
2777
2818
  continue;
2778
2819
  // #3185: canonical sentinel predicate (SENTINEL_RANGES [0,999]) — this was a local 999-only literal that admitted Phase 0.
2779
2820
  if (isSentinelPhaseId(phase['number']))
2780
2821
  continue;
2781
- if (phase['disk_status'] === 'executed') {
2822
+ if (phase['disk_status'] === phase_status_cjs_1.DISK_STATUS.EXECUTED) {
2782
2823
  recommendedActions.push({
2783
2824
  phase: phase['number'],
2784
2825
  phase_name: phase['name'],
@@ -2787,7 +2828,7 @@ function cmdInitManager(cwd, raw) {
2787
2828
  command: phase['verification_next_command'],
2788
2829
  });
2789
2830
  }
2790
- else if (phase['disk_status'] === 'planned' && phase['deps_satisfied']) {
2831
+ else if (phase['disk_status'] === phase_status_cjs_1.DISK_STATUS.PLANNED && phase['deps_satisfied']) {
2791
2832
  recommendedActions.push({
2792
2833
  phase: phase['number'],
2793
2834
  phase_name: phase['name'],
@@ -2796,8 +2837,8 @@ function cmdInitManager(cwd, raw) {
2796
2837
  command: `${(0, runtime_slash_cjs_1.formatGsdSlash)('execute-phase', _slashRuntime)} ${phase['number']}`,
2797
2838
  });
2798
2839
  }
2799
- else if (phase['disk_status'] === 'discussed' ||
2800
- phase['disk_status'] === 'researched') {
2840
+ else if (phase['disk_status'] === phase_status_cjs_1.DISK_STATUS.DISCUSSED ||
2841
+ phase['disk_status'] === phase_status_cjs_1.DISK_STATUS.RESEARCHED) {
2801
2842
  recommendedActions.push({
2802
2843
  phase: phase['number'],
2803
2844
  phase_name: phase['name'],
@@ -2806,7 +2847,7 @@ function cmdInitManager(cwd, raw) {
2806
2847
  command: `${(0, runtime_slash_cjs_1.formatGsdSlash)('plan-phase', _slashRuntime)} ${phase['number']}`,
2807
2848
  });
2808
2849
  }
2809
- else if ((phase['disk_status'] === 'empty' || phase['disk_status'] === 'no_directory') &&
2850
+ else if ((phase['disk_status'] === phase_status_cjs_1.DISK_STATUS.EMPTY || phase['disk_status'] === phase_status_cjs_1.DISK_STATUS.NO_DIRECTORY) &&
2810
2851
  phase['is_next_to_discuss']) {
2811
2852
  recommendedActions.push({
2812
2853
  phase: phase['number'],
@@ -2817,10 +2858,10 @@ function cmdInitManager(cwd, raw) {
2817
2858
  });
2818
2859
  }
2819
2860
  }
2820
- const activeExecuting = phases.filter((p) => p['disk_status'] === 'partial' ||
2821
- (p['disk_status'] === 'planned' && p['is_active']));
2861
+ const activeExecuting = phases.filter((p) => p['disk_status'] === phase_status_cjs_1.DISK_STATUS.PARTIAL ||
2862
+ (p['disk_status'] === phase_status_cjs_1.DISK_STATUS.PLANNED && p['is_active']));
2822
2863
  const activePlanning = phases.filter((p) => p['is_active'] &&
2823
- (p['disk_status'] === 'discussed' || p['disk_status'] === 'researched'));
2864
+ (p['disk_status'] === phase_status_cjs_1.DISK_STATUS.DISCUSSED || p['disk_status'] === phase_status_cjs_1.DISK_STATUS.RESEARCHED));
2824
2865
  const filteredActions = recommendedActions.filter((action) => {
2825
2866
  if (action['action'] === 'execute' && activeExecuting.length > 0) {
2826
2867
  return activeExecuting.every((active) => !hasDepRelationship(action['phase'], active['number']));
@@ -2863,7 +2904,7 @@ function cmdInitManager(cwd, raw) {
2863
2904
  phases,
2864
2905
  phase_count: phases.length,
2865
2906
  completed_count: completedCount,
2866
- in_progress_count: phases.filter((p) => ['executed', 'partial', 'planned', 'discussed', 'researched'].includes(p['disk_status'])).length,
2907
+ in_progress_count: phases.filter((p) => [phase_status_cjs_1.DISK_STATUS.EXECUTED, phase_status_cjs_1.DISK_STATUS.PARTIAL, phase_status_cjs_1.DISK_STATUS.PLANNED, phase_status_cjs_1.DISK_STATUS.DISCUSSED, phase_status_cjs_1.DISK_STATUS.RESEARCHED].includes(p['disk_status'])).length,
2867
2908
  recommended_actions: filteredActions,
2868
2909
  waiting_signal: waitingSignal,
2869
2910
  all_complete: completedCount === nonBacklogPhases.length && nonBacklogPhases.length > 0,
@@ -3213,10 +3254,34 @@ function cmdInitProgress(cwd, raw, options = {}) {
3213
3254
  // uncounted LABEL_ONLY consumer to init.cts's pinned
3214
3255
  // tests/adr-612-bracket-heading-selection.test.cjs census.
3215
3256
  // phase-id-owner: deliberately unmigrated (#4984 revert) — see comment above.
3216
- const cbPattern = new RegExp(`-\\s*\\[(x| )\\]\\s*.*Phase\\s+(${PHASE_NUMBER_TOKEN_SOURCE})[:\\s]`, 'gi');
3257
+ // #4982: anchored (`^`, `m`) — the phase label must be the FIRST thing
3258
+ // after the checkbox (tolerating only an optional `**` bold marker) — so
3259
+ // the greedy `.*` this replaces can no longer bind a line's checkbox to
3260
+ // the LAST "Phase N" mentioned anywhere in that line's prose. This value
3261
+ // feeds `roadmap_complete` AND directly gates next_phase/current_phase
3262
+ // selection below, so getting the wrong phase here is load-bearing, not
3263
+ // metadata-only (contrast the `_cbPattern` site in cmdInitManager).
3264
+ // First-match-wins (`if (!roadmapCheckboxStates.has(...))`) additionally
3265
+ // guards against a later anchored line (e.g. a per-plan sub-entry
3266
+ // self-titled "Phase N ...") overwriting an already-recorded phase's own
3267
+ // (first) checkbox — anchoring alone does not fully close that
3268
+ // "last-match-wins" composition defect.
3269
+ // `(?:\[[^\]\n]{0,200}\]\s*)?` tolerates an optional leading bracket tag
3270
+ // (literal mirror of BASE_ANY_BRACKET_HEADING_PREFIX_SRC, phase-id.cts)
3271
+ // BEFORE the literal "Phase" word — decoration tolerance only, no capture
3272
+ // group, no convention gating. Without it the anchor fix above regresses
3273
+ // a checklist line combining a bracket tag with literal "Phase N" wording
3274
+ // (e.g. `**[GSD.02] Phase 3: ...**`), which the old unanchored `.*`
3275
+ // matched (by absorbing the bracket text). This does NOT migrate the site
3276
+ // onto phaseHeadingPrefixSrcFor / the bracket convention — that stays
3277
+ // out of scope per the comment above (#4984 revert, pinned census).
3278
+ const cbPattern = new RegExp(`^[ \\t]*-[ \\t]*\\[(x| )\\][ \\t]*(?:\\*\\*)?(?:\\[[^\\]\\n]{0,200}\\]\\s*)?Phase\\s+(${PHASE_NUMBER_TOKEN_SOURCE})[:\\s]`, 'gim');
3217
3279
  let cbm;
3218
3280
  while ((cbm = cbPattern.exec(roadmapContent)) !== null) {
3219
- roadmapCheckboxStates.set(cbm[2], cbm[1].toLowerCase() === 'x');
3281
+ const cbKey = cbm[2];
3282
+ if (!roadmapCheckboxStates.has(cbKey)) {
3283
+ roadmapCheckboxStates.set(cbKey, cbm[1].toLowerCase() === 'x');
3284
+ }
3220
3285
  }
3221
3286
  }
3222
3287
  catch {
@@ -3238,8 +3303,9 @@ function cmdInitProgress(cwd, raw, options = {}) {
3238
3303
  seenPhaseNums.add(phaseNumber.replace(/^0+/, '') || '0');
3239
3304
  const phasePath = node_path_1.default.join(phasesDir, dir);
3240
3305
  const phaseFiles = node_fs_1.default.readdirSync(phasePath);
3241
- const plans = listPhasePlanFiles(phasePath);
3242
- const summaries = listPhaseSummaryFiles(phasePath);
3306
+ // #5060: Phase Status Module — the single owner of "what state is
3307
+ // phase P in?" (ADR-5057 §1/§2).
3308
+ const ps = (0, phase_status_cjs_1.phaseStatus)(phasePath, { convention: resolvePhaseIdConvention(cwd) });
3243
3309
  // #3511-class: scope the raw listing to THIS phase's own artifacts
3244
3310
  // before the hasResearch predicate runs, so a stray cross-phase
3245
3311
  // `-RESEARCH.md` sitting in this directory cannot win this phase's
@@ -3247,16 +3313,8 @@ function cmdInitProgress(cwd, raw, options = {}) {
3247
3313
  const scopedPhaseFiles = scopeToPhase(phaseFiles, dir);
3248
3314
  const hasResearch = scopedPhaseFiles.some((f) => f.endsWith('-RESEARCH.md') || f === 'RESEARCH.md');
3249
3315
  const phaseDirRel = toPosixPath(node_path_1.default.relative(cwd, node_path_1.default.join(planningDir(cwd), 'phases', dir)));
3250
- const completion = buildPhaseCompletionProjection(cwd, phaseNumber, phaseDirRel, plans.length, summaries.length, _slashRuntime);
3251
- const status = completion.phase_complete
3252
- ? 'complete'
3253
- : completion.implementation_complete
3254
- ? 'executed'
3255
- : plans.length > 0
3256
- ? 'in_progress'
3257
- : hasResearch
3258
- ? 'researched'
3259
- : 'pending';
3316
+ const completion = buildPhaseCompletionProjection(cwd, phaseNumber, phaseDirRel, ps.value.planCount, ps.value.summaryCount, _slashRuntime, resolvePhaseIdConvention(cwd));
3317
+ const status = (0, phase_status_cjs_1.toProgressStatus)(ps.value.status, { hasResearch });
3260
3318
  const phaseInfo = {
3261
3319
  number: phaseNumber,
3262
3320
  name: phaseName,
@@ -3265,30 +3323,37 @@ function cmdInitProgress(cwd, raw, options = {}) {
3265
3323
  // above still joins it against cwd.
3266
3324
  directory: toPosixPath(node_path_1.default.join(cwd, phaseDirRel)),
3267
3325
  status,
3268
- plan_count: plans.length,
3269
- summary_count: summaries.length,
3326
+ plan_count: ps.value.planCount,
3327
+ summary_count: ps.value.summaryCount,
3270
3328
  has_research: hasResearch,
3271
3329
  ...completion,
3272
3330
  };
3273
3331
  phases.push(phaseInfo);
3274
- if (!currentPhase && (status === 'executed' || status === 'in_progress' || status === 'researched')) {
3332
+ if (!currentPhase && (status === phase_status_cjs_1.PROGRESS_STATUS.EXECUTED || status === phase_status_cjs_1.PROGRESS_STATUS.IN_PROGRESS || status === phase_status_cjs_1.PROGRESS_STATUS.RESEARCHED)) {
3275
3333
  currentPhase = phaseInfo;
3276
3334
  }
3277
- if (!nextPhase && status === 'pending') {
3335
+ if (!nextPhase && status === phase_status_cjs_1.PROGRESS_STATUS.PENDING) {
3278
3336
  nextPhase = phaseInfo;
3279
3337
  }
3280
3338
  }
3281
3339
  }
3282
- catch {
3283
- /* intentionally empty */
3340
+ catch (err) {
3341
+ // #5118: the owner's out-of-set report error is not a scan failure to
3342
+ // degrade over — the bundle is never assembled over a refused report.
3343
+ if (err instanceof VerificationStatusError)
3344
+ throw err;
3345
+ /* otherwise intentionally empty */
3284
3346
  }
3285
3347
  for (const [num, name] of roadmapPhaseNames) {
3286
3348
  const stripped = num.replace(/^0+/, '') || '0';
3287
3349
  if (!seenPhaseNums.has(stripped)) {
3288
3350
  const checkboxComplete = roadmapCheckboxStates.get(num) === true ||
3289
3351
  roadmapCheckboxStates.get(stripped) === true;
3290
- const completion = buildPhaseCompletionProjection(cwd, num, null, 0, 0, _slashRuntime);
3291
- const status = 'not_started';
3352
+ const completion = buildPhaseCompletionProjection(cwd, num, null, 0, 0, _slashRuntime, resolvePhaseIdConvention(cwd));
3353
+ // #5060: this synthetic row has no phase directory at all — the
3354
+ // roadmap heading exists but no `seenPhaseNums` disk match was found —
3355
+ // so it is the ladder's own NOT_STARTED word, not a derived guess.
3356
+ const status = phase_status_cjs_1.PROGRESS_STATUS.NOT_STARTED;
3292
3357
  const phaseInfo = {
3293
3358
  number: num,
3294
3359
  // #3883 (ADR-3473 §8.3): delegate to the canonical slug formula
@@ -3325,7 +3390,7 @@ function cmdInitProgress(cwd, raw, options = {}) {
3325
3390
  {
3326
3391
  const frontier = phases.find((p) => {
3327
3392
  const st = p['status'];
3328
- return (st === 'pending' || st === 'not_started') && p['roadmap_complete'] !== true;
3393
+ return (st === phase_status_cjs_1.PROGRESS_STATUS.PENDING || st === phase_status_cjs_1.PROGRESS_STATUS.NOT_STARTED) && p['roadmap_complete'] !== true;
3329
3394
  });
3330
3395
  if (frontier)
3331
3396
  nextPhase = frontier;
@@ -3362,8 +3427,8 @@ function cmdInitProgress(cwd, raw, options = {}) {
3362
3427
  milestone_name: milestone['name'] ?? null,
3363
3428
  phases,
3364
3429
  phase_count: phases.length,
3365
- completed_count: phases.filter((p) => p['status'] === 'complete').length,
3366
- in_progress_count: phases.filter((p) => ['executed', 'in_progress'].includes(p['status'])).length,
3430
+ completed_count: phases.filter((p) => p['status'] === phase_status_cjs_1.PROGRESS_STATUS.COMPLETE).length,
3431
+ in_progress_count: phases.filter((p) => [phase_status_cjs_1.PROGRESS_STATUS.EXECUTED, phase_status_cjs_1.PROGRESS_STATUS.IN_PROGRESS].includes(p['status'])).length,
3367
3432
  current_phase: currentPhase,
3368
3433
  next_phase: nextPhase,
3369
3434
  paused_at: pausedAt,
@@ -3955,10 +4020,11 @@ function buildSkillManifest(cwd, skillsDir = null) {
3955
4020
  seenNamesInRoot.add(name);
3956
4021
  const description = frontmatter['description'] || '';
3957
4022
  const triggers = [];
3958
- const bodyMatch = content.match(/^---[\s\S]*?---\s*\r?\n([\s\S]*)$/);
3959
- if (bodyMatch) {
3960
- const body = bodyMatch[1];
3961
- const triggerLines = body.match(/^TRIGGER\s+when:\s*(.+)$/gmi);
4023
+ // TRIGGER lines are read from the body after the block `extractFrontmatter` read (the
4024
+ // one fence owner), so a `---` inside a frontmatter value cannot start the body early.
4025
+ const block = frontmatterBlock(content);
4026
+ if (block) {
4027
+ const triggerLines = block.rest.match(/^TRIGGER\s+when:\s*(.+)$/gmi);
3962
4028
  if (triggerLines) {
3963
4029
  for (const line of triggerLines) {
3964
4030
  const m = line.match(/^TRIGGER\s+when:\s*(.+)$/i);