@opengsd/gsd-core 1.14.0 → 1.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (551) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/.opencode/plugins/gsd-core.js +85 -5
  4. package/README.ja-JP.md +3 -3
  5. package/README.ko-KR.md +3 -3
  6. package/README.pt-BR.md +3 -3
  7. package/README.zh-CN.md +3 -3
  8. package/agents/gsd-code-fixer.compact.md +7 -6
  9. package/agents/gsd-code-fixer.md +9 -8
  10. package/agents/gsd-code-reviewer.compact.md +5 -3
  11. package/agents/gsd-code-reviewer.md +8 -6
  12. package/agents/gsd-debug-session-manager.compact.md +17 -2
  13. package/agents/gsd-debug-session-manager.md +17 -2
  14. package/agents/gsd-debugger.md +3 -3
  15. package/agents/gsd-eval-auditor.compact.md +1 -1
  16. package/agents/gsd-eval-auditor.md +1 -1
  17. package/agents/gsd-executor.md +17 -12
  18. package/agents/gsd-intel-updater.compact.md +1 -1
  19. package/agents/gsd-intel-updater.md +1 -1
  20. package/agents/gsd-mempalace-curator.md +2 -2
  21. package/agents/gsd-phase-researcher.md +19 -11
  22. package/agents/gsd-plan-checker.md +15 -9
  23. package/agents/gsd-planner.md +15 -11
  24. package/agents/gsd-project-researcher.compact.md +1 -1
  25. package/agents/gsd-project-researcher.md +1 -1
  26. package/agents/gsd-research-synthesizer.compact.md +1 -1
  27. package/agents/gsd-research-synthesizer.md +1 -1
  28. package/agents/gsd-ui-auditor.compact.md +21 -30
  29. package/agents/gsd-ui-auditor.md +166 -37
  30. package/agents/gsd-ui-researcher.compact.md +1 -1
  31. package/agents/gsd-ui-researcher.md +1 -1
  32. package/agents/gsd-verifier.md +37 -14
  33. package/bin/install.js +764 -287
  34. package/commands/gsd/add-tests.md +6 -1
  35. package/commands/gsd/ai-integration-phase.md +6 -1
  36. package/commands/gsd/audit-fix.md +5 -0
  37. package/commands/gsd/audit-milestone.md +6 -1
  38. package/commands/gsd/autonomous.md +7 -2
  39. package/commands/gsd/capture.md +9 -5
  40. package/commands/gsd/code-review.md +7 -2
  41. package/commands/gsd/complete-milestone.md +4 -0
  42. package/commands/gsd/config.md +7 -3
  43. package/commands/gsd/debug.md +11 -7
  44. package/commands/gsd/discuss-phase.md +7 -3
  45. package/commands/gsd/docs-update.md +12 -7
  46. package/commands/gsd/eval-review.md +6 -1
  47. package/commands/gsd/execute-phase.md +12 -7
  48. package/commands/gsd/extract-learnings.md +5 -0
  49. package/commands/gsd/fast.md +4 -0
  50. package/commands/gsd/forensics.md +5 -1
  51. package/commands/gsd/graphify.md +10 -6
  52. package/commands/gsd/health.md +5 -0
  53. package/commands/gsd/help.md +7 -2
  54. package/commands/gsd/import.md +7 -3
  55. package/commands/gsd/inbox.md +5 -0
  56. package/commands/gsd/ingest-docs.md +5 -1
  57. package/commands/gsd/manager.md +6 -1
  58. package/commands/gsd/map-codebase.md +7 -3
  59. package/commands/gsd/mempalace-capture.md +12 -4
  60. package/commands/gsd/mempalace-recall.md +5 -1
  61. package/commands/gsd/milestone-summary.md +5 -1
  62. package/commands/gsd/mvp-phase.md +8 -3
  63. package/commands/gsd/new-milestone.md +6 -1
  64. package/commands/gsd/new-project.md +5 -0
  65. package/commands/gsd/next.md +6 -1
  66. package/commands/gsd/ns-context.md +4 -0
  67. package/commands/gsd/ns-ideate.md +4 -0
  68. package/commands/gsd/ns-manage.md +4 -0
  69. package/commands/gsd/ns-project.md +4 -0
  70. package/commands/gsd/ns-review.md +4 -0
  71. package/commands/gsd/ns-workflow.md +4 -0
  72. package/commands/gsd/onboard.md +6 -1
  73. package/commands/gsd/pause-work.md +5 -1
  74. package/commands/gsd/phase.md +8 -4
  75. package/commands/gsd/plan-phase.md +6 -1
  76. package/commands/gsd/plan-review-convergence.md +11 -7
  77. package/commands/gsd/pr-branch.md +4 -0
  78. package/commands/gsd/profile-user.md +5 -1
  79. package/commands/gsd/progress.md +7 -2
  80. package/commands/gsd/quick-batch.md +21 -9
  81. package/commands/gsd/quick.md +12 -7
  82. package/commands/gsd/review.md +7 -4
  83. package/commands/gsd/secure-phase.md +6 -1
  84. package/commands/gsd/ship.md +5 -0
  85. package/commands/gsd/sketch.md +7 -2
  86. package/commands/gsd/spec-phase.md +5 -1
  87. package/commands/gsd/spike.md +8 -3
  88. package/commands/gsd/surface.md +5 -1
  89. package/commands/gsd/thread.md +4 -0
  90. package/commands/gsd/ui-phase.md +6 -1
  91. package/commands/gsd/ui-review.md +6 -1
  92. package/commands/gsd/ultraplan-phase.md +5 -1
  93. package/commands/gsd/undo.md +5 -1
  94. package/commands/gsd/update.md +6 -2
  95. package/commands/gsd/validate-phase.md +6 -1
  96. package/commands/gsd/verify-work.md +6 -1
  97. package/commands/gsd/workspace.md +7 -3
  98. package/gsd-core/bin/gsd-tools.cjs +477 -78
  99. package/gsd-core/bin/lib/active-workstream-store.cjs +15 -0
  100. package/gsd-core/bin/lib/adr-parser.cjs +3 -1
  101. package/gsd-core/bin/lib/agent-install-check.cjs +4 -1
  102. package/gsd-core/bin/lib/audit.cjs +144 -42
  103. package/gsd-core/bin/lib/broken-windows.cjs +13 -13
  104. package/gsd-core/bin/lib/capability-activation.cjs +9 -4
  105. package/gsd-core/bin/lib/capability-registry.cjs +197 -222
  106. package/gsd-core/bin/lib/capability-validator.cjs +16 -1
  107. package/gsd-core/bin/lib/check-auto-mode.cjs +35 -0
  108. package/gsd-core/bin/lib/check-command-router.cjs +164 -1625
  109. package/gsd-core/bin/lib/cjs-command-router-adapter.cjs +13 -2
  110. package/gsd-core/bin/lib/cli-exit.cjs +12 -0
  111. package/gsd-core/bin/lib/codex-agent-toml.cjs +32 -33
  112. package/gsd-core/bin/lib/command-aliases.cjs +7 -0
  113. package/gsd-core/bin/lib/command-routing-hub.cjs +48 -1
  114. package/gsd-core/bin/lib/commands.cjs +343 -207
  115. package/gsd-core/bin/lib/complexity-trigger.cjs +8 -7
  116. package/gsd-core/bin/lib/config-loader.cjs +65 -4
  117. package/gsd-core/bin/lib/config.cjs +76 -19
  118. package/gsd-core/bin/lib/core-utils.cjs +6 -1
  119. package/gsd-core/bin/lib/coverage.cjs +4 -8
  120. package/gsd-core/bin/lib/decision-coverage-support.cjs +259 -0
  121. package/gsd-core/bin/lib/decisions.cjs +30 -14
  122. package/gsd-core/bin/lib/drift.cjs +177 -42
  123. package/gsd-core/bin/lib/frontmatter-fence.cjs +90 -0
  124. package/gsd-core/bin/lib/frontmatter-splice.cjs +494 -0
  125. package/gsd-core/bin/lib/frontmatter.cjs +426 -234
  126. package/gsd-core/bin/lib/gap-checker.cjs +72 -29
  127. package/gsd-core/bin/lib/gate-api-coverage-verify-pre.cjs +381 -0
  128. package/gsd-core/bin/lib/gate-args.cjs +53 -0
  129. package/gsd-core/bin/lib/gate-codebase-drift.cjs +285 -0
  130. package/gsd-core/bin/lib/gate-config.cjs +46 -0
  131. package/gsd-core/bin/lib/gate-context-drift.cjs +141 -0
  132. package/gsd-core/bin/lib/gate-decision-coverage-plan.cjs +169 -0
  133. package/gsd-core/bin/lib/gate-decision-coverage-verify.cjs +126 -0
  134. package/gsd-core/bin/lib/gate-evaluation-scope.cjs +555 -0
  135. package/gsd-core/bin/lib/gate-evidence.cjs +138 -0
  136. package/gsd-core/bin/lib/gate-exit.cjs +27 -0
  137. package/gsd-core/bin/lib/gate-gap-analysis-plan-post.cjs +61 -0
  138. package/gsd-core/bin/lib/gate-phase-context.cjs +170 -0
  139. package/gsd-core/bin/lib/gate-predicate-evaluator.cjs +1 -1
  140. package/gsd-core/bin/lib/gate-predicate.cjs +165 -0
  141. package/gsd-core/bin/lib/gate-prohibition-enforcement.cjs +94 -0
  142. package/gsd-core/bin/lib/gate-schema-drift.cjs +165 -0
  143. package/gsd-core/bin/lib/gate-tdd-red-evidence.cjs +100 -0
  144. package/gsd-core/bin/lib/gate-tdd-review-checkpoint.cjs +182 -0
  145. package/gsd-core/bin/lib/gate-ui-plan.cjs +86 -0
  146. package/gsd-core/bin/lib/gate-ui-safety.cjs +80 -0
  147. package/gsd-core/bin/lib/gate-verdict.cjs +64 -0
  148. package/gsd-core/bin/lib/gate-verify-command-paths.cjs +78 -0
  149. package/gsd-core/bin/lib/gate-verify-failure-directions.cjs +41 -0
  150. package/gsd-core/bin/lib/graphify.cjs +10 -2
  151. package/gsd-core/bin/lib/health-diagnostic-rules/phase-structure.cjs +43 -47
  152. package/gsd-core/bin/lib/health-diagnostic.cjs +45 -8
  153. package/gsd-core/bin/lib/host-runtime-detection.cjs +9 -0
  154. package/gsd-core/bin/lib/init.cjs +364 -132
  155. package/gsd-core/bin/lib/install-engine.cjs +30 -33
  156. package/gsd-core/bin/lib/install-profiles.cjs +7 -4
  157. package/gsd-core/bin/lib/installer-migrations.cjs +8 -1
  158. package/gsd-core/bin/lib/io.cjs +122 -3
  159. package/gsd-core/bin/lib/loop-resolver.cjs +95 -0
  160. package/gsd-core/bin/lib/markdown-sectionizer.cjs +75 -1
  161. package/gsd-core/bin/lib/milestone.cjs +37 -6
  162. package/gsd-core/bin/lib/model-resolver.cjs +171 -62
  163. package/gsd-core/bin/lib/observability/event.cjs +1 -1
  164. package/gsd-core/bin/lib/observability/logger.cjs +46 -1
  165. package/gsd-core/bin/lib/pattern.cjs +10 -0
  166. package/gsd-core/bin/lib/phase-command-router.cjs +20 -5
  167. package/gsd-core/bin/lib/phase-estimation.cjs +5 -4
  168. package/gsd-core/bin/lib/phase-id-card.cjs +32 -0
  169. package/gsd-core/bin/lib/phase-id-display.cjs +78 -0
  170. package/gsd-core/bin/lib/phase-id.cjs +110 -8
  171. package/gsd-core/bin/lib/phase-lifecycle.cjs +9 -2
  172. package/gsd-core/bin/lib/phase-locator.cjs +29 -10
  173. package/gsd-core/bin/lib/phase-status.cjs +360 -0
  174. package/gsd-core/bin/lib/phase.cjs +489 -88
  175. package/gsd-core/bin/lib/plan-document.cjs +142 -20
  176. package/gsd-core/bin/lib/plan-drift-guard.cjs +5 -0
  177. package/gsd-core/bin/lib/planning-document.cjs +692 -0
  178. package/gsd-core/bin/lib/planning-inspect.cjs +60 -9
  179. package/gsd-core/bin/lib/planning-snapshot.cjs +18 -0
  180. package/gsd-core/bin/lib/planning-workspace.cjs +83 -55
  181. package/gsd-core/bin/lib/pr-branch-patterns.cjs +57 -0
  182. package/gsd-core/bin/lib/pristine-baseline.cjs +10 -0
  183. package/gsd-core/bin/lib/probe-core.cjs +7 -1
  184. package/gsd-core/bin/lib/profile-output.cjs +6 -3
  185. package/gsd-core/bin/lib/prohibition-enforcement.cjs +0 -55
  186. package/gsd-core/bin/lib/project-root.cjs +41 -2
  187. package/gsd-core/bin/lib/quick-batch-command-router.cjs +35 -9
  188. package/gsd-core/bin/lib/quick-batch-dispatch.cjs +11 -8
  189. package/gsd-core/bin/lib/real-home-guard.cjs +9 -1
  190. package/gsd-core/bin/lib/report-parser.cjs +269 -0
  191. package/gsd-core/bin/lib/review-lane-descriptor.cjs +10 -30
  192. package/gsd-core/bin/lib/review-reviewer-selection.cjs +2 -2
  193. package/gsd-core/bin/lib/roadmap-command-router.cjs +25 -19
  194. package/gsd-core/bin/lib/roadmap-parser.cjs +242 -15
  195. package/gsd-core/bin/lib/roadmap-upgrade.cjs +1653 -65
  196. package/gsd-core/bin/lib/roadmap.cjs +405 -88
  197. package/gsd-core/bin/lib/runtime-artifact-conversion.cjs +373 -187
  198. package/gsd-core/bin/lib/runtime-artifact-install-plan.cjs +5 -2
  199. package/gsd-core/bin/lib/runtime-artifact-layout.cjs +57 -1
  200. package/gsd-core/bin/lib/runtime-homes.cjs +14 -7
  201. package/gsd-core/bin/lib/runtime-hooks-surface.cjs +522 -624
  202. package/gsd-core/bin/lib/runtime-name-policy.cjs +246 -21
  203. package/gsd-core/bin/lib/runtime-slash.cjs +47 -30
  204. package/gsd-core/bin/lib/shell-command-projection.cjs +47 -8
  205. package/gsd-core/bin/lib/smart-entry.cjs +19 -3
  206. package/gsd-core/bin/lib/stale-bake-guard.cjs +32 -48
  207. package/gsd-core/bin/lib/state-contract.cjs +15 -18
  208. package/gsd-core/bin/lib/state-document.cjs +100 -22
  209. package/gsd-core/bin/lib/state-transition.cjs +39 -2
  210. package/gsd-core/bin/lib/state.cjs +256 -105
  211. package/gsd-core/bin/lib/surface.cjs +19 -2
  212. package/gsd-core/bin/lib/tdd-red-evidence.cjs +48 -79
  213. package/gsd-core/bin/lib/uat-predicate.cjs +359 -38
  214. package/gsd-core/bin/lib/uat.cjs +432 -7
  215. package/gsd-core/bin/lib/ui-consideration-probe.cjs +15 -2
  216. package/gsd-core/bin/lib/ui-frontend-evidence.cjs +167 -40
  217. package/gsd-core/bin/lib/undo-commit-selection.cjs +131 -0
  218. package/gsd-core/bin/lib/vendor/README.md +31 -9
  219. package/gsd-core/bin/lib/vendor/saxes.cjs +1934 -0
  220. package/gsd-core/bin/lib/vendor/saxes.cjs.LICENSE.txt +92 -0
  221. package/gsd-core/bin/lib/vendor/tap-parser.cjs +8927 -0
  222. package/gsd-core/bin/lib/vendor/tap-parser.cjs.LICENSE.txt +152 -0
  223. package/gsd-core/bin/lib/verification-command-router.cjs +2 -1
  224. package/gsd-core/bin/lib/verification.cjs +1378 -274
  225. package/gsd-core/bin/lib/verify-command-grounding.cjs +46 -2
  226. package/gsd-core/bin/lib/verify-command-router.cjs +18 -7
  227. package/gsd-core/bin/lib/verify.cjs +357 -531
  228. package/gsd-core/bin/lib/workstream-inventory-builder.cjs +14 -6
  229. package/gsd-core/bin/lib/workstream-inventory.cjs +31 -21
  230. package/gsd-core/bin/lib/workstream-name-policy.cjs +31 -1
  231. package/gsd-core/bin/lib/workstream.cjs +11 -2
  232. package/gsd-core/bin/lib/worktree-base-ref.cjs +482 -73
  233. package/gsd-core/bin/lib/worktree-safety.cjs +784 -51
  234. package/gsd-core/bin/shared/config-defaults.manifest.json +8 -0
  235. package/gsd-core/bin/shared/config-schema.manifest.json +5 -0
  236. package/gsd-core/references/autonomous-smart-discuss.md +2 -1
  237. package/gsd-core/references/autonomous-ui-design-contract.md +3 -3
  238. package/gsd-core/references/checkpoints.md +5 -3
  239. package/gsd-core/references/edge-probe-fixtures/01-round-half-even/expected-coverage.json +28 -3
  240. package/gsd-core/references/edge-probe-fixtures/02-merge-intervals/expected-coverage.json +37 -4
  241. package/gsd-core/references/edge-probe-fixtures/03-truncate-graphemes/expected-coverage.json +28 -3
  242. package/gsd-core/references/edge-probe-fixtures/04-money-rounding/expected-coverage.json +28 -3
  243. package/gsd-core/references/edge-probe-fixtures/05-list-dedupe/expected-coverage.json +37 -4
  244. package/gsd-core/references/edge-probe-fixtures/06-resolved-mixed/expected-coverage.json +37 -4
  245. package/gsd-core/references/edge-probe.md +195 -21
  246. package/gsd-core/references/execute-mvp-tdd.md +5 -10
  247. package/gsd-core/references/execute-phase-between-wave-reset.md +10 -6
  248. package/gsd-core/references/execute-phase-response-language.md +1 -1
  249. package/gsd-core/references/execute-phase-wave-guard.md +22 -11
  250. package/gsd-core/references/gsd-run-resolver.md +1 -1
  251. package/gsd-core/references/loop-hook-dispatch.md +7 -1
  252. package/gsd-core/references/model-profiles.md +1 -1
  253. package/gsd-core/references/offer-next.md +1 -1
  254. package/gsd-core/references/phase-argument-parsing.md +9 -7
  255. package/gsd-core/references/phase-id-convention.md +28 -0
  256. package/gsd-core/references/planner-gap-closure.md +2 -0
  257. package/gsd-core/references/planner-load-graph-context.md +24 -13
  258. package/gsd-core/references/planner-verify-command-grounding.md +14 -0
  259. package/gsd-core/references/planning-config.md +12 -3
  260. package/gsd-core/references/spidr-splitting.md +1 -1
  261. package/gsd-core/references/tdd.md +37 -8
  262. package/gsd-core/references/ui-consideration-probe.md +10 -5
  263. package/gsd-core/references/verifier-phase-gates.md +5 -2
  264. package/gsd-core/references/verify-command-path-resolvability.md +10 -2
  265. package/gsd-core/references/verify-mvp-mode.md +2 -2
  266. package/gsd-core/references/workstream-flag.md +33 -3
  267. package/gsd-core/references/worktree-path-safety.md +321 -0
  268. package/gsd-core/templates/README.md +1 -1
  269. package/gsd-core/templates/UAT.md +17 -1
  270. package/gsd-core/templates/config.json +2 -11
  271. package/gsd-core/templates/verification-report.md +1 -1
  272. package/gsd-core/workflows/_runtime-launcher.snippet.sh +1 -1
  273. package/gsd-core/workflows/add-backlog.md +1 -1
  274. package/gsd-core/workflows/add-phase.md +8 -7
  275. package/gsd-core/workflows/add-tests.md +4 -3
  276. package/gsd-core/workflows/add-todo.md +6 -5
  277. package/gsd-core/workflows/ai-integration-phase.md +13 -4
  278. package/gsd-core/workflows/audit-fix.md +1 -1
  279. package/gsd-core/workflows/audit-milestone.md +4 -3
  280. package/gsd-core/workflows/audit-uat.md +1 -1
  281. package/gsd-core/workflows/autonomous/steps/converge-fail-fast.md +9 -18
  282. package/gsd-core/workflows/autonomous.md +43 -23
  283. package/gsd-core/workflows/check-todos.md +7 -6
  284. package/gsd-core/workflows/cleanup.md +2 -2
  285. package/gsd-core/workflows/code-review/steps/dispatch-fix.md +4 -3
  286. package/gsd-core/workflows/code-review/steps/structural-pre-pass.md +20 -13
  287. package/gsd-core/workflows/code-review-fix.md +112 -25
  288. package/gsd-core/workflows/code-review.md +146 -135
  289. package/gsd-core/workflows/complete-milestone/detail/elaboration.md +4 -3
  290. package/gsd-core/workflows/complete-milestone.md +13 -8
  291. package/gsd-core/workflows/debug.md +32 -7
  292. package/gsd-core/workflows/diagnose-issues.md +3 -2
  293. package/gsd-core/workflows/discuss-phase/modes/advisor.md +1 -1
  294. package/gsd-core/workflows/discuss-phase/modes/chain.md +1 -1
  295. package/gsd-core/workflows/discuss-phase-assumptions.md +4 -3
  296. package/gsd-core/workflows/discuss-phase.md +4 -3
  297. package/gsd-core/workflows/do.md +2 -2
  298. package/gsd-core/workflows/docs-update.md +6 -5
  299. package/gsd-core/workflows/edit-phase.md +4 -3
  300. package/gsd-core/workflows/eval-review.md +14 -5
  301. package/gsd-core/workflows/execute-phase/detail/elaboration.md +2 -2
  302. package/gsd-core/workflows/execute-phase/steps/code-review-disposition.md +1019 -0
  303. package/gsd-core/workflows/execute-phase/steps/codebase-drift-gate.md +15 -4
  304. package/gsd-core/workflows/execute-phase/steps/completion-reconciliation.md +10 -7
  305. package/gsd-core/workflows/execute-phase/steps/executor-isolation-dispatch.md +37 -3
  306. package/gsd-core/workflows/execute-phase/steps/gap-closure-artifacts.md +3 -1
  307. package/gsd-core/workflows/execute-phase/steps/partial-wave.md +2 -2
  308. package/gsd-core/workflows/execute-phase/steps/per-plan-executor-routing.md +1 -1
  309. package/gsd-core/workflows/execute-phase/steps/per-plan-worktree-gate.md +1 -1
  310. package/gsd-core/workflows/execute-phase/steps/post-merge-gate.md +46 -9
  311. package/gsd-core/workflows/execute-phase/steps/protected-branch.md +1 -1
  312. package/gsd-core/workflows/execute-phase/steps/ready-wave-gate.md +37 -0
  313. package/gsd-core/workflows/execute-phase/steps/regression-gate-run.md +1 -1
  314. package/gsd-core/workflows/execute-phase/steps/regression-gate.md +2 -0
  315. package/gsd-core/workflows/execute-phase/steps/tdd-applicability-resolution.md +1 -1
  316. package/gsd-core/workflows/execute-phase/steps/threat-id-gate.md +28 -0
  317. package/gsd-core/workflows/execute-phase/steps/verify-phase-goal.md +187 -0
  318. package/gsd-core/workflows/execute-phase/steps/wave-post-gate-hooks.md +2 -3
  319. package/gsd-core/workflows/execute-phase/steps/worktree-base-check.md +25 -0
  320. package/gsd-core/workflows/execute-phase.md +96 -178
  321. package/gsd-core/workflows/execute-plan.md +18 -23
  322. package/gsd-core/workflows/explore.md +4 -4
  323. package/gsd-core/workflows/extract-learnings.md +4 -2
  324. package/gsd-core/workflows/fast.md +1 -1
  325. package/gsd-core/workflows/forensics.md +1 -1
  326. package/gsd-core/workflows/graduation.md +1 -1
  327. package/gsd-core/workflows/health.md +3 -2
  328. package/gsd-core/workflows/help/modes/full.compact.md +3 -3
  329. package/gsd-core/workflows/help/modes/full.md +5 -5
  330. package/gsd-core/workflows/help/modes/topic.md +15 -5
  331. package/gsd-core/workflows/import.md +4 -3
  332. package/gsd-core/workflows/inbox.md +2 -2
  333. package/gsd-core/workflows/ingest-docs.md +3 -3
  334. package/gsd-core/workflows/insert-phase.md +4 -3
  335. package/gsd-core/workflows/list-seeds.md +1 -1
  336. package/gsd-core/workflows/list-workspaces.md +1 -1
  337. package/gsd-core/workflows/manager.md +6 -4
  338. package/gsd-core/workflows/map-codebase.md +5 -4
  339. package/gsd-core/workflows/milestone-summary.md +3 -2
  340. package/gsd-core/workflows/mvp-phase.md +14 -14
  341. package/gsd-core/workflows/new-milestone.md +11 -11
  342. package/gsd-core/workflows/new-project/steps/auto-mode-config.md +3 -3
  343. package/gsd-core/workflows/new-project/steps/codebase-map-offer.md +1 -1
  344. package/gsd-core/workflows/new-project.md +7 -7
  345. package/gsd-core/workflows/new-workspace.md +2 -2
  346. package/gsd-core/workflows/next.md +1 -1
  347. package/gsd-core/workflows/note.md +1 -1
  348. package/gsd-core/workflows/onboard.md +1 -1
  349. package/gsd-core/workflows/pause-work.md +2 -2
  350. package/gsd-core/workflows/plan-phase/detail/elaboration.md +1 -1
  351. package/gsd-core/workflows/plan-phase/steps/chunked-planning-mode.md +17 -5
  352. package/gsd-core/workflows/plan-phase/steps/closed-phase-gate.md +1 -1
  353. package/gsd-core/workflows/plan-phase/steps/prd-express-path.md +1 -1
  354. package/gsd-core/workflows/plan-phase/steps/stall-detection-helpers.md +23 -5
  355. package/gsd-core/workflows/plan-phase.md +50 -24
  356. package/gsd-core/workflows/plan-review-convergence.md +21 -5
  357. package/gsd-core/workflows/plant-seed.md +62 -20
  358. package/gsd-core/workflows/pr-branch.md +113 -13
  359. package/gsd-core/workflows/profile-user.md +2 -2
  360. package/gsd-core/workflows/progress.md +19 -49
  361. package/gsd-core/workflows/quick/steps/plan-checker-loop.md +27 -0
  362. package/gsd-core/workflows/quick/steps/quick-verification.md +4 -4
  363. package/gsd-core/workflows/quick/steps/worktree-pre-dispatch-commit.md +30 -11
  364. package/gsd-core/workflows/quick-batch/steps/batch-init.md +1 -1
  365. package/gsd-core/workflows/quick-batch/steps/completion.md +1 -1
  366. package/gsd-core/workflows/quick-batch/steps/merge-wave.md +1 -1
  367. package/gsd-core/workflows/quick-batch/steps/planner-wave.md +1 -1
  368. package/gsd-core/workflows/quick-batch/steps/research-phase.md +1 -1
  369. package/gsd-core/workflows/quick-batch/steps/resume-mode.md +1 -1
  370. package/gsd-core/workflows/quick-batch/steps/verification-wave.md +9 -3
  371. package/gsd-core/workflows/quick-batch/steps/worktree-dispatch.md +1 -1
  372. package/gsd-core/workflows/quick-batch.md +15 -10
  373. package/gsd-core/workflows/quick.md +62 -39
  374. package/gsd-core/workflows/reapply-patches.md +9 -3
  375. package/gsd-core/workflows/remove-phase.md +3 -2
  376. package/gsd-core/workflows/remove-workspace.md +2 -2
  377. package/gsd-core/workflows/resume-project.md +3 -2
  378. package/gsd-core/workflows/review.md +33 -17
  379. package/gsd-core/workflows/scan.md +3 -2
  380. package/gsd-core/workflows/secure-phase.md +13 -13
  381. package/gsd-core/workflows/settings-advanced.md +30 -10
  382. package/gsd-core/workflows/settings-integrations.md +2 -3
  383. package/gsd-core/workflows/settings.md +4 -4
  384. package/gsd-core/workflows/ship.md +14 -13
  385. package/gsd-core/workflows/sketch-wrap-up.md +1 -1
  386. package/gsd-core/workflows/sketch.md +1 -1
  387. package/gsd-core/workflows/smart-entry.md +2 -2
  388. package/gsd-core/workflows/spec-phase.md +15 -5
  389. package/gsd-core/workflows/spike-wrap-up.md +1 -1
  390. package/gsd-core/workflows/spike.md +1 -1
  391. package/gsd-core/workflows/stats.md +1 -1
  392. package/gsd-core/workflows/sync-skills.md +5 -5
  393. package/gsd-core/workflows/thread.md +2 -2
  394. package/gsd-core/workflows/transition.md +13 -23
  395. package/gsd-core/workflows/ui-phase.md +48 -11
  396. package/gsd-core/workflows/ui-review.md +21 -6
  397. package/gsd-core/workflows/ultraplan-phase.md +3 -2
  398. package/gsd-core/workflows/undo.md +339 -20
  399. package/gsd-core/workflows/update.md +7 -7
  400. package/gsd-core/workflows/validate-phase.md +12 -13
  401. package/gsd-core/workflows/verify-work/detail/elaboration.md +43 -3
  402. package/gsd-core/workflows/verify-work/steps/automated-ui-verification.md +1 -1
  403. package/gsd-core/workflows/verify-work/steps/mvp-uat-framing.md +5 -3
  404. package/gsd-core/workflows/verify-work.md +129 -55
  405. package/hooks/dist/gsd-agent-isolation-guard.js +32 -0
  406. package/hooks/dist/gsd-check-update-worker.js +8 -0
  407. package/hooks/dist/gsd-check-update.js +8 -0
  408. package/hooks/dist/gsd-context-monitor.js +31 -8
  409. package/hooks/dist/gsd-cursor-subagent-start.js +8 -0
  410. package/hooks/dist/gsd-secret-read-guard.js +161 -4
  411. package/hooks/dist/gsd-statusline.js +85 -20
  412. package/hooks/dist/gsd-update-banner.js +8 -0
  413. package/hooks/dist/gsd-validate-commit.sh +63 -4
  414. package/hooks/dist/gsd-windsurf-pre-write.js +11 -2
  415. package/hooks/dist/gsd-workflow-guard.js +5 -4
  416. package/hooks/dist/gsd-worktree-path-guard.js +6 -2
  417. package/hooks/dist/lib/cli-exit.js +12 -0
  418. package/hooks/dist/lib/git-probe.js +17 -1
  419. package/hooks/dist/lib/isolation-sentinel.js +2 -2
  420. package/hooks/gsd-agent-isolation-guard.js +32 -0
  421. package/hooks/gsd-check-update-worker.js +8 -0
  422. package/hooks/gsd-check-update.js +8 -0
  423. package/hooks/gsd-context-monitor.js +31 -8
  424. package/hooks/gsd-cursor-subagent-start.js +8 -0
  425. package/hooks/gsd-secret-read-guard.js +161 -4
  426. package/hooks/gsd-statusline.js +85 -20
  427. package/hooks/gsd-update-banner.js +8 -0
  428. package/hooks/gsd-validate-commit.sh +63 -4
  429. package/hooks/gsd-windsurf-pre-write.js +11 -2
  430. package/hooks/gsd-workflow-guard.js +5 -4
  431. package/hooks/gsd-worktree-path-guard.js +6 -2
  432. package/hooks/hooks.json +5 -5
  433. package/hooks/lib/cli-exit.js +12 -0
  434. package/hooks/lib/git-probe.js +17 -1
  435. package/hooks/lib/isolation-sentinel.js +2 -2
  436. package/package.json +22 -4
  437. package/scripts/build-hooks.js +15 -6
  438. package/scripts/changeset/parse.cjs +52 -4
  439. package/scripts/check-contract-drift.cjs +127 -11
  440. package/scripts/ci-timeout-report.cjs +770 -4
  441. package/scripts/command-contract-helpers.cjs +15 -8
  442. package/scripts/docs-guard-registry.cjs +34 -0
  443. package/scripts/gen-features.cjs +13 -8
  444. package/scripts/gen-hooks-cli-exit.cjs +12 -28
  445. package/scripts/gen-loop-host-contract.cjs +79 -1
  446. package/scripts/gen-platform-conformance-tier.cjs +187 -1
  447. package/scripts/gen-plugin-skills.cjs +87 -1
  448. package/scripts/gen-research-agents.cjs +24 -31
  449. package/scripts/gen-scripts-cli-exit.cjs +30 -3
  450. package/scripts/gen-test-timings.cjs +32 -7
  451. package/scripts/lib/cli-exit.cjs +12 -0
  452. package/scripts/lib/macos-conformance-tier.generated.cjs +34 -2
  453. package/scripts/lib/ndjson-reporter.cjs +31 -5
  454. package/scripts/lib/platform-conformance-tier.generated.cjs +45 -5
  455. package/scripts/lib/registration-ledger-preload.cjs +155 -0
  456. package/scripts/lib/vendor-bundle.cjs +59 -0
  457. package/scripts/lib/vendor-licenses/saxes-6.0.0.txt +64 -0
  458. package/scripts/lint-allow-test-rule-refs.effective-ceiling.json +1 -1
  459. package/scripts/lint-allow-test-rule-refs.unverified-ceiling.json +1 -1
  460. package/scripts/lint-completion-predicate-drift.cjs +18 -19
  461. package/scripts/lint-descriptions.cjs +7 -3
  462. package/scripts/lint-docs-guard-registration.exempt-baseline.cjs +38 -1
  463. package/scripts/lint-eslint-glob-coverage.allowlist.json +20 -0
  464. package/scripts/lint-frontmatter-fence-drift.cjs +313 -0
  465. package/scripts/lint-frontmatter-scalar-broad-grep.cjs +122 -16
  466. package/scripts/lint-phase-arg-assignment.cjs +257 -0
  467. package/scripts/lint-phase-enumeration-drift.cjs +12 -8
  468. package/scripts/lint-phase-id-drift.cjs +319 -5
  469. package/scripts/lint-planning-document-positive-control.cjs +329 -0
  470. package/scripts/lint-pr-branch-pattern-drift.cjs +148 -0
  471. package/scripts/lint-response-language-coverage.cjs +3 -0
  472. package/scripts/lint-retired-runtime-name.cjs +619 -0
  473. package/scripts/lint-skill-deps.cjs +7 -3
  474. package/scripts/lint-state-write-path-drift.cjs +93 -0
  475. package/scripts/lint-test-file-count.allowlist.json +38 -9
  476. package/scripts/lint-test-file-count.cjs +34 -1
  477. package/scripts/lint-vendored-deps.cjs +41 -5
  478. package/scripts/lint-workflow-shellcheck-baseline.json +25 -10
  479. package/scripts/mutation-matrix.cjs +50 -5
  480. package/scripts/prompt-injection-scan.sh +4 -0
  481. package/scripts/release-tarball-smoke.cjs +194 -1
  482. package/scripts/require-issue-link-policy.cjs +6 -2
  483. package/scripts/sync-runtime-launcher.cjs +184 -2
  484. package/scripts/verify-npm-publish.cjs +76 -20
  485. package/skills/gsd-add-tests/SKILL.md +6 -1
  486. package/skills/gsd-ai-integration-phase/SKILL.md +6 -1
  487. package/skills/gsd-audit-fix/SKILL.md +5 -0
  488. package/skills/gsd-audit-milestone/SKILL.md +6 -1
  489. package/skills/gsd-autonomous/SKILL.md +7 -2
  490. package/skills/gsd-capture/SKILL.md +9 -5
  491. package/skills/gsd-code-review/SKILL.md +7 -2
  492. package/skills/gsd-complete-milestone/SKILL.md +4 -0
  493. package/skills/gsd-config/SKILL.md +8 -4
  494. package/skills/gsd-debug/SKILL.md +11 -7
  495. package/skills/gsd-discuss-phase/SKILL.md +7 -3
  496. package/skills/gsd-docs-update/SKILL.md +12 -7
  497. package/skills/gsd-eval-review/SKILL.md +6 -1
  498. package/skills/gsd-execute-phase/SKILL.md +12 -7
  499. package/skills/gsd-extract-learnings/SKILL.md +5 -0
  500. package/skills/gsd-fast/SKILL.md +4 -0
  501. package/skills/gsd-forensics/SKILL.md +5 -1
  502. package/skills/gsd-graphify/SKILL.md +10 -6
  503. package/skills/gsd-health/SKILL.md +5 -0
  504. package/skills/gsd-help/SKILL.md +7 -2
  505. package/skills/gsd-import/SKILL.md +7 -3
  506. package/skills/gsd-inbox/SKILL.md +5 -0
  507. package/skills/gsd-ingest-docs/SKILL.md +5 -1
  508. package/skills/gsd-manager/SKILL.md +6 -1
  509. package/skills/gsd-map-codebase/SKILL.md +7 -3
  510. package/skills/gsd-mempalace-capture/SKILL.md +12 -4
  511. package/skills/gsd-mempalace-recall/SKILL.md +5 -1
  512. package/skills/gsd-milestone-summary/SKILL.md +5 -1
  513. package/skills/gsd-mvp-phase/SKILL.md +8 -3
  514. package/skills/gsd-new-milestone/SKILL.md +6 -1
  515. package/skills/gsd-new-project/SKILL.md +5 -0
  516. package/skills/gsd-next/SKILL.md +6 -1
  517. package/skills/gsd-ns-context/SKILL.md +4 -0
  518. package/skills/gsd-ns-ideate/SKILL.md +4 -0
  519. package/skills/gsd-ns-manage/SKILL.md +4 -0
  520. package/skills/gsd-ns-project/SKILL.md +4 -0
  521. package/skills/gsd-ns-review/SKILL.md +4 -0
  522. package/skills/gsd-ns-workflow/SKILL.md +4 -0
  523. package/skills/gsd-onboard/SKILL.md +6 -1
  524. package/skills/gsd-pause-work/SKILL.md +5 -1
  525. package/skills/gsd-phase/SKILL.md +8 -4
  526. package/skills/gsd-plan-phase/SKILL.md +6 -1
  527. package/skills/gsd-plan-review-convergence/SKILL.md +10 -6
  528. package/skills/gsd-pr-branch/SKILL.md +4 -0
  529. package/skills/gsd-profile-user/SKILL.md +5 -1
  530. package/skills/gsd-progress/SKILL.md +7 -2
  531. package/skills/gsd-quick/SKILL.md +16 -10
  532. package/skills/gsd-quick-batch/SKILL.md +21 -9
  533. package/skills/gsd-review/SKILL.md +7 -4
  534. package/skills/gsd-review-backlog/SKILL.md +3 -2
  535. package/skills/gsd-secure-phase/SKILL.md +6 -1
  536. package/skills/gsd-ship/SKILL.md +5 -0
  537. package/skills/gsd-sketch/SKILL.md +7 -2
  538. package/skills/gsd-spec-phase/SKILL.md +5 -1
  539. package/skills/gsd-spike/SKILL.md +8 -3
  540. package/skills/gsd-surface/SKILL.md +5 -1
  541. package/skills/gsd-thread/SKILL.md +4 -0
  542. package/skills/gsd-ui-phase/SKILL.md +6 -1
  543. package/skills/gsd-ui-review/SKILL.md +6 -1
  544. package/skills/gsd-ultraplan-phase/SKILL.md +5 -1
  545. package/skills/gsd-undo/SKILL.md +5 -1
  546. package/skills/gsd-update/SKILL.md +6 -2
  547. package/skills/gsd-validate-phase/SKILL.md +6 -1
  548. package/skills/gsd-verify-work/SKILL.md +6 -1
  549. package/skills/gsd-workspace/SKILL.md +7 -3
  550. package/skills/gsd-workstreams/SKILL.md +6 -6
  551. package/vscode/package.json +1 -1
@@ -37,6 +37,12 @@
37
37
  * colon-namespace leaks (WORKFLOW_BODY_COLON_LEAK).
38
38
  * This check populates result.details with counters but does NOT return a
39
39
  * failure code by default; it is informational until enforcement is enabled.
40
+ *
41
+ * Configured-entrypoint checks (Cycle 4 — #4154):
42
+ * For each runtime in entrypointRuntimes, runs the tarball-installed
43
+ * installer into a throwaway HOME, then re-reads that runtime's own written
44
+ * config files and asserts every GSD-managed script path they name resolves
45
+ * to a file (ENTRYPOINT_UNRESOLVED). Requires fixtureDir.
40
46
  */
41
47
 
42
48
  'use strict';
@@ -47,6 +53,8 @@ const os = require('os');
47
53
  const path = require('path');
48
54
  const { PACKAGE_NAME } = require('../gsd-core/bin/lib/package-identity.cjs');
49
55
  const { ExitError, runMain } = require('./lib/cli-exit.cjs');
56
+ const shellCmdProjection = require('../gsd-core/bin/lib/shell-command-projection.cjs');
57
+ const { escapeRegex } = require('../gsd-core/bin/lib/pattern.cjs');
50
58
  // 120 s proved too tight for cold-cache `npm install -g` of a 1499-file tarball:
51
59
  // spawnSync fires SIGTERM at the deadline and returns { status: null, stdout: '',
52
60
  // stderr: '' } (Node docs: status is null when a subprocess is terminated by a
@@ -86,6 +94,8 @@ const SMOKE = Object.freeze({
86
94
  INIT_FAILED: 'init_failed',
87
95
  // Cycle 3 code
88
96
  WORKFLOW_BODY_COLON_LEAK: 'workflow_body_colon_leak',
97
+ // Cycle 4 code (#4154)
98
+ ENTRYPOINT_UNRESOLVED: 'entrypoint_unresolved',
89
99
  });
90
100
 
91
101
  // ---------------------------------------------------------------------------
@@ -274,6 +284,106 @@ function scanWorkflowColonLeak(filePath, cmdNames) {
274
284
  return null;
275
285
  }
276
286
 
287
+ // ---------------------------------------------------------------------------
288
+ // Cycle 4 helpers: configured-entrypoint resolution (#4154)
289
+ // ---------------------------------------------------------------------------
290
+
291
+ /**
292
+ * Top-level config files this scan reads. These are the surfaces that carry
293
+ * every GSD-managed launch path for the runtimes Cycle 4 actually installs
294
+ * (`entrypointRuntimes`, default claude + codex): claude registers into
295
+ * settings.json, codex into hooks.json and config.toml.
296
+ *
297
+ * This is NOT an exhaustive map of where GSD writes launch paths across all
298
+ * runtimes, and the scan is top-level only by design. Two known surfaces sit
299
+ * outside it: Cline registers its hook at `.clinerules/hooks/PreToolUse` (a
300
+ * subdirectory, and not one of these names — see writeClineArtifacts in
301
+ * src/runtime-hooks-surface.cts), and Kimi's native `[[hooks]]` config.toml
302
+ * lives under `resolveKimiHooksTomlDir()` (`~/.kimi`), a directory separate
303
+ * from Kimi's own GSD configDir. Adding either runtime to entrypointRuntimes
304
+ * requires teaching scanConfiguredEntrypoints about its surface first,
305
+ * otherwise the scan reports zero entrypoints and silently proves nothing.
306
+ */
307
+ const RUNTIME_CONFIG_FILES = Object.freeze(['settings.json', 'hooks.json', 'config.toml']);
308
+
309
+ /**
310
+ * Extract every script path `text` names underneath `configDir`.
311
+ *
312
+ * #4249 (antigravity review): anchored on the literal, already-known
313
+ * `configDir` prefix instead of a generic "any absolute path" character
314
+ * class. The prior version excluded whitespace from the match to avoid
315
+ * swallowing a shell command's trailing args, which also truncated any
316
+ * legitimate path containing a space (e.g. `/Users/John Doe/.claude`) —
317
+ * `scanConfiguredEntrypoints` would then silently report zero checked
318
+ * paths. Anchoring on `configDir` removes the ambiguity outright: a match
319
+ * can only start where the known prefix literally occurs in the text, so
320
+ * an interpreter path concatenated ahead of it (`"/usr/bin/node
321
+ * /configDir/hooks/foo.js"`) is never swallowed either, and interior
322
+ * whitespace inside `configDir` or the script's own path segments is safe
323
+ * to allow. This still scans raw, unparsed config text on purpose (see
324
+ * scanConfiguredEntrypoints's doc comment) — it catches a writer that
325
+ * embeds a launch path without registering it, which a structured
326
+ * JSON.parse of the expected schema would miss entirely.
327
+ *
328
+ * Windows configs store paths with backslashes, which JSON/TOML doubles on
329
+ * write; collapsing `\\` to `\` first makes the raw text scan work on both
330
+ * platforms without parsing each config format separately (POSIX text has no
331
+ * backslashes, so the collapse is a no-op there).
332
+ *
333
+ * Every writer bakes `configDir` through the same posixNormalize seam
334
+ * (src/runtime-hooks-surface.cts) before writing it into config text, on
335
+ * every platform — so the anchor must match that projection, not the
336
+ * OS-native `configDir` string this function receives.
337
+ */
338
+ function configuredEntrypointsIn(text, configDir) {
339
+ const normalizedPrefix = shellCmdProjection.posixNormalize(configDir).replace(/\/+$/, '') + '/';
340
+ const scriptPathRe = new RegExp(`${escapeRegex(normalizedPrefix)}[^"']{0,400}?\\.(?:js|cjs|mjs|sh|cmd|ps1)`, 'g');
341
+ const found = new Set();
342
+ for (const match of text.replace(/\\\\/g, '\\').matchAll(scriptPathRe)) {
343
+ found.add(path.resolve(match[0]));
344
+ }
345
+ return [...found];
346
+ }
347
+
348
+ /**
349
+ * Throwaway HOME the Cycle 4 install for `runtime` runs against. Exported so a
350
+ * test can seed that runtime's config before the install rather than
351
+ * hard-coding the layout runSmoke picks.
352
+ */
353
+ function entrypointFixtureHome(fixtureDir, runtime) {
354
+ return path.join(fixtureDir, `entrypoints-${runtime}`);
355
+ }
356
+
357
+ /**
358
+ * Re-derive the configured entrypoints a completed install wrote into a
359
+ * runtime's own config files and report the ones that do not resolve to a
360
+ * file. Internal to Cycle 4; the smoke's verdict is the exported contract.
361
+ *
362
+ * This deliberately does NOT consult the installer's own entrypoint list (the
363
+ * assertConfiguredEntrypoints gate in bin/install.js). That gate can only
364
+ * validate paths a config writer remembered to register; reading the written
365
+ * config back is what catches a writer that emits a launch path without
366
+ * registering it, and a stale registration an install left behind.
367
+ *
368
+ * @param {string} configDir - Absolute path to the runtime config dir.
369
+ * @returns {{ checked: string[], unresolved: { configPath: string, scriptPath: string }[] }}
370
+ */
371
+ function scanConfiguredEntrypoints(configDir) {
372
+ const checked = [];
373
+ const unresolved = [];
374
+ for (const name of RUNTIME_CONFIG_FILES) {
375
+ const configPath = path.join(configDir, name);
376
+ if (!fs.existsSync(configPath) || !fs.statSync(configPath).isFile()) continue;
377
+ const text = fs.readFileSync(configPath, 'utf-8');
378
+ for (const scriptPath of configuredEntrypointsIn(text, configDir)) {
379
+ checked.push(scriptPath);
380
+ if (fs.existsSync(scriptPath) && fs.statSync(scriptPath).isFile()) continue;
381
+ unresolved.push({ configPath, scriptPath });
382
+ }
383
+ }
384
+ return { checked, unresolved };
385
+ }
386
+
277
387
  // ---------------------------------------------------------------------------
278
388
  // Pure function: runSmoke
279
389
  // ---------------------------------------------------------------------------
@@ -285,6 +395,8 @@ function scanWorkflowColonLeak(filePath, cmdNames) {
285
395
  * @param {string} opts.expectedVersion - semver string to assert (e.g. "1.50.0")
286
396
  * @param {string} [opts.fixtureDir] - Temp dir to run `init` into (must NOT be HOME)
287
397
  * @param {string[]} [opts.lifecycleCommands] - Commands to file-check (default: see below)
398
+ * @param {string[]} [opts.entrypointRuntimes] - Runtime profiles whose configured entrypoints are
399
+ * re-checked after a real install (default: see below). Requires fixtureDir; pass [] to skip.
288
400
  * @param {boolean} [opts.dryRun=false] - If true, skip actual npm install; validate input only
289
401
  * @param {object} [opts.npmEnv] - Optional env dict for the internal npm install
290
402
  * spawnSync call. Pass an isolated HOME env (e.g. from isolatedNpmEnv() in tests/helpers.cjs)
@@ -298,6 +410,11 @@ function runSmoke({
298
410
  expectedVersion,
299
411
  fixtureDir,
300
412
  lifecycleCommands = ['init', 'discuss-phase', 'plan-phase', 'execute-phase'],
413
+ // claude and codex cover the two top-level config surfaces this scan knows
414
+ // how to read (settings.json, and hooks.json + config.toml). Most other
415
+ // runtimes reuse one of those two shapes; Cline and Kimi do not (see
416
+ // RUNTIME_CONFIG_FILES), so they are out of scope here rather than covered.
417
+ entrypointRuntimes = ['claude', 'codex'],
301
418
  dryRun = false,
302
419
  npmEnv = undefined,
303
420
  }) {
@@ -551,6 +668,75 @@ function runSmoke({
551
668
  // NOTE: colonLeakCount is informational here. Once the backlog is fixed,
552
669
  // a future enforcement mode can fail on non-zero counts.
553
670
 
671
+ // ─────────────────────────────────────────────────────────────────────────
672
+ // Cycle 4: configured-entrypoint resolution (#4154)
673
+ // ─────────────────────────────────────────────────────────────────────────
674
+
675
+ // The installer's own gate (assertConfiguredEntrypoints) runs in-process and
676
+ // only sees the paths a config writer registered with it. Installing the
677
+ // packed tarball for real and reading each runtime's written config back is
678
+ // what proves the launch paths a user's runtime will actually invoke exist
679
+ // in the shipped layout.
680
+ const entrypointProfiles = [];
681
+ if (fixtureDir && entrypointRuntimes.length > 0) {
682
+ for (const runtime of entrypointRuntimes) {
683
+ // Own HOME per runtime so a --global install cannot reach the real one.
684
+ const runtimeHome = entrypointFixtureHome(fixtureDir, runtime);
685
+ const configDir = path.join(runtimeHome, `.${runtime}`);
686
+ fs.mkdirSync(runtimeHome, { recursive: true });
687
+
688
+ const installResult = spawnSync(
689
+ process.execPath,
690
+ [path.join(pkg, 'bin', 'install.js'), `--${runtime}`, '--global', '--config-dir', configDir],
691
+ {
692
+ encoding: 'utf-8',
693
+ cwd: runtimeHome,
694
+ stdio: ['pipe', 'pipe', 'pipe'],
695
+ env: {
696
+ ...effectiveNpmEnv,
697
+ HOME: runtimeHome,
698
+ USERPROFILE: runtimeHome,
699
+ // Same reason as the init check above: install.js skips its main()
700
+ // block when GSD_TEST_MODE is set and would exit 0 writing nothing.
701
+ GSD_TEST_MODE: '',
702
+ NO_UPDATE_NOTIFIER: '1',
703
+ },
704
+ timeout: CHILD_TIMEOUT_MS,
705
+ },
706
+ );
707
+
708
+ if (installResult.status !== 0) {
709
+ // #4249 (antigravity review): this is the Cycle 4 per-runtime install,
710
+ // not Cycle 1's `gsd init` — SMOKE.INSTALL_FAILED is the code Cycle 2's
711
+ // identical spawnSync-failure check already uses for the same failure
712
+ // class; reusing SMOKE.INIT_FAILED here conflated the two lifecycle
713
+ // stages in the reported code.
714
+ return {
715
+ code: SMOKE.INSTALL_FAILED,
716
+ details: {
717
+ ...details,
718
+ runtime,
719
+ configDir,
720
+ stderr: installResult.stderr,
721
+ stdout: installResult.stdout,
722
+ },
723
+ };
724
+ }
725
+
726
+ const scan = scanConfiguredEntrypoints(configDir);
727
+ if (scan.unresolved.length > 0) {
728
+ return {
729
+ code: SMOKE.ENTRYPOINT_UNRESOLVED,
730
+ details: { ...details, runtime, configDir, unresolved: scan.unresolved },
731
+ };
732
+ }
733
+
734
+ entrypointProfiles.push({ runtime, configDir, entrypointsChecked: scan.checked.length });
735
+ }
736
+ }
737
+
738
+ details.entrypointProfiles = entrypointProfiles;
739
+
554
740
  return { code: SMOKE.OK, details };
555
741
  }
556
742
 
@@ -635,7 +821,14 @@ function cleanup(...dirs) {
635
821
  // Exports
636
822
  // ---------------------------------------------------------------------------
637
823
 
638
- module.exports = { SMOKE, runSmoke, binInvocation, CHILD_TIMEOUT_MS };
824
+ module.exports = {
825
+ SMOKE,
826
+ runSmoke,
827
+ binInvocation,
828
+ entrypointFixtureHome,
829
+ CHILD_TIMEOUT_MS,
830
+ configuredEntrypointsIn,
831
+ };
639
832
 
640
833
  if (require.main === module) {
641
834
  runMain(cliMain);
@@ -53,7 +53,10 @@ const DEPENDABOT_LOGIN = 'dependabot[bot]';
53
53
  // A follow-up-only PR (references an issue without closing it) is only
54
54
  // allowed to skip the closing keyword when every changed file is a test or
55
55
  // doc file — i.e. it cannot be the PR that actually implements the fix.
56
- const EXEMPT_PATH_PREFIXES = ['tests/', 'docs/'];
56
+ // #5061: .out-of-scope/ knowledge-base entries are informational documents,
57
+ // already doc-only in pre-pr-gate.sh's DOC_ONLY_RE. Only `*.md` entries
58
+ // qualify there (see allPathsAreTestsOrDocs): the KB holds nothing else.
59
+ const EXEMPT_PATH_PREFIXES = ['tests/', 'docs/', '.out-of-scope/'];
57
60
 
58
61
  // Root-level markdown is documentation — this mirrors the repo's own doc-only
59
62
  // classifier (.claude/hooks/pre-pr-gate.sh:111), whose `[^/]+\.md` anchor is
@@ -115,7 +118,7 @@ function normalizePath(p) {
115
118
  /**
116
119
  * Returns true iff every changed file qualifies as a test/doc file, i.e. each
117
120
  * one is one of:
118
- * 1. under one of EXEMPT_PATH_PREFIXES (`tests/`, `docs/`) — the trailing
121
+ * 1. under one of EXEMPT_PATH_PREFIXES (`tests/`, `docs/`, `.out-of-scope/`) — the trailing
119
122
  * slash on each prefix makes this directory-boundary aware, so
120
123
  * lookalikes like `tests-e2e/`, `testsuite/`, or `docsite/` are
121
124
  * correctly rejected (they are not `tests/` or `docs/`); or
@@ -126,6 +129,7 @@ function allPathsAreTestsOrDocs(changedFiles) {
126
129
  if (!Array.isArray(changedFiles) || changedFiles.length === 0) return false;
127
130
  return changedFiles.every((file) => {
128
131
  const normalized = normalizePath(file);
132
+ if (normalized.startsWith('.out-of-scope/')) return /\.md$/i.test(normalized);
129
133
  if (EXEMPT_PATH_PREFIXES.some((prefix) => normalized.startsWith(prefix))) return true;
130
134
  return isRootLevelDoc(normalized);
131
135
  });
@@ -272,6 +272,49 @@ function insertPreamble(lines, preamble) {
272
272
  return [...before, ...preamble, ...after];
273
273
  }
274
274
 
275
+ /**
276
+ * The first two statements EVERY version of the launcher preamble opens with
277
+ * (`_GSD_SHIM_NAME="gsd-tools.cjs"; _GSD_RUNTIME_ROOT=`). Matching the pair, not
278
+ * the bare `_GSD_SHIM_NAME=` prefix, means a prose sample or an intentionally
279
+ * different resolver that happens to start a line with the variable name is never
280
+ * mistaken for the preamble and never rewritten (#5169 review).
281
+ */
282
+ const PREAMBLE_LINE_RE = /^_GSD_SHIM_NAME="gsd-tools\.cjs"; _GSD_RUNTIME_ROOT=/;
283
+
284
+ /**
285
+ * Index of the line that starts a launcher preamble inside `lines`, or -1.
286
+ *
287
+ * Matched by the marker every version of the preamble opens with
288
+ * (`_GSD_SHIM_NAME=`), NOT by equality with the CURRENT text: the sync runs
289
+ * precisely when the snippet changed, so the copy in the file is by definition an
290
+ * older version, and an exact match never found it — which hoisted a guard-fronted
291
+ * preamble to the top of its block on every snippet change (#5169; caught by the
292
+ * #3861 guard-only extraction in tests/code-review-pipeline-regression.test.cjs).
293
+ */
294
+ function findPreambleStart(lines) {
295
+ return lines.findIndex((l) => PREAMBLE_LINE_RE.test(l));
296
+ }
297
+
298
+ /**
299
+ * Place the preamble in a block that ALREADY carried it. A block that opens
300
+ * with a guard (a status check that must run before any launcher resolution,
301
+ * e.g. execute-phase/steps/code-review-disposition.md, #3861) keeps the preamble
302
+ * BEHIND that guard: hoisting it to the top would put the resolver ahead of the
303
+ * guard and change what the guard-only extraction in the tests runs. A block
304
+ * whose preamble already sits at the top (after blank lines), or that had none,
305
+ * takes the ordinary top insertion.
306
+ *
307
+ * The position is kept in STRIPPED coordinates: the lines before the preamble
308
+ * are stripped on their own and their length is the insertion point.
309
+ */
310
+ function insertPreambleKeepingGuard(original, stripped, preamble) {
311
+ const k = findPreambleStart(original);
312
+ const firstContent = original.findIndex((l) => l.trim() !== '');
313
+ if (k <= firstContent) return insertPreamble(stripped, preamble);
314
+ const at = stripAndReplace(original.slice(0, k), preamble).length;
315
+ return [...stripped.slice(0, at), ...preamble, ...stripped.slice(at)];
316
+ }
317
+
275
318
  /**
276
319
  * Transform a single markdown file's content.
277
320
  * Returns new content string, or null if no changes needed.
@@ -366,7 +409,9 @@ function transformFile(content, preamble) {
366
409
  const delegates = delegatesToResolverReference(content);
367
410
  const finalBlocks = strippedBlocks.map((stripped, bi) => {
368
411
  if (!delegates && bi === preambleTargetIdx) {
369
- return insertPreamble(stripped, preamble);
412
+ const range = shellBlockRanges[bi];
413
+ const original = allLines.slice(range.contentStart, range.contentEnd);
414
+ return insertPreambleKeepingGuard(original, stripped, preamble);
370
415
  }
371
416
  return stripped;
372
417
  });
@@ -405,9 +450,137 @@ function delegatesToResolverReference(content) {
405
450
  return content.includes('references/gsd-run-resolver.md');
406
451
  }
407
452
 
453
+ // ---------------------------------------------------------------------------
454
+ // `_gsd_homes` — the launcher's runtime-home candidate list, DERIVED from the
455
+ // runtime descriptors (#5169, ADR-5057 §5 "one resolver", #4347).
456
+ //
457
+ // The JS resolver (src/runtime-homes.cts) resolves a runtime's home from its
458
+ // `configHome` descriptor. The shell launcher used to carry a hand-written copy
459
+ // of that list and drifted (it still probed GEMINI_CONFIG_DIR after the runtime
460
+ // was retired, and omitted zcode/pi/kimi). Both now read the same registry:
461
+ // this renderer is the only producer of the `_gsd_homes` text in the snippet,
462
+ // and tests/runtime-launcher-parity.test.cjs fails when the snippet differs
463
+ // from it.
464
+ // ---------------------------------------------------------------------------
465
+
466
+ const HOMES_START = '_gsd_homes() { ';
467
+ const HOMES_END = '; }; if _gsd_at';
468
+
469
+ function shellHomeExpr(configHome) {
470
+ const dotHome = (rel) => `$HOME/${rel}`;
471
+ const withEnvs = (envs, fallback) => envs.reduceRight((acc, name) => `\${${name}:-${acc}}`, fallback);
472
+ switch (configHome.kind) {
473
+ case 'dot-home':
474
+ return [withEnvs(configHome.env, dotHome(configHome.name))];
475
+ case 'dot-home-nested': {
476
+ const probes = configHome.probe && configHome.probe.length > 0 ? configHome.probe : [configHome.name];
477
+ const first = withEnvs(configHome.env.slice(0, 1), dotHome(`${configHome.parent}/${probes[0]}`));
478
+ return [first, ...probes.slice(1).map((p) => dotHome(`${configHome.parent}/${p}`))];
479
+ }
480
+ case 'xdg': {
481
+ const xdgVar = configHome.env[2];
482
+ const base = xdgVar ? `\${${xdgVar}:-$HOME/.config}` : '$HOME/.config';
483
+ return [withEnvs(configHome.env.slice(0, 1), `${base}/${configHome.name}`)];
484
+ }
485
+ case 'generic-agents-root': {
486
+ const probes = configHome.probe.map((p) => p.replace(/^~/, '$HOME'));
487
+ return [withEnvs(configHome.env.slice(0, 1), probes[0]), ...probes.slice(1)];
488
+ }
489
+ default:
490
+ return []; // kind "none": no file-projected home, nothing to probe
491
+ }
492
+ }
493
+
494
+ /** The `_gsd_homes() { _gsd_at ...; }` text for a registry + legacy-home table. */
495
+ function renderHomesFunction(registry, legacyHomes) {
496
+ const ids = Object.keys(registry.runtimes).sort((a, b) =>
497
+ a === 'claude' ? -1 : b === 'claude' ? 1 : a < b ? -1 : a > b ? 1 : 0);
498
+ const exprs = [];
499
+ for (const id of ids) {
500
+ const configHome = registry.runtimes[id].runtime && registry.runtimes[id].runtime.configHome;
501
+ if (configHome) exprs.push(...shellHomeExpr(configHome));
502
+ }
503
+ for (const id of Object.keys(legacyHomes).sort()) {
504
+ const legacy = legacyHomes[id];
505
+ exprs.push(`\${${legacy.env}:-$HOME/${legacy.dir.join('/')}}`);
506
+ }
507
+ // One loop over the homes, the `/gsd-core/bin/<shim>` suffix written once: the
508
+ // preamble is inlined into ~240 prompt files, several of which sit at a size cap.
509
+ // The homes are loaded into the FUNCTION's own positional parameters (`set --`
510
+ // is scoped to the function) and walked with `for _h; do`, not `for _h in <list>`:
511
+ // lint-workflow-shellcheck's #4109 structural check flags any `for x in` list that
512
+ // contains a `$`, without parsing the quoting around it.
513
+ const homes = [...new Set(exprs)].map((e) => `"${e}"`).join(' ');
514
+ return `${HOMES_START}set -- ${homes}; for _h; do _gsd_at "$_h/gsd-core/bin/\${_GSD_SHIM_NAME}" && return 0; done; return 1; }`;
515
+ }
516
+
517
+ /** Locate the `_gsd_homes` function text inside the snippet's single line. */
518
+ function extractHomesFunction(snippetText) {
519
+ const start = snippetText.indexOf(HOMES_START);
520
+ const end = snippetText.indexOf(HOMES_END, start);
521
+ if (start === -1 || end === -1) return null;
522
+ return { start, end: end + '; }'.length, text: snippetText.slice(start, end + '; }'.length) };
523
+ }
524
+
525
+ function loadDerivedHomes() {
526
+ const registry = require('../gsd-core/bin/lib/capability-registry.cjs');
527
+ const { LEGACY_NON_REGISTRY_RUNTIME_HOMES } = require('../gsd-core/bin/lib/runtime-name-policy.cjs');
528
+ return renderHomesFunction(registry, LEGACY_NON_REGISTRY_RUNTIME_HOMES);
529
+ }
530
+
531
+ /** Rewrite the snippet's `_gsd_homes` from the descriptors. Returns true when it changed. */
532
+ function refreshSnippetHomes() {
533
+ const raw = fs.readFileSync(SNIPPET_FILE, 'utf8');
534
+ const found = extractHomesFunction(raw);
535
+ if (!found) throw new Error('_runtime-launcher.snippet.sh has no _gsd_homes function to refresh');
536
+ const derived = loadDerivedHomes();
537
+ if (found.text === derived) return false;
538
+ fs.writeFileSync(SNIPPET_FILE, raw.slice(0, found.start) + derived + raw.slice(found.end), 'utf8');
539
+ return true;
540
+ }
541
+
542
+ // ---------------------------------------------------------------------------
543
+ // Files that carry the preamble as ONE line but are not transformed by
544
+ // `transformFile` (it would move a per-block definition into the first block):
545
+ // - gsd-core/references/gsd-run-resolver.md — the @-included canonical copy,
546
+ // asserted byte-equal to the snippet;
547
+ // - commands/**/*.md — slash-command templates whose every bash block carries
548
+ // its own definition (each block is a separate shell), originally copied from
549
+ // an older fixed-list resolver that still probed the retired gemini home.
550
+ // Every line that starts a resolver (PREAMBLE_LINE_RE) is replaced by the
551
+ // canonical preamble line, so these copies are generated, not hand-kept (#5169).
552
+ // ---------------------------------------------------------------------------
553
+ const RESOLVER_REFERENCE = path.join(__dirname, '..', 'gsd-core', 'references', 'gsd-run-resolver.md');
554
+ const COMMANDS_DIR = path.join(__dirname, '..', 'commands');
555
+
556
+ function replaceResolverLines(content, preambleLine) {
557
+ return content
558
+ .split('\n')
559
+ .map((line) => (PREAMBLE_LINE_RE.test(line) && line !== preambleLine ? preambleLine : line))
560
+ .join('\n');
561
+ }
562
+
563
+ function syncSingleLinePreambleFiles(preamble) {
564
+ if (preamble.length !== 1) throw new Error('the launcher preamble must be a single line to be inlined per block');
565
+ const files = [RESOLVER_REFERENCE, ...collectFiles(COMMANDS_DIR)];
566
+ let changed = 0;
567
+ for (const f of files) {
568
+ const content = fs.readFileSync(f, 'utf8');
569
+ const next = replaceResolverLines(content, preamble[0]);
570
+ if (next !== content) {
571
+ fs.writeFileSync(f, next, 'utf8');
572
+ changed++;
573
+ console.log(`transformed (preamble line): ${path.relative(path.join(__dirname, '..'), f)}`);
574
+ }
575
+ }
576
+ return changed;
577
+ }
578
+
408
579
  // Main
409
580
  function main() {
581
+ if (refreshSnippetHomes()) console.log('refreshed _gsd_homes in _runtime-launcher.snippet.sh from the runtime descriptors');
410
582
  const preamble = loadPreamble();
583
+ syncSingleLinePreambleFiles(preamble);
411
584
 
412
585
  let transformedCount = 0;
413
586
  let unchangedCount = 0;
@@ -447,4 +620,13 @@ if (require.main === module) {
447
620
  main();
448
621
  }
449
622
 
450
- module.exports = { transformFile };
623
+ module.exports = {
624
+ transformFile,
625
+ loadPreamble,
626
+ renderHomesFunction,
627
+ extractHomesFunction,
628
+ loadDerivedHomes,
629
+ refreshSnippetHomes,
630
+ replaceResolverLines,
631
+ PREAMBLE_LINE_RE,
632
+ };