@opengsd/gsd-core 1.9.1 → 1.11.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 (426) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +2 -3
  3. package/.opencode/plugins/gsd-core.js +8 -1
  4. package/agents/gsd-code-fixer.md +27 -3
  5. package/agents/gsd-debug-session-manager.md +11 -0
  6. package/agents/gsd-debugger.md +12 -246
  7. package/agents/gsd-doc-synthesizer.md +2 -4
  8. package/agents/gsd-executor.md +12 -10
  9. package/agents/gsd-integration-checker.md +3 -0
  10. package/agents/gsd-mempalace-curator.md +5 -2
  11. package/agents/gsd-phase-researcher.md +20 -1
  12. package/agents/gsd-plan-checker.md +46 -0
  13. package/agents/gsd-planner.md +49 -54
  14. package/agents/gsd-roadmapper.md +21 -3
  15. package/agents/gsd-user-profiler.md +3 -0
  16. package/agents/gsd-verifier.md +26 -73
  17. package/bin/install.js +1272 -1238
  18. package/bin/lib/ui-safety-gate.cjs +2 -0
  19. package/commands/gsd/code-review.md +1 -1
  20. package/commands/gsd/execute-phase.md +1 -1
  21. package/commands/gsd/map-codebase.md +1 -1
  22. package/commands/gsd/mempalace-capture.md +2 -2
  23. package/commands/gsd/mempalace-recall.md +1 -1
  24. package/commands/gsd/new-milestone.md +2 -2
  25. package/commands/gsd/plan-phase.md +1 -1
  26. package/commands/gsd/quick.md +1 -1
  27. package/commands/gsd/review-backlog.md +2 -1
  28. package/commands/gsd/verify-work.md +1 -1
  29. package/gsd-core/bin/gsd-tools.cjs +1009 -115
  30. package/gsd-core/bin/lib/active-workstream-store.cjs +153 -12
  31. package/gsd-core/bin/lib/agent-install-check.cjs +268 -38
  32. package/gsd-core/bin/lib/api-coverage.cjs +123 -5
  33. package/gsd-core/bin/lib/artifacts.cjs +3 -0
  34. package/gsd-core/bin/lib/assumption-delta.cjs +2 -4
  35. package/gsd-core/bin/lib/audit-command-router.cjs +9 -2
  36. package/gsd-core/bin/lib/audit.cjs +926 -202
  37. package/gsd-core/bin/lib/broken-windows.cjs +36 -6
  38. package/gsd-core/bin/lib/capability-consent.cjs +149 -15
  39. package/gsd-core/bin/lib/capability-lifecycle.cjs +45 -0
  40. package/gsd-core/bin/lib/capability-registry.cjs +608 -148
  41. package/gsd-core/bin/lib/capability-source.cjs +92 -0
  42. package/gsd-core/bin/lib/capability-trust.cjs +444 -25
  43. package/gsd-core/bin/lib/capability-validator.cjs +507 -24
  44. package/gsd-core/bin/lib/capability-writer.cjs +3 -2
  45. package/gsd-core/bin/lib/check-command-router.cjs +114 -38
  46. package/gsd-core/bin/lib/claude-orchestration.cjs +56 -3
  47. package/gsd-core/bin/lib/codex-agent-toml.cjs +329 -0
  48. package/gsd-core/bin/lib/command-aliases.cjs +94 -0
  49. package/gsd-core/bin/lib/command-roster.cjs +44 -1
  50. package/gsd-core/bin/lib/commands.cjs +665 -99
  51. package/gsd-core/bin/lib/commonjs-marker.cjs +142 -0
  52. package/gsd-core/bin/lib/complexity-trigger.cjs +1172 -0
  53. package/gsd-core/bin/lib/config-loader.cjs +76 -0
  54. package/gsd-core/bin/lib/config.cjs +22 -2
  55. package/gsd-core/bin/lib/context-composer.cjs +278 -0
  56. package/gsd-core/bin/lib/context-predicates.cjs +506 -0
  57. package/gsd-core/bin/lib/core-utils.cjs +217 -40
  58. package/gsd-core/bin/lib/decisions.cjs +23 -0
  59. package/gsd-core/bin/lib/docs.cjs +3 -2
  60. package/gsd-core/bin/lib/external-job.cjs +19 -4
  61. package/gsd-core/bin/lib/fallow-runner.cjs +20 -44
  62. package/gsd-core/bin/lib/frontmatter.cjs +239 -32
  63. package/gsd-core/bin/lib/gap-checker.cjs +68 -7
  64. package/gsd-core/bin/lib/gate-predicate-evaluator.cjs +57 -6
  65. package/gsd-core/bin/lib/git-base-branch.cjs +160 -15
  66. package/gsd-core/bin/lib/graphify.cjs +142 -27
  67. package/gsd-core/bin/lib/gsd2-import.cjs +37 -5
  68. package/gsd-core/bin/lib/health-diagnostic-rules/agent-install.cjs +101 -0
  69. package/gsd-core/bin/lib/health-diagnostic-rules/config-validation.cjs +348 -0
  70. package/gsd-core/bin/lib/health-diagnostic-rules/consistency.cjs +145 -0
  71. package/gsd-core/bin/lib/health-diagnostic-rules/install-surface-shadowing.cjs +98 -0
  72. package/gsd-core/bin/lib/health-diagnostic-rules/milestone-archive-hygiene.cjs +100 -0
  73. package/gsd-core/bin/lib/health-diagnostic-rules/phase-structure.cjs +222 -0
  74. package/gsd-core/bin/lib/health-diagnostic-rules/roadmap-disk-consistency.cjs +265 -0
  75. package/gsd-core/bin/lib/health-diagnostic-rules/root-existence.cjs +161 -0
  76. package/gsd-core/bin/lib/health-diagnostic-rules/state-consistency.cjs +303 -0
  77. package/gsd-core/bin/lib/health-diagnostic-rules/worktree-health.cjs +173 -0
  78. package/gsd-core/bin/lib/health-diagnostic-types.cjs +68 -0
  79. package/gsd-core/bin/lib/health-diagnostic.cjs +431 -0
  80. package/gsd-core/bin/lib/host-integration.cjs +13 -1
  81. package/gsd-core/bin/lib/host-runtime-detection.cjs +134 -0
  82. package/gsd-core/bin/lib/init-command-router.cjs +83 -8
  83. package/gsd-core/bin/lib/init.cjs +1325 -169
  84. package/gsd-core/bin/lib/install-effort-resolver.cjs +73 -30
  85. package/gsd-core/bin/lib/install-engine.cjs +805 -264
  86. package/gsd-core/bin/lib/install-fs-adapter.cjs +262 -0
  87. package/gsd-core/bin/lib/install-model-override-resolver.cjs +203 -0
  88. package/gsd-core/bin/lib/install-profiles.cjs +160 -57
  89. package/gsd-core/bin/lib/install-scope.cjs +270 -0
  90. package/gsd-core/bin/lib/install-shadow-report.cjs +385 -0
  91. package/gsd-core/bin/lib/installed-surface-resolver.cjs +381 -0
  92. package/gsd-core/bin/lib/installer-migration-authoring.cjs +3 -1
  93. package/gsd-core/bin/lib/installer-migration-report.cjs +4 -0
  94. package/gsd-core/bin/lib/installer-migrations/007-retire-config-root-commonjs-marker.cjs +149 -0
  95. package/gsd-core/bin/lib/installer-migrations/008-cursor-retire-commands-surface.cjs +55 -0
  96. package/gsd-core/bin/lib/installer-migrations/009-pi-retire-reserved-hooks-dir.cjs +199 -0
  97. package/gsd-core/bin/lib/installer-migrations.cjs +206 -13
  98. package/gsd-core/bin/lib/io.cjs +38 -3
  99. package/gsd-core/bin/lib/markdown-sectionizer.cjs +8 -1
  100. package/gsd-core/bin/lib/markdown-table.cjs +133 -20
  101. package/gsd-core/bin/lib/mcp-catalog.cjs +518 -0
  102. package/gsd-core/bin/lib/mcp-server.cjs +135 -3
  103. package/gsd-core/bin/lib/milestone-lock.cjs +248 -0
  104. package/gsd-core/bin/lib/milestone.cjs +821 -109
  105. package/gsd-core/bin/lib/model-catalog.cjs +59 -1
  106. package/gsd-core/bin/lib/model-resolver.cjs +183 -40
  107. package/gsd-core/bin/lib/normalize-test-command.cjs +1 -1
  108. package/gsd-core/bin/lib/pattern.cjs +122 -0
  109. package/gsd-core/bin/lib/phase-estimation.cjs +1 -1
  110. package/gsd-core/bin/lib/phase-id.cjs +507 -36
  111. package/gsd-core/bin/lib/phase-lifecycle.cjs +28 -3
  112. package/gsd-core/bin/lib/phase-locator.cjs +258 -58
  113. package/gsd-core/bin/lib/phase.cjs +891 -156
  114. package/gsd-core/bin/lib/plan-dependency-graph.cjs +303 -0
  115. package/gsd-core/bin/lib/plan-drift-guard.cjs +120 -0
  116. package/gsd-core/bin/lib/plan-scan.cjs +86 -2
  117. package/gsd-core/bin/lib/planning-scope.cjs +31 -0
  118. package/gsd-core/bin/lib/planning-snapshot.cjs +890 -0
  119. package/gsd-core/bin/lib/planning-workspace.cjs +60 -6
  120. package/gsd-core/bin/lib/probe-core.cjs +1 -1
  121. package/gsd-core/bin/lib/profile-output.cjs +1 -1
  122. package/gsd-core/bin/lib/prompt-budget.cjs +128 -165
  123. package/gsd-core/bin/lib/refactor-trigger-command-router.cjs +740 -0
  124. package/gsd-core/bin/lib/retired-artifact-cleanup.cjs +85 -0
  125. package/gsd-core/bin/lib/review-lane-descriptor.cjs +108 -0
  126. package/gsd-core/bin/lib/review-lane-invocation.cjs +30 -0
  127. package/gsd-core/bin/lib/review-lane-runner.cjs +447 -68
  128. package/gsd-core/bin/lib/review-reviewer-selection.cjs +13 -18
  129. package/gsd-core/bin/lib/roadmap-command-router.cjs +76 -9
  130. package/gsd-core/bin/lib/roadmap-parser.cjs +1035 -194
  131. package/gsd-core/bin/lib/roadmap-upgrade.cjs +37 -10
  132. package/gsd-core/bin/lib/roadmap.cjs +405 -84
  133. package/gsd-core/bin/lib/runtime-artifact-conversion.cjs +795 -100
  134. package/gsd-core/bin/lib/runtime-artifact-install-plan.cjs +14 -2
  135. package/gsd-core/bin/lib/runtime-artifact-layout.cjs +440 -57
  136. package/gsd-core/bin/lib/runtime-config-adapter-registry.cjs +3 -2
  137. package/gsd-core/bin/lib/runtime-homes.cjs +220 -41
  138. package/gsd-core/bin/lib/runtime-hooks-surface.cjs +220 -44
  139. package/gsd-core/bin/lib/runtime-name-policy.cjs +3 -1
  140. package/gsd-core/bin/lib/runtime-slash.cjs +27 -9
  141. package/gsd-core/bin/lib/section-manifest.cjs +209 -0
  142. package/gsd-core/bin/lib/security.cjs +104 -5
  143. package/gsd-core/bin/lib/shell-command-projection.cjs +388 -30
  144. package/gsd-core/bin/lib/smart-entry.cjs +154 -22
  145. package/gsd-core/bin/lib/state-command-router.cjs +5 -1
  146. package/gsd-core/bin/lib/state-document.cjs +152 -8
  147. package/gsd-core/bin/lib/state-transition.cjs +424 -105
  148. package/gsd-core/bin/lib/state.cjs +1927 -401
  149. package/gsd-core/bin/lib/surface.cjs +35 -10
  150. package/gsd-core/bin/lib/text-lines.cjs +80 -0
  151. package/gsd-core/bin/lib/token-scanner.cjs +76 -0
  152. package/gsd-core/bin/lib/uat-predicate.cjs +20 -4
  153. package/gsd-core/bin/lib/uat.cjs +706 -64
  154. package/gsd-core/bin/lib/ui-frontend-evidence.cjs +157 -0
  155. package/gsd-core/bin/lib/ui-safety-gate.cjs +14 -5
  156. package/gsd-core/bin/lib/unusable-input.cjs +33 -0
  157. package/gsd-core/bin/lib/update-context.cjs +8 -2
  158. package/gsd-core/bin/lib/user-artifact-staging.cjs +705 -0
  159. package/gsd-core/bin/lib/validate.cjs +20 -6
  160. package/gsd-core/bin/lib/vendor/README.md +37 -0
  161. package/gsd-core/bin/lib/vendor/re2js.cjs +6480 -0
  162. package/gsd-core/bin/lib/vendor/re2js.d.cts +938 -0
  163. package/gsd-core/bin/lib/verification-command-router.cjs +2 -1
  164. package/gsd-core/bin/lib/verification.cjs +287 -20
  165. package/gsd-core/bin/lib/verify.cjs +368 -880
  166. package/gsd-core/bin/lib/workflow-fragments.cjs +557 -0
  167. package/gsd-core/bin/lib/workstream-inventory-builder.cjs +203 -19
  168. package/gsd-core/bin/lib/workstream-inventory.cjs +576 -31
  169. package/gsd-core/bin/lib/workstream.cjs +8 -2
  170. package/gsd-core/bin/lib/worktree-base-ref.cjs +50 -6
  171. package/gsd-core/bin/lib/worktree-safety.cjs +450 -125
  172. package/gsd-core/bin/shared/config-defaults.manifest.json +1 -0
  173. package/gsd-core/bin/shared/config-schema.manifest.json +9 -1
  174. package/gsd-core/references/agent-contracts.md +43 -26
  175. package/gsd-core/references/artifact-types.md +10 -3
  176. package/gsd-core/references/autonomous-ui-design-contract.md +42 -0
  177. package/gsd-core/references/checkpoints.md +2 -2
  178. package/gsd-core/references/context-budget.md +1 -1
  179. package/gsd-core/references/debugger-techniques.md +255 -0
  180. package/gsd-core/references/dispatch-isolation-gate.md +138 -0
  181. package/gsd-core/references/doc-conflict-engine.md +1 -1
  182. package/gsd-core/references/execute-mvp-tdd.md +3 -3
  183. package/gsd-core/references/execute-phase-between-wave-reset.md +6 -2
  184. package/gsd-core/references/execute-phase-context-guard.md +1 -1
  185. package/gsd-core/references/execute-phase-response-language.md +1 -1
  186. package/gsd-core/references/execute-phase-wave-guard.md +6 -2
  187. package/gsd-core/references/gate-prompts.md +1 -1
  188. package/gsd-core/references/git-planning-commit.md +2 -1
  189. package/gsd-core/references/loop-hook-dispatch.md +39 -2
  190. package/gsd-core/references/model-profiles.md +12 -4
  191. package/gsd-core/references/mvp-concepts.md +9 -9
  192. package/gsd-core/references/planner-guidance.md +3 -9
  193. package/gsd-core/references/planner-preconditions.md +1 -1
  194. package/gsd-core/references/planner-reviews.md +1 -1
  195. package/gsd-core/references/planning-config.md +8 -6
  196. package/gsd-core/references/research-documentation-lookup.md +5 -3
  197. package/gsd-core/references/revision-loop.md +1 -1
  198. package/gsd-core/references/specless-probe-fallback.md +8 -7
  199. package/gsd-core/references/universal-anti-patterns.md +3 -3
  200. package/gsd-core/references/verifier-phase-gates.md +192 -0
  201. package/gsd-core/references/verifier-wiring-patterns.md +100 -0
  202. package/gsd-core/references/verify-mvp-mode.md +1 -1
  203. package/gsd-core/references/workstream-flag.md +22 -6
  204. package/gsd-core/references/worktree-branch-check.md +2 -2
  205. package/gsd-core/templates/discussion-log.md +1 -1
  206. package/gsd-core/templates/phase-prompt.md +2 -4
  207. package/gsd-core/templates/state.md +4 -4
  208. package/gsd-core/templates/summary-complex.md +2 -0
  209. package/gsd-core/templates/summary-minimal.md +2 -0
  210. package/gsd-core/templates/summary-standard.md +2 -0
  211. package/gsd-core/templates/summary.md +2 -0
  212. package/gsd-core/templates/verification-report.md +9 -1
  213. package/gsd-core/workflows/ai-integration-phase.md +9 -11
  214. package/gsd-core/workflows/audit-milestone.md +3 -0
  215. package/gsd-core/workflows/autonomous/steps/converge-banner.md +1 -0
  216. package/gsd-core/workflows/autonomous/steps/converge-dispatch-bg.md +11 -0
  217. package/gsd-core/workflows/autonomous/steps/converge-dispatch-inline.md +7 -0
  218. package/gsd-core/workflows/autonomous/steps/converge-fail-fast.md +21 -0
  219. package/gsd-core/workflows/autonomous/steps/converge-loop.md +7 -0
  220. package/gsd-core/workflows/autonomous.md +33 -70
  221. package/gsd-core/workflows/cleanup.md +62 -3
  222. package/gsd-core/workflows/code-review/steps/dispatch-fix.md +39 -0
  223. package/gsd-core/workflows/code-review/steps/structural-pre-pass.md +93 -0
  224. package/gsd-core/workflows/code-review-fix.md +37 -10
  225. package/gsd-core/workflows/code-review.md +74 -166
  226. package/gsd-core/workflows/complete-milestone/steps/git-tag.md +29 -0
  227. package/gsd-core/workflows/complete-milestone.md +160 -95
  228. package/gsd-core/workflows/debug.md +16 -17
  229. package/gsd-core/workflows/diagnose-issues.md +56 -8
  230. package/gsd-core/workflows/discuss-phase/modes/chain.md +2 -1
  231. package/gsd-core/workflows/discuss-phase/modes/default.md +1 -1
  232. package/gsd-core/workflows/discuss-phase-assumptions/steps/auto-advance-dispatch.md +15 -0
  233. package/gsd-core/workflows/discuss-phase-assumptions.md +7 -17
  234. package/gsd-core/workflows/docs-update/steps/dispatch-monorepo-packages.md +51 -0
  235. package/gsd-core/workflows/docs-update.md +8 -51
  236. package/gsd-core/workflows/edit-phase.md +26 -1
  237. package/gsd-core/workflows/eval-review.md +3 -5
  238. package/gsd-core/workflows/execute-phase/steps/executor-isolation-dispatch.md +64 -7
  239. package/gsd-core/workflows/execute-phase/steps/gap-closure-artifacts.md +50 -0
  240. package/gsd-core/workflows/execute-phase/steps/partial-wave.md +31 -0
  241. package/gsd-core/workflows/execute-phase/steps/per-plan-executor-routing.md +77 -0
  242. package/gsd-core/workflows/execute-phase/steps/per-plan-worktree-gate.md +21 -0
  243. package/gsd-core/workflows/execute-phase/steps/regression-gate-run.md +42 -0
  244. package/gsd-core/workflows/execute-phase/steps/regression-gate.md +43 -37
  245. package/gsd-core/workflows/execute-phase.md +103 -187
  246. package/gsd-core/workflows/execute-plan.md +36 -4
  247. package/gsd-core/workflows/explore.md +131 -4
  248. package/gsd-core/workflows/fast.md +10 -2
  249. package/gsd-core/workflows/health.md +73 -4
  250. package/gsd-core/workflows/help/modes/full.md +6 -1
  251. package/gsd-core/workflows/import.md +4 -4
  252. package/gsd-core/workflows/ingest-docs.md +7 -6
  253. package/gsd-core/workflows/mvp-phase.md +6 -3
  254. package/gsd-core/workflows/new-milestone/steps/project-md-milestone-write.md +16 -0
  255. package/gsd-core/workflows/new-milestone/steps/reset-phase-safety.md +19 -0
  256. package/gsd-core/workflows/new-milestone.md +35 -47
  257. package/gsd-core/workflows/new-project/steps/auto-mode-config.md +176 -0
  258. package/gsd-core/workflows/new-project/steps/auto-mode-detection.md +32 -0
  259. package/gsd-core/workflows/new-project/steps/codebase-map-offer.md +18 -0
  260. package/gsd-core/workflows/new-project.md +27 -240
  261. package/gsd-core/workflows/next.md +12 -0
  262. package/gsd-core/workflows/plan-phase/steps/adr-ingest-express-path.md +15 -0
  263. package/gsd-core/workflows/plan-phase/steps/chunked-planning-mode.md +110 -0
  264. package/gsd-core/workflows/plan-phase/steps/prd-express-gate.md +8 -0
  265. package/gsd-core/workflows/plan-phase/steps/research-only-early-exit.md +17 -0
  266. package/gsd-core/workflows/plan-phase/steps/research-only-modifiers.md +16 -0
  267. package/gsd-core/workflows/plan-phase/steps/reviews-prerequisite.md +17 -0
  268. package/gsd-core/workflows/plan-phase/steps/stall-detection-helpers.md +149 -0
  269. package/gsd-core/workflows/plan-phase.md +89 -209
  270. package/gsd-core/workflows/plan-review-convergence.md +50 -2
  271. package/gsd-core/workflows/progress/steps/forensic-audit.md +125 -0
  272. package/gsd-core/workflows/progress/steps/mvp-display.md +18 -0
  273. package/gsd-core/workflows/progress.md +45 -159
  274. package/gsd-core/workflows/quick/steps/discussion-phase.md +124 -0
  275. package/gsd-core/workflows/quick/steps/plan-checker-loop.md +111 -0
  276. package/gsd-core/workflows/quick/steps/quick-verification.md +67 -0
  277. package/gsd-core/workflows/quick/steps/research-phase.md +72 -0
  278. package/gsd-core/workflows/quick/steps/worktree-pre-dispatch-commit.md +37 -0
  279. package/gsd-core/workflows/quick.md +55 -405
  280. package/gsd-core/workflows/resume-project.md +3 -0
  281. package/gsd-core/workflows/review/steps/reviewer-instances-note-1.md +4 -0
  282. package/gsd-core/workflows/review/steps/reviewer-instances-note-2.md +3 -0
  283. package/gsd-core/workflows/review.md +41 -13
  284. package/gsd-core/workflows/section-manifest.json +219 -0
  285. package/gsd-core/workflows/secure-phase.md +1 -1
  286. package/gsd-core/workflows/session-report.md +2 -1
  287. package/gsd-core/workflows/settings.md +66 -2
  288. package/gsd-core/workflows/ship.md +104 -44
  289. package/gsd-core/workflows/sketch.md +1 -1
  290. package/gsd-core/workflows/spec-phase.md +41 -20
  291. package/gsd-core/workflows/spike-wrap-up.md +20 -5
  292. package/gsd-core/workflows/spike.md +50 -16
  293. package/gsd-core/workflows/sync-skills.md +106 -13
  294. package/gsd-core/workflows/transition/steps/workstream-collision-check.md +17 -0
  295. package/gsd-core/workflows/transition.md +53 -31
  296. package/gsd-core/workflows/ui-phase.md +13 -12
  297. package/gsd-core/workflows/ui-review.md +2 -2
  298. package/gsd-core/workflows/update/steps/channel-banner.md +7 -0
  299. package/gsd-core/workflows/update.md +19 -8
  300. package/gsd-core/workflows/validate-phase.md +1 -1
  301. package/gsd-core/workflows/verify-work/steps/automated-ui-verification.md +36 -0
  302. package/gsd-core/workflows/verify-work/steps/mvp-uat-framing.md +21 -0
  303. package/gsd-core/workflows/verify-work.md +17 -65
  304. package/hooks/dist/gsd-agent-isolation-guard.js +517 -0
  305. package/hooks/dist/gsd-check-update-worker.js +64 -12
  306. package/hooks/dist/gsd-check-update.js +19 -1
  307. package/hooks/dist/gsd-cursor-pre-tool.js +0 -3
  308. package/hooks/dist/gsd-cursor-subagent-start.js +607 -26
  309. package/hooks/dist/gsd-cursor-subagent-stop.js +3 -2
  310. package/hooks/dist/gsd-prompt-guard.js +21 -20
  311. package/hooks/dist/gsd-read-injection-scanner.js +45 -24
  312. package/hooks/dist/gsd-statusline.js +90 -6
  313. package/hooks/dist/gsd-update-banner.js +22 -1
  314. package/hooks/dist/gsd-workflow-guard.js +134 -36
  315. package/hooks/dist/gsd-worktree-path-guard.js +2 -1
  316. package/hooks/dist/gsd-write-guard.js +359 -0
  317. package/hooks/dist/lib/git-cmd.js +92 -59
  318. package/hooks/dist/lib/injection-patterns.js +45 -0
  319. package/hooks/dist/lib/isolation-deny-reason.js +39 -0
  320. package/hooks/dist/lib/isolation-sentinel.js +277 -0
  321. package/hooks/dist/managed-hooks-registry.cjs +2 -0
  322. package/hooks/gsd-agent-isolation-guard.js +517 -0
  323. package/hooks/gsd-check-update-worker.js +64 -12
  324. package/hooks/gsd-check-update.js +19 -1
  325. package/hooks/gsd-cursor-pre-tool.js +0 -3
  326. package/hooks/gsd-cursor-subagent-start.js +607 -26
  327. package/hooks/gsd-cursor-subagent-stop.js +3 -2
  328. package/hooks/gsd-prompt-guard.js +21 -20
  329. package/hooks/gsd-read-injection-scanner.js +45 -24
  330. package/hooks/gsd-statusline.js +90 -6
  331. package/hooks/gsd-update-banner.js +22 -1
  332. package/hooks/gsd-workflow-guard.js +134 -36
  333. package/hooks/gsd-worktree-path-guard.js +2 -1
  334. package/hooks/gsd-write-guard.js +359 -0
  335. package/hooks/hooks.json +12 -0
  336. package/hooks/lib/git-cmd.js +92 -59
  337. package/hooks/lib/injection-patterns.js +45 -0
  338. package/hooks/lib/isolation-deny-reason.js +39 -0
  339. package/hooks/lib/isolation-sentinel.js +277 -0
  340. package/hooks/managed-hooks-registry.cjs +2 -0
  341. package/package.json +31 -10
  342. package/pi/gsd.cjs +71 -12
  343. package/scripts/baselines/planning-prompt-drift-baseline.json +4 -0
  344. package/scripts/baselines/planning-snapshot-bypass-baseline.json +12 -0
  345. package/scripts/baselines/unreachable-guard-drift-baseline.json +4 -0
  346. package/scripts/build-hooks.js +9 -0
  347. package/scripts/changeset/lint.cjs +68 -6
  348. package/scripts/changeset/serialize.cjs +5 -1
  349. package/scripts/check-alias-drift.cjs +7 -43
  350. package/scripts/check-contract-drift.cjs +297 -0
  351. package/scripts/ci-test-scope.cjs +19 -2
  352. package/scripts/command-contract-helpers.cjs +903 -1
  353. package/scripts/gen-adr-index.cjs +728 -38
  354. package/scripts/gen-capability-matrix.cjs +1 -1
  355. package/scripts/gen-capability-registry.cjs +3 -15
  356. package/scripts/gen-context-index.cjs +439 -0
  357. package/scripts/gen-health-docs.cjs +390 -0
  358. package/scripts/gen-inventory-manifest.cjs +150 -4
  359. package/scripts/gen-loop-host-contract.cjs +4 -24
  360. package/scripts/gen-prompt-budget-parity-corpus.cjs +645 -0
  361. package/scripts/gen-registry.cjs +3 -14
  362. package/scripts/gen-section-manifest.cjs +638 -0
  363. package/scripts/generate-package-identity.cjs +4 -2
  364. package/scripts/lib/alias-drift-families.cjs +46 -0
  365. package/scripts/lib/drift-scan.cjs +278 -0
  366. package/scripts/lint-allow-test-rule-refs.allowlist.json +15 -54
  367. package/scripts/lint-allow-test-rule-refs.effective-ceiling.json +4 -0
  368. package/scripts/lint-allow-test-rule-refs.unverified-ceiling.json +3 -0
  369. package/scripts/lint-canary-version-leak.cjs +73 -0
  370. package/scripts/lint-command-contract.cjs +96 -13
  371. package/scripts/lint-compiled-artifact-sync.cjs +6 -1
  372. package/scripts/lint-completion-predicate-drift.cjs +933 -0
  373. package/scripts/lint-completion-ratio-drift.cjs +214 -0
  374. package/scripts/lint-default-flip-documentation.cjs +193 -0
  375. package/scripts/lint-docs-command-form.cjs +195 -0
  376. package/scripts/lint-docs-required.cjs +9 -1
  377. package/scripts/lint-emitted-drift-ack.cjs +215 -20
  378. package/scripts/lint-eslint-glob-coverage.allowlist.json +34 -0
  379. package/scripts/lint-eslint-glob-coverage.cjs +340 -0
  380. package/scripts/lint-example-parser-parity.cjs +395 -0
  381. package/scripts/lint-frontmatter-scalar-broad-grep.cjs +237 -0
  382. package/scripts/lint-health-diagnostic-rule-table.cjs +404 -0
  383. package/scripts/lint-hooks-runtime-build-seam.cjs +262 -0
  384. package/scripts/lint-milestone-window-drift.cjs +468 -0
  385. package/scripts/lint-phase-enumeration-drift.cjs +479 -0
  386. package/scripts/lint-plan-count-drift.cjs +318 -0
  387. package/scripts/lint-planning-artifact-writer-drift.cjs +398 -0
  388. package/scripts/lint-planning-prompt-drift.cjs +434 -0
  389. package/scripts/lint-planning-snapshot-bypass-drift.cjs +544 -0
  390. package/scripts/lint-regression-test-names.cjs +15 -13
  391. package/scripts/lint-removed-but-needed.cjs +320 -0
  392. package/scripts/lint-state-field-drift.cjs +805 -0
  393. package/scripts/lint-state-write-path-drift.cjs +1045 -0
  394. package/scripts/lint-test-file-count.allowlist.json +40 -3
  395. package/scripts/lint-unreachable-guard-drift.cjs +843 -0
  396. package/scripts/lint-vendored-deps.cjs +124 -0
  397. package/scripts/mutation-matrix.cjs +13 -0
  398. package/scripts/pr-changed-files.cjs +63 -0
  399. package/scripts/pr-template-policy.cjs +14 -4
  400. package/scripts/prompt-injection-scan.sh +52 -6
  401. package/scripts/require-issue-link-policy.cjs +192 -0
  402. package/scripts/state-write-path-drift-baseline.json +19 -0
  403. package/scripts/sync-runtime-launcher.cjs +2 -4
  404. package/skills/gsd-autonomous/SKILL.md +0 -1
  405. package/skills/gsd-code-review/SKILL.md +1 -1
  406. package/skills/gsd-execute-phase/SKILL.md +1 -2
  407. package/skills/gsd-map-codebase/SKILL.md +1 -1
  408. package/skills/gsd-mempalace-capture/SKILL.md +2 -2
  409. package/skills/gsd-mempalace-recall/SKILL.md +1 -1
  410. package/skills/gsd-new-milestone/SKILL.md +2 -2
  411. package/skills/gsd-next/SKILL.md +0 -1
  412. package/skills/gsd-plan-phase/SKILL.md +1 -2
  413. package/skills/gsd-progress/SKILL.md +0 -1
  414. package/skills/gsd-quick/SKILL.md +1 -1
  415. package/skills/gsd-review-backlog/SKILL.md +2 -1
  416. package/skills/gsd-stats/SKILL.md +0 -1
  417. package/skills/gsd-verify-work/SKILL.md +1 -1
  418. package/vscode/package.json +1 -1
  419. package/gsd-core/workflows/discovery-phase.md +0 -298
  420. package/gsd-core/workflows/plan-milestone-gaps.md +0 -281
  421. package/gsd-core/workflows/verify-phase.md +0 -577
  422. package/scripts/affected-tests-lib.cjs +0 -554
  423. package/scripts/gen-emitted-baseline.cjs +0 -145
  424. package/scripts/lint-allow-test-rule-refs.cjs +0 -162
  425. package/scripts/run-affected-tests.cjs +0 -7
  426. package/scripts/run-tests.cjs +0 -1050
@@ -43,6 +43,11 @@ const { readActiveProfile, resolveProfile, loadSkillsManifest,
43
43
  // below can never drift from what the stage-time writer actually wrote.
44
44
  CAPABILITY_SKILL_MARKER, } = installProfiles;
45
45
  const clusters_cjs_1 = require("./clusters.cjs");
46
+ // #2870: `isGlobalScope` centralizes the `scope === 'global'` boolean
47
+ // projection `applySurface` needs at `_computePathPrefix`'s `isGlobal:
48
+ // boolean` boundary (see its doc comment in install-scope.cts for why the
49
+ // projection is centralized rather than eliminated).
50
+ const install_scope_cjs_1 = require("./install-scope.cjs");
46
51
  // eslint-disable-next-line @typescript-eslint/no-require-imports
47
52
  const runtimeArtifactLayout = require("./runtime-artifact-layout.cjs");
48
53
  const { findInstallSourceRoot } = runtimeArtifactLayout;
@@ -50,6 +55,8 @@ const { findInstallSourceRoot } = runtimeArtifactLayout;
50
55
  const runtimeArtifactConversion = require("./runtime-artifact-conversion.cjs");
51
56
  // eslint-disable-next-line @typescript-eslint/no-require-imports
52
57
  const runtimeArtifactInstallPlan = require("./runtime-artifact-install-plan.cjs");
58
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
59
+ const retiredArtifactCleanup = require("./retired-artifact-cleanup.cjs");
53
60
  const { assertDestWithinConfigHome } = runtimeArtifactInstallPlan;
54
61
  const SURFACE_FILE_NAME = '.gsd-surface.json';
55
62
  /**
@@ -302,6 +309,9 @@ function applySurface(runtimeConfigDir, layout, manifest, clusterMap, registry,
302
309
  }
303
310
  const skillManifest = normalizeSkillManifest(layout.configDir, manifest);
304
311
  const resolved = resolveSurface(layout.configDir, skillManifest, clusterMap, registry);
312
+ // Profile toggles must converge retired surfaces too. Once a kind disappears
313
+ // from artifactLayout there is no normal sync pass left to prune it (#2644).
314
+ retiredArtifactCleanup.pruneRetiredRuntimeArtifacts(layout.runtime, layout.configDir);
305
315
  // #1575: agents kind now mirrors createRuntimeArtifactInstallPlan — build
306
316
  // agentCtx (pathPrefix + attribution) and pass it to kind.stage() so
307
317
  // stageAgentsForRuntimeWithConverter applies the full inline-loop pipeline
@@ -311,12 +321,23 @@ function applySurface(runtimeConfigDir, layout, manifest, clusterMap, registry,
311
321
  const _homedirFn = opts?.homedir ?? (() => node_os_1.default.homedir());
312
322
  const _resolvedTarget = (0, shell_command_projection_cjs_1.posixNormalize)(node_path_1.default.resolve(layout.configDir));
313
323
  const _homeDir = (0, shell_command_projection_cjs_1.posixNormalize)(_homedirFn());
314
- const _isGlobal = (layout.scope ?? 'global') === 'global';
324
+ // #2870: same judgment as createRuntimeArtifactInstallPlan's identical
325
+ // line — `layout.scope` is already the resolved scope value on the
326
+ // `Layout` this function received. `layout.scope` is optional, so the
327
+ // pre-existing `?? 'global'` default is kept ahead of the call: it must
328
+ // run BEFORE `isGlobalScope`, because `isGlobalScope(undefined)` throws
329
+ // (unlike the old inline `undefined === 'global'`, which silently
330
+ // evaluated to `false`) — the default is what makes an undefined scope
331
+ // resolve to `'global'` here, exactly as it did before. `isGlobalScope`
332
+ // then projects the defaulted value to the boolean `_computePathPrefix`'s
333
+ // existing `isGlobal: boolean` API requires.
334
+ const _isGlobal = (0, install_scope_cjs_1.isGlobalScope)(layout.scope ?? 'global');
315
335
  const _isOpencode = layout.runtime === 'opencode';
316
336
  const _isWindowsHost = (opts?.platform ?? process.platform) === 'win32';
317
337
  const _pathPrefix = runtimeArtifactConversion._computePathPrefix({ isGlobal: _isGlobal, isOpencode: _isOpencode, isWindowsHost: _isWindowsHost, resolvedTarget: _resolvedTarget, homeDir: _homeDir });
318
338
  const _attribution = opts?.resolveAttribution ? opts.resolveAttribution(layout.runtime) : undefined;
319
- const agentCtx = { runtime: layout.runtime, pathPrefix: _pathPrefix, attribution: _attribution };
339
+ // #2875 Part 2 (row I1): layout.configDir is this call's install root.
340
+ const agentCtx = { runtime: layout.runtime, pathPrefix: _pathPrefix, attribution: _attribution, targetDir: layout.configDir };
320
341
  const tempDirsToClean = [];
321
342
  // #1575: When the surface has no state modifications AND the base profile is
322
343
  // 'full', pass the '*' sentinel for agents staging so ALL agents are staged —
@@ -360,7 +381,13 @@ function applySurface(runtimeConfigDir, layout, manifest, clusterMap, registry,
360
381
  tempDirsToClean.push(rewritten);
361
382
  }
362
383
  }
363
- const dest = assertDestWithinConfigHome(layout.configDir, kind.destSubpath);
384
+ // #2911: honor kind.home as a FALLBACK-preferred override (e.g. Codex
385
+ // skills -> $HOME/.agents), never a blanket replacement — kinds without
386
+ // a `home` must keep resolving against layout.configDir. This must stay
387
+ // in lockstep with _copyStaged's root selection in src/install-engine.cts;
388
+ // the parity test in tests/runtime-artifact-layout-surface.test.cjs
389
+ // enforces that the two writers never diverge again.
390
+ const dest = assertDestWithinConfigHome(kind.home ?? layout.configDir, kind.destSubpath);
364
391
  _syncGsdDir(staged, dest, kind, skillManifest, layout.runtime);
365
392
  }
366
393
  }
@@ -546,13 +573,11 @@ function _syncGsdDir(stagedDir, destDir, kind, manifest, runtime) {
546
573
  // from install and orphaned the installed gsd-*.md files, and the unscoped
547
574
  // prune deleted user-owned command files.
548
575
  //
549
- // NOTE: the destName rule below intentionally mirrors bin/install.js
550
- // `_copyStaged` (the `namespacedByDir` decision). Keep them in sync.
551
- const destLast = (typeof kind === 'object' && kind !== null && kind.destSubpath)
552
- ? node_path_1.default.basename(kind.destSubpath)
553
- : '';
554
- const prefixStem = kindPrefix ? kindPrefix.replace(/-$/, '') : '';
555
- const namespacedByDir = kindName === 'commands' && destLast === prefixStem;
576
+ // Single source of truth: runtimeArtifactLayout.isNamespacedByDir (#2871
577
+ // Phase 2 review finding — this rule previously drifted independently
578
+ // across install-engine.cts / surface.cts / runtime-artifact-layout.cts).
579
+ const kindDestSubpath = (typeof kind === 'object' && kind !== null && kind.destSubpath) ? kind.destSubpath : '';
580
+ const namespacedByDir = runtimeArtifactLayout.isNamespacedByDir(kindName, kindDestSubpath, kindPrefix);
556
581
  const stagedFiles = node_fs_1.default.readdirSync(stagedDir).filter(f => f.endsWith('.md'));
557
582
  const stagedDestNames = new Set();
558
583
  for (const file of stagedFiles) {
@@ -0,0 +1,80 @@
1
+ "use strict";
2
+ /**
3
+ * text-lines.cts — the line-terminator seam (ADR-3212 §3, epic #3212 Phase 2,
4
+ * #3413).
5
+ *
6
+ * Source in src/text-lines.cts, compiled to gsd-core/bin/lib/text-lines.cjs
7
+ * (gitignored), per the repo's ADR-457 build-at-publish convention.
8
+ *
9
+ * Sole owner of `\r?\n` splitting and CRLF normalization. Closes #3360: a
10
+ * regex anchored on `^`/`$` under `/m` against a whole multi-line string is
11
+ * exposed to `\r` being its own LineTerminator (ECMA-262), so a greedy `\s*`
12
+ * can cross a CRLF boundary and inflate a captured indent by one character.
13
+ * Split-then-match — call `splitLines` first, then match per already-split
14
+ * line — is immune by construction, because a single split line can never
15
+ * contain the delimiter that produced it. This module exists so that shape
16
+ * is the easy, obvious way to write indentation-sensitive parsing, per the
17
+ * design doc (.gsd/phase/chore-3413-text-lines-seam/40-design.md).
18
+ *
19
+ * A "genuine leaf" module (CONTEXT.md's term, shared with Phase 1's sibling
20
+ * seam `src/pattern.cts`): zero I/O, zero imports from other `src/*.cts`
21
+ * modules, pure string functions only.
22
+ */
23
+ Object.defineProperty(exports, "__esModule", { value: true });
24
+ exports.splitLines = splitLines;
25
+ exports.normalizeEol = normalizeEol;
26
+ exports.detectEol = detectEol;
27
+ exports.joinLines = joinLines;
28
+ /**
29
+ * Split document content into lines on `\r\n` or `\n`. A lone `\r` (bare CR,
30
+ * no following `\n`) is NOT a delimiter — this matches every existing
31
+ * `\r?\n` call site in the repo and is intentionally narrower than "treat
32
+ * any LineTerminator as a break." Matches `String.prototype.split`'s own
33
+ * contract for a trailing terminator (a trailing empty element) and for the
34
+ * empty string (`[""]`).
35
+ */
36
+ function splitLines(content) {
37
+ if (typeof content !== 'string') {
38
+ throw new TypeError(`splitLines: expected a string, got ${typeof content}`);
39
+ }
40
+ return content.split(/\r?\n/);
41
+ }
42
+ /**
43
+ * Normalize all line endings to LF by stripping every `\r` character — not
44
+ * only `\r\n` pairs. This is byte-for-byte the same operation as the 4
45
+ * `scripts/gen-*.cjs` copies of `normalizeLineEndings` this module
46
+ * consolidates (`content.replace(/\r/g, '')`), so a lone/unpaired `\r` (old
47
+ * Mac-style content) is stripped too. Deliberately a different contract from
48
+ * `splitLines`, which does NOT treat a bare `\r` as a delimiter (row 6) —
49
+ * these are two different operations kept as two separate functions rather
50
+ * than one "handle all CR-ish things" primitive.
51
+ */
52
+ function normalizeEol(content) {
53
+ return content.replace(/\r/g, '');
54
+ }
55
+ /**
56
+ * Detect the dominant line-terminator in `content`: `'\r\n'` when CRLF pairs
57
+ * outnumber bare LFs, `'\n'` when bare LFs outnumber CRLF pairs, and `'\r\n'`
58
+ * as the default when there is no bare LF at all (all-CRLF content, or no
59
+ * terminator present whatsoever — an empty or single-line input). See the
60
+ * design doc's Rejected section for why the tie/empty default is `'\r\n'`
61
+ * rather than `'\n'`: this function exists to PRESERVE whatever a file
62
+ * already uses, not to bias toward LF the way a write-time normalizer would.
63
+ */
64
+ function detectEol(content) {
65
+ const crlfCount = (content.match(/\r\n/g) || []).length;
66
+ const totalLfCount = (content.match(/\n/g) || []).length;
67
+ const bareLfCount = totalLfCount - crlfCount;
68
+ if (bareLfCount === 0 || crlfCount >= bareLfCount)
69
+ return '\r\n';
70
+ return '\n';
71
+ }
72
+ /**
73
+ * Join lines back into a single string with `eol` (default `'\n'`) between
74
+ * each pair — the inverse of `splitLines`. `joinLines(splitLines(x),
75
+ * detectEol(x))` reproduces `x` byte-for-byte for any `x` already in
76
+ * canonical (single-terminator) form (ADR-3212 §3's round-trip property).
77
+ */
78
+ function joinLines(lines, eol) {
79
+ return lines.join(eol ?? '\n');
80
+ }
@@ -0,0 +1,76 @@
1
+ "use strict";
2
+ /**
3
+ * token-scanner.cts — the tokenizer-first seam for stateful grammars (ADR-3212
4
+ * §4, epic #3212 Phase 3, #3414).
5
+ *
6
+ * Source in src/token-scanner.cts, compiled to gsd-core/bin/lib/token-scanner.cjs
7
+ * (gitignored), per the repo's ADR-457 build-at-publish convention.
8
+ *
9
+ * Generalizes the proven `hooks/lib/git-cmd.js` token-walk (#3129 — "has not
10
+ * re-opened") into a primitive other stateful-grammar consumers can share.
11
+ * `git-cmd.js` migrates onto `tokenizeShellLike` with zero behavior change
12
+ * (ADR §6); its own env-prefix/flag/subcommand walk logic stays put — only
13
+ * the character-level tokenizer moves here.
14
+ *
15
+ * `indentWidth` is the primitive `src/decisions.cts`'s #3169 fix needs: a
16
+ * decision-bullet list can NEST (a bullet elaborating on an already-open
17
+ * decision, indented deeper than it), and a per-line regex cannot see that
18
+ * nesting — only tracking indentation relative to the currently-open
19
+ * decision can (ADR §4 criterion 1). See
20
+ * .gsd/phase/chore-3414-tokenizer-first-seam/40-design.md §1.3 for the
21
+ * disproven bold-run-content-classification alternative and why nesting
22
+ * depth, not bullet content, is the actual distinguishing signal.
23
+ */
24
+ Object.defineProperty(exports, "__esModule", { value: true });
25
+ exports.tokenizeShellLike = tokenizeShellLike;
26
+ exports.indentWidth = indentWidth;
27
+ /**
28
+ * Tokenize a shell-like command string: whitespace-split, with single- and
29
+ * double-quoted spans taken as one token each. No escape handling, no
30
+ * brace/variable expansion — matches `hooks/lib/git-cmd.js`'s original
31
+ * `tokenize()` exactly (parity-asserted in tests/token-scanner.test.cjs).
32
+ */
33
+ function tokenizeShellLike(cmd) {
34
+ const tokens = [];
35
+ let i = 0;
36
+ const len = cmd.length;
37
+ while (i < len) {
38
+ while (i < len && /\s/.test(cmd[i]))
39
+ i++;
40
+ if (i >= len)
41
+ break;
42
+ let token = '';
43
+ while (i < len && !/\s/.test(cmd[i])) {
44
+ if (cmd[i] === "'") {
45
+ i++;
46
+ while (i < len && cmd[i] !== "'")
47
+ token += cmd[i++];
48
+ if (i < len)
49
+ i++;
50
+ }
51
+ else if (cmd[i] === '"') {
52
+ i++;
53
+ while (i < len && cmd[i] !== '"')
54
+ token += cmd[i++];
55
+ if (i < len)
56
+ i++;
57
+ }
58
+ else {
59
+ token += cmd[i++];
60
+ }
61
+ }
62
+ if (token)
63
+ tokens.push(token);
64
+ }
65
+ return tokens;
66
+ }
67
+ /**
68
+ * Count a line's leading whitespace width. Tabs count as one column each
69
+ * (not expanded) — matches `src/decisions.cts`'s existing continuation-line
70
+ * check (`/^[ \t]/`), which never expanded tabs either; this function does
71
+ * not introduce a new tab-width policy.
72
+ */
73
+ function indentWidth(line) {
74
+ const match = line.match(/^[ \t]*/);
75
+ return match ? match[0].length : 0;
76
+ }
@@ -25,6 +25,9 @@ const { stripFencedCode } = markdownSectionizer;
25
25
  // eslint-disable-next-line @typescript-eslint/no-require-imports
26
26
  const verification = require("./verification.cjs");
27
27
  const { readVerificationStatus } = verification;
28
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
29
+ const phaseIdMod = require("./phase-id.cjs");
30
+ const { scopeToPhase } = phaseIdMod;
28
31
  // ─── Blocking state sets (documented for maintainability) ─────────────────────
29
32
  // UAT file frontmatter `status` values that indicate the file is not fully done
30
33
  const BLOCKING_UAT_FM_STATUSES = new Set([
@@ -186,11 +189,16 @@ function evaluateUatPassed(phaseFullDir, opts) {
186
189
  blockers,
187
190
  no_uat_artifacts,
188
191
  policy: { require_verification: requireVerification },
192
+ // readVerificationStatus was never reached on this early-return path.
193
+ verification_stale_check_indeterminate: false,
189
194
  };
190
195
  }
191
- // Filter UAT and VERIFICATION files using the same filter as cmdPhaseComplete
192
- const uatFileNames = dirEntries.filter(f => f.includes('-UAT') && f.endsWith('.md'));
193
- const verFileNames = dirEntries.filter(f => f.includes('-VERIFICATION') && f.endsWith('.md'));
196
+ // Filter UAT and VERIFICATION files using the same filter as cmdPhaseComplete,
197
+ // scoped to THIS phase's own token (#3511) — a stray, cross-phase, or ad-hoc
198
+ // file can no longer contribute a blocker to a phase it does not belong to.
199
+ const phaseDirBaseName = node_path_1.default.basename(phaseFullDir);
200
+ const uatFileNames = scopeToPhase(dirEntries.filter(f => f.includes('-UAT') && f.endsWith('.md')), phaseDirBaseName);
201
+ const verFileNames = scopeToPhase(dirEntries.filter(f => f.includes('-VERIFICATION') && f.endsWith('.md')), phaseDirBaseName);
194
202
  // ── Process UAT files ──────────────────────────────────────────────────────
195
203
  for (const file of uatFileNames) {
196
204
  uatFiles.push(file);
@@ -263,8 +271,15 @@ function evaluateUatPassed(phaseFullDir, opts) {
263
271
  // (handled by the requireVerification policy check below if needed)
264
272
  }
265
273
  // ── Policy: requireVerification ───────────────────────────────────────────
274
+ // #3057 B3: routing here is UNCHANGED — an indeterminate staleness check
275
+ // still falls through to the same `verificationStatus !== 'passed'` branch
276
+ // it always did (the pre-existing fail-open contract). `verificationStaleCheckIndeterminate`
277
+ // only records the fact for the report below; it never itself gates `blockers`.
278
+ let verificationStaleCheckIndeterminate = false;
266
279
  if (requireVerification) {
267
- const verificationStatus = readVerificationStatus(phaseFullDir).status;
280
+ const verificationResult = readVerificationStatus(phaseFullDir);
281
+ const verificationStatus = verificationResult.status;
282
+ verificationStaleCheckIndeterminate = verificationResult.staleCheckIndeterminate === true;
268
283
  if (verificationStatus === 'stale') {
269
284
  blockers.push('policy: verification status=stale');
270
285
  }
@@ -288,6 +303,7 @@ function evaluateUatPassed(phaseFullDir, opts) {
288
303
  policy: {
289
304
  require_verification: requireVerification,
290
305
  },
306
+ verification_stale_check_indeterminate: verificationStaleCheckIndeterminate,
291
307
  };
292
308
  }
293
309
  module.exports = {