@opengsd/gsd-core 1.14.0 → 1.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (551) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/.opencode/plugins/gsd-core.js +85 -5
  4. package/README.ja-JP.md +3 -3
  5. package/README.ko-KR.md +3 -3
  6. package/README.pt-BR.md +3 -3
  7. package/README.zh-CN.md +3 -3
  8. package/agents/gsd-code-fixer.compact.md +7 -6
  9. package/agents/gsd-code-fixer.md +9 -8
  10. package/agents/gsd-code-reviewer.compact.md +5 -3
  11. package/agents/gsd-code-reviewer.md +8 -6
  12. package/agents/gsd-debug-session-manager.compact.md +17 -2
  13. package/agents/gsd-debug-session-manager.md +17 -2
  14. package/agents/gsd-debugger.md +3 -3
  15. package/agents/gsd-eval-auditor.compact.md +1 -1
  16. package/agents/gsd-eval-auditor.md +1 -1
  17. package/agents/gsd-executor.md +17 -12
  18. package/agents/gsd-intel-updater.compact.md +1 -1
  19. package/agents/gsd-intel-updater.md +1 -1
  20. package/agents/gsd-mempalace-curator.md +2 -2
  21. package/agents/gsd-phase-researcher.md +19 -11
  22. package/agents/gsd-plan-checker.md +15 -9
  23. package/agents/gsd-planner.md +15 -11
  24. package/agents/gsd-project-researcher.compact.md +1 -1
  25. package/agents/gsd-project-researcher.md +1 -1
  26. package/agents/gsd-research-synthesizer.compact.md +1 -1
  27. package/agents/gsd-research-synthesizer.md +1 -1
  28. package/agents/gsd-ui-auditor.compact.md +21 -30
  29. package/agents/gsd-ui-auditor.md +166 -37
  30. package/agents/gsd-ui-researcher.compact.md +1 -1
  31. package/agents/gsd-ui-researcher.md +1 -1
  32. package/agents/gsd-verifier.md +37 -14
  33. package/bin/install.js +764 -287
  34. package/commands/gsd/add-tests.md +6 -1
  35. package/commands/gsd/ai-integration-phase.md +6 -1
  36. package/commands/gsd/audit-fix.md +5 -0
  37. package/commands/gsd/audit-milestone.md +6 -1
  38. package/commands/gsd/autonomous.md +7 -2
  39. package/commands/gsd/capture.md +9 -5
  40. package/commands/gsd/code-review.md +7 -2
  41. package/commands/gsd/complete-milestone.md +4 -0
  42. package/commands/gsd/config.md +7 -3
  43. package/commands/gsd/debug.md +11 -7
  44. package/commands/gsd/discuss-phase.md +7 -3
  45. package/commands/gsd/docs-update.md +12 -7
  46. package/commands/gsd/eval-review.md +6 -1
  47. package/commands/gsd/execute-phase.md +12 -7
  48. package/commands/gsd/extract-learnings.md +5 -0
  49. package/commands/gsd/fast.md +4 -0
  50. package/commands/gsd/forensics.md +5 -1
  51. package/commands/gsd/graphify.md +10 -6
  52. package/commands/gsd/health.md +5 -0
  53. package/commands/gsd/help.md +7 -2
  54. package/commands/gsd/import.md +7 -3
  55. package/commands/gsd/inbox.md +5 -0
  56. package/commands/gsd/ingest-docs.md +5 -1
  57. package/commands/gsd/manager.md +6 -1
  58. package/commands/gsd/map-codebase.md +7 -3
  59. package/commands/gsd/mempalace-capture.md +12 -4
  60. package/commands/gsd/mempalace-recall.md +5 -1
  61. package/commands/gsd/milestone-summary.md +5 -1
  62. package/commands/gsd/mvp-phase.md +8 -3
  63. package/commands/gsd/new-milestone.md +6 -1
  64. package/commands/gsd/new-project.md +5 -0
  65. package/commands/gsd/next.md +6 -1
  66. package/commands/gsd/ns-context.md +4 -0
  67. package/commands/gsd/ns-ideate.md +4 -0
  68. package/commands/gsd/ns-manage.md +4 -0
  69. package/commands/gsd/ns-project.md +4 -0
  70. package/commands/gsd/ns-review.md +4 -0
  71. package/commands/gsd/ns-workflow.md +4 -0
  72. package/commands/gsd/onboard.md +6 -1
  73. package/commands/gsd/pause-work.md +5 -1
  74. package/commands/gsd/phase.md +8 -4
  75. package/commands/gsd/plan-phase.md +6 -1
  76. package/commands/gsd/plan-review-convergence.md +11 -7
  77. package/commands/gsd/pr-branch.md +4 -0
  78. package/commands/gsd/profile-user.md +5 -1
  79. package/commands/gsd/progress.md +7 -2
  80. package/commands/gsd/quick-batch.md +21 -9
  81. package/commands/gsd/quick.md +12 -7
  82. package/commands/gsd/review.md +7 -4
  83. package/commands/gsd/secure-phase.md +6 -1
  84. package/commands/gsd/ship.md +5 -0
  85. package/commands/gsd/sketch.md +7 -2
  86. package/commands/gsd/spec-phase.md +5 -1
  87. package/commands/gsd/spike.md +8 -3
  88. package/commands/gsd/surface.md +5 -1
  89. package/commands/gsd/thread.md +4 -0
  90. package/commands/gsd/ui-phase.md +6 -1
  91. package/commands/gsd/ui-review.md +6 -1
  92. package/commands/gsd/ultraplan-phase.md +5 -1
  93. package/commands/gsd/undo.md +5 -1
  94. package/commands/gsd/update.md +6 -2
  95. package/commands/gsd/validate-phase.md +6 -1
  96. package/commands/gsd/verify-work.md +6 -1
  97. package/commands/gsd/workspace.md +7 -3
  98. package/gsd-core/bin/gsd-tools.cjs +477 -78
  99. package/gsd-core/bin/lib/active-workstream-store.cjs +15 -0
  100. package/gsd-core/bin/lib/adr-parser.cjs +3 -1
  101. package/gsd-core/bin/lib/agent-install-check.cjs +4 -1
  102. package/gsd-core/bin/lib/audit.cjs +144 -42
  103. package/gsd-core/bin/lib/broken-windows.cjs +13 -13
  104. package/gsd-core/bin/lib/capability-activation.cjs +9 -4
  105. package/gsd-core/bin/lib/capability-registry.cjs +197 -222
  106. package/gsd-core/bin/lib/capability-validator.cjs +16 -1
  107. package/gsd-core/bin/lib/check-auto-mode.cjs +35 -0
  108. package/gsd-core/bin/lib/check-command-router.cjs +164 -1625
  109. package/gsd-core/bin/lib/cjs-command-router-adapter.cjs +13 -2
  110. package/gsd-core/bin/lib/cli-exit.cjs +12 -0
  111. package/gsd-core/bin/lib/codex-agent-toml.cjs +32 -33
  112. package/gsd-core/bin/lib/command-aliases.cjs +7 -0
  113. package/gsd-core/bin/lib/command-routing-hub.cjs +48 -1
  114. package/gsd-core/bin/lib/commands.cjs +343 -207
  115. package/gsd-core/bin/lib/complexity-trigger.cjs +8 -7
  116. package/gsd-core/bin/lib/config-loader.cjs +65 -4
  117. package/gsd-core/bin/lib/config.cjs +76 -19
  118. package/gsd-core/bin/lib/core-utils.cjs +6 -1
  119. package/gsd-core/bin/lib/coverage.cjs +4 -8
  120. package/gsd-core/bin/lib/decision-coverage-support.cjs +259 -0
  121. package/gsd-core/bin/lib/decisions.cjs +30 -14
  122. package/gsd-core/bin/lib/drift.cjs +177 -42
  123. package/gsd-core/bin/lib/frontmatter-fence.cjs +90 -0
  124. package/gsd-core/bin/lib/frontmatter-splice.cjs +494 -0
  125. package/gsd-core/bin/lib/frontmatter.cjs +426 -234
  126. package/gsd-core/bin/lib/gap-checker.cjs +72 -29
  127. package/gsd-core/bin/lib/gate-api-coverage-verify-pre.cjs +381 -0
  128. package/gsd-core/bin/lib/gate-args.cjs +53 -0
  129. package/gsd-core/bin/lib/gate-codebase-drift.cjs +285 -0
  130. package/gsd-core/bin/lib/gate-config.cjs +46 -0
  131. package/gsd-core/bin/lib/gate-context-drift.cjs +141 -0
  132. package/gsd-core/bin/lib/gate-decision-coverage-plan.cjs +169 -0
  133. package/gsd-core/bin/lib/gate-decision-coverage-verify.cjs +126 -0
  134. package/gsd-core/bin/lib/gate-evaluation-scope.cjs +555 -0
  135. package/gsd-core/bin/lib/gate-evidence.cjs +138 -0
  136. package/gsd-core/bin/lib/gate-exit.cjs +27 -0
  137. package/gsd-core/bin/lib/gate-gap-analysis-plan-post.cjs +61 -0
  138. package/gsd-core/bin/lib/gate-phase-context.cjs +170 -0
  139. package/gsd-core/bin/lib/gate-predicate-evaluator.cjs +1 -1
  140. package/gsd-core/bin/lib/gate-predicate.cjs +165 -0
  141. package/gsd-core/bin/lib/gate-prohibition-enforcement.cjs +94 -0
  142. package/gsd-core/bin/lib/gate-schema-drift.cjs +165 -0
  143. package/gsd-core/bin/lib/gate-tdd-red-evidence.cjs +100 -0
  144. package/gsd-core/bin/lib/gate-tdd-review-checkpoint.cjs +182 -0
  145. package/gsd-core/bin/lib/gate-ui-plan.cjs +86 -0
  146. package/gsd-core/bin/lib/gate-ui-safety.cjs +80 -0
  147. package/gsd-core/bin/lib/gate-verdict.cjs +64 -0
  148. package/gsd-core/bin/lib/gate-verify-command-paths.cjs +78 -0
  149. package/gsd-core/bin/lib/gate-verify-failure-directions.cjs +41 -0
  150. package/gsd-core/bin/lib/graphify.cjs +10 -2
  151. package/gsd-core/bin/lib/health-diagnostic-rules/phase-structure.cjs +43 -47
  152. package/gsd-core/bin/lib/health-diagnostic.cjs +45 -8
  153. package/gsd-core/bin/lib/host-runtime-detection.cjs +9 -0
  154. package/gsd-core/bin/lib/init.cjs +364 -132
  155. package/gsd-core/bin/lib/install-engine.cjs +30 -33
  156. package/gsd-core/bin/lib/install-profiles.cjs +7 -4
  157. package/gsd-core/bin/lib/installer-migrations.cjs +8 -1
  158. package/gsd-core/bin/lib/io.cjs +122 -3
  159. package/gsd-core/bin/lib/loop-resolver.cjs +95 -0
  160. package/gsd-core/bin/lib/markdown-sectionizer.cjs +75 -1
  161. package/gsd-core/bin/lib/milestone.cjs +37 -6
  162. package/gsd-core/bin/lib/model-resolver.cjs +171 -62
  163. package/gsd-core/bin/lib/observability/event.cjs +1 -1
  164. package/gsd-core/bin/lib/observability/logger.cjs +46 -1
  165. package/gsd-core/bin/lib/pattern.cjs +10 -0
  166. package/gsd-core/bin/lib/phase-command-router.cjs +20 -5
  167. package/gsd-core/bin/lib/phase-estimation.cjs +5 -4
  168. package/gsd-core/bin/lib/phase-id-card.cjs +32 -0
  169. package/gsd-core/bin/lib/phase-id-display.cjs +78 -0
  170. package/gsd-core/bin/lib/phase-id.cjs +110 -8
  171. package/gsd-core/bin/lib/phase-lifecycle.cjs +9 -2
  172. package/gsd-core/bin/lib/phase-locator.cjs +29 -10
  173. package/gsd-core/bin/lib/phase-status.cjs +360 -0
  174. package/gsd-core/bin/lib/phase.cjs +489 -88
  175. package/gsd-core/bin/lib/plan-document.cjs +142 -20
  176. package/gsd-core/bin/lib/plan-drift-guard.cjs +5 -0
  177. package/gsd-core/bin/lib/planning-document.cjs +692 -0
  178. package/gsd-core/bin/lib/planning-inspect.cjs +60 -9
  179. package/gsd-core/bin/lib/planning-snapshot.cjs +18 -0
  180. package/gsd-core/bin/lib/planning-workspace.cjs +83 -55
  181. package/gsd-core/bin/lib/pr-branch-patterns.cjs +57 -0
  182. package/gsd-core/bin/lib/pristine-baseline.cjs +10 -0
  183. package/gsd-core/bin/lib/probe-core.cjs +7 -1
  184. package/gsd-core/bin/lib/profile-output.cjs +6 -3
  185. package/gsd-core/bin/lib/prohibition-enforcement.cjs +0 -55
  186. package/gsd-core/bin/lib/project-root.cjs +41 -2
  187. package/gsd-core/bin/lib/quick-batch-command-router.cjs +35 -9
  188. package/gsd-core/bin/lib/quick-batch-dispatch.cjs +11 -8
  189. package/gsd-core/bin/lib/real-home-guard.cjs +9 -1
  190. package/gsd-core/bin/lib/report-parser.cjs +269 -0
  191. package/gsd-core/bin/lib/review-lane-descriptor.cjs +10 -30
  192. package/gsd-core/bin/lib/review-reviewer-selection.cjs +2 -2
  193. package/gsd-core/bin/lib/roadmap-command-router.cjs +25 -19
  194. package/gsd-core/bin/lib/roadmap-parser.cjs +242 -15
  195. package/gsd-core/bin/lib/roadmap-upgrade.cjs +1653 -65
  196. package/gsd-core/bin/lib/roadmap.cjs +405 -88
  197. package/gsd-core/bin/lib/runtime-artifact-conversion.cjs +373 -187
  198. package/gsd-core/bin/lib/runtime-artifact-install-plan.cjs +5 -2
  199. package/gsd-core/bin/lib/runtime-artifact-layout.cjs +57 -1
  200. package/gsd-core/bin/lib/runtime-homes.cjs +14 -7
  201. package/gsd-core/bin/lib/runtime-hooks-surface.cjs +522 -624
  202. package/gsd-core/bin/lib/runtime-name-policy.cjs +246 -21
  203. package/gsd-core/bin/lib/runtime-slash.cjs +47 -30
  204. package/gsd-core/bin/lib/shell-command-projection.cjs +47 -8
  205. package/gsd-core/bin/lib/smart-entry.cjs +19 -3
  206. package/gsd-core/bin/lib/stale-bake-guard.cjs +32 -48
  207. package/gsd-core/bin/lib/state-contract.cjs +15 -18
  208. package/gsd-core/bin/lib/state-document.cjs +100 -22
  209. package/gsd-core/bin/lib/state-transition.cjs +39 -2
  210. package/gsd-core/bin/lib/state.cjs +256 -105
  211. package/gsd-core/bin/lib/surface.cjs +19 -2
  212. package/gsd-core/bin/lib/tdd-red-evidence.cjs +48 -79
  213. package/gsd-core/bin/lib/uat-predicate.cjs +359 -38
  214. package/gsd-core/bin/lib/uat.cjs +432 -7
  215. package/gsd-core/bin/lib/ui-consideration-probe.cjs +15 -2
  216. package/gsd-core/bin/lib/ui-frontend-evidence.cjs +167 -40
  217. package/gsd-core/bin/lib/undo-commit-selection.cjs +131 -0
  218. package/gsd-core/bin/lib/vendor/README.md +31 -9
  219. package/gsd-core/bin/lib/vendor/saxes.cjs +1934 -0
  220. package/gsd-core/bin/lib/vendor/saxes.cjs.LICENSE.txt +92 -0
  221. package/gsd-core/bin/lib/vendor/tap-parser.cjs +8927 -0
  222. package/gsd-core/bin/lib/vendor/tap-parser.cjs.LICENSE.txt +152 -0
  223. package/gsd-core/bin/lib/verification-command-router.cjs +2 -1
  224. package/gsd-core/bin/lib/verification.cjs +1378 -274
  225. package/gsd-core/bin/lib/verify-command-grounding.cjs +46 -2
  226. package/gsd-core/bin/lib/verify-command-router.cjs +18 -7
  227. package/gsd-core/bin/lib/verify.cjs +357 -531
  228. package/gsd-core/bin/lib/workstream-inventory-builder.cjs +14 -6
  229. package/gsd-core/bin/lib/workstream-inventory.cjs +31 -21
  230. package/gsd-core/bin/lib/workstream-name-policy.cjs +31 -1
  231. package/gsd-core/bin/lib/workstream.cjs +11 -2
  232. package/gsd-core/bin/lib/worktree-base-ref.cjs +482 -73
  233. package/gsd-core/bin/lib/worktree-safety.cjs +784 -51
  234. package/gsd-core/bin/shared/config-defaults.manifest.json +8 -0
  235. package/gsd-core/bin/shared/config-schema.manifest.json +5 -0
  236. package/gsd-core/references/autonomous-smart-discuss.md +2 -1
  237. package/gsd-core/references/autonomous-ui-design-contract.md +3 -3
  238. package/gsd-core/references/checkpoints.md +5 -3
  239. package/gsd-core/references/edge-probe-fixtures/01-round-half-even/expected-coverage.json +28 -3
  240. package/gsd-core/references/edge-probe-fixtures/02-merge-intervals/expected-coverage.json +37 -4
  241. package/gsd-core/references/edge-probe-fixtures/03-truncate-graphemes/expected-coverage.json +28 -3
  242. package/gsd-core/references/edge-probe-fixtures/04-money-rounding/expected-coverage.json +28 -3
  243. package/gsd-core/references/edge-probe-fixtures/05-list-dedupe/expected-coverage.json +37 -4
  244. package/gsd-core/references/edge-probe-fixtures/06-resolved-mixed/expected-coverage.json +37 -4
  245. package/gsd-core/references/edge-probe.md +195 -21
  246. package/gsd-core/references/execute-mvp-tdd.md +5 -10
  247. package/gsd-core/references/execute-phase-between-wave-reset.md +10 -6
  248. package/gsd-core/references/execute-phase-response-language.md +1 -1
  249. package/gsd-core/references/execute-phase-wave-guard.md +22 -11
  250. package/gsd-core/references/gsd-run-resolver.md +1 -1
  251. package/gsd-core/references/loop-hook-dispatch.md +7 -1
  252. package/gsd-core/references/model-profiles.md +1 -1
  253. package/gsd-core/references/offer-next.md +1 -1
  254. package/gsd-core/references/phase-argument-parsing.md +9 -7
  255. package/gsd-core/references/phase-id-convention.md +28 -0
  256. package/gsd-core/references/planner-gap-closure.md +2 -0
  257. package/gsd-core/references/planner-load-graph-context.md +24 -13
  258. package/gsd-core/references/planner-verify-command-grounding.md +14 -0
  259. package/gsd-core/references/planning-config.md +12 -3
  260. package/gsd-core/references/spidr-splitting.md +1 -1
  261. package/gsd-core/references/tdd.md +37 -8
  262. package/gsd-core/references/ui-consideration-probe.md +10 -5
  263. package/gsd-core/references/verifier-phase-gates.md +5 -2
  264. package/gsd-core/references/verify-command-path-resolvability.md +10 -2
  265. package/gsd-core/references/verify-mvp-mode.md +2 -2
  266. package/gsd-core/references/workstream-flag.md +33 -3
  267. package/gsd-core/references/worktree-path-safety.md +321 -0
  268. package/gsd-core/templates/README.md +1 -1
  269. package/gsd-core/templates/UAT.md +17 -1
  270. package/gsd-core/templates/config.json +2 -11
  271. package/gsd-core/templates/verification-report.md +1 -1
  272. package/gsd-core/workflows/_runtime-launcher.snippet.sh +1 -1
  273. package/gsd-core/workflows/add-backlog.md +1 -1
  274. package/gsd-core/workflows/add-phase.md +8 -7
  275. package/gsd-core/workflows/add-tests.md +4 -3
  276. package/gsd-core/workflows/add-todo.md +6 -5
  277. package/gsd-core/workflows/ai-integration-phase.md +13 -4
  278. package/gsd-core/workflows/audit-fix.md +1 -1
  279. package/gsd-core/workflows/audit-milestone.md +4 -3
  280. package/gsd-core/workflows/audit-uat.md +1 -1
  281. package/gsd-core/workflows/autonomous/steps/converge-fail-fast.md +9 -18
  282. package/gsd-core/workflows/autonomous.md +43 -23
  283. package/gsd-core/workflows/check-todos.md +7 -6
  284. package/gsd-core/workflows/cleanup.md +2 -2
  285. package/gsd-core/workflows/code-review/steps/dispatch-fix.md +4 -3
  286. package/gsd-core/workflows/code-review/steps/structural-pre-pass.md +20 -13
  287. package/gsd-core/workflows/code-review-fix.md +112 -25
  288. package/gsd-core/workflows/code-review.md +146 -135
  289. package/gsd-core/workflows/complete-milestone/detail/elaboration.md +4 -3
  290. package/gsd-core/workflows/complete-milestone.md +13 -8
  291. package/gsd-core/workflows/debug.md +32 -7
  292. package/gsd-core/workflows/diagnose-issues.md +3 -2
  293. package/gsd-core/workflows/discuss-phase/modes/advisor.md +1 -1
  294. package/gsd-core/workflows/discuss-phase/modes/chain.md +1 -1
  295. package/gsd-core/workflows/discuss-phase-assumptions.md +4 -3
  296. package/gsd-core/workflows/discuss-phase.md +4 -3
  297. package/gsd-core/workflows/do.md +2 -2
  298. package/gsd-core/workflows/docs-update.md +6 -5
  299. package/gsd-core/workflows/edit-phase.md +4 -3
  300. package/gsd-core/workflows/eval-review.md +14 -5
  301. package/gsd-core/workflows/execute-phase/detail/elaboration.md +2 -2
  302. package/gsd-core/workflows/execute-phase/steps/code-review-disposition.md +1019 -0
  303. package/gsd-core/workflows/execute-phase/steps/codebase-drift-gate.md +15 -4
  304. package/gsd-core/workflows/execute-phase/steps/completion-reconciliation.md +10 -7
  305. package/gsd-core/workflows/execute-phase/steps/executor-isolation-dispatch.md +37 -3
  306. package/gsd-core/workflows/execute-phase/steps/gap-closure-artifacts.md +3 -1
  307. package/gsd-core/workflows/execute-phase/steps/partial-wave.md +2 -2
  308. package/gsd-core/workflows/execute-phase/steps/per-plan-executor-routing.md +1 -1
  309. package/gsd-core/workflows/execute-phase/steps/per-plan-worktree-gate.md +1 -1
  310. package/gsd-core/workflows/execute-phase/steps/post-merge-gate.md +46 -9
  311. package/gsd-core/workflows/execute-phase/steps/protected-branch.md +1 -1
  312. package/gsd-core/workflows/execute-phase/steps/ready-wave-gate.md +37 -0
  313. package/gsd-core/workflows/execute-phase/steps/regression-gate-run.md +1 -1
  314. package/gsd-core/workflows/execute-phase/steps/regression-gate.md +2 -0
  315. package/gsd-core/workflows/execute-phase/steps/tdd-applicability-resolution.md +1 -1
  316. package/gsd-core/workflows/execute-phase/steps/threat-id-gate.md +28 -0
  317. package/gsd-core/workflows/execute-phase/steps/verify-phase-goal.md +187 -0
  318. package/gsd-core/workflows/execute-phase/steps/wave-post-gate-hooks.md +2 -3
  319. package/gsd-core/workflows/execute-phase/steps/worktree-base-check.md +25 -0
  320. package/gsd-core/workflows/execute-phase.md +96 -178
  321. package/gsd-core/workflows/execute-plan.md +18 -23
  322. package/gsd-core/workflows/explore.md +4 -4
  323. package/gsd-core/workflows/extract-learnings.md +4 -2
  324. package/gsd-core/workflows/fast.md +1 -1
  325. package/gsd-core/workflows/forensics.md +1 -1
  326. package/gsd-core/workflows/graduation.md +1 -1
  327. package/gsd-core/workflows/health.md +3 -2
  328. package/gsd-core/workflows/help/modes/full.compact.md +3 -3
  329. package/gsd-core/workflows/help/modes/full.md +5 -5
  330. package/gsd-core/workflows/help/modes/topic.md +15 -5
  331. package/gsd-core/workflows/import.md +4 -3
  332. package/gsd-core/workflows/inbox.md +2 -2
  333. package/gsd-core/workflows/ingest-docs.md +3 -3
  334. package/gsd-core/workflows/insert-phase.md +4 -3
  335. package/gsd-core/workflows/list-seeds.md +1 -1
  336. package/gsd-core/workflows/list-workspaces.md +1 -1
  337. package/gsd-core/workflows/manager.md +6 -4
  338. package/gsd-core/workflows/map-codebase.md +5 -4
  339. package/gsd-core/workflows/milestone-summary.md +3 -2
  340. package/gsd-core/workflows/mvp-phase.md +14 -14
  341. package/gsd-core/workflows/new-milestone.md +11 -11
  342. package/gsd-core/workflows/new-project/steps/auto-mode-config.md +3 -3
  343. package/gsd-core/workflows/new-project/steps/codebase-map-offer.md +1 -1
  344. package/gsd-core/workflows/new-project.md +7 -7
  345. package/gsd-core/workflows/new-workspace.md +2 -2
  346. package/gsd-core/workflows/next.md +1 -1
  347. package/gsd-core/workflows/note.md +1 -1
  348. package/gsd-core/workflows/onboard.md +1 -1
  349. package/gsd-core/workflows/pause-work.md +2 -2
  350. package/gsd-core/workflows/plan-phase/detail/elaboration.md +1 -1
  351. package/gsd-core/workflows/plan-phase/steps/chunked-planning-mode.md +17 -5
  352. package/gsd-core/workflows/plan-phase/steps/closed-phase-gate.md +1 -1
  353. package/gsd-core/workflows/plan-phase/steps/prd-express-path.md +1 -1
  354. package/gsd-core/workflows/plan-phase/steps/stall-detection-helpers.md +23 -5
  355. package/gsd-core/workflows/plan-phase.md +50 -24
  356. package/gsd-core/workflows/plan-review-convergence.md +21 -5
  357. package/gsd-core/workflows/plant-seed.md +62 -20
  358. package/gsd-core/workflows/pr-branch.md +113 -13
  359. package/gsd-core/workflows/profile-user.md +2 -2
  360. package/gsd-core/workflows/progress.md +19 -49
  361. package/gsd-core/workflows/quick/steps/plan-checker-loop.md +27 -0
  362. package/gsd-core/workflows/quick/steps/quick-verification.md +4 -4
  363. package/gsd-core/workflows/quick/steps/worktree-pre-dispatch-commit.md +30 -11
  364. package/gsd-core/workflows/quick-batch/steps/batch-init.md +1 -1
  365. package/gsd-core/workflows/quick-batch/steps/completion.md +1 -1
  366. package/gsd-core/workflows/quick-batch/steps/merge-wave.md +1 -1
  367. package/gsd-core/workflows/quick-batch/steps/planner-wave.md +1 -1
  368. package/gsd-core/workflows/quick-batch/steps/research-phase.md +1 -1
  369. package/gsd-core/workflows/quick-batch/steps/resume-mode.md +1 -1
  370. package/gsd-core/workflows/quick-batch/steps/verification-wave.md +9 -3
  371. package/gsd-core/workflows/quick-batch/steps/worktree-dispatch.md +1 -1
  372. package/gsd-core/workflows/quick-batch.md +15 -10
  373. package/gsd-core/workflows/quick.md +62 -39
  374. package/gsd-core/workflows/reapply-patches.md +9 -3
  375. package/gsd-core/workflows/remove-phase.md +3 -2
  376. package/gsd-core/workflows/remove-workspace.md +2 -2
  377. package/gsd-core/workflows/resume-project.md +3 -2
  378. package/gsd-core/workflows/review.md +33 -17
  379. package/gsd-core/workflows/scan.md +3 -2
  380. package/gsd-core/workflows/secure-phase.md +13 -13
  381. package/gsd-core/workflows/settings-advanced.md +30 -10
  382. package/gsd-core/workflows/settings-integrations.md +2 -3
  383. package/gsd-core/workflows/settings.md +4 -4
  384. package/gsd-core/workflows/ship.md +14 -13
  385. package/gsd-core/workflows/sketch-wrap-up.md +1 -1
  386. package/gsd-core/workflows/sketch.md +1 -1
  387. package/gsd-core/workflows/smart-entry.md +2 -2
  388. package/gsd-core/workflows/spec-phase.md +15 -5
  389. package/gsd-core/workflows/spike-wrap-up.md +1 -1
  390. package/gsd-core/workflows/spike.md +1 -1
  391. package/gsd-core/workflows/stats.md +1 -1
  392. package/gsd-core/workflows/sync-skills.md +5 -5
  393. package/gsd-core/workflows/thread.md +2 -2
  394. package/gsd-core/workflows/transition.md +13 -23
  395. package/gsd-core/workflows/ui-phase.md +48 -11
  396. package/gsd-core/workflows/ui-review.md +21 -6
  397. package/gsd-core/workflows/ultraplan-phase.md +3 -2
  398. package/gsd-core/workflows/undo.md +339 -20
  399. package/gsd-core/workflows/update.md +7 -7
  400. package/gsd-core/workflows/validate-phase.md +12 -13
  401. package/gsd-core/workflows/verify-work/detail/elaboration.md +43 -3
  402. package/gsd-core/workflows/verify-work/steps/automated-ui-verification.md +1 -1
  403. package/gsd-core/workflows/verify-work/steps/mvp-uat-framing.md +5 -3
  404. package/gsd-core/workflows/verify-work.md +129 -55
  405. package/hooks/dist/gsd-agent-isolation-guard.js +32 -0
  406. package/hooks/dist/gsd-check-update-worker.js +8 -0
  407. package/hooks/dist/gsd-check-update.js +8 -0
  408. package/hooks/dist/gsd-context-monitor.js +31 -8
  409. package/hooks/dist/gsd-cursor-subagent-start.js +8 -0
  410. package/hooks/dist/gsd-secret-read-guard.js +161 -4
  411. package/hooks/dist/gsd-statusline.js +85 -20
  412. package/hooks/dist/gsd-update-banner.js +8 -0
  413. package/hooks/dist/gsd-validate-commit.sh +63 -4
  414. package/hooks/dist/gsd-windsurf-pre-write.js +11 -2
  415. package/hooks/dist/gsd-workflow-guard.js +5 -4
  416. package/hooks/dist/gsd-worktree-path-guard.js +6 -2
  417. package/hooks/dist/lib/cli-exit.js +12 -0
  418. package/hooks/dist/lib/git-probe.js +17 -1
  419. package/hooks/dist/lib/isolation-sentinel.js +2 -2
  420. package/hooks/gsd-agent-isolation-guard.js +32 -0
  421. package/hooks/gsd-check-update-worker.js +8 -0
  422. package/hooks/gsd-check-update.js +8 -0
  423. package/hooks/gsd-context-monitor.js +31 -8
  424. package/hooks/gsd-cursor-subagent-start.js +8 -0
  425. package/hooks/gsd-secret-read-guard.js +161 -4
  426. package/hooks/gsd-statusline.js +85 -20
  427. package/hooks/gsd-update-banner.js +8 -0
  428. package/hooks/gsd-validate-commit.sh +63 -4
  429. package/hooks/gsd-windsurf-pre-write.js +11 -2
  430. package/hooks/gsd-workflow-guard.js +5 -4
  431. package/hooks/gsd-worktree-path-guard.js +6 -2
  432. package/hooks/hooks.json +5 -5
  433. package/hooks/lib/cli-exit.js +12 -0
  434. package/hooks/lib/git-probe.js +17 -1
  435. package/hooks/lib/isolation-sentinel.js +2 -2
  436. package/package.json +22 -4
  437. package/scripts/build-hooks.js +15 -6
  438. package/scripts/changeset/parse.cjs +52 -4
  439. package/scripts/check-contract-drift.cjs +127 -11
  440. package/scripts/ci-timeout-report.cjs +770 -4
  441. package/scripts/command-contract-helpers.cjs +15 -8
  442. package/scripts/docs-guard-registry.cjs +34 -0
  443. package/scripts/gen-features.cjs +13 -8
  444. package/scripts/gen-hooks-cli-exit.cjs +12 -28
  445. package/scripts/gen-loop-host-contract.cjs +79 -1
  446. package/scripts/gen-platform-conformance-tier.cjs +187 -1
  447. package/scripts/gen-plugin-skills.cjs +87 -1
  448. package/scripts/gen-research-agents.cjs +24 -31
  449. package/scripts/gen-scripts-cli-exit.cjs +30 -3
  450. package/scripts/gen-test-timings.cjs +32 -7
  451. package/scripts/lib/cli-exit.cjs +12 -0
  452. package/scripts/lib/macos-conformance-tier.generated.cjs +34 -2
  453. package/scripts/lib/ndjson-reporter.cjs +31 -5
  454. package/scripts/lib/platform-conformance-tier.generated.cjs +45 -5
  455. package/scripts/lib/registration-ledger-preload.cjs +155 -0
  456. package/scripts/lib/vendor-bundle.cjs +59 -0
  457. package/scripts/lib/vendor-licenses/saxes-6.0.0.txt +64 -0
  458. package/scripts/lint-allow-test-rule-refs.effective-ceiling.json +1 -1
  459. package/scripts/lint-allow-test-rule-refs.unverified-ceiling.json +1 -1
  460. package/scripts/lint-completion-predicate-drift.cjs +18 -19
  461. package/scripts/lint-descriptions.cjs +7 -3
  462. package/scripts/lint-docs-guard-registration.exempt-baseline.cjs +38 -1
  463. package/scripts/lint-eslint-glob-coverage.allowlist.json +20 -0
  464. package/scripts/lint-frontmatter-fence-drift.cjs +313 -0
  465. package/scripts/lint-frontmatter-scalar-broad-grep.cjs +122 -16
  466. package/scripts/lint-phase-arg-assignment.cjs +257 -0
  467. package/scripts/lint-phase-enumeration-drift.cjs +12 -8
  468. package/scripts/lint-phase-id-drift.cjs +319 -5
  469. package/scripts/lint-planning-document-positive-control.cjs +329 -0
  470. package/scripts/lint-pr-branch-pattern-drift.cjs +148 -0
  471. package/scripts/lint-response-language-coverage.cjs +3 -0
  472. package/scripts/lint-retired-runtime-name.cjs +619 -0
  473. package/scripts/lint-skill-deps.cjs +7 -3
  474. package/scripts/lint-state-write-path-drift.cjs +93 -0
  475. package/scripts/lint-test-file-count.allowlist.json +38 -9
  476. package/scripts/lint-test-file-count.cjs +34 -1
  477. package/scripts/lint-vendored-deps.cjs +41 -5
  478. package/scripts/lint-workflow-shellcheck-baseline.json +25 -10
  479. package/scripts/mutation-matrix.cjs +50 -5
  480. package/scripts/prompt-injection-scan.sh +4 -0
  481. package/scripts/release-tarball-smoke.cjs +194 -1
  482. package/scripts/require-issue-link-policy.cjs +6 -2
  483. package/scripts/sync-runtime-launcher.cjs +184 -2
  484. package/scripts/verify-npm-publish.cjs +76 -20
  485. package/skills/gsd-add-tests/SKILL.md +6 -1
  486. package/skills/gsd-ai-integration-phase/SKILL.md +6 -1
  487. package/skills/gsd-audit-fix/SKILL.md +5 -0
  488. package/skills/gsd-audit-milestone/SKILL.md +6 -1
  489. package/skills/gsd-autonomous/SKILL.md +7 -2
  490. package/skills/gsd-capture/SKILL.md +9 -5
  491. package/skills/gsd-code-review/SKILL.md +7 -2
  492. package/skills/gsd-complete-milestone/SKILL.md +4 -0
  493. package/skills/gsd-config/SKILL.md +8 -4
  494. package/skills/gsd-debug/SKILL.md +11 -7
  495. package/skills/gsd-discuss-phase/SKILL.md +7 -3
  496. package/skills/gsd-docs-update/SKILL.md +12 -7
  497. package/skills/gsd-eval-review/SKILL.md +6 -1
  498. package/skills/gsd-execute-phase/SKILL.md +12 -7
  499. package/skills/gsd-extract-learnings/SKILL.md +5 -0
  500. package/skills/gsd-fast/SKILL.md +4 -0
  501. package/skills/gsd-forensics/SKILL.md +5 -1
  502. package/skills/gsd-graphify/SKILL.md +10 -6
  503. package/skills/gsd-health/SKILL.md +5 -0
  504. package/skills/gsd-help/SKILL.md +7 -2
  505. package/skills/gsd-import/SKILL.md +7 -3
  506. package/skills/gsd-inbox/SKILL.md +5 -0
  507. package/skills/gsd-ingest-docs/SKILL.md +5 -1
  508. package/skills/gsd-manager/SKILL.md +6 -1
  509. package/skills/gsd-map-codebase/SKILL.md +7 -3
  510. package/skills/gsd-mempalace-capture/SKILL.md +12 -4
  511. package/skills/gsd-mempalace-recall/SKILL.md +5 -1
  512. package/skills/gsd-milestone-summary/SKILL.md +5 -1
  513. package/skills/gsd-mvp-phase/SKILL.md +8 -3
  514. package/skills/gsd-new-milestone/SKILL.md +6 -1
  515. package/skills/gsd-new-project/SKILL.md +5 -0
  516. package/skills/gsd-next/SKILL.md +6 -1
  517. package/skills/gsd-ns-context/SKILL.md +4 -0
  518. package/skills/gsd-ns-ideate/SKILL.md +4 -0
  519. package/skills/gsd-ns-manage/SKILL.md +4 -0
  520. package/skills/gsd-ns-project/SKILL.md +4 -0
  521. package/skills/gsd-ns-review/SKILL.md +4 -0
  522. package/skills/gsd-ns-workflow/SKILL.md +4 -0
  523. package/skills/gsd-onboard/SKILL.md +6 -1
  524. package/skills/gsd-pause-work/SKILL.md +5 -1
  525. package/skills/gsd-phase/SKILL.md +8 -4
  526. package/skills/gsd-plan-phase/SKILL.md +6 -1
  527. package/skills/gsd-plan-review-convergence/SKILL.md +10 -6
  528. package/skills/gsd-pr-branch/SKILL.md +4 -0
  529. package/skills/gsd-profile-user/SKILL.md +5 -1
  530. package/skills/gsd-progress/SKILL.md +7 -2
  531. package/skills/gsd-quick/SKILL.md +16 -10
  532. package/skills/gsd-quick-batch/SKILL.md +21 -9
  533. package/skills/gsd-review/SKILL.md +7 -4
  534. package/skills/gsd-review-backlog/SKILL.md +3 -2
  535. package/skills/gsd-secure-phase/SKILL.md +6 -1
  536. package/skills/gsd-ship/SKILL.md +5 -0
  537. package/skills/gsd-sketch/SKILL.md +7 -2
  538. package/skills/gsd-spec-phase/SKILL.md +5 -1
  539. package/skills/gsd-spike/SKILL.md +8 -3
  540. package/skills/gsd-surface/SKILL.md +5 -1
  541. package/skills/gsd-thread/SKILL.md +4 -0
  542. package/skills/gsd-ui-phase/SKILL.md +6 -1
  543. package/skills/gsd-ui-review/SKILL.md +6 -1
  544. package/skills/gsd-ultraplan-phase/SKILL.md +5 -1
  545. package/skills/gsd-undo/SKILL.md +5 -1
  546. package/skills/gsd-update/SKILL.md +6 -2
  547. package/skills/gsd-validate-phase/SKILL.md +6 -1
  548. package/skills/gsd-verify-work/SKILL.md +6 -1
  549. package/skills/gsd-workspace/SKILL.md +7 -3
  550. package/skills/gsd-workstreams/SKILL.md +6 -6
  551. package/vscode/package.json +1 -1
@@ -0,0 +1,165 @@
1
+ "use strict";
2
+ /**
3
+ * `check verify-schema-drift` as a gate module (#5219, epic #5056, ADR-5057 §4 closing arm C): it
4
+ * returns a `GateResult`; the command router formats it. Imports no io module and performs no direct
5
+ * console/stdout/stderr write (ESLint-enforced).
6
+ *
7
+ * The `drift` capability's blocking gate at `execute:wave:post`. It reports schema-relevant files the
8
+ * phase's plans declare in `files_modified` for which no database push is evidenced in the phase's
9
+ * summaries or its own commit subjects (`checkSchemaDrift`, `schema-detect.cjs`).
10
+ *
11
+ * Dispatched gate, payload exit mode: the verdict is read from stdout (`.block`) and a non-zero exit
12
+ * is "the check command failed" (gsd-core/workflows/execute-phase/steps/wave-post-gate-hooks.md step
13
+ * 1; gsd-core/references/loop-hook-dispatch.md "a gate verb never exits non-zero to say blocked";
14
+ * capabilities/drift declares schema-drift `blocking: true, onError: skip`). A blocking verdict is
15
+ * therefore exit 0 and "could not look" is exit 69 (#5170); the router declares both.
16
+ *
17
+ * Non-blocking contract: a throw anywhere yields a non-blocking `unreadable` verdict, never a crash.
18
+ *
19
+ * Argv after the verb: `<phase>`. The bypass (`GSD_SKIP_SCHEMA_CHECK=true`) arrives as `env`, read by
20
+ * the router from the process environment; the gate reads no ambient state for it.
21
+ */
22
+ var __importDefault = (this && this.__importDefault) || function (mod) {
23
+ return (mod && mod.__esModule) ? mod : { "default": mod };
24
+ };
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ exports.evaluateSchemaDriftGate = evaluateSchemaDriftGate;
27
+ const node_path_1 = __importDefault(require("node:path"));
28
+ const gate_verdict_cjs_1 = require("./gate-verdict.cjs");
29
+ const gate_evidence_cjs_1 = require("./gate-evidence.cjs");
30
+ const gate_evaluation_scope_cjs_1 = require("./gate-evaluation-scope.cjs");
31
+ const schema_detect_cjs_1 = require("./schema-detect.cjs");
32
+ const gate_phase_context_cjs_1 = require("./gate-phase-context.cjs");
33
+ // eslint-disable-next-line @typescript-eslint/no-require-imports -- planning-workspace.cjs is an export= CommonJS module
34
+ const planningWorkspace = require("./planning-workspace.cjs");
35
+ // eslint-disable-next-line @typescript-eslint/no-require-imports -- plan-document.cjs is an export= CommonJS module
36
+ const planDocumentMod = require("./plan-document.cjs");
37
+ const { planningDir } = planningWorkspace;
38
+ const { parsePlanDocument } = planDocumentMod;
39
+ /**
40
+ * The schema-drift verdict for "drift was not evaluated" (#5170): non-blocking payload (the
41
+ * gate's non-blocking contract), outcome `unreadable` so the exit status says "could not look".
42
+ */
43
+ function schemaDriftUnreadable(message, detail) {
44
+ return (0, gate_verdict_cjs_1.gateUnreadable)(false, {
45
+ block: false,
46
+ drift_detected: false,
47
+ blocking: false,
48
+ ...(detail === undefined ? {} : { unreadable: true, unreadable_file: detail.file, read_error: detail.reason }),
49
+ message,
50
+ });
51
+ }
52
+ function runSchemaDriftGate(cwd, phaseArg, skipFlag) {
53
+ const pDir = planningDir(cwd);
54
+ const phasesDir = node_path_1.default.join(pDir, 'phases');
55
+ // An ABSENT phases directory is the documented "nothing to check" (`none`); one that cannot be
56
+ // examined (an EACCES on a parent — `fs.existsSync` said `false` for it) is `unreadable`.
57
+ const phasesRoot = (0, gate_evidence_cjs_1.statEvidence)(phasesDir);
58
+ if (phasesRoot.kind === 'unreadable') {
59
+ return schemaDriftUnreadable(`schema-drift could not examine ${phasesDir} (${phasesRoot.reason}); drift was not evaluated`, { file: phasesDir, reason: phasesRoot.reason });
60
+ }
61
+ if (phasesRoot.kind === 'none') {
62
+ return (0, gate_verdict_cjs_1.gateVerdict)('skip', false, { block: false, drift_detected: false, blocking: false, message: 'No phases directory' });
63
+ }
64
+ // Resolve the phase directory with the canonical phase-directory matcher
65
+ // (phase-id.cjs::matchPhaseDirs), not a naive substring test. A bare
66
+ // `.includes(phaseArg)` lets a non-existent phase silently match a different
67
+ // phase whose directory name merely contains the requested token (e.g. "1"
68
+ // matching "11-expansion"), making the drift gate inspect the wrong phase.
69
+ // This shares the one selection rule with find-phase / verify
70
+ // phase-completeness rather than restating it. (#1571, #2528)
71
+ const phaseDir = (0, gate_phase_context_cjs_1.resolvePhaseDirByToken)(phasesDir, phaseArg);
72
+ if (!phaseDir) {
73
+ // An unresolvable phase is "could not look" (#5170): there is no phase directory to evaluate.
74
+ return schemaDriftUnreadable(`Phase directory not found: ${phaseArg}`);
75
+ }
76
+ // #3183: canonical LIVE plan/summary sets (root+nested,
77
+ // status: superseded EXCLUDED) from the single owner, rather than a
78
+ // root-only readdirSync filter — a superseded plan's claimed
79
+ // files_modified is no longer treated as an expected drift target, and
80
+ // nested (#3139 layout) plans/summaries are no longer invisible to the
81
+ // drift check.
82
+ // A scan that did not see every plan (an existing nested plans/ that could not be read) is
83
+ // `unreadable`, never a short plan set: the files_modified of the plans it missed are drift targets.
84
+ const planScan = (0, gate_evidence_cjs_1.readPlanScanEvidence)(phaseDir);
85
+ if (planScan.kind === 'unreadable' && !skipFlag) {
86
+ return schemaDriftUnreadable(`schema-drift could not scan the plans of ${phaseDir} (${planScan.reason}); drift was not evaluated`, { file: phaseDir, reason: planScan.reason });
87
+ }
88
+ const { planFiles, summaryFiles } = planScan.kind === 'found' ? planScan.value : { planFiles: [], summaryFiles: [] };
89
+ // #5170 (ADR-5057 §4): every read here is typed evidence. A file that cannot be read is
90
+ // `unreadable` and is reported as such — it is never "no files, so no drift". A file that
91
+ // vanished since the scan (`none`) contributes nothing.
92
+ let unreadableRead = null;
93
+ const allFiles = [];
94
+ for (const pf of planFiles) {
95
+ const read = (0, gate_evidence_cjs_1.readTextEvidence)(node_path_1.default.join(phaseDir, pf));
96
+ if (read.kind === 'unreadable') {
97
+ unreadableRead = unreadableRead ?? { file: pf, reason: read.reason };
98
+ continue;
99
+ }
100
+ if (read.kind === 'none')
101
+ continue;
102
+ // `files_modified` through the Frontmatter Module (the read phase-plan-index uses via
103
+ // RawPlan.filesModified): block sequences, inline arrays and CRLF all yield their files.
104
+ for (const file of parsePlanDocument(read.value).filesModified) {
105
+ const trimmed = file.trim();
106
+ if (trimmed)
107
+ allFiles.push(trimmed);
108
+ }
109
+ }
110
+ let executionLog = '';
111
+ for (const sf of summaryFiles) {
112
+ const read = (0, gate_evidence_cjs_1.readTextEvidence)(node_path_1.default.join(phaseDir, sf));
113
+ if (read.kind === 'unreadable') {
114
+ unreadableRead = unreadableRead ?? { file: sf, reason: read.reason };
115
+ continue;
116
+ }
117
+ if (read.kind === 'found')
118
+ executionLog += read.value + '\n';
119
+ }
120
+ // `--skip` (GSD_SKIP_SCHEMA_CHECK) bypasses the gate, so what could not be read is moot then.
121
+ if (unreadableRead !== null && !skipFlag) {
122
+ return schemaDriftUnreadable(`schema-drift could not read ${unreadableRead.file} (${unreadableRead.reason}); drift was not evaluated`, { file: unreadableRead.file, reason: unreadableRead.reason });
123
+ }
124
+ // #5164: the phase's own commits from the evaluation-scope resolver (ADR-5057 §4) — the former
125
+ // `git log --all -50` let a commit on ANY branch, from ANY phase, put a schema push in the log.
126
+ const phaseScope = (0, gate_evaluation_scope_cjs_1.resolveEvaluationScope)(cwd, { kind: 'phase', phase: phaseArg, phaseDir }, { includeFiles: false });
127
+ if (phaseScope.commits.length > 0) {
128
+ // Subjects only, as the `git log --oneline` it replaces: a quoted push command in a commit BODY must not change the verdict.
129
+ executionLog += '\n' + phaseScope.commits.map((c) => `${c.sha.slice(0, 7)} ${c.subject}`).join('\n');
130
+ }
131
+ const result = (0, schema_detect_cjs_1.checkSchemaDrift)(allFiles, executionLog, { skipCheck: skipFlag });
132
+ const isSkipped = !!result['skipped'];
133
+ // Uniform gate contract: `block` = true means "this gate's bad condition is met".
134
+ // When skipCheck is true (GSD_SKIP_SCHEMA_CHECK=true), the gate is bypassed —
135
+ // block must be false regardless of whether drift was detected.
136
+ // drift_detected and blocking are kept for compatibility.
137
+ const block = isSkipped ? false : !!result['driftDetected'];
138
+ return (0, gate_verdict_cjs_1.gateVerdict)(isSkipped ? 'skip' : (block ? 'block' : 'pass'), block, {
139
+ block,
140
+ drift_detected: result['driftDetected'],
141
+ blocking: result['blocking'],
142
+ schema_files: result['schemaFiles'],
143
+ orms: result['orms'],
144
+ unpushed_orms: result['unpushedOrms'],
145
+ message: result['message'],
146
+ skipped: isSkipped,
147
+ });
148
+ }
149
+ function evaluateSchemaDriftGate(input) {
150
+ const phaseArg = input.args[0] || '';
151
+ if (!phaseArg) {
152
+ // UNKNOWN: the pre-move `error('Usage…')` named no reason, and the reason is observable (#5219).
153
+ return (0, gate_verdict_cjs_1.gateUsageFailure)(gate_verdict_cjs_1.GATE_FAILURE_CODE.UNKNOWN, 'Usage: verify schema-drift <phase> [--skip]');
154
+ }
155
+ const skipFlag = input.env?.['GSD_SKIP_SCHEMA_CHECK'] === 'true';
156
+ // Non-blocking contract: a throw anywhere yields a non-blocking payload, never a crash.
157
+ try {
158
+ return runSchemaDriftGate(input.projectDir, phaseArg, skipFlag);
159
+ }
160
+ catch (err) {
161
+ // #5170: a gate that threw did not evaluate drift. The payload stays non-blocking (the contract
162
+ // above), but the exit status says "could not look" (UNAVAILABLE) instead of a clean exit 0.
163
+ return schemaDriftUnreadable('exception: ' + (err instanceof Error ? err.message : String(err)));
164
+ }
165
+ }
@@ -0,0 +1,100 @@
1
+ "use strict";
2
+ /**
3
+ * `check tdd-red-evidence` as a gate module (#5139, epic #5056, ADR-5057 §4 first bullet, #3770):
4
+ * it returns a `GateResult`; the command router formats it. Imports no io module and performs no
5
+ * direct console/stdout/stderr write (ESLint-enforced).
6
+ *
7
+ * Validates a persisted RED-phase test-run record for a `type: tdd` plan. Only an INTENTIONAL
8
+ * failure of the target test (verdict RED_EVIDENCE_OK) may authorize GREEN; zero-test discovery,
9
+ * fixture/load crashes, nonzero exits without a failing test, unrelated failures, and unexpected
10
+ * greens are INVALID_RED and block GREEN. The record is the JSON the executor persists after
11
+ * running the RED command: `{ command, exitCode, output, targetTest, targetFile?, expected?,
12
+ * actual? }`. Fail-closed: a missing/unreadable/unparseable record is INVALID_RED (reason
13
+ * `unreadable_record`), never a pass.
14
+ *
15
+ * Argv after the verb: `<record.json>`. The record path resolves against the PROCESS cwd
16
+ * (`path.resolve`), as before the move, and must then stay INSIDE the project directory (realpath
17
+ * containment, ADR-4650) BEFORE anything is read: a record path that escapes it is the usage
18
+ * failure `path escapes its allowed directory: <arg>`, so the gate cannot be made to read — and
19
+ * echo the fields of — an arbitrary readable file (#5139 security review). The path echoed in the
20
+ * payload stays the resolved (not realpath'd) form, unchanged.
21
+ *
22
+ * Consequence of resolving against the process cwd: the CLI runs with cwd === projectDir in every
23
+ * workflow, so a project-relative path (`r.json`) works. Invoked with cwd !== projectDir, that same
24
+ * relative path resolves outside the project and is the usage failure above (it was an
25
+ * `unreadable_record` verdict before containment); an absolute path inside the project works from
26
+ * any cwd.
27
+ */
28
+ var __importDefault = (this && this.__importDefault) || function (mod) {
29
+ return (mod && mod.__esModule) ? mod : { "default": mod };
30
+ };
31
+ Object.defineProperty(exports, "__esModule", { value: true });
32
+ exports.evaluateTddRedEvidence = evaluateTddRedEvidence;
33
+ const node_path_1 = __importDefault(require("node:path"));
34
+ const security_cjs_1 = require("./security.cjs");
35
+ const gate_verdict_cjs_1 = require("./gate-verdict.cjs");
36
+ const gate_evidence_cjs_1 = require("./gate-evidence.cjs");
37
+ const tdd_red_evidence_cjs_1 = require("./tdd-red-evidence.cjs");
38
+ /** Parse the persisted record. A parse failure is typed evidence (never a swallowed `null`). */
39
+ function parseRecordEvidence(text, span) {
40
+ try {
41
+ return (0, gate_evidence_cjs_1.evidenceFound)((JSON.parse(text) ?? {}));
42
+ }
43
+ catch (err) {
44
+ return (0, gate_evidence_cjs_1.evidenceFromError)(err, span);
45
+ }
46
+ }
47
+ function evaluateTddRedEvidence(input) {
48
+ const recordPath = typeof input.args[0] === 'string' ? input.args[0] : '';
49
+ if (!recordPath) {
50
+ return (0, gate_verdict_cjs_1.gateUsageFailure)(gate_verdict_cjs_1.GATE_FAILURE_CODE.SDK_MISSING_ARG, 'tdd-red-evidence requires a record path: check tdd-red-evidence <record.json>');
51
+ }
52
+ const resolved = node_path_1.default.resolve(recordPath);
53
+ // Containment BEFORE the read (the read follows symlinks, so it is decided on the resolved
54
+ // target). Only the verdict of the predicate is used; the echoed path stays `resolved`.
55
+ if ((0, security_cjs_1.tryWithinRoot)(resolved, input.projectDir, security_cjs_1.PathAcceptance.AbsoluteInsideRoot) === null) {
56
+ return (0, gate_verdict_cjs_1.gateUsageFailure)(gate_verdict_cjs_1.GATE_FAILURE_CODE.USAGE, `path escapes its allowed directory: ${recordPath}`);
57
+ }
58
+ const read = (0, gate_evidence_cjs_1.readTextEvidence)(resolved);
59
+ const text = read.kind === 'found' ? read.value : '';
60
+ const parsed = text ? parseRecordEvidence(text, resolved) : null;
61
+ // Malformed JSON is content that WAS read: it is a failing record (`block`), not a swallowed error.
62
+ const record = parsed !== null && parsed.kind === 'found' ? parsed.value : null;
63
+ if (!record) {
64
+ const payload = {
65
+ passed: false,
66
+ block: true,
67
+ verdict: 'INVALID_RED',
68
+ reason: 'unreadable_record',
69
+ record: resolved,
70
+ readError: text ? `record is not valid JSON: ${resolved}` : `record not found or unreadable: ${resolved}`,
71
+ };
72
+ // Fail-closed policy is unchanged (`block: true`); a record that exists but could not be read
73
+ // is "could not look" (#5170), so its outcome is `unreadable` and the exit status follows it.
74
+ return read.kind === 'unreadable' ? (0, gate_verdict_cjs_1.gateUnreadable)(true, payload) : (0, gate_verdict_cjs_1.gateVerdict)('block', true, payload);
75
+ }
76
+ const evidenceInput = {
77
+ command: record['command'],
78
+ exitCode: record['exitCode'],
79
+ output: record['output'],
80
+ targetTest: record['targetTest'],
81
+ targetFile: record['targetFile'],
82
+ expected: record['expected'],
83
+ actual: record['actual'],
84
+ };
85
+ const result = (0, tdd_red_evidence_cjs_1.classifyRedEvidence)(evidenceInput);
86
+ const built = (0, tdd_red_evidence_cjs_1.buildRedEvidenceRecord)(evidenceInput, result);
87
+ const ok = result.verdict === 'RED_EVIDENCE_OK';
88
+ // Uniform gate contract: block = !passed. INVALID_RED blocks GREEN.
89
+ return (0, gate_verdict_cjs_1.gateVerdict)(ok ? 'pass' : 'block', !ok, {
90
+ passed: ok,
91
+ block: !ok,
92
+ verdict: result.verdict,
93
+ reason: result.reason,
94
+ evidence: result.evidence,
95
+ record: built,
96
+ message: ok
97
+ ? `RED evidence verified: target test "${result.evidence.target_test}" failed as expected (exit ${result.evidence.exit_code}). GREEN authorized.`
98
+ : `INVALID_RED (${result.reason}): GREEN blocked. Fix the RED phase — only an intentional failure of target test "${result.evidence.target_test}" authorizes production edits.`,
99
+ });
100
+ }
@@ -0,0 +1,182 @@
1
+ "use strict";
2
+ /**
3
+ * `check tdd-review-checkpoint` as a gate module (#5139, epic #5056, ADR-5057 §4 first bullet): it
4
+ * returns a `GateResult`; the command router formats it. Imports no io module and performs no
5
+ * direct console/stdout/stderr write (ESLint-enforced).
6
+ *
7
+ * End-of-phase advisory check: scans `type: tdd` plans for RED/GREEN/REFACTOR gate-sequence
8
+ * compliance (`test(<plan>):` / `feat(<plan>):` / `refactor(<plan>):` commits) and builds a review
9
+ * table. `passed` is always true (advisory — never truly blocks); `block` is `violations > 0` so
10
+ * the host loop can read one uniform field.
11
+ *
12
+ * `type: tdd` is detected by the Frontmatter Module's `frontmatterKeyHasValue` (the old
13
+ * `^type:\s*tdd\s*$` multiline test over the fence owner's block, key and value escaped).
14
+ *
15
+ * A plan's commits come from the evaluation-scope resolver (#5164, ADR-5057 §4): the commits
16
+ * reachable from HEAD whose SUBJECT is `<type>(<phase>-<plan>):`, anchored and zero-padding
17
+ * tolerant. A plan id that is not `<phase>-<plan>` (a plan named `.*-PLAN.md`) matches nothing,
18
+ * and a git failure is "no commits" exactly as before.
19
+ *
20
+ * Argv after the verb: `<phase>` (a number; an unresolvable phase reports zero plans).
21
+ */
22
+ var __importDefault = (this && this.__importDefault) || function (mod) {
23
+ return (mod && mod.__esModule) ? mod : { "default": mod };
24
+ };
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ exports.evaluateTddReviewCheckpoint = evaluateTddReviewCheckpoint;
27
+ const node_path_1 = __importDefault(require("node:path"));
28
+ const gate_verdict_cjs_1 = require("./gate-verdict.cjs");
29
+ const gate_phase_context_cjs_1 = require("./gate-phase-context.cjs");
30
+ const gate_evidence_cjs_1 = require("./gate-evidence.cjs");
31
+ const gate_evaluation_scope_cjs_1 = require("./gate-evaluation-scope.cjs");
32
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
33
+ const frontmatterMod = require("./frontmatter.cjs");
34
+ const { frontmatterKeyHasValue } = frontmatterMod;
35
+ /**
36
+ * True when the plan's frontmatter declares `type: tdd` (CRLF included, #2449). The block is the
37
+ * one fence owner's, read as RAW text — not through the YAML parser — so a block the parser refuses
38
+ * (a `--- x` line before `type:`) still classifies, exactly as under the old `^type:\s*tdd\s*$`
39
+ * multiline regex, whose edge behaviour (a duplicate `type:` key, a value on the next line,
40
+ * `type : tdd` NOT matching, `type: "tdd"` / `type: tdd # note` NOT matching) is preserved.
41
+ */
42
+ function isTddPlan(content) {
43
+ return frontmatterKeyHasValue(content, 'type', 'tdd');
44
+ }
45
+ /**
46
+ * The commit types (`test`, `feat`, `refactor`, …) among the plan's own commits — those that
47
+ * touched at least one path (`pathspecs: ['.']`, as the old `git log -- .` lookup did). An
48
+ * unresolvable scope (git unavailable, an id that is not `<phase>-<plan>`) is "no commits".
49
+ */
50
+ function planCommitKinds(projectDir, planId) {
51
+ const scope = (0, gate_evaluation_scope_cjs_1.resolveEvaluationScope)(projectDir, { kind: 'plan', planId }, { pathspecs: ['.'], commitsOnly: true });
52
+ const kinds = new Set();
53
+ for (const commit of scope.commits) {
54
+ const kind = /^([a-z]+)\(/.exec(commit.subject)?.[1];
55
+ if (kind)
56
+ kinds.add(kind);
57
+ }
58
+ return kinds;
59
+ }
60
+ /**
61
+ * The verdict when the review could not read a plan or the phase directory. Advisory policy is
62
+ * unchanged (`block: false`); the outcome is `unreadable` (exit UNAVAILABLE) and `passed` is false
63
+ * because nothing was certified.
64
+ */
65
+ function unreadableReview(phase, tddPlans, unreadable) {
66
+ const names = unreadable.map((u) => `${u.source} (${u.reason})`).join(', ');
67
+ return (0, gate_verdict_cjs_1.gateUnreadable)(false, {
68
+ block: false,
69
+ passed: false,
70
+ tddPlans,
71
+ violations: 0,
72
+ table: '',
73
+ rows: [],
74
+ unreadable,
75
+ message: `TDD review could not read: ${names}. Phase ${phase} was not reviewed.`,
76
+ });
77
+ }
78
+ function evaluateTddReviewCheckpoint(input) {
79
+ const { projectDir } = input;
80
+ const phase = input.args[0] || '';
81
+ if (!phase) {
82
+ return (0, gate_verdict_cjs_1.gateUsageFailure)(gate_verdict_cjs_1.GATE_FAILURE_CODE.SDK_MISSING_ARG, 'tdd.review-checkpoint requires a phase argument: check tdd.review-checkpoint <phase>');
83
+ }
84
+ // #5170 (ADR-5057 §4): an ABSENT phase directory is `none` (no plans, the skip below); anything
85
+ // that exists but cannot be read is `unreadable` and the verdict says so — an unreadable plan is
86
+ // never "not a TDD plan".
87
+ const located = (0, gate_phase_context_cjs_1.resolvePhaseDir)(projectDir, phase);
88
+ if (located.kind === 'unreadable') {
89
+ return unreadableReview(phase, 0, [{ source: `phase ${phase}`, reason: located.reason }]);
90
+ }
91
+ const phaseDir = located.kind === 'found' ? located.value : '';
92
+ // Find all PLAN.md files with type: tdd in frontmatter
93
+ const tddPlanFiles = [];
94
+ const unreadable = [];
95
+ if (phaseDir) {
96
+ const entries = (0, gate_evidence_cjs_1.readDirEvidence)(phaseDir);
97
+ if (entries.kind === 'unreadable') {
98
+ unreadable.push({ source: phaseDir, reason: entries.reason });
99
+ }
100
+ else if (entries.kind === 'found') {
101
+ // #3183: canonical plan set (root+nested, superseded-excluded) from the single owner. A scan
102
+ // that did not see every plan (an unreadable nested plans/) is `unreadable`, never a short list.
103
+ const planSet = (0, gate_evidence_cjs_1.readPlanSetEvidence)(phaseDir);
104
+ if (planSet.kind === 'unreadable') {
105
+ unreadable.push({ source: planSet.span ?? phaseDir, reason: planSet.reason });
106
+ }
107
+ else {
108
+ for (const file of planSet.value) {
109
+ const planPath = node_path_1.default.join(phaseDir, file);
110
+ const plan = (0, gate_evidence_cjs_1.readTextEvidence)(planPath);
111
+ if (plan.kind === 'unreadable')
112
+ unreadable.push({ source: planPath, reason: plan.reason });
113
+ else if (plan.kind === 'found' && isTddPlan(plan.value))
114
+ tddPlanFiles.push(planPath);
115
+ }
116
+ }
117
+ }
118
+ }
119
+ if (unreadable.length > 0)
120
+ return unreadableReview(phase, tddPlanFiles.length, unreadable);
121
+ if (tddPlanFiles.length === 0) {
122
+ return (0, gate_verdict_cjs_1.gateVerdict)('skip', false, {
123
+ // Uniform gate contract: block = violations > 0 (advisory; never truly blocks).
124
+ block: false,
125
+ passed: true,
126
+ tddPlans: 0,
127
+ violations: 0,
128
+ table: '',
129
+ rows: [],
130
+ message: `No type:tdd plans found in phase ${phase}. TDD review skipped.`,
131
+ });
132
+ }
133
+ // For each TDD plan, extract the plan ID (e.g. "01-02-PLAN.md" → "01-02") and check git log
134
+ const rows = [];
135
+ for (const planPath of tddPlanFiles) {
136
+ const planId = node_path_1.default.basename(planPath, '-PLAN.md');
137
+ const kinds = planCommitKinds(projectDir, planId);
138
+ const red = kinds.has('test');
139
+ const green = kinds.has('feat');
140
+ const refactor = kinds.has('refactor');
141
+ const missing = [];
142
+ if (!red)
143
+ missing.push('RED');
144
+ if (!green)
145
+ missing.push('GREEN');
146
+ const status = missing.length === 0 ? 'Pass' : 'FAIL';
147
+ rows.push({ planId, red, green, refactor, status, missing });
148
+ }
149
+ const violations = rows.filter(r => r.status === 'FAIL').length;
150
+ // Build review table
151
+ const tableHeader = '| Plan | RED | GREEN | REFACTOR | Status |';
152
+ const tableDivider = '|------|-----|-------|----------|--------|';
153
+ const tableRows = rows.map(r => `| ${r.planId.padEnd(4)} | ${r.red ? ' ✓ ' : ' ✗ '} | ${r.green ? ' ✓ ' : ' ✗ '} | ${r.refactor ? ' ✓ ' : ' — '} | ${r.status.padEnd(6)} |`);
154
+ let table = [
155
+ `### TDD REVIEW — Phase ${phase}`,
156
+ '',
157
+ `TDD Plans: ${tddPlanFiles.length} | Gate violations: ${violations}`,
158
+ '',
159
+ tableHeader,
160
+ tableDivider,
161
+ ...tableRows,
162
+ ].join('\n');
163
+ if (violations > 0) {
164
+ table += '\n\n⚠ Gate violations are advisory — review before advancing.';
165
+ for (const r of rows.filter(row => row.status === 'FAIL')) {
166
+ table += `\n Plan ${r.planId} missing: ${r.missing.join(', ')} gate commit(s).`;
167
+ table += `\n Expected commit pattern: test(${r.planId}): ... → feat(${r.planId}): ...`;
168
+ }
169
+ }
170
+ // Uniform gate contract: block = violations > 0. The gate is advisory (blocking:false in
171
+ // capability.json), so block:true only surfaces as a warning, never halts. The human-readable
172
+ // report is carried in `message` (and `table`) for the dispatch's advisory branch.
173
+ return (0, gate_verdict_cjs_1.gateVerdict)(violations > 0 ? 'advisory' : 'pass', violations > 0, {
174
+ block: violations > 0,
175
+ passed: true,
176
+ tddPlans: tddPlanFiles.length,
177
+ violations,
178
+ table,
179
+ rows,
180
+ message: table,
181
+ });
182
+ }
@@ -0,0 +1,86 @@
1
+ "use strict";
2
+ /**
3
+ * `check ui-plan-gate` as a gate module (#5139, epic #5056, ADR-5057 §4 first bullet): it returns a
4
+ * `GateResult`; the command router formats it. Imports no io module and performs no direct
5
+ * console/stdout/stderr write (ESLint-enforced).
6
+ *
7
+ * Given a phase number, checks whether the phase has frontend indicators and whether a
8
+ * `*-UI-SPEC.md` already exists in the phase directory. Uses `checkUiPresence` from
9
+ * `ui-safety-gate.cjs` (frontend detection is not reimplemented) and the shared phase-context
10
+ * helpers for the ROADMAP lookup and the phase directory.
11
+ *
12
+ * Argv after the verb: `<phase>`.
13
+ */
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.computeUiPlanGate = computeUiPlanGate;
16
+ exports.evaluateUiPlanGate = evaluateUiPlanGate;
17
+ const gate_verdict_cjs_1 = require("./gate-verdict.cjs");
18
+ const gate_phase_context_cjs_1 = require("./gate-phase-context.cjs");
19
+ const ui_safety_gate_cjs_1 = require("./ui-safety-gate.cjs");
20
+ const ui_frontend_evidence_cjs_1 = require("./ui-frontend-evidence.cjs");
21
+ const gate_evidence_cjs_1 = require("./gate-evidence.cjs");
22
+ /**
23
+ * Pure logic for ui-plan-gate — exposed for direct behavioral testing.
24
+ *
25
+ * Given a projectDir and phase number:
26
+ * (a) Reads the phase section from ROADMAP.md via the two-pass lookup `roadmap.get-phase` uses
27
+ * (current milestone → full roadmap). ROADMAP.md missing = project has no roadmap = cannot
28
+ * be frontend. Phase absent from a present ROADMAP.md sets `phaseLookupFailed` so callers
29
+ * can surface the miss — we do NOT silently degrade to frontend:false.
30
+ * (b) Runs checkUiPresence (frontend detection).
31
+ * (c) Resolves the phase directory; checks for *-UI-SPEC.md.
32
+ *
33
+ * `block = frontend && hasFrontendEvidence && !hasUiSpec` (#3312): `frontend` is a vocabulary
34
+ * signal only (a hyphen is a word boundary, so a repo named `dashboard-financeiro` matches the
35
+ * token `dashboard`; the boundary rule of #3718 is intentional), so the gate blocks only when the
36
+ * token match is corroborated by static frontend evidence in the repo tree
37
+ * (`hasStaticFrontendEvidence`). matchedToken/matchedLine surface what tripped the sniffer.
38
+ */
39
+ function computeUiPlanGate(projectDir, phase) {
40
+ // (a) phase section text
41
+ const { phaseSection, phaseLookupFailed, readError: roadmapReadError } = (0, gate_phase_context_cjs_1.lookupRoadmapPhase)(projectDir, phase);
42
+ // (b) frontend detection — reuse the existing helper; no reimplementation
43
+ const presenceResult = (0, ui_safety_gate_cjs_1.checkUiPresence)(phaseSection);
44
+ const frontend = presenceResult.hasUI;
45
+ // (b') #3312 — static structural corroboration. Only probed when the sniffer matched. `unreadable`
46
+ // (#5170) is a manifest or tree the probe could not look at: absence of evidence is then not
47
+ // established, and the verdict says so (below) instead of reading it as "no frontend".
48
+ const frontendEvidence = frontend ? (0, ui_frontend_evidence_cjs_1.readStaticFrontendEvidence)(projectDir) : (0, gate_evidence_cjs_1.evidenceNone)();
49
+ const hasFrontendEvidence = frontendEvidence.kind === 'found';
50
+ // (c) phase directory and *-UI-SPEC.md. `none` is "no spec"; `unreadable` is "could not look"
51
+ // (#5170) and is carried to the verdict, never read as "no spec".
52
+ const uiSpec = (0, gate_phase_context_cjs_1.locateUiSpec)(projectDir, phase);
53
+ const uiSpecPath = uiSpec.kind === 'found' ? uiSpec.value : '';
54
+ const hasUiSpec = uiSpecPath !== '';
55
+ // Unreadable frontend evidence only matters when it could flip the verdict: with a UI-SPEC present the
56
+ // gate does not block whatever the tree holds.
57
+ const frontendReadError = frontendEvidence.kind === 'unreadable' && !hasUiSpec
58
+ ? `static frontend evidence could not be read (${frontendEvidence.reason})`
59
+ : undefined;
60
+ const readError = roadmapReadError ?? (uiSpec.kind === 'unreadable' ? uiSpec.reason : undefined) ?? frontendReadError;
61
+ // block = frontend phase with structural frontend evidence and no UI-SPEC (#3312)
62
+ const block = frontend && hasFrontendEvidence && !hasUiSpec;
63
+ const result = {
64
+ frontend, hasFrontendEvidence, hasUiSpec, block,
65
+ uiSpecPath: hasUiSpec ? uiSpecPath : null,
66
+ matchedToken: presenceResult.matchedToken,
67
+ matchedLine: presenceResult.matchedLine,
68
+ };
69
+ if (phaseLookupFailed)
70
+ result.phaseLookupFailed = true;
71
+ if (readError !== undefined)
72
+ result.readError = readError;
73
+ return result;
74
+ }
75
+ function evaluateUiPlanGate(input) {
76
+ const phase = input.args[0] || '';
77
+ if (!phase) {
78
+ return (0, gate_verdict_cjs_1.gateUsageFailure)(gate_verdict_cjs_1.GATE_FAILURE_CODE.SDK_MISSING_ARG, 'ui-plan-gate requires a phase argument: check ui-plan-gate <phase>');
79
+ }
80
+ const result = computeUiPlanGate(input.projectDir, phase);
81
+ // Evidence the gate could not read is "could not look", never a pass (ADR-5057 §4). `block` is
82
+ // the gate's own policy and is unchanged; the exit status follows the outcome.
83
+ if (result.readError !== undefined)
84
+ return (0, gate_verdict_cjs_1.gateUnreadable)(result.block, { ...result });
85
+ return (0, gate_verdict_cjs_1.gateVerdict)(result.block ? 'block' : 'pass', result.block, { ...result });
86
+ }
@@ -0,0 +1,80 @@
1
+ "use strict";
2
+ /**
3
+ * `check ui-safety-gate` as a gate module (#5139, epic #5056, ADR-5057 §4 first bullet): it returns
4
+ * a `GateResult`; the command router formats it. Imports no io module and performs no direct
5
+ * console/stdout/stderr write (ESLint-enforced).
6
+ *
7
+ * Post-wave check that verifies UI-changed files conform to the active UI-SPEC for the phase.
8
+ * Uses `checkUiPresence` from `ui-safety-gate.cjs` (frontend detection is not reimplemented) and
9
+ * looks for frontend files in the phase's evaluation scope (#5164, ADR-5057 §4): the union of the
10
+ * phase's own commits' file sets from `gate-evaluation-scope`, not the last commit. A scope the
11
+ * resolver could not read, or had to widen, is reported (`scopeStatus` / `scopeReason`), never
12
+ * silently treated as "no UI files".
13
+ *
14
+ * Argv after the verb: `<phase>`.
15
+ */
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.computeUiSafetyGate = computeUiSafetyGate;
18
+ exports.evaluateUiSafetyGate = evaluateUiSafetyGate;
19
+ const gate_verdict_cjs_1 = require("./gate-verdict.cjs");
20
+ const gate_phase_context_cjs_1 = require("./gate-phase-context.cjs");
21
+ const gate_evaluation_scope_cjs_1 = require("./gate-evaluation-scope.cjs");
22
+ const ui_safety_gate_cjs_1 = require("./ui-safety-gate.cjs");
23
+ const UI_FILE_EXTENSIONS_RE = /\.(tsx|jsx|css|scss|sass|less|vue|svelte|html)$/i;
24
+ const UI_PATH_PATTERNS_RE = /\/(components|pages|views|screens|layouts|ui|frontend)\//i;
25
+ /**
26
+ * Pure logic for ui-safety-gate — exposed for direct behavioral testing.
27
+ *
28
+ * (a) ROADMAP phase section via the shared lookup (same as ui-plan-gate) → is this a frontend phase.
29
+ * (b) checkUiPresence (frontend detection).
30
+ * (c) UI files among the phase's evaluation scope (`resolveEvaluationScope`, phase unit; every
31
+ * git call is bounded by the resolver's seam; an unreadable scope is reported, not "clean").
32
+ * (d) Phase directory → `*-UI-SPEC.md`.
33
+ *
34
+ * `block = frontend && hasUiFiles && !hasUiSpec`.
35
+ */
36
+ function computeUiSafetyGate(projectDir, phase) {
37
+ // (a) phase section text (same two-pass lookup as computeUiPlanGate)
38
+ const { phaseSection, phaseLookupFailed, readError: roadmapReadError } = (0, gate_phase_context_cjs_1.lookupRoadmapPhase)(projectDir, phase);
39
+ // (b) frontend detection — reuse the existing helper; no reimplementation
40
+ const presenceResult = (0, ui_safety_gate_cjs_1.checkUiPresence)(phaseSection);
41
+ const frontend = presenceResult.hasUI;
42
+ // (c) any UI files in the phase's own commits? (deleted paths count: a removed component is a UI change)
43
+ const scope = (0, gate_evaluation_scope_cjs_1.resolveEvaluationScope)(projectDir, { kind: 'phase', phase });
44
+ const hasUiFiles = scope.changedFiles.some((f) => f.trim() && (UI_FILE_EXTENSIONS_RE.test(f) || UI_PATH_PATTERNS_RE.test(f)));
45
+ // (d) phase directory and *-UI-SPEC.md
46
+ // `none` is "no spec"; `unreadable` is "could not look" (#5170) and is carried to the verdict.
47
+ const uiSpec = (0, gate_phase_context_cjs_1.locateUiSpec)(projectDir, phase);
48
+ const hasUiSpec = uiSpec.kind === 'found';
49
+ const readError = roadmapReadError ?? (uiSpec.kind === 'unreadable' ? uiSpec.reason : undefined);
50
+ // block only when: this is a frontend phase AND UI files were changed AND no UI-SPEC exists
51
+ const block = frontend && hasUiFiles && !hasUiSpec;
52
+ const result = { frontend, hasUiFiles, hasUiSpec, block };
53
+ if (block) {
54
+ result.message = `UI files changed in this wave but no UI-SPEC.md exists for Phase ${phase}. ` +
55
+ `Run /gsd:ui-phase ${phase} to generate the design contract before continuing.`;
56
+ }
57
+ if (phaseLookupFailed)
58
+ result.phaseLookupFailed = true;
59
+ if (scope.status !== 'resolved') {
60
+ result.scopeStatus = scope.status;
61
+ result.scopeReason = scope.reason ?? '';
62
+ }
63
+ if (readError !== undefined)
64
+ result.readError = readError;
65
+ return result;
66
+ }
67
+ function evaluateUiSafetyGate(input) {
68
+ const phase = input.args[0] || '';
69
+ if (!phase) {
70
+ return (0, gate_verdict_cjs_1.gateUsageFailure)(gate_verdict_cjs_1.GATE_FAILURE_CODE.SDK_MISSING_ARG, 'ui-safety-gate requires a phase argument: check ui-safety-gate <phase>');
71
+ }
72
+ const result = computeUiSafetyGate(input.projectDir, phase);
73
+ // A scope the resolver could not read, or a ROADMAP / phase directory that could not be read, is
74
+ // "could not look", never a pass (ADR-5057 §4): the outcome is `unreadable` and the exit status
75
+ // follows it. `block` is the gate's own policy and is unchanged.
76
+ if (result.scopeStatus === 'unresolvable' || result.readError !== undefined) {
77
+ return (0, gate_verdict_cjs_1.gateUnreadable)(result.block, { ...result });
78
+ }
79
+ return (0, gate_verdict_cjs_1.gateVerdict)(result.block ? 'block' : 'pass', result.block, { ...result });
80
+ }