@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
@@ -128,6 +128,19 @@ const SCHEMA_DEFAULTS = {
128
128
  // WARNING_THRESHOLD/CRITICAL_THRESHOLD so the copies cannot drift.
129
129
  'hooks.context_warning_threshold': 35,
130
130
  'hooks.context_critical_threshold': 25,
131
+ // #4974: gates.* confirmation toggles — an absent key must resolve to the
132
+ // documented default (true) rather than "Key not found", matching
133
+ // config-defaults.manifest.json's `gates` block. Literal here (like
134
+ // git.create_tag above) rather than derived from config-loader.cjs's flat
135
+ // CONFIG_DEFAULTS: that flat projection is enumerated 1:1 against
136
+ // gsd-core/references/planning-config.md by
137
+ // tests/config-field-docs.test.cjs, and these 3 keys are internal workflow
138
+ // wiring, not part of that public flat-key surface. Only the 3 keys
139
+ // actually read by workflow conditions are registered — see
140
+ // gsd-core/bin/shared/config-schema.manifest.json.
141
+ 'gates.execute_next_plan': true,
142
+ 'gates.confirm_transition': true,
143
+ 'gates.confirm_milestone_scope': true,
131
144
  };
132
145
  /**
133
146
  * Resolve a schema-level default for an absent key (#2256). Checks the legacy
@@ -264,7 +277,8 @@ function validateShipPrBodySections(value) {
264
277
  *
265
278
  * Merges (increasing priority):
266
279
  * 1. Hardcoded defaults — every key that loadConfig() resolves, plus mode/granularity
267
- * 2. User-level defaults from ~/.gsd/defaults.json (if present)
280
+ * 2. User-level defaults from $GSD_HOME/.gsd/defaults.json (if present;
281
+ * GSD_HOME defaults to the home directory, as in the config loader)
268
282
  * 3. userChoices — the settings the user explicitly selected during /gsd:new-project
269
283
  *
270
284
  * Uses the canonical `git` namespace for branching keys (consistent with VALID_CONFIG_KEYS
@@ -275,24 +289,27 @@ function validateShipPrBodySections(value) {
275
289
  */
276
290
  function buildNewProjectConfig(userChoices) {
277
291
  const choices = userChoices || {};
278
- const homedir = node_os_1.default.homedir();
292
+ // #4976: the GSD-owned store resolves exactly as the config loader resolves
293
+ // it (`GSD_HOME || homedir()`), so the defaults.json seeding this project is
294
+ // the one the loader and its #3532 shadow warning read in the same run.
295
+ const gsdHome = process.env['GSD_HOME'] || node_os_1.default.homedir();
279
296
  // Detect API key availability
280
- const braveKeyFile = node_path_1.default.join(homedir, '.gsd', 'brave_api_key');
297
+ const braveKeyFile = node_path_1.default.join(gsdHome, '.gsd', 'brave_api_key');
281
298
  const hasBraveSearch = !!(process.env['BRAVE_API_KEY'] || node_fs_1.default.existsSync(braveKeyFile));
282
- const firecrawlKeyFile = node_path_1.default.join(homedir, '.gsd', 'firecrawl_api_key');
299
+ const firecrawlKeyFile = node_path_1.default.join(gsdHome, '.gsd', 'firecrawl_api_key');
283
300
  const hasFirecrawl = !!(process.env['FIRECRAWL_API_KEY'] || node_fs_1.default.existsSync(firecrawlKeyFile));
284
- const exaKeyFile = node_path_1.default.join(homedir, '.gsd', 'exa_api_key');
301
+ const exaKeyFile = node_path_1.default.join(gsdHome, '.gsd', 'exa_api_key');
285
302
  const hasExaSearch = !!(process.env['EXA_API_KEY'] || node_fs_1.default.existsSync(exaKeyFile));
286
- const tavilyKeyFile = node_path_1.default.join(homedir, '.gsd', 'tavily_api_key');
303
+ const tavilyKeyFile = node_path_1.default.join(gsdHome, '.gsd', 'tavily_api_key');
287
304
  const hasTavilySearch = !!(process.env['TAVILY_API_KEY'] || node_fs_1.default.existsSync(tavilyKeyFile));
288
- const refKeyFile = node_path_1.default.join(homedir, '.gsd', 'ref_api_key');
305
+ const refKeyFile = node_path_1.default.join(gsdHome, '.gsd', 'ref_api_key');
289
306
  const hasRefSearch = !!(process.env['REF_API_KEY'] || node_fs_1.default.existsSync(refKeyFile));
290
- const perplexityKeyFile = node_path_1.default.join(homedir, '.gsd', 'perplexity_api_key');
307
+ const perplexityKeyFile = node_path_1.default.join(gsdHome, '.gsd', 'perplexity_api_key');
291
308
  const hasPerplexity = !!(process.env['PERPLEXITY_API_KEY'] || node_fs_1.default.existsSync(perplexityKeyFile));
292
- const jinaKeyFile = node_path_1.default.join(homedir, '.gsd', 'jina_api_key');
309
+ const jinaKeyFile = node_path_1.default.join(gsdHome, '.gsd', 'jina_api_key');
293
310
  const hasJina = !!(process.env['JINA_API_KEY'] || node_fs_1.default.existsSync(jinaKeyFile));
294
- // Load user-level defaults from ~/.gsd/defaults.json if available
295
- const globalDefaultsPath = node_path_1.default.join(homedir, '.gsd', 'defaults.json');
311
+ // Load user-level defaults from $GSD_HOME/.gsd/defaults.json if available
312
+ const globalDefaultsPath = node_path_1.default.join(gsdHome, '.gsd', 'defaults.json');
296
313
  let userDefaults = {};
297
314
  try {
298
315
  if (node_fs_1.default.existsSync(globalDefaultsPath)) {
@@ -434,7 +451,7 @@ function buildNewProjectConfig(userChoices) {
434
451
  *
435
452
  * Accepts user-chosen settings as a JSON string (the keys the user explicitly
436
453
  * configured during /gsd:new-project). All remaining keys are filled from
437
- * hardcoded defaults and optional ~/.gsd/defaults.json.
454
+ * hardcoded defaults and optional $GSD_HOME/.gsd/defaults.json.
438
455
  *
439
456
  * Idempotent: if config.json already exists, returns { created: false }.
440
457
  */
@@ -818,6 +835,13 @@ function cmdConfigSet(cwd, keyPath, value, raw, options = {}) {
818
835
  const VALID_CONTEXT_VALUES = ['dev', 'research', 'review'];
819
836
  if (kp === 'context')
820
837
  assertEnumValue(parsedValue, val, VALID_CONTEXT_VALUES, 'context value');
838
+ // #4974: `mode` was never enum-validated — `config-set mode custom` (or any
839
+ // other string) silently succeeded, even though only "interactive" and
840
+ // "yolo" are documented/read values (gsd-core/references/planning-config.md,
841
+ // docs/CONFIGURATION.md, pinned by tests/config-field-docs.test.cjs).
842
+ const VALID_MODE_VALUES = ['interactive', 'yolo'];
843
+ if (kp === 'mode')
844
+ assertEnumValue(parsedValue, val, VALID_MODE_VALUES, 'mode');
821
845
  if (kp === 'phase_id_convention') {
822
846
  assertEnumValue(parsedValue, val, VALID_PHASE_ID_CONVENTIONS, 'phase_id_convention');
823
847
  }
@@ -875,6 +899,13 @@ function cmdConfigSet(cwd, keyPath, value, raw, options = {}) {
875
899
  error(`Invalid planner.stall_detection_enabled '${val}'. Must be a boolean (true or false).`);
876
900
  }
877
901
  }
902
+ // Dispatch audit-trail opt-in (#4975) — boolean only. The live seams honour
903
+ // only a real `true`, so any other stored value would be silently ignored.
904
+ if (kp === 'audit.enabled') {
905
+ if (typeof parsedValue !== 'boolean') {
906
+ error(`Invalid audit.enabled '${val}'. Must be a boolean (true or false).`);
907
+ }
908
+ }
878
909
  // #3086 — git.create_tag: boolean only
879
910
  if (kp === 'git.create_tag') {
880
911
  if (typeof parsedValue !== 'boolean') {
@@ -15,6 +15,7 @@
15
15
  * - node:fs / node:path (stdlib)
16
16
  * - ./phase-id.cjs (comparePhaseNum, used by readSubdirectories)
17
17
  * - ./planning-workspace.cjs (findContextMdIn, used by getPhaseFileStats)
18
+ * - ./frontmatter-fence.cjs (locateFrontmatterFence, used by extractOneLinerFromBody)
18
19
  *
19
20
  * #3883 (ADR-3473 §8.3): two of this module's cyclic partners require
20
21
  * generateSlugInternal, the canonical slug formula:
@@ -37,6 +38,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
37
38
  };
38
39
  const node_fs_1 = __importDefault(require("node:fs"));
39
40
  const node_path_1 = __importDefault(require("node:path"));
41
+ // frontmatter-fence.cjs is a leaf module (no imports), so this adds no cycle.
42
+ const frontmatter_fence_cjs_1 = require("./frontmatter-fence.cjs");
40
43
  // eslint-disable-next-line @typescript-eslint/no-require-imports
41
44
  const phaseIdModule = require("./phase-id.cjs");
42
45
  // eslint-disable-next-line @typescript-eslint/no-require-imports
@@ -139,7 +142,9 @@ function extractOneLinerFromBody(content) {
139
142
  if (!content)
140
143
  return null;
141
144
  const normalized = content.replace(/\r\n/g, '\n').replace(/\r/g, '\n');
142
- const body = normalized.replace(/^---\r?\n[\s\S]*?\r?\n---\r?\n*/, '');
145
+ // The body starts after the block the one fence owner finds, and the blank lines after it.
146
+ const fence = (0, frontmatter_fence_cjs_1.locateFrontmatterFence)(normalized);
147
+ const body = fence?.closed ? normalized.slice(fence.closingFenceEnd).replace(/^\n+/, '') : normalized;
143
148
  // #3170: anchor to a summary-shaped heading (Summary / Overview /
144
149
  // Accomplishments) so an incidental first heading (a rule list, task
145
150
  // breakdown, deviation note) does not contribute its first bold run as the
@@ -34,6 +34,7 @@ const { output, error } = io;
34
34
  const coreUtils = require("./core-utils.cjs");
35
35
  const { toPosixPath } = coreUtils;
36
36
  const security_cjs_1 = require("./security.cjs");
37
+ const frontmatter_fence_cjs_1 = require("./frontmatter-fence.cjs");
37
38
  // ─── Frozen typed-IR surface ────────────────────────────────────────────────
38
39
  const MODE = Object.freeze({
39
40
  COVERAGE: 'coverage',
@@ -186,15 +187,10 @@ function setKey(obj, key, value) {
186
187
  obj[key] = value;
187
188
  }
188
189
  // ─── Frontmatter region helpers ──────────────────────────────────────────────
190
+ /** The closed frontmatter block's YAML text, as the one fence owner finds it, or null. */
189
191
  function getFrontmatterYaml(content) {
190
- const headerEnd = content.startsWith('---\r\n') ? 5 : content.startsWith('---\n') ? 4 : -1;
191
- if (headerEnd === -1)
192
- return null;
193
- const closingLineStart = content.indexOf('\n---', headerEnd);
194
- if (closingLineStart === -1)
195
- return null;
196
- const yamlEnd = content[closingLineStart - 1] === '\r' ? closingLineStart - 1 : closingLineStart;
197
- return content.slice(headerEnd, yamlEnd);
192
+ const fence = (0, frontmatter_fence_cjs_1.locateFrontmatterFence)(content);
193
+ return fence?.closed ? content.slice(fence.openEnd, fence.bodyEnd) : null;
198
194
  }
199
195
  /**
200
196
  * Locate and parse the top-level `coverage:` block from a SUMMARY document.
@@ -0,0 +1,259 @@
1
+ "use strict";
2
+ /**
3
+ * Decision-coverage support — the shared reading/matching helpers of the two decision-coverage
4
+ * gates (#5139, epic #5056, ADR-5057 §4 first bullet, design D3/D4).
5
+ *
6
+ * Moved verbatim (behaviour preserved) from `check-command-router.cts`, with the raw-content
7
+ * parsers replaced by their owning seams:
8
+ * - the frontmatter `must_haves` / `truths` / `objective` blocks are read through the
9
+ * Frontmatter Module (`frontmatterKeyBlockText`, the moved `extractYamlBlock`: raw text off
10
+ * the one fence owner's block, so frontmatter the YAML parser refuses is still scanned), and
11
+ * the SUMMARY `files_modified` list through its parsed reader (`rawFrontmatterField`), not a
12
+ * `files_modified:` regex;
13
+ * - the XML-tag body extraction lives in `markdown-sectionizer.cts` (`extractXmlTagBodies`).
14
+ *
15
+ * The router-facing gate modules (`gate-decision-coverage-plan.cts`,
16
+ * `gate-decision-coverage-verify.cts`) import from here. This module imports no io module and
17
+ * performs no direct console/stdout/stderr write (ESLint-enforced).
18
+ */
19
+ var __importDefault = (this && this.__importDefault) || function (mod) {
20
+ return (mod && mod.__esModule) ? mod : { "default": mod };
21
+ };
22
+ Object.defineProperty(exports, "__esModule", { value: true });
23
+ exports.decisionMentioned = decisionMentioned;
24
+ exports.loadPlanContents = loadPlanContents;
25
+ exports.loadSummaryContents = loadSummaryContents;
26
+ exports.loadDecisionExtraction = loadDecisionExtraction;
27
+ exports.extractPlanDesignatedSections = extractPlanDesignatedSections;
28
+ exports.buildPlanMessage = buildPlanMessage;
29
+ exports.buildVerifyMessage = buildVerifyMessage;
30
+ exports.phaseCommitMessages = phaseCommitMessages;
31
+ exports.readModifiedFilesContent = readModifiedFilesContent;
32
+ const node_path_1 = __importDefault(require("node:path"));
33
+ const decisions_cjs_1 = require("./decisions.cjs");
34
+ const frontmatter_fence_cjs_1 = require("./frontmatter-fence.cjs");
35
+ const markdown_sectionizer_cjs_1 = require("./markdown-sectionizer.cjs");
36
+ const security_cjs_1 = require("./security.cjs");
37
+ const gate_evidence_cjs_1 = require("./gate-evidence.cjs");
38
+ const gate_evaluation_scope_cjs_1 = require("./gate-evaluation-scope.cjs");
39
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
40
+ const frontmatterMod = require("./frontmatter.cjs");
41
+ const { rawFrontmatterField, frontmatterKeyBlockText } = frontmatterMod;
42
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
43
+ const planScanMod = require("./plan-scan.cjs");
44
+ const { scanPhasePlans } = planScanMod;
45
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
46
+ const planningScopeMod = require("./planning-scope.cjs");
47
+ const { SCOPE } = planningScopeMod;
48
+ // ─── Decision matching ────────────────────────────────────────────────────────
49
+ function normalizePhrase(text) {
50
+ // eslint-disable-next-line @typescript-eslint/no-base-to-string
51
+ return String(text || '')
52
+ .toLowerCase()
53
+ .replace(/[^a-z0-9\s]/g, ' ')
54
+ .replace(/\s+/g, ' ')
55
+ .trim();
56
+ }
57
+ const SOFT_PHRASE_MIN_WORDS = 6;
58
+ function softPhrase(text) {
59
+ const words = normalizePhrase(text).split(' ').filter(Boolean);
60
+ if (words.length < SOFT_PHRASE_MIN_WORDS)
61
+ return '';
62
+ return words.slice(0, SOFT_PHRASE_MIN_WORDS).join(' ');
63
+ }
64
+ function decisionMentioned(haystack, decision) {
65
+ if (!haystack)
66
+ return false;
67
+ if (new RegExp(`\\b${decision.id}\\b`).test(haystack))
68
+ return true;
69
+ const phrase = softPhrase(decision.text);
70
+ return phrase ? normalizePhrase(haystack).includes(phrase) : false;
71
+ }
72
+ // ─── File reading ─────────────────────────────────────────────────────────────
73
+ /**
74
+ * The contents of the phase files `pick` selects (#5170, ADR-5057 §4). An ABSENT phase directory
75
+ * is "no files" (`found []`); a directory or file that exists but cannot be read is `unreadable` —
76
+ * a gate must not take "could not read the plan" for "the plan does not cite the decision".
77
+ */
78
+ function readPhaseFiles(phaseDir, pick) {
79
+ const entries = (0, gate_evidence_cjs_1.readDirEvidence)(phaseDir);
80
+ if (entries.kind === 'none')
81
+ return (0, gate_evidence_cjs_1.evidenceFound)([]);
82
+ if (entries.kind === 'unreadable')
83
+ return entries;
84
+ const contents = [];
85
+ // #3183 (lint-plan-count-drift): source live plan/summary files from the single
86
+ // owner (scanPhasePlans) instead of a local readdirSync filter — picks up bare PLAN.md and
87
+ // nested plans/, and excludes plans marked `status: superseded`.
88
+ // Only SCOPE.COMPLETE is a real answer: an existing nested plans/ that could not be read (TRUNCATED)
89
+ // would otherwise hand the gate a short plan set and let it conclude "no plan cites the decision".
90
+ const scan = scanPhasePlans(phaseDir);
91
+ if (scan.scope !== SCOPE.COMPLETE) {
92
+ return { kind: 'unreadable', reason: `plan scan ${scan.scope}`, span: phaseDir };
93
+ }
94
+ for (const entry of pick(scan)) {
95
+ const read = (0, gate_evidence_cjs_1.readTextEvidence)(node_path_1.default.join(phaseDir, entry));
96
+ if (read.kind === 'unreadable')
97
+ return read;
98
+ if (read.kind === 'found')
99
+ contents.push(read.value);
100
+ }
101
+ return (0, gate_evidence_cjs_1.evidenceFound)(contents);
102
+ }
103
+ function loadPlanContents(phaseDir) {
104
+ return readPhaseFiles(phaseDir, (scan) => scan.planFiles);
105
+ }
106
+ /**
107
+ * #3183 (lint-plan-count-drift): same single-owner sourcing as `loadPlanContents` —
108
+ * scanPhasePlans's summaryFiles instead of a local `-SUMMARY.md` readdirSync filter.
109
+ */
110
+ function loadSummaryContents(phaseDir) {
111
+ return readPhaseFiles(phaseDir, (scan) => scan.summaryFiles);
112
+ }
113
+ /**
114
+ * The decisions of `CONTEXT.md`. `none` is an absent file (the caller's legitimate "nothing to
115
+ * check"); `unreadable` is a file that exists but could not be read — it must never be extracted as
116
+ * empty text, which would certify "no trackable decisions".
117
+ */
118
+ function loadDecisionExtraction(contextPath) {
119
+ const read = (0, gate_evidence_cjs_1.readTextEvidence)(contextPath);
120
+ if (read.kind !== 'found')
121
+ return read;
122
+ const extraction = (0, decisions_cjs_1.extractDecisions)(read.value);
123
+ return (0, gate_evidence_cjs_1.evidenceFound)({
124
+ trackable: extraction.decisions.filter((d) => d.trackable),
125
+ outcome: extraction.outcome,
126
+ unreadableIds: extraction.unreadableIds ?? [],
127
+ });
128
+ }
129
+ // ─── Plan surfaces scanned for a decision citation ────────────────────────────
130
+ const DESIGNATED_HEADINGS_RE = /^#{1,6}\s+(?:must[_ ]haves?|truths?|tasks?|objective)\b/i;
131
+ function stripCommentsAndFences(text) {
132
+ // HTML-comment stripping stays caller-side (the seam does not strip HTML comments).
133
+ // Stop-at-next-open body (ReDoS-safe, #2128); an UNCLOSED `<!--` does not match,
134
+ // so downstream tags are preserved (unlike a `(?:-->|$)` fallback, which would
135
+ // wipe to EOF and fail-close the decision-coverage gate).
136
+ const htmlStripped = text.replace(/<!--(?:(?!<!--)[\s\S])*?-->/g, ' ');
137
+ // Fenced-code stripping: delegate to the canonical CommonMark-correct seam.
138
+ // replaces the prior independent regex copy (```` ``` ``` ```` + `~~~ ~~~`).
139
+ return (0, markdown_sectionizer_cjs_1.stripFencedCode)(htmlStripped).text;
140
+ }
141
+ function extractPlanDesignatedSections(planContent) {
142
+ if (!planContent)
143
+ return '';
144
+ const cleaned = stripCommentsAndFences(planContent);
145
+ // The block is the one the one fence owner finds; the body starts after the closing fence
146
+ // line's line ending.
147
+ const fence = (0, frontmatter_fence_cjs_1.locateFrontmatterFence)(cleaned);
148
+ const body = fence?.closed ? cleaned.slice(fence.closingFenceEnd).replace(/^\r?\n/, '') : cleaned;
149
+ const parts = [];
150
+ for (const key of ['must_haves', 'truths', 'objective']) {
151
+ const block = frontmatterKeyBlockText(cleaned, key);
152
+ if (block)
153
+ parts.push(block);
154
+ }
155
+ // Replace hand-rolled split(/\r?\n/) + heading walk with the seam's collectSections.
156
+ // stopPredicate fires on EVERY heading (collectSections needs to start a section at
157
+ // each heading), then we filter to designated ones — same semantics as the prior
158
+ // inDesignated flag: emit the heading line + body only when DESIGNATED_HEADINGS_RE matches.
159
+ const sections = (0, markdown_sectionizer_cjs_1.collectSections)(body, () => true);
160
+ const bodyParts = [];
161
+ for (const section of sections) {
162
+ const headingLine = '#'.repeat(section.heading.level) + ' ' + section.heading.text;
163
+ if (DESIGNATED_HEADINGS_RE.test(headingLine)) {
164
+ bodyParts.push(headingLine);
165
+ if (section.body)
166
+ bodyParts.push(section.body);
167
+ }
168
+ }
169
+ parts.push(bodyParts.join('\n'));
170
+ parts.push((0, markdown_sectionizer_cjs_1.extractXmlTagBodies)(cleaned));
171
+ return parts.join('\n\n');
172
+ }
173
+ function buildPlanMessage(uncovered) {
174
+ if (uncovered.length === 0)
175
+ return 'All trackable CONTEXT.md decisions are covered by plans.';
176
+ return [
177
+ '## Decision Coverage Gap',
178
+ '',
179
+ `${uncovered.length} CONTEXT.md decision(s) are not covered by any plan:`,
180
+ '',
181
+ ...uncovered.map((item) => `- **${item.id}** (${item.category || 'uncategorized'}): ${item.text}`),
182
+ '',
183
+ 'Resolve by citing `D-NN:` in any of the scanned plan surfaces: front-matter',
184
+ '`must_haves`/`truths`/`objective`, a `## must_haves`/`truths`/`tasks`/`objective`',
185
+ 'heading, or an `<objective>`/`<tasks>`/`<task>`/`<action>`/`<read_first>`/`<behavior>`/`<verify>`/`<acceptance_criteria>`/`<done>`',
186
+ 'tag body. Other locations (prose outside those headings, comments, other XML tags) are not scanned.',
187
+ 'OR move the decision to `### Claude\'s Discretion` / tag it `[informational]` if it should not be tracked.',
188
+ ].join('\n');
189
+ }
190
+ function buildVerifyMessage(notHonored) {
191
+ if (notHonored.length === 0)
192
+ return 'All trackable CONTEXT.md decisions are honored by shipped artifacts.';
193
+ return [
194
+ '### Decision Coverage (warning)',
195
+ '',
196
+ `${notHonored.length} decision(s) not found in shipped artifacts:`,
197
+ '',
198
+ ...notHonored.map((item) => `- **${item.id}** (${item.category || 'uncategorized'}): ${item.text}`),
199
+ '',
200
+ 'This is a soft warning - verification status is unchanged.',
201
+ ].join('\n');
202
+ }
203
+ // ─── Shipped-artifact haystack (verify gate) ──────────────────────────────────
204
+ /**
205
+ * The subjects and bodies of the PHASE'S OWN commits (#5164, ADR-5057 §4) — the evaluation-scope
206
+ * resolver's commit set for `phaseDir`, not the last 200 commits of whatever branch is checked
207
+ * out. A phase with no recorded task commits widens to the commits in its directory range (the
208
+ * resolver says so); an unreadable phase or repository yields '' ("could not look"), and a git
209
+ * failure on a non-git project dir writes nothing to the terminal.
210
+ */
211
+ function phaseCommitMessages(projectDir, phaseDir) {
212
+ const scope = (0, gate_evaluation_scope_cjs_1.resolveEvaluationScope)(projectDir, { kind: 'phase', phase: '', phaseDir }, { includeBody: true, includeFiles: false });
213
+ return scope.commits.map((c) => `${c.subject}\n${c.body ?? ''}`).join('\n');
214
+ }
215
+ /** Cap on files read across all SUMMARYs, and on bytes read per file. */
216
+ const MODIFIED_FILES_MAX_COUNT = 50;
217
+ const MODIFIED_FILES_MAX_BYTES = 256 * 1024;
218
+ /**
219
+ * The contents of every file the SUMMARYs list under frontmatter `files_modified`, contained to
220
+ * `projectDir` and capped at `MODIFIED_FILES_MAX_COUNT` files / `MODIFIED_FILES_MAX_BYTES` each.
221
+ */
222
+ function readModifiedFilesContent(projectDir, summaries) {
223
+ const out = [];
224
+ let total = 0;
225
+ for (const summary of summaries) {
226
+ if (!summary)
227
+ continue;
228
+ if (total >= MODIFIED_FILES_MAX_COUNT)
229
+ break;
230
+ const field = rawFrontmatterField(summary, 'files_modified');
231
+ const listed = field && Array.isArray(field.value) ? field.value : [];
232
+ for (const entry of listed) {
233
+ if (total >= MODIFIED_FILES_MAX_COUNT)
234
+ break;
235
+ if (typeof entry !== 'string')
236
+ continue;
237
+ const file = entry.trim();
238
+ if (!file)
239
+ continue;
240
+ // Migrated off the hand-rolled prefix check (ADR-4650): resolve+contain in one
241
+ // step via the canonical realpath predicate — the eventual read below follows
242
+ // symlinks, so containment must be decided on the resolved target, not a lexical
243
+ // prefix. Read the value the predicate RETURNED; do not re-derive the path.
244
+ const candidate = node_path_1.default.isAbsolute(file) ? file : node_path_1.default.join(projectDir, file);
245
+ const contained = (0, security_cjs_1.tryWithinRoot)(candidate, projectDir, security_cjs_1.PathAcceptance.AbsoluteInsideRoot);
246
+ if (contained === null)
247
+ continue;
248
+ // An absent listed file contributes nothing readable (`''`); one that exists but cannot be
249
+ // read is `unreadable` — the decision it may cite was never seen (#5170).
250
+ const read = (0, gate_evidence_cjs_1.readTextEvidence)(contained);
251
+ if (read.kind === 'unreadable')
252
+ return read;
253
+ const content = read.kind === 'found' ? read.value : '';
254
+ out.push(content.length > MODIFIED_FILES_MAX_BYTES ? content.slice(0, MODIFIED_FILES_MAX_BYTES) : content);
255
+ total++;
256
+ }
257
+ }
258
+ return (0, gate_evidence_cjs_1.evidenceFound)(out.join('\n\n'));
259
+ }