@opengsd/gsd-core 1.10.0 → 1.12.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 (544) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/agents/gsd-code-fixer.md +1 -1
  4. package/agents/gsd-debug-session-manager.md +12 -1
  5. package/agents/gsd-debugger.md +1 -1
  6. package/agents/gsd-doc-synthesizer.md +2 -4
  7. package/agents/gsd-dom-verifier.md +169 -0
  8. package/agents/gsd-eval-auditor.md +1 -1
  9. package/agents/gsd-executor.md +22 -14
  10. package/agents/gsd-framework-selector.md +1 -3
  11. package/agents/gsd-intel-updater.md +1 -1
  12. package/agents/gsd-mempalace-curator.md +5 -3
  13. package/agents/gsd-pattern-mapper.md +11 -0
  14. package/agents/gsd-phase-researcher.md +23 -2
  15. package/agents/gsd-plan-checker.md +50 -53
  16. package/agents/gsd-planner.md +50 -50
  17. package/agents/gsd-project-researcher.md +1 -1
  18. package/agents/gsd-research-synthesizer.md +2 -2
  19. package/agents/gsd-roadmapper.md +15 -11
  20. package/agents/gsd-ui-checker.md +63 -4
  21. package/agents/gsd-ui-researcher.md +41 -3
  22. package/agents/gsd-user-profiler.md +3 -0
  23. package/agents/gsd-verifier.md +13 -4
  24. package/bin/install.js +1448 -1103
  25. package/commands/gsd/code-review.md +1 -1
  26. package/commands/gsd/discuss-phase.md +1 -1
  27. package/commands/gsd/execute-phase.md +1 -1
  28. package/commands/gsd/import.md +1 -1
  29. package/commands/gsd/map-codebase.md +1 -1
  30. package/commands/gsd/mempalace-capture.md +1 -1
  31. package/commands/gsd/mempalace-recall.md +1 -1
  32. package/commands/gsd/new-milestone.md +1 -1
  33. package/commands/gsd/quick.md +9 -5
  34. package/commands/gsd/review-backlog.md +2 -1
  35. package/commands/gsd/verify-work.md +1 -1
  36. package/gsd-core/bin/gsd-tools.cjs +1035 -138
  37. package/gsd-core/bin/lib/active-workstream-store.cjs +146 -22
  38. package/gsd-core/bin/lib/adr-parser.cjs +13 -7
  39. package/gsd-core/bin/lib/agent-install-check.cjs +392 -32
  40. package/gsd-core/bin/lib/api-coverage.cjs +33 -14
  41. package/gsd-core/bin/lib/artifacts.cjs +5 -0
  42. package/gsd-core/bin/lib/assumption-delta.cjs +32 -15
  43. package/gsd-core/bin/lib/audit-command-router.cjs +9 -2
  44. package/gsd-core/bin/lib/audit.cjs +1026 -268
  45. package/gsd-core/bin/lib/broken-windows.cjs +306 -28
  46. package/gsd-core/bin/lib/capability-consent.cjs +149 -15
  47. package/gsd-core/bin/lib/capability-lifecycle.cjs +45 -0
  48. package/gsd-core/bin/lib/capability-lock.cjs +10 -4
  49. package/gsd-core/bin/lib/capability-registry.cjs +845 -130
  50. package/gsd-core/bin/lib/capability-source.cjs +92 -0
  51. package/gsd-core/bin/lib/capability-state.cjs +18 -3
  52. package/gsd-core/bin/lib/capability-trust.cjs +444 -25
  53. package/gsd-core/bin/lib/capability-validator.cjs +700 -40
  54. package/gsd-core/bin/lib/capability-writer.cjs +3 -2
  55. package/gsd-core/bin/lib/check-command-router.cjs +216 -42
  56. package/gsd-core/bin/lib/claude-orchestration.cjs +56 -3
  57. package/gsd-core/bin/lib/cli-exit.cjs +496 -10
  58. package/gsd-core/bin/lib/code-review-depth.cjs +288 -0
  59. package/gsd-core/bin/lib/codex-agent-toml.cjs +735 -0
  60. package/gsd-core/bin/lib/command-aliases.cjs +22 -0
  61. package/gsd-core/bin/lib/command-arg-projection.cjs +144 -14
  62. package/gsd-core/bin/lib/command-roster.cjs +44 -1
  63. package/gsd-core/bin/lib/command-routing-hub.cjs +31 -2
  64. package/gsd-core/bin/lib/commands.cjs +1172 -108
  65. package/gsd-core/bin/lib/commonjs-marker.cjs +12 -6
  66. package/gsd-core/bin/lib/complexity-trigger.cjs +1192 -0
  67. package/gsd-core/bin/lib/config-loader.cjs +187 -23
  68. package/gsd-core/bin/lib/config.cjs +102 -3
  69. package/gsd-core/bin/lib/configuration.cjs +129 -37
  70. package/gsd-core/bin/lib/core-utils.cjs +208 -33
  71. package/gsd-core/bin/lib/decisions.cjs +23 -0
  72. package/gsd-core/bin/lib/edge-probe.cjs +9 -1
  73. package/gsd-core/bin/lib/estimate-cli.cjs +55 -11
  74. package/gsd-core/bin/lib/exit-code-registry.cjs +98 -0
  75. package/gsd-core/bin/lib/fallow-runner.cjs +20 -44
  76. package/gsd-core/bin/lib/frontmatter.cjs +899 -229
  77. package/gsd-core/bin/lib/gap-checker.cjs +95 -10
  78. package/gsd-core/bin/lib/git-base-branch.cjs +276 -39
  79. package/gsd-core/bin/lib/gsd2-import.cjs +10 -1
  80. package/gsd-core/bin/lib/health-diagnostic-rules/agent-install.cjs +101 -0
  81. package/gsd-core/bin/lib/health-diagnostic-rules/config-validation.cjs +348 -0
  82. package/gsd-core/bin/lib/health-diagnostic-rules/consistency.cjs +149 -0
  83. package/gsd-core/bin/lib/health-diagnostic-rules/install-surface-shadowing.cjs +98 -0
  84. package/gsd-core/bin/lib/health-diagnostic-rules/milestone-archive-hygiene.cjs +100 -0
  85. package/gsd-core/bin/lib/health-diagnostic-rules/phase-structure.cjs +222 -0
  86. package/gsd-core/bin/lib/health-diagnostic-rules/roadmap-disk-consistency.cjs +268 -0
  87. package/gsd-core/bin/lib/health-diagnostic-rules/root-existence.cjs +161 -0
  88. package/gsd-core/bin/lib/health-diagnostic-rules/state-consistency.cjs +303 -0
  89. package/gsd-core/bin/lib/health-diagnostic-rules/worktree-health.cjs +187 -0
  90. package/gsd-core/bin/lib/health-diagnostic-types.cjs +68 -0
  91. package/gsd-core/bin/lib/health-diagnostic.cjs +451 -0
  92. package/gsd-core/bin/lib/host-integration.cjs +39 -6
  93. package/gsd-core/bin/lib/host-runtime-detection.cjs +134 -0
  94. package/gsd-core/bin/lib/init-command-router.cjs +118 -21
  95. package/gsd-core/bin/lib/init.cjs +439 -168
  96. package/gsd-core/bin/lib/install-effort-resolver.cjs +73 -30
  97. package/gsd-core/bin/lib/install-engine.cjs +811 -259
  98. package/gsd-core/bin/lib/install-fs-adapter.cjs +262 -0
  99. package/gsd-core/bin/lib/install-model-override-resolver.cjs +235 -0
  100. package/gsd-core/bin/lib/install-profiles.cjs +212 -61
  101. package/gsd-core/bin/lib/install-scope.cjs +270 -0
  102. package/gsd-core/bin/lib/install-shadow-report.cjs +385 -0
  103. package/gsd-core/bin/lib/installed-surface-resolver.cjs +381 -0
  104. package/gsd-core/bin/lib/installer-migration-report.cjs +3 -0
  105. package/gsd-core/bin/lib/installer-migrations/010-antigravity-retire-confighome-artifacts.cjs +169 -0
  106. package/gsd-core/bin/lib/installer-migrations.cjs +148 -38
  107. package/gsd-core/bin/lib/intel.cjs +101 -26
  108. package/gsd-core/bin/lib/io.cjs +170 -15
  109. package/gsd-core/bin/lib/learnings.cjs +85 -14
  110. package/gsd-core/bin/lib/legacy-cleanup.cjs +8 -2
  111. package/gsd-core/bin/lib/markdown-sectionizer.cjs +2 -1
  112. package/gsd-core/bin/lib/markdown-table.cjs +183 -22
  113. package/gsd-core/bin/lib/milestone-lock.cjs +248 -0
  114. package/gsd-core/bin/lib/milestone.cjs +842 -73
  115. package/gsd-core/bin/lib/model-catalog.cjs +232 -16
  116. package/gsd-core/bin/lib/model-resolver.cjs +193 -68
  117. package/gsd-core/bin/lib/normalize-test-command.cjs +1 -1
  118. package/gsd-core/bin/lib/onboard-projection.cjs +5 -1
  119. package/gsd-core/bin/lib/pattern.cjs +122 -0
  120. package/gsd-core/bin/lib/phase-estimation.cjs +18 -9
  121. package/gsd-core/bin/lib/phase-id.cjs +514 -40
  122. package/gsd-core/bin/lib/phase-lifecycle.cjs +52 -19
  123. package/gsd-core/bin/lib/phase-locator.cjs +262 -34
  124. package/gsd-core/bin/lib/phase.cjs +1038 -214
  125. package/gsd-core/bin/lib/plan-dependency-graph.cjs +72 -1
  126. package/gsd-core/bin/lib/plan-document.cjs +263 -0
  127. package/gsd-core/bin/lib/plan-drift-guard.cjs +120 -0
  128. package/gsd-core/bin/lib/plan-scan.cjs +98 -3
  129. package/gsd-core/bin/lib/planning-command-router.cjs +61 -0
  130. package/gsd-core/bin/lib/planning-inspect.cjs +1168 -0
  131. package/gsd-core/bin/lib/planning-scope.cjs +31 -0
  132. package/gsd-core/bin/lib/planning-snapshot.cjs +894 -0
  133. package/gsd-core/bin/lib/planning-workspace.cjs +112 -6
  134. package/gsd-core/bin/lib/probe-core.cjs +5 -2
  135. package/gsd-core/bin/lib/profile-output.cjs +1 -1
  136. package/gsd-core/bin/lib/profile-pipeline-command-router.cjs +50 -7
  137. package/gsd-core/bin/lib/profile-pipeline.cjs +6 -3
  138. package/gsd-core/bin/lib/real-home-guard.cjs +419 -0
  139. package/gsd-core/bin/lib/refactor-trigger-command-router.cjs +766 -0
  140. package/gsd-core/bin/lib/retired-artifact-cleanup.cjs +11 -6
  141. package/gsd-core/bin/lib/review-lane-descriptor.cjs +22 -13
  142. package/gsd-core/bin/lib/review-lane-invocation.cjs +30 -0
  143. package/gsd-core/bin/lib/review-lane-runner.cjs +421 -66
  144. package/gsd-core/bin/lib/review-reviewer-selection.cjs +13 -18
  145. package/gsd-core/bin/lib/roadmap-command-router.cjs +59 -11
  146. package/gsd-core/bin/lib/roadmap-parser.cjs +1006 -184
  147. package/gsd-core/bin/lib/roadmap-upgrade.cjs +37 -10
  148. package/gsd-core/bin/lib/roadmap.cjs +442 -96
  149. package/gsd-core/bin/lib/runtime-artifact-conversion.cjs +702 -52
  150. package/gsd-core/bin/lib/runtime-artifact-install-plan.cjs +14 -2
  151. package/gsd-core/bin/lib/runtime-artifact-layout.cjs +459 -55
  152. package/gsd-core/bin/lib/runtime-config-adapter-registry.cjs +3 -2
  153. package/gsd-core/bin/lib/runtime-homes.cjs +69 -3
  154. package/gsd-core/bin/lib/runtime-hooks-surface.cjs +402 -58
  155. package/gsd-core/bin/lib/runtime-identity.cjs +234 -0
  156. package/gsd-core/bin/lib/runtime-name-policy.cjs +3 -1
  157. package/gsd-core/bin/lib/runtime-slash.cjs +96 -8
  158. package/gsd-core/bin/lib/security.cjs +104 -5
  159. package/gsd-core/bin/lib/shell-command-projection.cjs +342 -7
  160. package/gsd-core/bin/lib/smart-entry.cjs +133 -23
  161. package/gsd-core/bin/lib/spec-section.cjs +12 -7
  162. package/gsd-core/bin/lib/state-command-router.cjs +52 -19
  163. package/gsd-core/bin/lib/state-contract.cjs +359 -0
  164. package/gsd-core/bin/lib/state-document.cjs +338 -8
  165. package/gsd-core/bin/lib/state-md-schema.cjs +221 -0
  166. package/gsd-core/bin/lib/state-transition.cjs +846 -176
  167. package/gsd-core/bin/lib/state.cjs +2589 -369
  168. package/gsd-core/bin/lib/surface.cjs +33 -11
  169. package/gsd-core/bin/lib/task-command-router.cjs +111 -1
  170. package/gsd-core/bin/lib/task-content-resolution.cjs +368 -0
  171. package/gsd-core/bin/lib/teams-status.cjs +4 -1
  172. package/gsd-core/bin/lib/text-lines.cjs +80 -0
  173. package/gsd-core/bin/lib/token-scanner.cjs +76 -0
  174. package/gsd-core/bin/lib/uat-predicate.cjs +67 -23
  175. package/gsd-core/bin/lib/uat.cjs +1761 -167
  176. package/gsd-core/bin/lib/ui-consideration-probe.cjs +9 -1
  177. package/gsd-core/bin/lib/ui-frontend-evidence.cjs +157 -0
  178. package/gsd-core/bin/lib/ui-safety-gate.cjs +51 -12
  179. package/gsd-core/bin/lib/unusable-input.cjs +37 -0
  180. package/gsd-core/bin/lib/update-context.cjs +8 -2
  181. package/gsd-core/bin/lib/user-artifact-staging.cjs +705 -0
  182. package/gsd-core/bin/lib/validate-command-router.cjs +2 -2
  183. package/gsd-core/bin/lib/validate.cjs +20 -6
  184. package/gsd-core/bin/lib/vendor/README.md +75 -0
  185. package/gsd-core/bin/lib/vendor/js-yaml.cjs +3014 -0
  186. package/gsd-core/bin/lib/vendor/re2js.cjs +6480 -0
  187. package/gsd-core/bin/lib/vendor/re2js.d.cts +938 -0
  188. package/gsd-core/bin/lib/verification-command-router.cjs +2 -1
  189. package/gsd-core/bin/lib/verification.cjs +272 -9
  190. package/gsd-core/bin/lib/verify-command-grounding.cjs +846 -0
  191. package/gsd-core/bin/lib/verify.cjs +453 -918
  192. package/gsd-core/bin/lib/workstream-inventory-builder.cjs +53 -32
  193. package/gsd-core/bin/lib/workstream-inventory.cjs +63 -10
  194. package/gsd-core/bin/lib/workstream-name-policy.cjs +25 -4
  195. package/gsd-core/bin/lib/workstream.cjs +2 -2
  196. package/gsd-core/bin/lib/worktree-base-ref.cjs +66 -12
  197. package/gsd-core/bin/lib/worktree-safety.cjs +341 -18
  198. package/gsd-core/bin/shared/config-defaults.manifest.json +8 -1
  199. package/gsd-core/bin/shared/config-schema.manifest.json +12 -1
  200. package/gsd-core/bin/shared/exit-codes.json +8 -0
  201. package/gsd-core/bin/shared/exit-codes.sh +20 -0
  202. package/gsd-core/bin/shared/model-catalog.json +8 -1
  203. package/gsd-core/references/agent-contracts.md +44 -26
  204. package/gsd-core/references/api-coverage.md +24 -2
  205. package/gsd-core/references/autonomous-smart-discuss.md +3 -3
  206. package/gsd-core/references/checkpoints.md +39 -21
  207. package/gsd-core/references/context-budget.md +1 -1
  208. package/gsd-core/references/decimal-phase-calculation.md +5 -5
  209. package/gsd-core/references/dispatch-isolation-gate.md +138 -0
  210. package/gsd-core/references/doc-conflict-engine.md +1 -1
  211. package/gsd-core/references/edge-probe.md +8 -0
  212. package/gsd-core/references/execute-mvp-tdd.md +4 -6
  213. package/gsd-core/references/execute-phase-between-wave-reset.md +15 -14
  214. package/gsd-core/references/execute-phase-context-guard.md +1 -1
  215. package/gsd-core/references/execute-phase-response-language.md +1 -1
  216. package/gsd-core/references/execute-phase-wave-guard.md +17 -11
  217. package/gsd-core/references/failing-direction.md +78 -0
  218. package/gsd-core/references/gate-prompts.md +1 -1
  219. package/gsd-core/references/git-integration.md +5 -5
  220. package/gsd-core/references/git-planning-commit.md +5 -4
  221. package/gsd-core/references/gsd-run-resolver.md +1 -1
  222. package/gsd-core/references/loop-hook-dispatch.md +61 -2
  223. package/gsd-core/references/model-profiles.md +12 -4
  224. package/gsd-core/references/mvp-concepts.md +9 -9
  225. package/gsd-core/references/nyquist-compliance.md +74 -0
  226. package/gsd-core/references/offer-next.md +3 -5
  227. package/gsd-core/references/phase-argument-parsing.md +3 -3
  228. package/gsd-core/references/planner-failing-direction.md +53 -0
  229. package/gsd-core/references/planner-guidance.md +3 -9
  230. package/gsd-core/references/planner-human-verify-mode.md +15 -1
  231. package/gsd-core/references/planner-preconditions.md +1 -1
  232. package/gsd-core/references/planner-reviews.md +1 -1
  233. package/gsd-core/references/planner-revision.md +1 -1
  234. package/gsd-core/references/planner-verify-command-grounding.md +17 -0
  235. package/gsd-core/references/planning-config.md +44 -13
  236. package/gsd-core/references/reviewer-instances.md +31 -0
  237. package/gsd-core/references/revision-loop.md +1 -1
  238. package/gsd-core/references/runtime-aware-dispatch.md +1 -1
  239. package/gsd-core/references/specless-probe-fallback.md +1 -1
  240. package/gsd-core/references/tdd.md +1 -3
  241. package/gsd-core/references/ui-brand.md +65 -21
  242. package/gsd-core/references/ui-consideration-probe.md +1 -1
  243. package/gsd-core/references/universal-anti-patterns.md +5 -5
  244. package/gsd-core/references/verifier-phase-gates.md +192 -0
  245. package/gsd-core/references/verify-command-path-resolvability.md +42 -0
  246. package/gsd-core/references/verify-mvp-mode.md +2 -2
  247. package/gsd-core/references/workstream-flag.md +33 -17
  248. package/gsd-core/templates/README.md +1 -1
  249. package/gsd-core/templates/SECURITY.md +3 -3
  250. package/gsd-core/templates/UI-SPEC.md +25 -3
  251. package/gsd-core/templates/VALIDATION.md +3 -3
  252. package/gsd-core/templates/discussion-log.md +1 -1
  253. package/gsd-core/templates/phase-prompt.md +5 -4
  254. package/gsd-core/templates/state.md +11 -4
  255. package/gsd-core/templates/verification-report.md +9 -1
  256. package/gsd-core/workflows/_runtime-launcher.snippet.sh +1 -1
  257. package/gsd-core/workflows/add-backlog.md +1 -1
  258. package/gsd-core/workflows/add-phase.md +3 -3
  259. package/gsd-core/workflows/add-tests.md +3 -8
  260. package/gsd-core/workflows/add-todo.md +1 -1
  261. package/gsd-core/workflows/ai-integration-phase.md +13 -20
  262. package/gsd-core/workflows/audit-fix.md +12 -3
  263. package/gsd-core/workflows/audit-milestone.md +9 -9
  264. package/gsd-core/workflows/audit-uat.md +17 -2
  265. package/gsd-core/workflows/autonomous/steps/converge-fail-fast.md +2 -2
  266. package/gsd-core/workflows/autonomous.md +11 -27
  267. package/gsd-core/workflows/check-todos.md +1 -1
  268. package/gsd-core/workflows/cleanup.md +64 -5
  269. package/gsd-core/workflows/code-review/steps/structural-pre-pass.md +14 -4
  270. package/gsd-core/workflows/code-review-fix.md +38 -11
  271. package/gsd-core/workflows/code-review.md +159 -52
  272. package/gsd-core/workflows/complete-milestone.md +151 -23
  273. package/gsd-core/workflows/debug.md +12 -8
  274. package/gsd-core/workflows/diagnose-issues.md +47 -15
  275. package/gsd-core/workflows/discuss-phase/modes/advisor.md +1 -1
  276. package/gsd-core/workflows/discuss-phase/modes/chain.md +5 -8
  277. package/gsd-core/workflows/discuss-phase/modes/default.md +1 -1
  278. package/gsd-core/workflows/discuss-phase/modes/text.md +1 -1
  279. package/gsd-core/workflows/discuss-phase-assumptions/steps/auto-advance-dispatch.md +1 -3
  280. package/gsd-core/workflows/discuss-phase-assumptions.md +4 -3
  281. package/gsd-core/workflows/discuss-phase.md +1 -1
  282. package/gsd-core/workflows/do.md +3 -6
  283. package/gsd-core/workflows/docs-update.md +5 -4
  284. package/gsd-core/workflows/edit-phase.md +27 -2
  285. package/gsd-core/workflows/eval-review.md +7 -14
  286. package/gsd-core/workflows/execute-phase/steps/codebase-drift-gate.md +1 -1
  287. package/gsd-core/workflows/execute-phase/steps/executor-isolation-dispatch.md +142 -15
  288. package/gsd-core/workflows/execute-phase/steps/gap-closure-artifacts.md +1 -1
  289. package/gsd-core/workflows/execute-phase/steps/partial-wave.md +1 -1
  290. package/gsd-core/workflows/execute-phase/steps/per-plan-executor-routing.md +77 -0
  291. package/gsd-core/workflows/execute-phase/steps/per-plan-worktree-gate.md +24 -4
  292. package/gsd-core/workflows/execute-phase/steps/post-merge-gate.md +2 -2
  293. package/gsd-core/workflows/execute-phase/steps/protected-branch.md +21 -0
  294. package/gsd-core/workflows/execute-phase/steps/regression-gate-run.md +2 -2
  295. package/gsd-core/workflows/execute-phase/steps/wave-post-gate-hooks.md +39 -0
  296. package/gsd-core/workflows/execute-phase.md +72 -100
  297. package/gsd-core/workflows/execute-plan.md +52 -15
  298. package/gsd-core/workflows/explore.md +131 -4
  299. package/gsd-core/workflows/extract-learnings.md +1 -1
  300. package/gsd-core/workflows/fast.md +10 -2
  301. package/gsd-core/workflows/forensics.md +1 -1
  302. package/gsd-core/workflows/graduation.md +5 -5
  303. package/gsd-core/workflows/health.md +76 -10
  304. package/gsd-core/workflows/import.md +18 -15
  305. package/gsd-core/workflows/inbox.md +4 -5
  306. package/gsd-core/workflows/ingest-docs.md +49 -16
  307. package/gsd-core/workflows/insert-phase.md +5 -5
  308. package/gsd-core/workflows/list-seeds.md +5 -3
  309. package/gsd-core/workflows/list-workspaces.md +1 -1
  310. package/gsd-core/workflows/manager.md +12 -23
  311. package/gsd-core/workflows/map-codebase.md +1 -1
  312. package/gsd-core/workflows/milestone-summary.md +1 -1
  313. package/gsd-core/workflows/mvp-phase.md +8 -5
  314. package/gsd-core/workflows/new-milestone.md +22 -29
  315. package/gsd-core/workflows/new-project/steps/auto-mode-config.md +1 -1
  316. package/gsd-core/workflows/new-project.md +26 -40
  317. package/gsd-core/workflows/new-workspace.md +1 -1
  318. package/gsd-core/workflows/next.md +14 -2
  319. package/gsd-core/workflows/pause-work.md +1 -1
  320. package/gsd-core/workflows/plan-phase/steps/adr-ingest-express-path.md +1 -1
  321. package/gsd-core/workflows/plan-phase/steps/chunked-planning-mode.md +1 -1
  322. package/gsd-core/workflows/plan-phase/steps/prd-express-path.md +2 -4
  323. package/gsd-core/workflows/plan-phase/steps/stall-detection-helpers.md +3 -3
  324. package/gsd-core/workflows/plan-phase.md +162 -59
  325. package/gsd-core/workflows/plan-review-convergence.md +96 -11
  326. package/gsd-core/workflows/plant-seed.md +2 -2
  327. package/gsd-core/workflows/pr-branch.md +187 -51
  328. package/gsd-core/workflows/profile-user.md +16 -14
  329. package/gsd-core/workflows/progress.md +61 -18
  330. package/gsd-core/workflows/quick/steps/discussion-phase.md +1 -3
  331. package/gsd-core/workflows/quick/steps/plan-checker-loop.md +5 -7
  332. package/gsd-core/workflows/quick/steps/quick-verification.md +28 -9
  333. package/gsd-core/workflows/quick/steps/research-phase.md +4 -6
  334. package/gsd-core/workflows/quick/steps/worktree-pre-dispatch-commit.md +3 -3
  335. package/gsd-core/workflows/quick.md +55 -44
  336. package/gsd-core/workflows/remove-phase.md +4 -4
  337. package/gsd-core/workflows/remove-workspace.md +2 -2
  338. package/gsd-core/workflows/resume-project.md +8 -12
  339. package/gsd-core/workflows/review.md +219 -20
  340. package/gsd-core/workflows/scan.md +1 -1
  341. package/gsd-core/workflows/secure-phase.md +3 -3
  342. package/gsd-core/workflows/session-report.md +2 -1
  343. package/gsd-core/workflows/settings-advanced.md +7 -9
  344. package/gsd-core/workflows/settings-integrations.md +64 -31
  345. package/gsd-core/workflows/settings.md +69 -7
  346. package/gsd-core/workflows/ship.md +116 -50
  347. package/gsd-core/workflows/sketch-wrap-up.md +11 -17
  348. package/gsd-core/workflows/sketch.md +12 -18
  349. package/gsd-core/workflows/smart-entry.md +3 -5
  350. package/gsd-core/workflows/spec-phase.md +53 -13
  351. package/gsd-core/workflows/spike-wrap-up.md +7 -11
  352. package/gsd-core/workflows/spike.md +20 -31
  353. package/gsd-core/workflows/stats.md +2 -2
  354. package/gsd-core/workflows/sync-skills.md +64 -9
  355. package/gsd-core/workflows/thread.md +11 -7
  356. package/gsd-core/workflows/transition.md +49 -14
  357. package/gsd-core/workflows/ui-phase.md +15 -21
  358. package/gsd-core/workflows/ui-review.md +8 -12
  359. package/gsd-core/workflows/ultraplan-phase.md +5 -13
  360. package/gsd-core/workflows/undo.md +8 -16
  361. package/gsd-core/workflows/update.md +7 -11
  362. package/gsd-core/workflows/validate-phase.md +3 -3
  363. package/gsd-core/workflows/verify-work/steps/automated-ui-verification.md +25 -1
  364. package/gsd-core/workflows/verify-work/steps/mvp-uat-framing.md +1 -1
  365. package/gsd-core/workflows/verify-work.md +66 -25
  366. package/hooks/dist/gsd-agent-isolation-guard.js +158 -30
  367. package/hooks/dist/gsd-check-update-worker.js +56 -13
  368. package/hooks/dist/gsd-check-update.js +19 -1
  369. package/hooks/dist/gsd-config-reload.js +18 -12
  370. package/hooks/dist/gsd-context-monitor.js +19 -10
  371. package/hooks/dist/gsd-cursor-post-tool.js +3 -1
  372. package/hooks/dist/gsd-cursor-pre-tool.js +2 -3
  373. package/hooks/dist/gsd-cursor-session-start.js +2 -1
  374. package/hooks/dist/gsd-cursor-stop.js +2 -1
  375. package/hooks/dist/gsd-cursor-subagent-start.js +83 -3
  376. package/hooks/dist/gsd-cursor-subagent-stop.js +6 -3
  377. package/hooks/dist/gsd-ensure-canonical-path.js +2 -1
  378. package/hooks/dist/gsd-graphify-update.sh +22 -18
  379. package/hooks/dist/gsd-node-runner.sh +76 -0
  380. package/hooks/dist/gsd-phase-boundary.sh +1 -0
  381. package/hooks/dist/gsd-prompt-guard.js +37 -27
  382. package/hooks/dist/gsd-read-guard.js +16 -7
  383. package/hooks/dist/gsd-read-injection-scanner.js +55 -32
  384. package/hooks/dist/gsd-session-state.sh +1 -0
  385. package/hooks/dist/gsd-statusline.js +231 -24
  386. package/hooks/dist/gsd-update-banner.js +22 -1
  387. package/hooks/dist/gsd-validate-commit.sh +80 -6
  388. package/hooks/dist/gsd-windsurf-pre-command.js +16 -11
  389. package/hooks/dist/gsd-windsurf-pre-write.js +22 -13
  390. package/hooks/dist/gsd-workflow-guard.js +162 -46
  391. package/hooks/dist/gsd-worktree-path-guard.js +36 -21
  392. package/hooks/dist/gsd-write-guard.js +35 -25
  393. package/hooks/dist/lib/cli-exit.js +560 -0
  394. package/hooks/dist/lib/exit-code-registry.js +98 -0
  395. package/hooks/dist/lib/git-cmd.js +92 -59
  396. package/hooks/dist/lib/git-probe.js +84 -0
  397. package/hooks/dist/lib/hook-exit.js +81 -0
  398. package/hooks/dist/lib/injection-patterns.js +45 -0
  399. package/hooks/dist/lib/isolation-deny-reason.js +39 -0
  400. package/hooks/dist/lib/isolation-sentinel.js +9 -0
  401. package/hooks/dist/managed-hooks-registry.cjs +3 -0
  402. package/hooks/gsd-agent-isolation-guard.js +158 -30
  403. package/hooks/gsd-check-update-worker.js +56 -13
  404. package/hooks/gsd-check-update.js +19 -1
  405. package/hooks/gsd-config-reload.js +18 -12
  406. package/hooks/gsd-context-monitor.js +19 -10
  407. package/hooks/gsd-cursor-post-tool.js +3 -1
  408. package/hooks/gsd-cursor-pre-tool.js +2 -3
  409. package/hooks/gsd-cursor-session-start.js +2 -1
  410. package/hooks/gsd-cursor-stop.js +2 -1
  411. package/hooks/gsd-cursor-subagent-start.js +83 -3
  412. package/hooks/gsd-cursor-subagent-stop.js +6 -3
  413. package/hooks/gsd-ensure-canonical-path.js +2 -1
  414. package/hooks/gsd-graphify-update.sh +22 -18
  415. package/hooks/gsd-node-runner.sh +76 -0
  416. package/hooks/gsd-phase-boundary.sh +1 -0
  417. package/hooks/gsd-prompt-guard.js +37 -27
  418. package/hooks/gsd-read-guard.js +16 -7
  419. package/hooks/gsd-read-injection-scanner.js +55 -32
  420. package/hooks/gsd-session-state.sh +1 -0
  421. package/hooks/gsd-statusline.js +231 -24
  422. package/hooks/gsd-update-banner.js +22 -1
  423. package/hooks/gsd-validate-commit.sh +80 -6
  424. package/hooks/gsd-windsurf-pre-command.js +16 -11
  425. package/hooks/gsd-windsurf-pre-write.js +22 -13
  426. package/hooks/gsd-workflow-guard.js +162 -46
  427. package/hooks/gsd-worktree-path-guard.js +36 -21
  428. package/hooks/gsd-write-guard.js +35 -25
  429. package/hooks/lib/cli-exit.js +560 -0
  430. package/hooks/lib/exit-code-registry.js +98 -0
  431. package/hooks/lib/git-cmd.js +92 -59
  432. package/hooks/lib/git-probe.js +84 -0
  433. package/hooks/lib/hook-exit.js +81 -0
  434. package/hooks/lib/injection-patterns.js +45 -0
  435. package/hooks/lib/isolation-deny-reason.js +39 -0
  436. package/hooks/lib/isolation-sentinel.js +9 -0
  437. package/hooks/managed-hooks-registry.cjs +3 -0
  438. package/package.json +28 -11
  439. package/pi/gsd.cjs +19 -5
  440. package/scripts/base64-scan.sh +74 -12
  441. package/scripts/baselines/planning-prompt-drift-baseline.json +4 -0
  442. package/scripts/baselines/planning-snapshot-bypass-baseline.json +12 -0
  443. package/scripts/baselines/unreachable-guard-drift-baseline.json +4 -0
  444. package/scripts/build-hooks.js +5 -0
  445. package/scripts/changeset/lint.cjs +60 -5
  446. package/scripts/check-alias-drift.cjs +7 -43
  447. package/scripts/check-contract-drift.cjs +297 -0
  448. package/scripts/check-glossary-refs.cjs +77 -15
  449. package/scripts/check-mutation-score-ratchet.cjs +156 -0
  450. package/scripts/ci-check-job-near-cap.cjs +49 -0
  451. package/scripts/ci-pr-mergeability.cjs +262 -0
  452. package/scripts/ci-test-scope.cjs +64 -14
  453. package/scripts/ci-timeout-report.cjs +230 -0
  454. package/scripts/command-contract-helpers.cjs +903 -1
  455. package/scripts/docs-guard-registry.cjs +396 -0
  456. package/scripts/gen-adr-index.cjs +728 -38
  457. package/scripts/gen-capability-registry.cjs +11 -21
  458. package/scripts/gen-context-index.cjs +2 -11
  459. package/scripts/gen-exit-code-docs.cjs +318 -0
  460. package/scripts/gen-exit-code-registry.cjs +891 -0
  461. package/scripts/gen-features.cjs +836 -0
  462. package/scripts/gen-health-docs.cjs +390 -0
  463. package/scripts/gen-hooks-cli-exit.cjs +239 -0
  464. package/scripts/gen-install-tree-fixtures.cjs +2 -2
  465. package/scripts/gen-inventory-manifest.cjs +50 -4
  466. package/scripts/gen-loop-host-contract.cjs +138 -25
  467. package/scripts/gen-registry.cjs +3 -14
  468. package/scripts/gen-scripts-cli-exit.cjs +185 -0
  469. package/scripts/gen-state-md-docs.cjs +727 -0
  470. package/scripts/{test-failure-reasons.cjs → gsd-test-gate-reasons.cjs} +6 -0
  471. package/scripts/lib/alias-drift-families.cjs +46 -0
  472. package/scripts/lib/ci-job-timing.cjs +72 -0
  473. package/scripts/lib/cli-exit.cjs +546 -44
  474. package/scripts/lib/drift-scan.cjs +308 -0
  475. package/scripts/lib/exit-code-registry.cjs +98 -0
  476. package/scripts/lib/ndjson-reporter.cjs +119 -0
  477. package/scripts/lint-allow-test-rule-refs.allowlist.json +1 -26
  478. package/scripts/lint-allow-test-rule-refs.effective-ceiling.json +4 -0
  479. package/scripts/lint-allow-test-rule-refs.unverified-ceiling.json +3 -0
  480. package/scripts/lint-canary-version-leak.cjs +73 -0
  481. package/scripts/lint-command-contract.cjs +96 -13
  482. package/scripts/lint-completion-predicate-drift.cjs +933 -0
  483. package/scripts/lint-completion-ratio-drift.cjs +214 -0
  484. package/scripts/lint-default-flip-documentation.cjs +193 -0
  485. package/scripts/lint-docs-guard-registration.cjs +495 -0
  486. package/scripts/lint-docs-guard-registration.exempt-baseline.cjs +193 -0
  487. package/scripts/lint-eslint-glob-coverage.allowlist.json +38 -0
  488. package/scripts/lint-eslint-glob-coverage.cjs +340 -0
  489. package/scripts/{lint-fix-has-regression-test.cjs → lint-fix-has-regression-tests.cjs} +12 -6
  490. package/scripts/lint-frontmatter-scalar-broad-grep.cjs +237 -0
  491. package/scripts/lint-health-diagnostic-rule-table.cjs +461 -0
  492. package/scripts/lint-hooks-runtime-build-seam.cjs +262 -0
  493. package/scripts/lint-milestone-window-drift.cjs +468 -0
  494. package/scripts/lint-mutation-test-derivation-drift.cjs +86 -0
  495. package/scripts/lint-phase-enumeration-drift.cjs +492 -0
  496. package/scripts/lint-plan-count-drift.cjs +318 -0
  497. package/scripts/lint-planning-artifact-writer-drift.cjs +398 -0
  498. package/scripts/lint-planning-prompt-drift.cjs +471 -0
  499. package/scripts/lint-planning-snapshot-bypass-drift.cjs +544 -0
  500. package/scripts/lint-regression-test-names.cjs +15 -13
  501. package/scripts/lint-removed-but-needed.cjs +488 -0
  502. package/scripts/lint-seam-enforcement.cjs +182 -0
  503. package/scripts/lint-slug-derivation-drift.cjs +921 -0
  504. package/scripts/lint-source-test-name-collision.cjs +241 -0
  505. package/scripts/lint-state-field-drift.cjs +805 -0
  506. package/scripts/lint-state-write-path-drift.cjs +950 -0
  507. package/scripts/lint-test-file-count.allowlist.json +137 -8
  508. package/scripts/lint-test-file-count.cjs +25 -3
  509. package/scripts/lint-unreachable-guard-drift.cjs +830 -0
  510. package/scripts/lint-vendored-deps.cjs +297 -0
  511. package/scripts/mutation-matrix.cjs +599 -50
  512. package/scripts/pr-changed-files.cjs +63 -0
  513. package/scripts/pr-template-policy.cjs +14 -4
  514. package/scripts/prompt-injection-scan.sh +100 -14
  515. package/scripts/require-issue-link-policy.cjs +192 -0
  516. package/scripts/secret-scan.sh +75 -13
  517. package/scripts/select-docs-guards.cjs +56 -0
  518. package/scripts/sync-runtime-launcher.cjs +24 -7
  519. package/skills/gsd-autonomous/SKILL.md +0 -1
  520. package/skills/gsd-code-review/SKILL.md +1 -1
  521. package/skills/gsd-discuss-phase/SKILL.md +1 -1
  522. package/skills/gsd-execute-phase/SKILL.md +1 -2
  523. package/skills/gsd-import/SKILL.md +1 -1
  524. package/skills/gsd-map-codebase/SKILL.md +1 -1
  525. package/skills/gsd-mempalace-capture/SKILL.md +1 -1
  526. package/skills/gsd-mempalace-recall/SKILL.md +1 -1
  527. package/skills/gsd-new-milestone/SKILL.md +1 -1
  528. package/skills/gsd-next/SKILL.md +0 -1
  529. package/skills/gsd-plan-phase/SKILL.md +0 -1
  530. package/skills/gsd-progress/SKILL.md +0 -1
  531. package/skills/gsd-quick/SKILL.md +9 -5
  532. package/skills/gsd-review-backlog/SKILL.md +2 -1
  533. package/skills/gsd-stats/SKILL.md +0 -1
  534. package/skills/gsd-verify-work/SKILL.md +1 -1
  535. package/vscode/package.json +1 -1
  536. package/bin/lib/ui-safety-gate.cjs +0 -107
  537. package/gsd-core/workflows/discovery-phase.md +0 -298
  538. package/gsd-core/workflows/plan-milestone-gaps.md +0 -281
  539. package/gsd-core/workflows/verify-phase.md +0 -574
  540. package/scripts/affected-tests-lib.cjs +0 -554
  541. package/scripts/lint-allow-test-rule-refs.cjs +0 -162
  542. package/scripts/lint-emitted-drift-ack.cjs +0 -344
  543. package/scripts/run-affected-tests.cjs +0 -7
  544. package/scripts/run-tests.cjs +0 -1051
@@ -32,6 +32,9 @@ exports.analyzeCoverage = analyzeCoverage;
32
32
  exports.proposeElements = proposeElements;
33
33
  exports.autoResolve = autoResolve;
34
34
  const probe_core_cjs_1 = require("./probe-core.cjs");
35
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
36
+ const cliExitModule = require("./cli-exit.cjs");
37
+ const { runMain } = cliExitModule;
35
38
  /**
36
39
  * Word-boundary cues mapping element prose -> UI element kind.
37
40
  * Heuristic and intentionally lossy; an authored `elements` array overrides it. Every pattern is a
@@ -245,5 +248,10 @@ function autoResolve(items) {
245
248
  * so it runs only when the compiled `.cjs` is executed directly.
246
249
  */
247
250
  if (require.main === module) {
248
- (0, probe_core_cjs_1.runProbeCli)((elements, resolutions) => analyzeCoverage(elements, resolutions), { usage: 'ui-consideration-probe.cjs <elements.json> [resolutions.json]' });
251
+ // runProbeCli's default `exit` now throws ExitError (src/probe-core.cts) rather
252
+ // than calling process.exit directly, so this entry point must run under
253
+ // runMain to translate that throw into process.exitCode.
254
+ runMain(() => {
255
+ (0, probe_core_cjs_1.runProbeCli)((elements, resolutions) => analyzeCoverage(elements, resolutions), { usage: 'ui-consideration-probe.cjs <elements.json> [resolutions.json]' });
256
+ });
249
257
  }
@@ -0,0 +1,157 @@
1
+ "use strict";
2
+ /**
3
+ * Static frontend-evidence detector — plan-time structural corroboration for the
4
+ * UI plan gate (#3312).
5
+ *
6
+ * `checkUiPresence` (ui-safety-gate.cjs) is a *vocabulary* signal: a hyphen is a
7
+ * word boundary, so a phase section naming the repo `dashboard-financeiro` matches
8
+ * the token `dashboard` exactly like the real UI compound `micro-frontend` does.
9
+ * That boundary rule is intentional (#3718) and must not be weakened — instead,
10
+ * the plan gate (`computeUiPlanGate` in check-command-router.cjs) corroborates the
11
+ * token match against the static repo tree before blocking.
12
+ *
13
+ * This mirrors what the sibling post-wave gate (`computeUiSafetyGate`) already
14
+ * does dynamically: it blocks only when `git diff HEAD~1 HEAD` touches UI files.
15
+ * Plan time has no diff to inspect, so the corroboration here is static:
16
+ *
17
+ * (a) a `package.json` (root) with a known UI-framework dependency — a project
18
+ * that ships react/vue/svelte/... in its manifest is a frontend regardless
19
+ * of file layout;
20
+ * (b) any `*.tsx` / `*.jsx` / `*.vue` / `*.svelte` file in the tree — the
21
+ * component-framework subset of `UI_FILE_EXTENSIONS_RE`
22
+ * (check-command-router.cjs). The weaker members of that list (css, scss,
23
+ * html, ...) are deliberately NOT static evidence: docs sites and
24
+ * markdown/bash/config repos routinely carry stray `.html`/`.css`, which
25
+ * is precisely the false-positive class #3312 reports.
26
+ *
27
+ * All I/O failures degrade to `false` (no evidence) — never throw.
28
+ */
29
+ var __importDefault = (this && this.__importDefault) || function (mod) {
30
+ return (mod && mod.__esModule) ? mod : { "default": mod };
31
+ };
32
+ Object.defineProperty(exports, "__esModule", { value: true });
33
+ exports.UI_COMPONENT_FILE_RE = void 0;
34
+ exports.hasStaticFrontendEvidence = hasStaticFrontendEvidence;
35
+ const node_fs_1 = __importDefault(require("node:fs"));
36
+ const node_path_1 = __importDefault(require("node:path"));
37
+ /** Component-framework file extensions — the static-evidence subset of UI_FILE_EXTENSIONS_RE. */
38
+ exports.UI_COMPONENT_FILE_RE = /\.(tsx|jsx|vue|svelte)$/i;
39
+ /**
40
+ * UI-framework package.json dependencies (dependencies OR devDependencies).
41
+ * Component frameworks/renderers only — deliberately excludes meta tooling
42
+ * (typescript, eslint, ...) that non-frontend Node projects also carry.
43
+ */
44
+ const UI_FRAMEWORK_DEPS = new Set([
45
+ 'react',
46
+ 'react-dom',
47
+ 'vue',
48
+ 'svelte',
49
+ '@sveltejs/kit',
50
+ 'angular',
51
+ '@angular/core',
52
+ 'preact',
53
+ 'solid-js',
54
+ 'lit',
55
+ 'lit-element',
56
+ 'ember-source',
57
+ '@remix-run/react',
58
+ 'react-native',
59
+ 'expo',
60
+ 'next',
61
+ 'nuxt',
62
+ 'gatsby',
63
+ 'astro',
64
+ '@ionic/react',
65
+ '@ionic/vue',
66
+ '@ionic/angular',
67
+ ]);
68
+ /** Directories never walked — dependencies, VCS data, build output, GSD planning state. */
69
+ const SKIP_DIRS = new Set([
70
+ 'node_modules',
71
+ '.git',
72
+ '.planning',
73
+ 'dist',
74
+ 'build',
75
+ 'out',
76
+ '.next',
77
+ '.nuxt',
78
+ '.output',
79
+ 'coverage',
80
+ 'vendor',
81
+ '.cache',
82
+ ]);
83
+ /** Walk safety cap — beyond this the tree is treated as scanned (evidence decided by then). */
84
+ const MAX_WALK_ENTRIES = 10_000;
85
+ function packageJsonHasUiFramework(projectDir) {
86
+ let raw;
87
+ try {
88
+ raw = node_fs_1.default.readFileSync(node_path_1.default.join(projectDir, 'package.json'), 'utf8');
89
+ }
90
+ catch {
91
+ return false; // no/unreadable package.json → no evidence from this signal
92
+ }
93
+ let parsed;
94
+ try {
95
+ parsed = JSON.parse(raw);
96
+ }
97
+ catch {
98
+ return false; // malformed package.json → no evidence from this signal
99
+ }
100
+ if (parsed === null || typeof parsed !== 'object')
101
+ return false;
102
+ const pkg = parsed;
103
+ for (const field of ['dependencies', 'devDependencies', 'peerDependencies']) {
104
+ const deps = pkg[field];
105
+ if (deps === null || typeof deps !== 'object')
106
+ continue;
107
+ for (const name of Object.keys(deps)) {
108
+ if (UI_FRAMEWORK_DEPS.has(name))
109
+ return true;
110
+ }
111
+ }
112
+ return false;
113
+ }
114
+ function treeHasComponentFile(projectDir) {
115
+ // Iterative BFS — bounded by MAX_WALK_ENTRIES so a pathological tree cannot
116
+ // stall the gate. Symlinks are never followed (withFileTypes + isDirectory).
117
+ const queue = [projectDir];
118
+ let visited = 0;
119
+ while (queue.length > 0 && visited < MAX_WALK_ENTRIES) {
120
+ const dir = queue.shift();
121
+ let entries;
122
+ try {
123
+ entries = node_fs_1.default.readdirSync(dir, { withFileTypes: true });
124
+ }
125
+ catch {
126
+ continue; // unreadable directory → skip it
127
+ }
128
+ for (const entry of entries) {
129
+ visited++;
130
+ if (visited >= MAX_WALK_ENTRIES)
131
+ return false;
132
+ if (entry.isDirectory()) {
133
+ if (!SKIP_DIRS.has(entry.name))
134
+ queue.push(node_path_1.default.join(dir, entry.name));
135
+ }
136
+ else if (entry.isFile() && exports.UI_COMPONENT_FILE_RE.test(entry.name)) {
137
+ return true;
138
+ }
139
+ }
140
+ }
141
+ return false;
142
+ }
143
+ /**
144
+ * Does the project tree carry static evidence of a frontend?
145
+ *
146
+ * @param projectDir - Absolute path to the project root (the gate's cwd).
147
+ * @returns true when package.json declares a UI-framework dependency or the
148
+ * tree contains a component-framework file; false otherwise (including
149
+ * on any I/O failure — evidence must be affirmative).
150
+ */
151
+ function hasStaticFrontendEvidence(projectDir) {
152
+ if (typeof projectDir !== 'string' || projectDir === '')
153
+ return false;
154
+ if (packageJsonHasUiFramework(projectDir))
155
+ return true;
156
+ return treeHasComponentFile(projectDir);
157
+ }
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  /**
3
3
  * UI Safety Gate — shell-free implementation (ADR-457 build-at-publish: the
4
- * hand-written bin/lib/ui-safety-gate.cjs collapsed to a TypeScript source of
4
+ * hand-written root copy of this file collapsed to a TypeScript source of
5
5
  * truth). Behaviour is preserved byte-for-behaviour from the prior hand-written
6
6
  * .cjs; only types are added.
7
7
  *
@@ -17,17 +17,22 @@
17
17
  * matched; "micro-frontend" and "micro frontend" ARE matched).
18
18
  *
19
19
  * Public API:
20
- * checkUiPresence(text: string): { hasUI: boolean, tokens: string[] }
20
+ * checkUiPresence(text: string): { hasUI: boolean, tokens: string[],
21
+ * matchedToken: string|null, matchedLine: string|null }
21
22
  *
22
23
  * CLI usage — reads phase-section text from STDIN to avoid ARG_MAX limits:
23
24
  * echo "$PHASE_SECTION" | node gsd-core/bin/lib/ui-safety-gate.cjs
24
- * echo $? → 0 if UI tokens found, 1 if not, 2 on usage error
25
+ * echo $? → 0 if UI tokens found, 1 if not (real input, none found),
26
+ * NO_INPUT (registry, src/cli-exit.cts) if stdin was empty or
27
+ * whitespace-only, UNAVAILABLE (registry) if stdin read failed
28
+ * (ADR-3889 Phase 3, #3907)
25
29
  *
26
- * Exit codes mirror grep: 0 = match found, 1 = no match, 2 = usage error.
27
30
  *
28
31
  * Canonical location: gsd-core/bin/lib/ui-safety-gate.cjs (#448)
29
32
  * This path is deployed by the GSD installer to $RUNTIME_DIR/gsd-core/bin/lib/.
30
- * bin/lib/ui-safety-gate.cjs (root) is retained for source-repo and npm usage.
33
+ * The former root-level copy of this file (outside gsd-core/) was removed in
34
+ * #3907 as dead code: no installer reference, no workflow invocation, and no
35
+ * fallback chain in shipped content ever pointed at it. Do not re-create it.
31
36
  */
32
37
  Object.defineProperty(exports, "__esModule", { value: true });
33
38
  exports.UI_TOKENS = void 0;
@@ -63,7 +68,7 @@ const UI_GATE_PATTERN_GLOBAL = new RegExp(UI_GATE_PATTERN.source, 'gi');
63
68
  */
64
69
  function checkUiPresence(text) {
65
70
  if (typeof text !== 'string') {
66
- return { hasUI: false, tokens: [] };
71
+ return { hasUI: false, tokens: [], matchedToken: null, matchedLine: null };
67
72
  }
68
73
  // Normalise CRLF so the pattern sees consistent line boundaries.
69
74
  const normalised = text.replace(/\r\n/g, '\n');
@@ -84,37 +89,71 @@ function checkUiPresence(text) {
84
89
  .filter((line) => !/^\s*\*\*UI hint\*\*\s*:/i.test(line))
85
90
  .join('\n');
86
91
  const found = new Set();
92
+ let matchedToken = null;
93
+ let matchedLine = null;
87
94
  for (const line of sniffable.split('\n')) {
88
95
  // Reset lastIndex before each line so the global pattern restarts from 0.
89
96
  UI_GATE_PATTERN_GLOBAL.lastIndex = 0;
90
97
  for (const m of line.matchAll(UI_GATE_PATTERN_GLOBAL)) {
98
+ if (matchedToken === null) {
99
+ // #3312: record the FIRST match so gate consumers can surface the
100
+ // triggering token/line for one-second operator triage.
101
+ matchedToken = m[2].toLowerCase();
102
+ matchedLine = line;
103
+ }
91
104
  found.add(m[2].toLowerCase());
92
105
  }
93
106
  }
94
107
  if (hint === 'no') {
95
- return { hasUI: false, tokens: [] };
108
+ return { hasUI: false, tokens: [], matchedToken: null, matchedLine: null };
96
109
  }
97
110
  if (hint === 'yes') {
98
- return { hasUI: true, tokens: [...found] };
111
+ return { hasUI: true, tokens: [...found], matchedToken, matchedLine };
99
112
  }
100
- return { hasUI: found.size > 0, tokens: [...found] };
113
+ return { hasUI: found.size > 0, tokens: [...found], matchedToken, matchedLine };
101
114
  }
102
115
  // ── CLI entry point ─────────────────────────────────────────────────────────
103
116
  // Reads phase-section text from STDIN (not argv) to avoid OS ARG_MAX limits.
104
117
  // Invoked by workflow .md bash blocks as: echo "$PHASE_SECTION" | node .../ui-safety-gate.cjs
105
- // Exit 0 = UI found, 1 = no UI, 2 = startup error.
118
+ //
119
+ // Exit codes (ADR-3889 Phase 3, #3907): 0 = UI found, 1 = no UI (real input,
120
+ // examined, nothing found), NO_INPUT (registry — see src/cli-exit.cts) = stdin
121
+ // closed with zero bytes (or whitespace-only), UNAVAILABLE (registry) = stdin
122
+ // read failed. The prior single "2 = startup error" arm conflated "I was
123
+ // handed nothing" with "the phase says it has no UI" — those are different
124
+ // answers; only the former is new here. `hint === 'no'` on REAL input still
125
+ // exits 1 — that is the author's own declaration, not an empty-input
126
+ // artifact.
127
+ //
128
+ // Terminates via terminateNow (src/cli-exit.cts), not raw process.exit: these
129
+ // exits fire from inside a stdin event handler, which is exactly what
130
+ // terminateNow (write-then-terminate) exists for, and it is total (cannot
131
+ // throw or return). This module never emits --json, so every payload here is
132
+ // `undefined` — terminateNow's JSON.stringify(undefined) is not a valid
133
+ // Buffer source and is swallowed by its own emission-failure guard, so
134
+ // nothing is written to stdout, preserving this CLI's historical contract of
135
+ // silence.
106
136
  if (require.main === module) {
137
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
138
+ const cliExit = require('./cli-exit.cjs');
107
139
  // Collect stdin chunks asynchronously.
108
140
  const chunks = [];
109
141
  process.stdin.setEncoding('utf-8');
110
142
  process.stdin.on('data', (chunk) => chunks.push(chunk));
111
143
  process.stdin.on('end', () => {
112
144
  const input = chunks.join('');
145
+ // Whitespace-only counts as empty (ADR-3889 §1's NO_INPUT: "zero units
146
+ // were in scope, and that emptiness is known to be genuine"). Real input
147
+ // — including a lone NUL byte, which .trim() does not strip — always
148
+ // falls through to the detector.
149
+ if (input.trim().length === 0) {
150
+ cliExit.terminateNow('NO_INPUT', undefined);
151
+ }
113
152
  const result = checkUiPresence(input);
114
- process.exit(result.hasUI ? 0 : 1);
153
+ cliExit.terminateNow(result.hasUI ? 'PASS' : 'FAIL', undefined);
115
154
  });
116
155
  process.stdin.on('error', (err) => {
117
156
  process.stderr.write(`ERROR: ui-safety-gate.cjs stdin read failed: ${err.message}\n`);
118
- process.exit(2);
157
+ cliExit.terminateNow('UNAVAILABLE', undefined);
119
158
  });
120
159
  }
@@ -58,12 +58,49 @@ const UNUSABLE_REASON = Object.freeze({
58
58
  * silent degradation is visible. (#3099, sixth #1879 site)
59
59
  */
60
60
  LAST_ACTIVITY_UNPARSEABLE: 'last_activity_unparseable',
61
+ /**
62
+ * A STATE.md exists but could not be read (EACCES/EIO/…). Distinct from a project that has
63
+ * not run `state.init` yet: absence returns the same non-answer, silently — only an
64
+ * exists-but-unreadable STATE.md is corruption. (#3308, seventh #1879 site —
65
+ * planning-snapshot's current-phase field)
66
+ */
67
+ STATE_UNREADABLE: 'state_unreadable',
68
+ /**
69
+ * A config.json exists but could not be read/parsed (EACCES/EIO/malformed JSON/…).
70
+ * Distinct from a project that has not run any config-writing command yet: absence
71
+ * returns the same non-answer, silently — only an exists-but-unreadable config.json
72
+ * is corruption. (#3309, eighth #1879 site — planning-snapshot's config field)
73
+ */
74
+ CONFIG_UNREADABLE: 'config_unreadable',
75
+ /**
76
+ * A PROJECT.md exists but could not be read (EACCES/EIO/…). Distinct from a project that has
77
+ * not run any project-writing command yet: absence returns the same non-answer, silently —
78
+ * only an exists-but-unreadable PROJECT.md is corruption. (#3309, ninth #1879 site —
79
+ * planning-snapshot's projectSections field)
80
+ */
81
+ PROJECT_UNREADABLE: 'project_unreadable',
82
+ /**
83
+ * A config.json parsed cleanly, but a section that a legacy-key migration needed to write
84
+ * into (`git`, `planning`) holds something that is not an object — a string, number, boolean
85
+ * or array. Distinct from the section being absent: absence is the ordinary path and the
86
+ * migration simply creates the section. Only a PRESENT non-object is corruption, and it is
87
+ * exactly the ADR-227 "shape, not just parseability" class one level down from the top-level
88
+ * document check `_readConfigFile` already performs. The migration is refused rather than
89
+ * applied — spreading the value would enumerate a string into character keys, and a number
90
+ * or boolean into nothing at all — so the section, the legacy key, and the file on disk are
91
+ * all left exactly as the user wrote them. (#3760, tenth #1879 site)
92
+ */
93
+ CONFIG_SECTION_NOT_OBJECT: 'config_section_not_object',
61
94
  });
62
95
  /** One human-readable clause per reason. Prose lives here, never in a test assertion. */
63
96
  const REASON_PROSE = Object.freeze({
64
97
  [UNUSABLE_REASON.FRONTMATTER_UNTERMINATED]: 'frontmatter opens with "---" but never closes; metadata was NOT applied',
65
98
  [UNUSABLE_REASON.ROADMAP_UNREADABLE]: 'ROADMAP.md exists but could not be read; phase and milestone lookups fell back to defaults',
66
99
  [UNUSABLE_REASON.LAST_ACTIVITY_UNPARSEABLE]: 'last_activity in STATE.md is present but unparseable as a date; stale_activity fell back to false (idle-stranded suppressed)',
100
+ [UNUSABLE_REASON.STATE_UNREADABLE]: 'STATE.md exists but could not be read; the current-phase label fell back to unavailable',
101
+ [UNUSABLE_REASON.CONFIG_UNREADABLE]: 'config.json exists but could not be read or parsed; the config field fell back to unavailable',
102
+ [UNUSABLE_REASON.PROJECT_UNREADABLE]: 'PROJECT.md exists but could not be read; the projectSections field fell back to unavailable',
103
+ [UNUSABLE_REASON.CONFIG_SECTION_NOT_OBJECT]: 'a config section that a legacy-key migration targets holds a non-object value; the migration was SKIPPED and both the section and the legacy key were left unchanged — fix the section by hand, or the legacy key will never migrate',
67
104
  });
68
105
  // ─── Dedup state ──────────────────────────────────────────────────────────────
69
106
  /**
@@ -10,7 +10,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
10
10
  return (mod && mod.__esModule) ? mod : { "default": mod };
11
11
  };
12
12
  Object.defineProperty(exports, "__esModule", { value: true });
13
- exports.RUNTIME_DIRS = void 0;
13
+ exports.CODEX_CONFIG_MARKER = exports.RUNTIME_DIRS = void 0;
14
14
  exports.inferPreferredRuntime = inferPreferredRuntime;
15
15
  exports.envRuntimeDirs = envRuntimeDirs;
16
16
  exports.resolveUpdateContext = resolveUpdateContext;
@@ -38,6 +38,12 @@ exports.RUNTIME_DIRS = [
38
38
  ['codex', '.codex'],
39
39
  ];
40
40
  const SEMVER_PREFIX = /^\d+\.\d+\.\d+/;
41
+ // Shared Codex config-root marker filename. Single-sourced here (this module
42
+ // is the pre-existing, dependency-free owner) and re-exported by
43
+ // host-runtime-detection.cts, whose detection rung reuses this exact probe
44
+ // filename (though NOT the truthiness rule below — see that module's header
45
+ // comment for the deliberate divergence).
46
+ exports.CODEX_CONFIG_MARKER = 'config.toml';
41
47
  function expandHome(p, home) {
42
48
  if (!p)
43
49
  return '';
@@ -72,7 +78,7 @@ function inferPreferredRuntime({ fs, env, preferredConfigDir }) {
72
78
  if (fs.exists(node_path_1.default.join(preferredConfigDir, 'opencode.json')) ||
73
79
  fs.exists(node_path_1.default.join(preferredConfigDir, 'opencode.jsonc')))
74
80
  return 'opencode';
75
- if (fs.exists(node_path_1.default.join(preferredConfigDir, 'config.toml')))
81
+ if (fs.exists(node_path_1.default.join(preferredConfigDir, exports.CODEX_CONFIG_MARKER)))
76
82
  return 'codex';
77
83
  }
78
84
  if (env['CODEX_HOME'])