@opengsd/gsd-core 1.15.0 → 1.17.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 (505) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -2
  3. package/.opencode/plugins/gsd-core.js +336 -6
  4. package/.opencode/plugins/gsd-statusline/tui.tsx +55 -0
  5. package/GEMINI.md +1 -1
  6. package/agents/gsd-code-fixer.compact.md +1 -1
  7. package/agents/gsd-code-fixer.md +1 -1
  8. package/agents/gsd-code-reviewer.compact.md +5 -3
  9. package/agents/gsd-code-reviewer.md +8 -6
  10. package/agents/gsd-debug-session-manager.compact.md +7 -1
  11. package/agents/gsd-debug-session-manager.md +7 -1
  12. package/agents/gsd-debugger.md +2 -2
  13. package/agents/gsd-eval-auditor.compact.md +1 -1
  14. package/agents/gsd-eval-auditor.md +1 -1
  15. package/agents/gsd-executor.md +4 -4
  16. package/agents/gsd-intel-updater.compact.md +1 -1
  17. package/agents/gsd-intel-updater.md +1 -1
  18. package/agents/gsd-mempalace-curator.md +2 -2
  19. package/agents/gsd-phase-researcher.md +1 -1
  20. package/agents/gsd-plan-checker.md +7 -2
  21. package/agents/gsd-planner.md +3 -3
  22. package/agents/gsd-project-researcher.compact.md +1 -1
  23. package/agents/gsd-project-researcher.md +1 -1
  24. package/agents/gsd-research-synthesizer.compact.md +1 -1
  25. package/agents/gsd-research-synthesizer.md +1 -1
  26. package/agents/gsd-ui-auditor.compact.md +21 -30
  27. package/agents/gsd-ui-auditor.md +42 -51
  28. package/agents/gsd-ui-researcher.compact.md +1 -1
  29. package/agents/gsd-ui-researcher.md +1 -1
  30. package/agents/gsd-verifier.md +31 -9
  31. package/bin/gsd-mcp-server.js +3 -1
  32. package/bin/install.js +487 -290
  33. package/commands/gsd/add-tests.md +6 -1
  34. package/commands/gsd/ai-integration-phase.md +6 -1
  35. package/commands/gsd/audit-fix.md +5 -0
  36. package/commands/gsd/audit-milestone.md +6 -1
  37. package/commands/gsd/autonomous.md +5 -0
  38. package/commands/gsd/capture.md +8 -4
  39. package/commands/gsd/code-review.md +7 -2
  40. package/commands/gsd/complete-milestone.md +4 -0
  41. package/commands/gsd/config.md +7 -3
  42. package/commands/gsd/debug.md +11 -7
  43. package/commands/gsd/discuss-phase.md +7 -3
  44. package/commands/gsd/docs-update.md +12 -7
  45. package/commands/gsd/eval-review.md +6 -1
  46. package/commands/gsd/execute-phase.md +12 -7
  47. package/commands/gsd/extract-learnings.md +5 -0
  48. package/commands/gsd/fast.md +4 -0
  49. package/commands/gsd/forensics.md +5 -1
  50. package/commands/gsd/graphify.md +10 -6
  51. package/commands/gsd/health.md +5 -0
  52. package/commands/gsd/help.md +7 -2
  53. package/commands/gsd/import.md +7 -3
  54. package/commands/gsd/inbox.md +5 -0
  55. package/commands/gsd/ingest-docs.md +5 -1
  56. package/commands/gsd/manager.md +6 -1
  57. package/commands/gsd/map-codebase.md +7 -3
  58. package/commands/gsd/mempalace-capture.md +5 -1
  59. package/commands/gsd/mempalace-recall.md +5 -1
  60. package/commands/gsd/milestone-summary.md +5 -1
  61. package/commands/gsd/mvp-phase.md +8 -3
  62. package/commands/gsd/new-milestone.md +6 -1
  63. package/commands/gsd/new-project.md +5 -0
  64. package/commands/gsd/next.md +6 -1
  65. package/commands/gsd/ns-context.md +4 -0
  66. package/commands/gsd/ns-ideate.md +4 -0
  67. package/commands/gsd/ns-manage.md +4 -0
  68. package/commands/gsd/ns-project.md +4 -0
  69. package/commands/gsd/ns-review.md +4 -0
  70. package/commands/gsd/ns-workflow.md +4 -0
  71. package/commands/gsd/onboard.md +6 -1
  72. package/commands/gsd/pause-work.md +5 -1
  73. package/commands/gsd/phase.md +8 -4
  74. package/commands/gsd/plan-phase.md +6 -1
  75. package/commands/gsd/plan-review-convergence.md +5 -1
  76. package/commands/gsd/pr-branch.md +4 -0
  77. package/commands/gsd/profile-user.md +5 -1
  78. package/commands/gsd/progress.md +6 -1
  79. package/commands/gsd/quick-batch.md +20 -8
  80. package/commands/gsd/quick.md +12 -7
  81. package/commands/gsd/review.md +5 -1
  82. package/commands/gsd/secure-phase.md +6 -1
  83. package/commands/gsd/ship.md +5 -0
  84. package/commands/gsd/sketch.md +7 -2
  85. package/commands/gsd/spec-phase.md +5 -1
  86. package/commands/gsd/spike.md +8 -3
  87. package/commands/gsd/surface.md +5 -1
  88. package/commands/gsd/thread.md +4 -0
  89. package/commands/gsd/ui-phase.md +6 -1
  90. package/commands/gsd/ui-review.md +6 -1
  91. package/commands/gsd/ultraplan-phase.md +5 -1
  92. package/commands/gsd/undo.md +5 -1
  93. package/commands/gsd/update.md +6 -2
  94. package/commands/gsd/validate-phase.md +6 -1
  95. package/commands/gsd/verify-work.md +6 -1
  96. package/commands/gsd/workspace.md +7 -3
  97. package/gsd-core/bin/gsd-tools.cjs +159 -58
  98. package/gsd-core/bin/lib/active-workstream-store.cjs +15 -0
  99. package/gsd-core/bin/lib/adr-parser.cjs +37 -5
  100. package/gsd-core/bin/lib/agent-install-check.cjs +4 -1
  101. package/gsd-core/bin/lib/audit.cjs +78 -44
  102. package/gsd-core/bin/lib/broken-windows.cjs +13 -13
  103. package/gsd-core/bin/lib/capability-activation.cjs +9 -4
  104. package/gsd-core/bin/lib/capability-registry.cjs +249 -117
  105. package/gsd-core/bin/lib/capability-validator.cjs +18 -1
  106. package/gsd-core/bin/lib/capability-writer.cjs +2 -1
  107. package/gsd-core/bin/lib/check-auto-mode.cjs +35 -0
  108. package/gsd-core/bin/lib/check-command-router.cjs +164 -1712
  109. package/gsd-core/bin/lib/cjs-command-router-adapter.cjs +13 -2
  110. package/gsd-core/bin/lib/cli-exit.cjs +12 -0
  111. package/gsd-core/bin/lib/codex-agent-toml.cjs +11 -8
  112. package/gsd-core/bin/lib/command-aliases.cjs +7 -0
  113. package/gsd-core/bin/lib/command-routing-hub.cjs +48 -1
  114. package/gsd-core/bin/lib/commands.cjs +201 -178
  115. package/gsd-core/bin/lib/complexity-trigger.cjs +8 -7
  116. package/gsd-core/bin/lib/config.cjs +43 -12
  117. package/gsd-core/bin/lib/core-utils.cjs +6 -1
  118. package/gsd-core/bin/lib/coverage.cjs +4 -8
  119. package/gsd-core/bin/lib/decision-coverage-support.cjs +259 -0
  120. package/gsd-core/bin/lib/drift.cjs +177 -42
  121. package/gsd-core/bin/lib/frontmatter-fence.cjs +90 -0
  122. package/gsd-core/bin/lib/frontmatter-splice.cjs +494 -0
  123. package/gsd-core/bin/lib/frontmatter.cjs +413 -234
  124. package/gsd-core/bin/lib/gap-checker.cjs +72 -29
  125. package/gsd-core/bin/lib/gate-api-coverage-verify-pre.cjs +381 -0
  126. package/gsd-core/bin/lib/gate-args.cjs +53 -0
  127. package/gsd-core/bin/lib/gate-codebase-drift.cjs +285 -0
  128. package/gsd-core/bin/lib/gate-config.cjs +46 -0
  129. package/gsd-core/bin/lib/gate-context-drift.cjs +142 -0
  130. package/gsd-core/bin/lib/gate-decision-coverage-plan.cjs +169 -0
  131. package/gsd-core/bin/lib/gate-decision-coverage-verify.cjs +126 -0
  132. package/gsd-core/bin/lib/gate-evaluation-scope.cjs +555 -0
  133. package/gsd-core/bin/lib/gate-evidence.cjs +138 -0
  134. package/gsd-core/bin/lib/gate-exit.cjs +27 -0
  135. package/gsd-core/bin/lib/gate-gap-analysis-plan-post.cjs +61 -0
  136. package/gsd-core/bin/lib/gate-phase-context.cjs +170 -0
  137. package/gsd-core/bin/lib/gate-predicate-evaluator.cjs +1 -1
  138. package/gsd-core/bin/lib/gate-predicate.cjs +165 -0
  139. package/gsd-core/bin/lib/gate-prohibition-enforcement.cjs +94 -0
  140. package/gsd-core/bin/lib/gate-schema-drift.cjs +165 -0
  141. package/gsd-core/bin/lib/gate-tdd-red-evidence.cjs +100 -0
  142. package/gsd-core/bin/lib/gate-tdd-review-checkpoint.cjs +182 -0
  143. package/gsd-core/bin/lib/gate-ui-plan.cjs +86 -0
  144. package/gsd-core/bin/lib/gate-ui-safety.cjs +81 -0
  145. package/gsd-core/bin/lib/gate-verdict.cjs +64 -0
  146. package/gsd-core/bin/lib/gate-verify-command-paths.cjs +78 -0
  147. package/gsd-core/bin/lib/gate-verify-failure-directions.cjs +41 -0
  148. package/gsd-core/bin/lib/graphify.cjs +3 -2
  149. package/gsd-core/bin/lib/health-diagnostic-rules/phase-structure.cjs +43 -47
  150. package/gsd-core/bin/lib/health-diagnostic.cjs +45 -8
  151. package/gsd-core/bin/lib/init.cjs +194 -108
  152. package/gsd-core/bin/lib/install-engine.cjs +30 -35
  153. package/gsd-core/bin/lib/install-profiles.cjs +7 -4
  154. package/gsd-core/bin/lib/install-shadow-report.cjs +12 -0
  155. package/gsd-core/bin/lib/installer-migrations/011-opencode-mcp-no-prompts.cjs +99 -0
  156. package/gsd-core/bin/lib/installer-migrations.cjs +54 -1
  157. package/gsd-core/bin/lib/io.cjs +122 -3
  158. package/gsd-core/bin/lib/jsonc-edit.cjs +418 -0
  159. package/gsd-core/bin/lib/loop-host-contract.cjs +2 -1
  160. package/gsd-core/bin/lib/loop-resolver.cjs +95 -0
  161. package/gsd-core/bin/lib/markdown-sectionizer.cjs +75 -1
  162. package/gsd-core/bin/lib/mcp-server.cjs +5 -1
  163. package/gsd-core/bin/lib/milestone.cjs +19 -1
  164. package/gsd-core/bin/lib/model-resolver.cjs +18 -18
  165. package/gsd-core/bin/lib/observability/event.cjs +1 -1
  166. package/gsd-core/bin/lib/observability/logger.cjs +46 -1
  167. package/gsd-core/bin/lib/opencode-mcp-entry.cjs +39 -0
  168. package/gsd-core/bin/lib/opencode-version.cjs +486 -0
  169. package/gsd-core/bin/lib/pattern.cjs +10 -0
  170. package/gsd-core/bin/lib/phase-command-router.cjs +11 -4
  171. package/gsd-core/bin/lib/phase-estimation.cjs +5 -4
  172. package/gsd-core/bin/lib/phase-id.cjs +1 -1
  173. package/gsd-core/bin/lib/phase-lifecycle.cjs +9 -2
  174. package/gsd-core/bin/lib/phase-status.cjs +360 -0
  175. package/gsd-core/bin/lib/phase.cjs +301 -80
  176. package/gsd-core/bin/lib/plan-document.cjs +93 -19
  177. package/gsd-core/bin/lib/plan-drift-guard.cjs +5 -0
  178. package/gsd-core/bin/lib/planning-document.cjs +273 -40
  179. package/gsd-core/bin/lib/planning-inspect.cjs +42 -8
  180. package/gsd-core/bin/lib/planning-snapshot.cjs +18 -0
  181. package/gsd-core/bin/lib/planning-workspace.cjs +76 -53
  182. package/gsd-core/bin/lib/pristine-baseline.cjs +10 -0
  183. package/gsd-core/bin/lib/profile-output.cjs +6 -3
  184. package/gsd-core/bin/lib/prohibition-enforcement.cjs +0 -55
  185. package/gsd-core/bin/lib/quick-batch-command-router.cjs +35 -9
  186. package/gsd-core/bin/lib/quick-batch-dispatch.cjs +13 -9
  187. package/gsd-core/bin/lib/real-home-guard.cjs +9 -1
  188. package/gsd-core/bin/lib/report-parser.cjs +269 -0
  189. package/gsd-core/bin/lib/roadmap-command-router.cjs +13 -15
  190. package/gsd-core/bin/lib/roadmap-parser.cjs +82 -15
  191. package/gsd-core/bin/lib/roadmap-upgrade.cjs +127 -65
  192. package/gsd-core/bin/lib/roadmap.cjs +169 -72
  193. package/gsd-core/bin/lib/runtime-artifact-conversion.cjs +186 -161
  194. package/gsd-core/bin/lib/runtime-artifact-install-plan.cjs +2 -1
  195. package/gsd-core/bin/lib/runtime-artifact-layout.cjs +57 -1
  196. package/gsd-core/bin/lib/runtime-homes.cjs +13 -10
  197. package/gsd-core/bin/lib/runtime-hooks-surface.cjs +365 -594
  198. package/gsd-core/bin/lib/runtime-name-policy.cjs +142 -27
  199. package/gsd-core/bin/lib/runtime-slash.cjs +60 -30
  200. package/gsd-core/bin/lib/shell-command-projection.cjs +37 -2
  201. package/gsd-core/bin/lib/smart-entry.cjs +111 -56
  202. package/gsd-core/bin/lib/stale-bake-guard.cjs +32 -48
  203. package/gsd-core/bin/lib/state-contract.cjs +15 -18
  204. package/gsd-core/bin/lib/state-document.cjs +100 -22
  205. package/gsd-core/bin/lib/state-transition.cjs +67 -9
  206. package/gsd-core/bin/lib/state.cjs +668 -171
  207. package/gsd-core/bin/lib/surface.cjs +2 -1
  208. package/gsd-core/bin/lib/tdd-red-evidence.cjs +48 -152
  209. package/gsd-core/bin/lib/uat-predicate.cjs +313 -35
  210. package/gsd-core/bin/lib/uat.cjs +424 -7
  211. package/gsd-core/bin/lib/ui-frontend-evidence.cjs +94 -58
  212. package/gsd-core/bin/lib/update-context.cjs +18 -1
  213. package/gsd-core/bin/lib/vendor/README.md +31 -9
  214. package/gsd-core/bin/lib/vendor/saxes.cjs +1934 -0
  215. package/gsd-core/bin/lib/vendor/saxes.cjs.LICENSE.txt +92 -0
  216. package/gsd-core/bin/lib/vendor/tap-parser.cjs +8927 -0
  217. package/gsd-core/bin/lib/vendor/tap-parser.cjs.LICENSE.txt +152 -0
  218. package/gsd-core/bin/lib/verification-command-router.cjs +2 -1
  219. package/gsd-core/bin/lib/verification.cjs +1265 -324
  220. package/gsd-core/bin/lib/verify-command-router.cjs +18 -7
  221. package/gsd-core/bin/lib/verify.cjs +286 -567
  222. package/gsd-core/bin/lib/workstream-inventory-builder.cjs +14 -6
  223. package/gsd-core/bin/lib/workstream-inventory.cjs +31 -21
  224. package/gsd-core/bin/lib/workstream-name-policy.cjs +31 -1
  225. package/gsd-core/bin/lib/workstream.cjs +11 -2
  226. package/gsd-core/bin/shared/config-defaults.manifest.json +5 -0
  227. package/gsd-core/bin/shared/config-schema.manifest.json +4 -0
  228. package/gsd-core/references/autonomous-smart-discuss.md +2 -1
  229. package/gsd-core/references/autonomous-ui-design-contract.md +3 -3
  230. package/gsd-core/references/execute-mvp-tdd.md +5 -10
  231. package/gsd-core/references/execute-phase-between-wave-reset.md +3 -0
  232. package/gsd-core/references/execute-phase-response-language.md +1 -1
  233. package/gsd-core/references/gsd-run-resolver.md +1 -1
  234. package/gsd-core/references/loop-hook-dispatch.md +7 -1
  235. package/gsd-core/references/offer-next.md +1 -1
  236. package/gsd-core/references/planning-config.md +1 -1
  237. package/gsd-core/references/spidr-splitting.md +1 -1
  238. package/gsd-core/references/tdd.md +10 -4
  239. package/gsd-core/references/verifier-phase-gates.md +5 -2
  240. package/gsd-core/references/verify-mvp-mode.md +2 -2
  241. package/gsd-core/references/workstream-flag.md +33 -3
  242. package/gsd-core/templates/README.md +1 -1
  243. package/gsd-core/templates/UAT.md +17 -1
  244. package/gsd-core/templates/config.json +2 -11
  245. package/gsd-core/templates/verification-report.md +1 -1
  246. package/gsd-core/workflows/_runtime-launcher.snippet.sh +1 -1
  247. package/gsd-core/workflows/add-backlog.md +1 -1
  248. package/gsd-core/workflows/add-phase.md +8 -7
  249. package/gsd-core/workflows/add-tests.md +3 -2
  250. package/gsd-core/workflows/add-todo.md +4 -3
  251. package/gsd-core/workflows/ai-integration-phase.md +3 -2
  252. package/gsd-core/workflows/audit-fix.md +1 -1
  253. package/gsd-core/workflows/audit-milestone.md +4 -3
  254. package/gsd-core/workflows/audit-uat.md +1 -1
  255. package/gsd-core/workflows/autonomous.md +28 -18
  256. package/gsd-core/workflows/check-todos.md +6 -5
  257. package/gsd-core/workflows/cleanup.md +1 -1
  258. package/gsd-core/workflows/code-review/steps/structural-pre-pass.md +20 -13
  259. package/gsd-core/workflows/code-review-fix.md +5 -4
  260. package/gsd-core/workflows/code-review.md +100 -91
  261. package/gsd-core/workflows/complete-milestone/detail/elaboration.md +4 -3
  262. package/gsd-core/workflows/complete-milestone.md +12 -7
  263. package/gsd-core/workflows/debug.md +30 -5
  264. package/gsd-core/workflows/diagnose-issues.md +3 -2
  265. package/gsd-core/workflows/discuss-phase/modes/advisor.md +1 -1
  266. package/gsd-core/workflows/discuss-phase/modes/chain.md +1 -1
  267. package/gsd-core/workflows/discuss-phase-assumptions.md +4 -3
  268. package/gsd-core/workflows/discuss-phase.md +4 -3
  269. package/gsd-core/workflows/do.md +1 -1
  270. package/gsd-core/workflows/docs-update.md +4 -3
  271. package/gsd-core/workflows/edit-phase.md +4 -3
  272. package/gsd-core/workflows/eval-review.md +5 -3
  273. package/gsd-core/workflows/execute-phase/detail/elaboration.md +1 -1
  274. package/gsd-core/workflows/execute-phase/steps/code-review-disposition.md +4 -2
  275. package/gsd-core/workflows/execute-phase/steps/codebase-drift-gate.md +15 -4
  276. package/gsd-core/workflows/execute-phase/steps/completion-reconciliation.md +10 -7
  277. package/gsd-core/workflows/execute-phase/steps/executor-isolation-dispatch.md +2 -2
  278. package/gsd-core/workflows/execute-phase/steps/gap-closure-artifacts.md +3 -1
  279. package/gsd-core/workflows/execute-phase/steps/partial-wave.md +2 -2
  280. package/gsd-core/workflows/execute-phase/steps/per-plan-executor-routing.md +1 -1
  281. package/gsd-core/workflows/execute-phase/steps/per-plan-worktree-gate.md +1 -1
  282. package/gsd-core/workflows/execute-phase/steps/post-merge-gate.md +1 -1
  283. package/gsd-core/workflows/execute-phase/steps/protected-branch.md +1 -1
  284. package/gsd-core/workflows/execute-phase/steps/regression-gate-run.md +1 -1
  285. package/gsd-core/workflows/execute-phase/steps/regression-gate.md +2 -0
  286. package/gsd-core/workflows/execute-phase/steps/tdd-applicability-resolution.md +1 -1
  287. package/gsd-core/workflows/execute-phase/steps/verify-phase-goal.md +187 -0
  288. package/gsd-core/workflows/execute-phase/steps/wave-post-gate-hooks.md +2 -3
  289. package/gsd-core/workflows/execute-phase.md +81 -171
  290. package/gsd-core/workflows/execute-plan.md +13 -19
  291. package/gsd-core/workflows/explore.md +2 -2
  292. package/gsd-core/workflows/extract-learnings.md +3 -2
  293. package/gsd-core/workflows/fast.md +1 -1
  294. package/gsd-core/workflows/forensics.md +1 -1
  295. package/gsd-core/workflows/graduation.md +1 -1
  296. package/gsd-core/workflows/health.md +2 -1
  297. package/gsd-core/workflows/import.md +3 -2
  298. package/gsd-core/workflows/inbox.md +1 -1
  299. package/gsd-core/workflows/ingest-docs.md +1 -1
  300. package/gsd-core/workflows/insert-phase.md +4 -3
  301. package/gsd-core/workflows/list-seeds.md +1 -1
  302. package/gsd-core/workflows/list-workspaces.md +1 -1
  303. package/gsd-core/workflows/manager.md +5 -3
  304. package/gsd-core/workflows/map-codebase.md +4 -3
  305. package/gsd-core/workflows/milestone-summary.md +3 -2
  306. package/gsd-core/workflows/mvp-phase.md +14 -14
  307. package/gsd-core/workflows/new-milestone.md +10 -10
  308. package/gsd-core/workflows/new-project/steps/auto-mode-config.md +1 -1
  309. package/gsd-core/workflows/new-project.md +1 -1
  310. package/gsd-core/workflows/new-workspace.md +1 -1
  311. package/gsd-core/workflows/next.md +1 -1
  312. package/gsd-core/workflows/pause-work.md +2 -2
  313. package/gsd-core/workflows/plan-phase/detail/elaboration.md +1 -1
  314. package/gsd-core/workflows/plan-phase/steps/chunked-planning-mode.md +1 -1
  315. package/gsd-core/workflows/plan-phase/steps/closed-phase-gate.md +1 -1
  316. package/gsd-core/workflows/plan-phase/steps/prd-express-path.md +1 -1
  317. package/gsd-core/workflows/plan-phase/steps/stall-detection-helpers.md +1 -1
  318. package/gsd-core/workflows/plan-phase.md +27 -18
  319. package/gsd-core/workflows/plan-review-convergence.md +1 -1
  320. package/gsd-core/workflows/plant-seed.md +1 -1
  321. package/gsd-core/workflows/pr-branch.md +1 -1
  322. package/gsd-core/workflows/profile-user.md +1 -1
  323. package/gsd-core/workflows/progress.md +19 -49
  324. package/gsd-core/workflows/quick/steps/plan-checker-loop.md +4 -2
  325. package/gsd-core/workflows/quick/steps/quick-verification.md +4 -4
  326. package/gsd-core/workflows/quick/steps/worktree-pre-dispatch-commit.md +30 -11
  327. package/gsd-core/workflows/quick-batch/steps/batch-init.md +1 -1
  328. package/gsd-core/workflows/quick-batch/steps/completion.md +1 -1
  329. package/gsd-core/workflows/quick-batch/steps/merge-wave.md +1 -1
  330. package/gsd-core/workflows/quick-batch/steps/planner-wave.md +1 -1
  331. package/gsd-core/workflows/quick-batch/steps/research-phase.md +1 -1
  332. package/gsd-core/workflows/quick-batch/steps/resume-mode.md +1 -1
  333. package/gsd-core/workflows/quick-batch/steps/verification-wave.md +9 -3
  334. package/gsd-core/workflows/quick-batch/steps/worktree-dispatch.md +1 -1
  335. package/gsd-core/workflows/quick-batch.md +15 -10
  336. package/gsd-core/workflows/quick.md +42 -31
  337. package/gsd-core/workflows/remove-phase.md +3 -2
  338. package/gsd-core/workflows/remove-workspace.md +1 -1
  339. package/gsd-core/workflows/resume-project.md +17 -12
  340. package/gsd-core/workflows/review.md +3 -2
  341. package/gsd-core/workflows/scan.md +3 -2
  342. package/gsd-core/workflows/secure-phase.md +11 -12
  343. package/gsd-core/workflows/settings-advanced.md +1 -1
  344. package/gsd-core/workflows/settings-integrations.md +1 -1
  345. package/gsd-core/workflows/settings.md +1 -1
  346. package/gsd-core/workflows/ship.md +12 -12
  347. package/gsd-core/workflows/sketch-wrap-up.md +1 -1
  348. package/gsd-core/workflows/sketch.md +1 -1
  349. package/gsd-core/workflows/smart-entry.md +1 -1
  350. package/gsd-core/workflows/spec-phase.md +1 -1
  351. package/gsd-core/workflows/spike-wrap-up.md +1 -1
  352. package/gsd-core/workflows/spike.md +1 -1
  353. package/gsd-core/workflows/stats.md +1 -1
  354. package/gsd-core/workflows/sync-skills.md +1 -1
  355. package/gsd-core/workflows/thread.md +2 -2
  356. package/gsd-core/workflows/transition.md +13 -23
  357. package/gsd-core/workflows/ui-phase.md +5 -4
  358. package/gsd-core/workflows/ui-review.md +4 -3
  359. package/gsd-core/workflows/ultraplan-phase.md +3 -2
  360. package/gsd-core/workflows/undo.md +1 -1
  361. package/gsd-core/workflows/validate-phase.md +10 -12
  362. package/gsd-core/workflows/verify-work/detail/elaboration.md +43 -3
  363. package/gsd-core/workflows/verify-work/steps/automated-ui-verification.md +1 -1
  364. package/gsd-core/workflows/verify-work/steps/mvp-uat-framing.md +5 -3
  365. package/gsd-core/workflows/verify-work.md +68 -59
  366. package/hooks/dist/gsd-agent-isolation-guard.js +8 -0
  367. package/hooks/dist/gsd-check-update-worker.js +8 -0
  368. package/hooks/dist/gsd-check-update.js +34 -20
  369. package/hooks/dist/gsd-context-monitor.js +45 -13
  370. package/hooks/dist/gsd-cursor-subagent-start.js +8 -0
  371. package/hooks/dist/gsd-secret-read-guard.js +263 -16
  372. package/hooks/dist/gsd-statusline.js +336 -29
  373. package/hooks/dist/gsd-update-banner.js +8 -0
  374. package/hooks/dist/gsd-windsurf-pre-write.js +11 -2
  375. package/hooks/dist/gsd-workflow-guard.js +5 -4
  376. package/hooks/dist/gsd-worktree-path-guard.js +6 -2
  377. package/hooks/dist/lib/cli-exit.js +12 -0
  378. package/hooks/dist/lib/git-probe.js +17 -1
  379. package/hooks/dist/lib/isolation-sentinel.js +2 -2
  380. package/hooks/gsd-agent-isolation-guard.js +8 -0
  381. package/hooks/gsd-check-update-worker.js +8 -0
  382. package/hooks/gsd-check-update.js +34 -20
  383. package/hooks/gsd-context-monitor.js +45 -13
  384. package/hooks/gsd-cursor-subagent-start.js +8 -0
  385. package/hooks/gsd-secret-read-guard.js +263 -16
  386. package/hooks/gsd-statusline.js +336 -29
  387. package/hooks/gsd-update-banner.js +8 -0
  388. package/hooks/gsd-windsurf-pre-write.js +11 -2
  389. package/hooks/gsd-workflow-guard.js +5 -4
  390. package/hooks/gsd-worktree-path-guard.js +6 -2
  391. package/hooks/hooks.json +5 -5
  392. package/hooks/lib/cli-exit.js +12 -0
  393. package/hooks/lib/git-probe.js +17 -1
  394. package/hooks/lib/isolation-sentinel.js +2 -2
  395. package/package.json +21 -4
  396. package/scripts/changeset/parse.cjs +52 -4
  397. package/scripts/ci-timeout-report.cjs +770 -4
  398. package/scripts/command-contract-helpers.cjs +12 -8
  399. package/scripts/docs-guard-registry.cjs +6 -0
  400. package/scripts/gen-capability-registry.cjs +7 -1
  401. package/scripts/gen-features.cjs +13 -8
  402. package/scripts/gen-hooks-cli-exit.cjs +12 -28
  403. package/scripts/gen-loop-host-contract.cjs +14 -2
  404. package/scripts/gen-platform-conformance-tier.cjs +187 -1
  405. package/scripts/gen-plugin-skills.cjs +87 -1
  406. package/scripts/gen-research-agents.cjs +24 -31
  407. package/scripts/gen-scripts-cli-exit.cjs +30 -3
  408. package/scripts/gen-test-timings.cjs +32 -7
  409. package/scripts/lib/cli-exit.cjs +12 -0
  410. package/scripts/lib/macos-conformance-tier.generated.cjs +24 -2
  411. package/scripts/lib/ndjson-reporter.cjs +28 -3
  412. package/scripts/lib/platform-conformance-tier.generated.cjs +44 -5
  413. package/scripts/lib/registration-ledger-preload.cjs +155 -0
  414. package/scripts/lib/vendor-bundle.cjs +59 -0
  415. package/scripts/lib/vendor-licenses/saxes-6.0.0.txt +64 -0
  416. package/scripts/lint-allow-test-rule-refs.effective-ceiling.json +1 -1
  417. package/scripts/lint-allow-test-rule-refs.unverified-ceiling.json +1 -1
  418. package/scripts/lint-completion-predicate-drift.cjs +18 -19
  419. package/scripts/lint-descriptions.cjs +7 -3
  420. package/scripts/lint-docs-guard-registration.exempt-baseline.cjs +10 -0
  421. package/scripts/lint-eslint-glob-coverage.allowlist.json +20 -0
  422. package/scripts/lint-frontmatter-fence-drift.cjs +313 -0
  423. package/scripts/lint-frontmatter-scalar-broad-grep.cjs +122 -16
  424. package/scripts/lint-phase-enumeration-drift.cjs +12 -8
  425. package/scripts/lint-phase-id-drift.cjs +29 -0
  426. package/scripts/lint-planning-document-positive-control.cjs +329 -0
  427. package/scripts/lint-response-language-coverage.cjs +3 -0
  428. package/scripts/lint-skill-deps.cjs +7 -3
  429. package/scripts/lint-test-file-count.allowlist.json +11 -1
  430. package/scripts/lint-test-file-count.cjs +34 -1
  431. package/scripts/lint-vendored-deps.cjs +41 -5
  432. package/scripts/lint-workflow-shellcheck-baseline.json +10 -10
  433. package/scripts/mutation-matrix.cjs +53 -6
  434. package/scripts/release-tarball-smoke.cjs +14 -7
  435. package/scripts/require-issue-link-policy.cjs +6 -2
  436. package/scripts/sync-runtime-launcher.cjs +184 -2
  437. package/scripts/verify-npm-publish.cjs +76 -20
  438. package/skills/gsd-add-tests/SKILL.md +6 -1
  439. package/skills/gsd-ai-integration-phase/SKILL.md +6 -1
  440. package/skills/gsd-audit-fix/SKILL.md +5 -0
  441. package/skills/gsd-audit-milestone/SKILL.md +6 -1
  442. package/skills/gsd-autonomous/SKILL.md +5 -0
  443. package/skills/gsd-capture/SKILL.md +8 -4
  444. package/skills/gsd-code-review/SKILL.md +7 -2
  445. package/skills/gsd-complete-milestone/SKILL.md +4 -0
  446. package/skills/gsd-config/SKILL.md +8 -4
  447. package/skills/gsd-debug/SKILL.md +11 -7
  448. package/skills/gsd-discuss-phase/SKILL.md +7 -3
  449. package/skills/gsd-docs-update/SKILL.md +12 -7
  450. package/skills/gsd-eval-review/SKILL.md +6 -1
  451. package/skills/gsd-execute-phase/SKILL.md +12 -7
  452. package/skills/gsd-extract-learnings/SKILL.md +5 -0
  453. package/skills/gsd-fast/SKILL.md +4 -0
  454. package/skills/gsd-forensics/SKILL.md +5 -1
  455. package/skills/gsd-graphify/SKILL.md +10 -6
  456. package/skills/gsd-health/SKILL.md +5 -0
  457. package/skills/gsd-help/SKILL.md +7 -2
  458. package/skills/gsd-import/SKILL.md +7 -3
  459. package/skills/gsd-inbox/SKILL.md +5 -0
  460. package/skills/gsd-ingest-docs/SKILL.md +5 -1
  461. package/skills/gsd-manager/SKILL.md +6 -1
  462. package/skills/gsd-map-codebase/SKILL.md +7 -3
  463. package/skills/gsd-mempalace-capture/SKILL.md +5 -1
  464. package/skills/gsd-mempalace-recall/SKILL.md +5 -1
  465. package/skills/gsd-milestone-summary/SKILL.md +5 -1
  466. package/skills/gsd-mvp-phase/SKILL.md +8 -3
  467. package/skills/gsd-new-milestone/SKILL.md +6 -1
  468. package/skills/gsd-new-project/SKILL.md +5 -0
  469. package/skills/gsd-next/SKILL.md +6 -1
  470. package/skills/gsd-ns-context/SKILL.md +4 -0
  471. package/skills/gsd-ns-ideate/SKILL.md +4 -0
  472. package/skills/gsd-ns-manage/SKILL.md +4 -0
  473. package/skills/gsd-ns-project/SKILL.md +4 -0
  474. package/skills/gsd-ns-review/SKILL.md +4 -0
  475. package/skills/gsd-ns-workflow/SKILL.md +4 -0
  476. package/skills/gsd-onboard/SKILL.md +6 -1
  477. package/skills/gsd-pause-work/SKILL.md +5 -1
  478. package/skills/gsd-phase/SKILL.md +8 -4
  479. package/skills/gsd-plan-phase/SKILL.md +6 -1
  480. package/skills/gsd-plan-review-convergence/SKILL.md +5 -1
  481. package/skills/gsd-pr-branch/SKILL.md +4 -0
  482. package/skills/gsd-profile-user/SKILL.md +5 -1
  483. package/skills/gsd-progress/SKILL.md +6 -1
  484. package/skills/gsd-quick/SKILL.md +16 -10
  485. package/skills/gsd-quick-batch/SKILL.md +20 -8
  486. package/skills/gsd-review/SKILL.md +5 -1
  487. package/skills/gsd-review-backlog/SKILL.md +3 -2
  488. package/skills/gsd-secure-phase/SKILL.md +6 -1
  489. package/skills/gsd-ship/SKILL.md +5 -0
  490. package/skills/gsd-sketch/SKILL.md +7 -2
  491. package/skills/gsd-spec-phase/SKILL.md +5 -1
  492. package/skills/gsd-spike/SKILL.md +8 -3
  493. package/skills/gsd-surface/SKILL.md +5 -1
  494. package/skills/gsd-thread/SKILL.md +4 -0
  495. package/skills/gsd-ui-phase/SKILL.md +6 -1
  496. package/skills/gsd-ui-review/SKILL.md +6 -1
  497. package/skills/gsd-ultraplan-phase/SKILL.md +5 -1
  498. package/skills/gsd-undo/SKILL.md +5 -1
  499. package/skills/gsd-update/SKILL.md +6 -2
  500. package/skills/gsd-validate-phase/SKILL.md +6 -1
  501. package/skills/gsd-verify-work/SKILL.md +6 -1
  502. package/skills/gsd-workspace/SKILL.md +7 -3
  503. package/skills/gsd-workstreams/SKILL.md +6 -6
  504. package/vscode/package.json +1 -1
  505. package/gsd-core/workflows/execute-phase/steps/stale-reverification.md +0 -24
@@ -55,7 +55,7 @@ const install_scope_cjs_1 = require("./install-scope.cjs");
55
55
  const { processAttribution } = runtimeArtifactConversion;
56
56
  // resolveRuntimeArtifactLayout: accessed via module ref (not destructured) so
57
57
  // test stubs that monkeypatch the module's exports are seen at call time.
58
- const { getDirName } = runtimeNamePolicy;
58
+ const { getDirName, hostBehaviorsFor } = runtimeNamePolicy;
59
59
  function withInstallerPackageSource(configDir, fn) {
60
60
  // Reuse the existing compatibility-marker contract through the existing fs
61
61
  // seam. The marker exists only in this synchronous call tree: no disk state,
@@ -181,7 +181,7 @@ function provisionRuntimeSurfaceCorpus(layout, configDir, scope) {
181
181
  const destination = node_path_1.default.join(corpusRoot, 'agents');
182
182
  syncRuntimeSurfaceCorpus(source, destination, configDir, 'gsd-core/agents/');
183
183
  }
184
- const markerFile = _hostBehaviors(layout.runtime).sourceMarkerFile;
184
+ const markerFile = hostBehaviorsFor(layout.runtime).sourceMarkerFile;
185
185
  if (typeof markerFile === 'string' && markerFile !== '' && required.has('commands')) {
186
186
  try {
187
187
  const markerPath = runtimeArtifactInstallPlan.assertDestWithinConfigHome(configDir, markerFile);
@@ -220,25 +220,6 @@ function executingPackageRoot() { return node_path_1.default.dirname(node_path_1
220
220
  */
221
221
  const USER_OWNED_ARTIFACTS = ['USER-PROFILE.md'];
222
222
  // ---------------------------------------------------------------------------
223
- // Host-behavior helpers
224
- // ---------------------------------------------------------------------------
225
- /**
226
- * Host-specific install behaviors declared on the runtime descriptor
227
- * (capabilities/<runtime>/capability.json -> runtime.hostBehaviors).
228
- * Mirrors bin/install.js's `_hostBehaviors` (ADR-1239 / #2086/#2087). Returns
229
- * {} for runtimes that declare none or if the registry fails to load, so
230
- * every behavior branch degrades to the generic path by default.
231
- */
232
- function _hostBehaviors(runtime) {
233
- try {
234
- const reg = require('./capability-registry.cjs');
235
- return (reg && reg.runtimes && reg.runtimes[runtime] && reg.runtimes[runtime].runtime && reg.runtimes[runtime].runtime.hostBehaviors) || {};
236
- }
237
- catch {
238
- return {};
239
- }
240
- }
241
- // ---------------------------------------------------------------------------
242
223
  // Conversion helpers
243
224
  // ---------------------------------------------------------------------------
244
225
  /**
@@ -737,8 +718,9 @@ function _copyStaged(stagedDir, destDir, kind, configDir, runtime) {
737
718
  // files whose `name:` frontmatter is identical to their canonical
738
719
  // sibling's, leaving the harness resolution unstated. Claude never
739
720
  // selects compact, so claude is the one runtime whose agents kind skips
740
- // them; every other runtime's emission is byte-identical.
741
- if (kind.kind === 'agents' && runtime === 'claude' && entry.name.endsWith('.compact.md'))
721
+ // them; every other runtime's emission is byte-identical. #5169: the
722
+ // descriptor declares this (`hostBehaviors.skipCompactAgents`), not a name test.
723
+ if (kind.kind === 'agents' && hostBehaviorsFor(runtime).skipCompactAgents && entry.name.endsWith('.compact.md'))
742
724
  continue;
743
725
  const stem = entry.name.slice(0, -3); // strip .md
744
726
  let destName;
@@ -748,7 +730,7 @@ function _copyStaged(stagedDir, destDir, kind, configDir, runtime) {
748
730
  // hardcoded `runtime === 'copilot'`). copilot declares '.agent.md';
749
731
  // every other runtime's descriptor leaves this unset, so destName falls
750
732
  // back to entry.name unchanged (byte-parity, #1575 origin comment).
751
- const _agentExt = runtime ? _hostBehaviors(runtime).agentFileExtension : undefined;
733
+ const _agentExt = runtime ? hostBehaviorsFor(runtime).agentFileExtension : undefined;
752
734
  destName = _agentExt
753
735
  ? entry.name.replace(/\.md$/, _agentExt)
754
736
  : entry.name;
@@ -887,7 +869,7 @@ function _runLegacyInstallMigrations(runtime, configDir, scope = 'global') {
887
869
  // that for Hermes the flat skills/gsd-*/ removal (below) does not delete the freshly
888
870
  // created skills/gsd-dev-preferences/ skill dir.
889
871
  let stagedLegacyArtifacts = null;
890
- if (_hostBehaviors(runtime).legacyCommandsGsdInstallMigration) {
872
+ if (hostBehaviorsFor(runtime).legacyCommandsGsdInstallMigration) {
891
873
  if (installFs().existsSync(legacyCommandsGsd)) {
892
874
  // #2875: staging root resolved lazily, only when there is actually
893
875
  // something to stage — reused below by every other call site sharing
@@ -911,8 +893,8 @@ function _runLegacyInstallMigrations(runtime, configDir, scope = 'global') {
911
893
  }
912
894
  }
913
895
  // Hermes: remove pre-#2841 flat skills/gsd-*/ entries that lived alongside
914
- // the new skills/gsd/ nested layout.
915
- if (runtime === 'hermes') {
896
+ // the new skills/gsd/ nested layout. (#5169: `hostBehaviors.legacyFlatSkillsCleanup`.)
897
+ if (hostBehaviorsFor(runtime).legacyFlatSkillsCleanup) {
916
898
  const flatSkillsDir = node_path_1.default.join(configDir, 'skills');
917
899
  if (installFs().existsSync(flatSkillsDir)) {
918
900
  for (const entry of installFs().readdirSync(flatSkillsDir, { withFileTypes: true })) {
@@ -1050,7 +1032,7 @@ function _runLegacyUninstallCleanup(runtime, configDir, scope = 'global') {
1050
1032
  // commands/gsd/ for claude local, preserving dev-preferences.md by restoring it
1051
1033
  // to the same location (#1423). Using migrateLegacyDevPreferencesToSkill here
1052
1034
  // (which would redirect to skills/) conflicts with the test contract for local installs.
1053
- const _lu = _hostBehaviors(runtime).legacyCommandsGsdUninstall;
1035
+ const _lu = hostBehaviorsFor(runtime).legacyCommandsGsdUninstall;
1054
1036
  // #2870: `scope` keeps its exported `string = 'global'` signature (no
1055
1037
  // signature change), but every real caller — `uninstallRuntimeArtifacts`'s
1056
1038
  // own required `scope` param, always fed a validated 'global' | 'local'
@@ -1075,8 +1057,8 @@ function _runLegacyUninstallCleanup(runtime, configDir, scope = 'global') {
1075
1057
  }
1076
1058
  }
1077
1059
  }
1078
- // Hermes: pre-#2841 flat skills/gsd-*/ entries
1079
- if (runtime === 'hermes') {
1060
+ // Hermes: pre-#2841 flat skills/gsd-*/ entries (#5169: `legacyFlatSkillsCleanup`)
1061
+ if (hostBehaviorsFor(runtime).legacyFlatSkillsCleanup) {
1080
1062
  const flatSkillsDir = node_path_1.default.join(configDir, 'skills');
1081
1063
  if (node_fs_1.default.existsSync(flatSkillsDir)) {
1082
1064
  for (const entry of node_fs_1.default.readdirSync(flatSkillsDir, { withFileTypes: true })) {
@@ -1085,6 +1067,8 @@ function _runLegacyUninstallCleanup(runtime, configDir, scope = 'global') {
1085
1067
  }
1086
1068
  }
1087
1069
  }
1070
+ }
1071
+ if (hostBehaviorsFor(runtime).bareStemSkillsCleanup) {
1088
1072
  // Hermes: pre-#947 bare-stem skills/gsd/<stem>/ entries (dirs that do NOT
1089
1073
  // start with 'gsd-') — the #3664 layout used prefix='' so GSD-owned skills
1090
1074
  // had bare names (e.g. skills/gsd/help/). These are stale on uninstall.
@@ -1142,7 +1126,7 @@ function installRuntimeArtifacts(runtime, configDir, scope, resolvedProfile, res
1142
1126
  // the dedicated combined commands+skills+plugin orchestrator instead of the
1143
1127
  // generic layout-driven loop below, mirroring the bespoke install path that
1144
1128
  // previously lived inline in bin/install.js.
1145
- const behaviors = _hostBehaviors(runtime);
1129
+ const behaviors = hostBehaviorsFor(runtime);
1146
1130
  const projectDir = scope === 'global' ? process.cwd() : configDir;
1147
1131
  if (behaviors.combinedFamilyInstall) {
1148
1132
  // #2329: combined-family runtimes (OpenCode/Kilo) bypass
@@ -1336,7 +1320,7 @@ function installRuntimeArtifacts(runtime, configDir, scope, resolvedProfile, res
1336
1320
  // with the same prefix). User-owned bare dirs with no gsd-<stem> counterpart
1337
1321
  // are untouched.
1338
1322
  let hermesBareStemCleanup = false;
1339
- if (runtime === 'hermes') {
1323
+ if (hostBehaviorsFor(runtime).bareStemSkillsCleanup) {
1340
1324
  const nestedGsdDirForCleanup = node_path_1.default.join(configDir, 'skills', 'gsd');
1341
1325
  _removeHermesBareStemDirs(nestedGsdDirForCleanup);
1342
1326
  hermesBareStemCleanup = true;
@@ -1688,7 +1672,7 @@ function installOpencodeFamilyCommands(runtime, destDir, srcDir, pathPrefix, res
1688
1672
  // already satisfies the fold-to-descriptor requirement. Only the SKILLS
1689
1673
  // converter site above (installOpencodeFamilySkills) has a real
1690
1674
  // `converter` string to key on via SKILLS_CONVERTER_REGISTRY.
1691
- content = _hostBehaviors(runtime).frontmatterDialect === 'kilo'
1675
+ content = hostBehaviorsFor(runtime).frontmatterDialect === 'kilo'
1692
1676
  ? runtimeArtifactConversion.convertClaudeToKiloFrontmatter(content)
1693
1677
  : runtimeArtifactConversion.convertClaudeToOpencodeFrontmatter(content);
1694
1678
  installFs().writeFileSync(node_path_1.default.join(destDir, destName), content);
@@ -1757,6 +1741,17 @@ function _installNativePluginIfDeclared(runtime, configDir, behaviors, src) {
1757
1741
  }
1758
1742
  }
1759
1743
  }
1744
+ // OpenCode 2.x terminal-client plugin (ADR-5331 Phase 3): a TUI entrypoint kept in its own directory under
1745
+ // plugins/. OpenCode 1.x scans plugins/*.js|ts only, so it never loads this directory.
1746
+ const cli = behaviors.nativeCliPlugin;
1747
+ if (cli && cli.source) {
1748
+ const cliSrc = node_path_1.default.join(src, cli.source);
1749
+ if (installFs().existsSync(cliSrc)) {
1750
+ const cliDest = runtimeArtifactInstallPlan.assertDestWithinConfigHome(configDir, node_path_1.default.join(cli.dir, cli.file));
1751
+ installFs().mkdirSync(node_path_1.default.dirname(cliDest), { recursive: true });
1752
+ installFs().copyFileSync(cliSrc, cliDest);
1753
+ }
1754
+ }
1760
1755
  }
1761
1756
  // ---------------------------------------------------------------------------
1762
1757
  // _migrateLegacyOpencodeCommandDir
@@ -1971,7 +1966,8 @@ function uninstallRuntimeArtifacts(runtime, configDir, scope, deps = {}) {
1971
1966
  // the GSD-managed DESCRIPTION.md and then the category dir itself if it
1972
1967
  // contains no user content (#947). _removeGsdEntries removed gsd-* dirs
1973
1968
  // but left the category container and DESCRIPTION.md intact.
1974
- if (runtime === 'hermes') {
1969
+ // (#5169: `hostBehaviors.categoryContainerCleanup`.)
1970
+ if (hostBehaviorsFor(runtime).categoryContainerCleanup) {
1975
1971
  const nestedGsdDir = node_path_1.default.join(configDir, 'skills', 'gsd');
1976
1972
  if (node_fs_1.default.existsSync(nestedGsdDir)) {
1977
1973
  // Remove GSD-owned DESCRIPTION.md (written by writeHermesCategoryDescription)
@@ -2029,7 +2025,6 @@ module.exports = {
2029
2025
  installAgentsKindStandalone,
2030
2026
  installOpencodeFamilyArtifacts,
2031
2027
  _installNativePluginIfDeclared,
2032
- _hostBehaviors,
2033
2028
  _copyStaged,
2034
2029
  hasExistingSymlinkBetween,
2035
2030
  isSymlinkedDestOptIn,
@@ -27,6 +27,7 @@ const node_os_1 = __importDefault(require("node:os"));
27
27
  const installFsAdapter = require("./install-fs-adapter.cjs");
28
28
  const { installFs, mkInstallTempDir } = installFsAdapter;
29
29
  const shell_command_projection_cjs_1 = require("./shell-command-projection.cjs");
30
+ const frontmatter_fence_cjs_1 = require("./frontmatter-fence.cjs");
30
31
  // #2322: reuse the existing pure path-containment seam (ADR-1239 Phase C-2)
31
32
  // instead of hand-rolling a new traversal check for capability skill stems.
32
33
  const external_descriptor_trust_cjs_1 = require("./external-descriptor-trust.cjs");
@@ -95,13 +96,15 @@ const PROFILES = Object.freeze({
95
96
  * Returns string[] — empty array if no requires: field.
96
97
  *
97
98
  * No external YAML parser dependency — hand-parse the single line
98
- * since GSD enforces flow-style arrays for requires:.
99
+ * since GSD enforces flow-style arrays for requires:. The block is the one the
100
+ * one fence owner (`locateFrontmatterFence`) finds — a `---` pair later in the
101
+ * body (a thematic break, a YAML example) is never frontmatter.
99
102
  */
100
103
  function parseRequires(content) {
101
- const fmMatch = content.match(/^---\r?\n([\s\S]*?)\r?\n---/m);
102
- if (!fmMatch)
104
+ const fence = (0, frontmatter_fence_cjs_1.locateFrontmatterFence)(content);
105
+ if (!fence?.closed)
103
106
  return [];
104
- const fm = fmMatch[1];
107
+ const fm = content.slice(fence.openEnd, fence.bodyEnd);
105
108
  const line = fm.match(/^requires:\s*(.+)$/m);
106
109
  if (!line)
107
110
  return [];
@@ -23,6 +23,10 @@
23
23
  * (design row #5 / "Not-corruption"). `kindsDiffer` on `ShadowReport` is what
24
24
  * lets `renderShadowReport` word the two cases correctly.
25
25
  *
26
+ * Same-scope pairs are not reported: a runtime whose layout installs `commands` and `skills` side by side at one
27
+ * scope (OpenCode, Kilo, Augment, CodeBuddy, ZCode) writes both on purpose, and `isGenuinelyShadowed` requires the
28
+ * winner and the loser to sit in different scopes (#5344).
29
+ *
26
30
  * ── Report, don't correct (mirrors the resolver's own law) ─────────────────
27
31
  * `mismatches` surfaces a declared runtime/scope that disagrees with the
28
32
  * probed one (Postel's Law, design doc: liberal in what is accepted, but the
@@ -218,6 +222,14 @@ function stemFromTrigger(trigger, prefix) {
218
222
  function isGenuinelyShadowed(t, scopeRecords, prefixFor) {
219
223
  if (t.shadowedBy === null)
220
224
  return false;
225
+ // This is a CROSS-SCOPE report (see the module comment). A winner and a loser in the SAME scope are the two
226
+ // kinds one install deliberately wrote side by side — OpenCode, Kilo, Augment, CodeBuddy and ZCode install
227
+ // `commands` and `skills` for every trigger at one scope. GSD wrote both, the operator cannot act on it, and
228
+ // the host's own dedupe (OpenCode 1.x lists the command and drops the same-named skill; 2.x keeps them on
229
+ // separate surfaces) is not a loss of reachability. Reporting it printed "72 triggers shadowed" on every
230
+ // install of those five runtimes (#5344).
231
+ if (t.shadowedBy.scope === t.scope)
232
+ return false;
221
233
  const winnerRecord = scopeRecords.get(t.shadowedBy.scope);
222
234
  const shadowedRecord = scopeRecords.get(t.scope);
223
235
  const winnerStem = stemFromTrigger(t.trigger, prefixFor(t.shadowedBy.scope, t.shadowedBy.kind));
@@ -0,0 +1,99 @@
1
+ "use strict";
2
+ /**
3
+ * Installer migration: stop the GSD MCP companion from duplicating every GSD command in OpenCode
4
+ * (#5338; epic #5331, ADR-5331 D6).
5
+ *
6
+ * OpenCode turns each MCP prompt into a `<server>:<prompt>` slash command. The GSD companion server
7
+ * advertised its whole prompt catalog, so with the command files the installer already writes every GSD
8
+ * command appeared twice (`gsd-plan-phase` and `gsd:plan-phase`; 143 entries against 72 observed on
9
+ * OpenCode 2.0.27). New installs register the server with `--no-prompts`. This migration converges an
10
+ * existing install by adding that flag to the `gsd` MCP entry GSD itself wrote — and only that entry: a
11
+ * `gsd` server the user edited or defined does not match the installer's shape and is never touched.
12
+ *
13
+ * It applies to OpenCode on both generations (the entry is the same shape), covers the 1.x `mcp.gsd` and
14
+ * the 2.x native `mcp.servers.gsd` locations, and edits the config as text so a commented `opencode.jsonc`
15
+ * keeps its comments and layout (#5334).
16
+ *
17
+ * Is the action safe in non-interactive install?
18
+ * Yes. `rewrite-json` is non-interactive and journaled; the rewrite is a one-token append to a command
19
+ * array the installer wrote.
20
+ *
21
+ * See docs/installer-migrations.md#shipped-migrations and the OpenCode row of
22
+ * docs/installer-migrations.md#runtime-configuration-contract-registry.
23
+ */
24
+ var __importDefault = (this && this.__importDefault) || function (mod) {
25
+ return (mod && mod.__esModule) ? mod : { "default": mod };
26
+ };
27
+ const node_fs_1 = __importDefault(require("node:fs"));
28
+ const node_path_1 = __importDefault(require("node:path"));
29
+ const jsonc_edit_cjs_1 = require("../jsonc-edit.cjs");
30
+ const opencode_mcp_entry_cjs_1 = require("../opencode-mcp-entry.cjs");
31
+ /** OpenCode reads `opencode.jsonc` in preference to `opencode.json` when both exist. */
32
+ const CONFIG_CANDIDATES = ['opencode.jsonc', 'opencode.json'];
33
+ function isPlainObject(v) {
34
+ return v !== null && typeof v === 'object' && !Array.isArray(v);
35
+ }
36
+ const migration = {
37
+ id: '2026-10-12-opencode-mcp-no-prompts',
38
+ title: 'Stop the GSD MCP companion duplicating GSD commands in OpenCode',
39
+ description: 'Add --no-prompts to the GSD-written `gsd` MCP server entry in opencode.json(c) (mcp.gsd, and the ' +
40
+ 'OpenCode 2.x native mcp.servers.gsd) so OpenCode no longer lists every GSD command a second time as ' +
41
+ 'a `gsd:<name>` MCP-prompt command. Only the entry the installer wrote is changed; comments and ' +
42
+ 'layout in a JSONC config are preserved (#5338, #5334).',
43
+ introducedIn: '1.17.0',
44
+ runtimes: ['opencode'],
45
+ scopes: ['global', 'local'],
46
+ destructive: false,
47
+ runtimeContract: 'docs/installer-migrations.md#runtime-configuration-contract-registry OpenCode row',
48
+ plan: (ctx) => {
49
+ if (ctx.runtime !== 'opencode')
50
+ return [];
51
+ // The file OpenCode (and the installer's resolveOpencodeConfigPath) treats as THE config.
52
+ const relPath = CONFIG_CANDIDATES.find((name) => node_fs_1.default.existsSync(node_path_1.default.join(ctx.configDir, name)));
53
+ if (!relPath)
54
+ return [];
55
+ let config;
56
+ try {
57
+ config = (0, jsonc_edit_cjs_1.parseJsonc)(node_fs_1.default.readFileSync(node_path_1.default.join(ctx.configDir, relPath), 'utf8'));
58
+ }
59
+ catch {
60
+ return []; // unparseable: never touch a config we cannot read (same posture as the installer)
61
+ }
62
+ if (!isPlainObject(config) || !isPlainObject(config['mcp']))
63
+ return [];
64
+ const mcp = config['mcp'];
65
+ const edits = [];
66
+ const next = { ...config, mcp: { ...mcp } };
67
+ const nextMcp = next['mcp'];
68
+ const legacy = mcp['gsd'];
69
+ if ((0, opencode_mcp_entry_cjs_1.isGsdMcpEntry)(legacy) && !(0, opencode_mcp_entry_cjs_1.hasNoPromptsFlag)(legacy)) {
70
+ const updated = (0, opencode_mcp_entry_cjs_1.withNoPromptsFlag)(legacy);
71
+ nextMcp['gsd'] = updated;
72
+ edits.push({ path: ['mcp', 'gsd', 'command'], value: updated.command });
73
+ }
74
+ const servers = mcp['servers'];
75
+ if (isPlainObject(servers)) {
76
+ const native = servers['gsd'];
77
+ if ((0, opencode_mcp_entry_cjs_1.isGsdMcpEntry)(native) && !(0, opencode_mcp_entry_cjs_1.hasNoPromptsFlag)(native)) {
78
+ const updated = (0, opencode_mcp_entry_cjs_1.withNoPromptsFlag)(native);
79
+ nextMcp['servers'] = { ...servers, gsd: updated };
80
+ edits.push({ path: ['mcp', 'servers', 'gsd', 'command'], value: updated.command });
81
+ }
82
+ }
83
+ if (edits.length === 0)
84
+ return [];
85
+ return [
86
+ {
87
+ type: 'rewrite-json',
88
+ relPath,
89
+ value: next,
90
+ edits,
91
+ reason: 'the GSD MCP companion advertised its prompt catalog, which OpenCode lists as a second set of ' +
92
+ '`gsd:<name>` slash commands next to the installed command files',
93
+ ownershipEvidence: "the entry matches the exact shape configureOpencodePermissions writes: type 'local' and a command " +
94
+ "array of `npx … <package> gsd-mcp-server`; a user-edited or user-defined `gsd` server does not match",
95
+ },
96
+ ];
97
+ },
98
+ };
99
+ module.exports = migration;
@@ -18,6 +18,7 @@ const shell_command_projection_cjs_1 = require("./shell-command-projection.cjs")
18
18
  const clock_cjs_1 = require("./clock.cjs");
19
19
  const install_scope_cjs_1 = require("./install-scope.cjs");
20
20
  const security_cjs_1 = require("./security.cjs");
21
+ const jsonc_edit_cjs_1 = require("./jsonc-edit.cjs");
21
22
  // #2874 (ADR-58 cleanup phase): this file is the ~1200-line migration
22
23
  // plan/apply/rollback/lock/journal engine — almost none of it is on the
23
24
  // installRuntimeArtifacts call tree. Only `readInstallManifest` and
@@ -293,15 +294,25 @@ function readInstallManifest(configDir) {
293
294
  scope: (0, install_scope_cjs_1.isInstallScopeId)(m.scope) ? m.scope : null,
294
295
  };
295
296
  }
297
+ function normalizeHostGeneration(raw) {
298
+ if (!raw || typeof raw !== 'object')
299
+ return undefined;
300
+ const r = raw;
301
+ if (r.runtime !== 'opencode' || (r.generation !== 1 && r.generation !== 2))
302
+ return undefined;
303
+ return { runtime: 'opencode', generation: r.generation, version: typeof r.version === 'string' ? r.version : null };
304
+ }
296
305
  function readInstallState(configDir) {
297
306
  const state = readJsonIfPresent(node_path_1.default.join(configDir, INSTALL_STATE_NAME), STRICT_JSON);
298
307
  if (!state || typeof state !== 'object') {
299
308
  return { schemaVersion: 1, appliedMigrations: [] };
300
309
  }
301
310
  const s = state;
311
+ const hostGeneration = normalizeHostGeneration(s.hostGeneration);
302
312
  return {
303
313
  schemaVersion: typeof s.schemaVersion === 'number' ? s.schemaVersion : 1,
304
314
  appliedMigrations: Array.isArray(s.appliedMigrations) ? s.appliedMigrations : [],
315
+ ...(hostGeneration ? { hostGeneration } : {}),
305
316
  };
306
317
  }
307
318
  // Strict atomic write for the install state: must never be left half-written.
@@ -654,6 +665,31 @@ function journalAction(action, status, extras = {}) {
654
665
  const { value: _value, ...safeAction } = action;
655
666
  return { ...safeAction, ...extras, status };
656
667
  }
668
+ /**
669
+ * The text a `rewrite-json` action writes. A file with JSONC syntax (comments, trailing commas, or a
670
+ * `.jsonc` name) is edited in place from the action's `edits`, so the user's annotations survive (#5334);
671
+ * everything else, and any edit the text editor cannot place, is written as the action's whole `value`.
672
+ */
673
+ function renderRewrittenJson(fullPath, action) {
674
+ if (Array.isArray(action.edits) && action.edits.length > 0) {
675
+ let original = null;
676
+ try {
677
+ original = node_fs_1.default.readFileSync(fullPath, 'utf8');
678
+ }
679
+ catch { /* fall through to the value rewrite */ }
680
+ if (original !== null && (fullPath.endsWith('.jsonc') || (0, jsonc_edit_cjs_1.hasJsoncFeatures)(original))) {
681
+ let text = original;
682
+ for (const edit of action.edits) {
683
+ text = (0, jsonc_edit_cjs_1.setJsoncValue)(text, edit.path, edit.value);
684
+ if (text === null)
685
+ break;
686
+ }
687
+ if (text !== null)
688
+ return text;
689
+ }
690
+ }
691
+ return JSON.stringify(action.value, null, 2) + '\n';
692
+ }
657
693
  function planInstallerMigrations({ configDir, runtime = null, scope = null, migrations, baselineScan = false, now = () => new Date().toISOString(), }) {
658
694
  if (!configDir)
659
695
  throw new Error('configDir is required');
@@ -725,6 +761,8 @@ function planInstallerMigrations({ configDir, runtime = null, scope = null, migr
725
761
  }
726
762
  if (action.type === 'rewrite-json') {
727
763
  action.value = rawAction.value;
764
+ if (Array.isArray(rawAction.edits))
765
+ action.edits = rawAction.edits;
728
766
  action.deleteIfEmpty = rawAction.deleteIfEmpty === true;
729
767
  }
730
768
  if (rawAction.prompt)
@@ -896,7 +934,7 @@ function applyInstallerMigrationPlan({ configDir, plan, now = () => new Date().t
896
934
  }));
897
935
  }
898
936
  else {
899
- (0, shell_command_projection_cjs_1.platformWriteSync)(fullPath, JSON.stringify(action.value, null, 2) + '\n');
937
+ (0, shell_command_projection_cjs_1.platformWriteSync)(fullPath, renderRewrittenJson(fullPath, action));
900
938
  journal.actions.push(journalAction(action, 'rewritten', {
901
939
  rollbackRelPath: node_path_1.default.posix.join(rollbackRootRelPath, normalized),
902
940
  }));
@@ -945,6 +983,7 @@ function applyInstallerMigrationPlan({ configDir, plan, now = () => new Date().t
945
983
  writeInstallState(configDir, {
946
984
  schemaVersion: 1,
947
985
  appliedMigrations: nextApplied,
986
+ ...(state.hostGeneration ? { hostGeneration: state.hostGeneration } : {}),
948
987
  });
949
988
  return {
950
989
  appliedMigrationIds: journal.appliedMigrationIds,
@@ -1017,6 +1056,7 @@ function markPendingMigrationsApplied({ configDir, plan, now = () => new Date().
1017
1056
  writeInstallState(configDir, {
1018
1057
  schemaVersion: 1,
1019
1058
  appliedMigrations: nextApplied,
1059
+ ...(state.hostGeneration ? { hostGeneration: state.hostGeneration } : {}),
1020
1060
  });
1021
1061
  }
1022
1062
  return newlyApplied;
@@ -1073,6 +1113,18 @@ function runInstallerMigrations({ configDir, runtime = null, scope = null, migra
1073
1113
  // Unused but kept to satisfy eslint — sleepSync is referenced in the original
1074
1114
  // and may be used by test code that patches this module.
1075
1115
  void sleepSync;
1116
+ /**
1117
+ * Record which OpenCode generation this install targets (ADR-5331 D2; #5337). Idempotent and
1118
+ * atomic; leaves the applied-migrations journal untouched.
1119
+ */
1120
+ function recordHostGeneration(configDir, info) {
1121
+ const state = readInstallState(configDir);
1122
+ const next = { runtime: 'opencode', generation: info.generation, version: info.version ?? null };
1123
+ const prev = state.hostGeneration;
1124
+ if (prev && prev.generation === next.generation && prev.version === next.version)
1125
+ return;
1126
+ writeInstallState(configDir, { ...state, hostGeneration: next });
1127
+ }
1076
1128
  module.exports = {
1077
1129
  DEFAULT_MIGRATIONS_DIR,
1078
1130
  INSTALL_MIGRATION_LOCK_NAME,
@@ -1089,6 +1141,7 @@ module.exports = {
1089
1141
  planInstallerMigrations,
1090
1142
  readInstallManifest,
1091
1143
  readInstallState,
1144
+ recordHostGeneration,
1092
1145
  runInstallerMigrations,
1093
1146
  writeInstallState,
1094
1147
  };
@@ -121,6 +121,84 @@ function writeAllSync(fd, data) {
121
121
  }
122
122
  }
123
123
  }
124
+ /**
125
+ * Temporarily patch `fs.writeSync` so everything written to fd 1 (stdout) is
126
+ * captured into a string instead of reaching the real stdout, run `run`, then
127
+ * restore the original `fs.writeSync` and resolve with what was captured.
128
+ *
129
+ * The ONE shared helper (#5105 S9) for "run a nested command and read its own
130
+ * JSON envelope back as data instead of letting it reach the real stdout" —
131
+ * used by gsd-tools.cjs's `--pick`/`@file:` resolution and by `uat.cts`'s
132
+ * `cmdUatCompleteSession` (which needs `cmdCommit`'s result object without
133
+ * emitting cmdCommit's own envelope as a second line of output). A single
134
+ * definition means both callers see the same Buffer/string/encoding handling
135
+ * and the same throw-mid-write flush behavior, rather than two hand-rolled
136
+ * monkeypatches drifting apart.
137
+ *
138
+ * On a throw from `run`, whatever was captured before the throw is flushed to
139
+ * the REAL stdout — the wrapped command may have already written its own
140
+ * JSON envelope and THEN thrown to set a non-zero exit code (e.g. a
141
+ * capability set/disable on an unknown id); without this flush that output
142
+ * would be silently discarded, since the success-path flush at the call site
143
+ * never runs on a throw. The error still propagates so the exit code is
144
+ * preserved.
145
+ */
146
+ function captureStdoutSyncWrites(run) {
147
+ const originalWriteSync = node_fs_1.default.writeSync;
148
+ let captured = '';
149
+ node_fs_1.default.writeSync = ((fd, data, ...rest) => {
150
+ if (fd === 1) {
151
+ if (Buffer.isBuffer(data)) {
152
+ captured += data.toString('utf-8');
153
+ return data.length;
154
+ }
155
+ const text = String(data);
156
+ captured += text;
157
+ let encoding = 'utf-8';
158
+ if (typeof rest[1] === 'string')
159
+ encoding = rest[1];
160
+ return Buffer.byteLength(text, encoding);
161
+ }
162
+ return originalWriteSync.call(node_fs_1.default, fd, data, ...rest);
163
+ });
164
+ const restore = () => {
165
+ node_fs_1.default.writeSync = originalWriteSync;
166
+ };
167
+ return Promise.resolve()
168
+ .then(() => run())
169
+ .then(() => {
170
+ restore();
171
+ return captured;
172
+ }, (err) => {
173
+ restore();
174
+ if (captured) {
175
+ try {
176
+ originalWriteSync.call(node_fs_1.default, 1, captured);
177
+ }
178
+ catch { /* best-effort flush */ }
179
+ }
180
+ throw err;
181
+ });
182
+ }
183
+ /**
184
+ * Resolve `output()`'s `@file:<path>` redirection (emitted for a >50KB JSON
185
+ * payload) back to the real content, or return `captured` unchanged when it
186
+ * is not that shape.
187
+ *
188
+ * #5105 review finding 7: the ONE definition, shared by gsd-tools.cjs's
189
+ * `--pick`/CLI-passthrough resolution and by `uat.cts`'s
190
+ * `cmdUatCompleteSession` (which reads `cmdCommit`'s captured result back
191
+ * without emitting cmdCommit's own envelope as a second stdout line) — same
192
+ * reasoning as `captureStdoutSyncWrites` just below: one definition means
193
+ * both callers agree on the trailing-newline-free prefix and the read
194
+ * encoding, rather than two hand-rolled `startsWith('@file:')` checks
195
+ * drifting apart.
196
+ */
197
+ function resolveAtFileOutput(captured) {
198
+ if (!captured.startsWith('@file:'))
199
+ return captured;
200
+ return node_fs_1.default.readFileSync(captured.slice('@file:'.length), 'utf-8');
201
+ }
124
202
  /**
125
203
  * The wire form of a JSON result: the exact bytes `output()` emits for it.
126
204
  *
@@ -290,6 +368,16 @@ const ERROR_REASON = Object.freeze({
290
368
  // exit 0. See .gsd/phase/feat-3884-failure-is-a-value/40-design.md.
291
369
  PICK_FIELD_ABSENT: 'pick_field_absent',
292
370
  PICK_OUTPUT_NOT_JSON: 'pick_output_not_json',
371
+ // summary-extract (#5013): the SUMMARY's frontmatter fence exists but failed
372
+ // to parse (extractFrontmatter's FRONTMATTER_UNPARSEABLE marker) — a
373
+ // distinct failure from "no frontmatter"/"field absent", never a silent
374
+ // demotion to empty fields at exit 0.
375
+ SUMMARY_EXTRACT_UNPARSEABLE: 'summary_extract_unparseable',
376
+ // verification (#5118, ADR-5057 Phase 4): a *-VERIFICATION.md frontmatter
377
+ // `status` outside the closed writer set (`passed | gaps_found |
378
+ // human_needed`) — verification.cts's VerificationStatusError, translated
379
+ // once, centrally, by gsd-tools.cjs. Never read as "no result" at exit 0.
380
+ VERIFICATION_STATUS_INVALID: 'verification_status_invalid',
293
381
  // generic
294
382
  USAGE: 'usage',
295
383
  UNKNOWN: 'unknown',
@@ -334,14 +422,35 @@ const ERROR_REASON = Object.freeze({
334
422
  * more than one line or introduce an unescaped `"`. Callers embedding the
335
423
  * result MUST NOT add their own surrounding quotes — that would
336
424
  * double-quote it.
425
+ *
426
+ * #5118 security review: `JSON.stringify` leaves characters that render
427
+ * invisibly or reorder the text around them untouched — DEL and the C1
428
+ * controls (U+007F–U+009F), the line/paragraph separators (U+2028–U+2029),
429
+ * zero-width and directional marks (U+200B–U+200F), the bidi embeddings and
430
+ * overrides (U+202A–U+202E), the bidi isolates (U+2066–U+2069) and the BOM
431
+ * (U+FEFF). Each is escaped as `\uXXXX` so the token reads exactly as its
432
+ * code points are, whoever renders it.
337
433
  */
434
+ const INVISIBLE_OR_BIDI_RANGES = [
435
+ [0x7f, 0x9f],
436
+ [0x2028, 0x2029],
437
+ [0x200b, 0x200f],
438
+ [0x202a, 0x202e],
439
+ [0x2066, 0x2069],
440
+ [0xfeff, 0xfeff],
441
+ ];
442
+ /** Code points as `\uXXXX` escape text (source stays ASCII; no literal invisible characters). */
443
+ function toUnicodeEscape(codePoint) {
444
+ return `\\u${codePoint.toString(16).padStart(4, '0')}`;
445
+ }
446
+ const INVISIBLE_OR_BIDI_RE = new RegExp(`[${INVISIBLE_OR_BIDI_RANGES.map(([lo, hi]) => `${toUnicodeEscape(lo)}-${toUnicodeEscape(hi)}`).join('')}]`, 'g');
338
447
  function formatDiagnosticToken(value) {
339
- return JSON.stringify(value);
448
+ return JSON.stringify(value).replace(INVISIBLE_OR_BIDI_RE, (ch) => toUnicodeEscape(ch.charCodeAt(0)));
340
449
  }
341
450
  /**
342
451
  * Map an ERROR_REASON wire value onto a declared outcome name (#3912,
343
- * ADR-3889 §4). Closed over the 25-member enum: every reason gets an
344
- * explicit entry below, so a 26th member added without a mapping falls
452
+ * ADR-3889 §4). Closed over the 27-member enum: every reason gets an
453
+ * explicit entry below, so a 28th member added without a mapping falls
345
454
  * through to the `?? 'FAIL'` default rather than silently mis-projecting —
346
455
  * and tests/A1 iterates `Object.values(ERROR_REASON)`, so that default is
347
456
  * exactly what makes an unmapped addition visible instead of invisible.
@@ -389,6 +498,14 @@ const REASON_TO_OUTCOME = Object.freeze({
389
498
  // supposed to be there and was not; a prerequisite of the query failed.
390
499
  [ERROR_REASON.PICK_FIELD_ABSENT]: 'UNAVAILABLE',
391
500
  [ERROR_REASON.PICK_OUTPUT_NOT_JSON]: 'UNAVAILABLE',
501
+ // #5013: the SUMMARY's frontmatter fence exists but failed to parse — the
502
+ // prerequisite of the query (readable frontmatter) is what's broken, same
503
+ // shape as PICK_FIELD_ABSENT/PICK_OUTPUT_NOT_JSON just above.
504
+ [ERROR_REASON.SUMMARY_EXTRACT_UNPARSEABLE]: 'UNAVAILABLE',
505
+ // #5118: the verification report exists but its `status` is not a verdict
506
+ // the reader accepts — a broken prerequisite of the query, the same shape
507
+ // as SUMMARY_EXTRACT_UNPARSEABLE just above.
508
+ [ERROR_REASON.VERIFICATION_STATUS_INVALID]: 'UNAVAILABLE',
392
509
  // Self-failure: the run itself broke, not its inputs.
393
510
  [ERROR_REASON.SDK_FAIL_FAST]: 'INTERNAL',
394
511
  [ERROR_REASON.SECURITY_SCAN_FAILED]: 'INTERNAL',
@@ -433,4 +550,6 @@ module.exports = {
433
550
  getJsonErrorMode,
434
551
  error,
435
552
  formatDiagnosticToken,
553
+ captureStdoutSyncWrites,
554
+ resolveAtFileOutput,
436
555
  };