@opengsd/gsd-core 1.10.0 → 1.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (544) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/agents/gsd-code-fixer.md +1 -1
  4. package/agents/gsd-debug-session-manager.md +12 -1
  5. package/agents/gsd-debugger.md +1 -1
  6. package/agents/gsd-doc-synthesizer.md +2 -4
  7. package/agents/gsd-dom-verifier.md +169 -0
  8. package/agents/gsd-eval-auditor.md +1 -1
  9. package/agents/gsd-executor.md +22 -14
  10. package/agents/gsd-framework-selector.md +1 -3
  11. package/agents/gsd-intel-updater.md +1 -1
  12. package/agents/gsd-mempalace-curator.md +5 -3
  13. package/agents/gsd-pattern-mapper.md +11 -0
  14. package/agents/gsd-phase-researcher.md +23 -2
  15. package/agents/gsd-plan-checker.md +50 -53
  16. package/agents/gsd-planner.md +50 -50
  17. package/agents/gsd-project-researcher.md +1 -1
  18. package/agents/gsd-research-synthesizer.md +2 -2
  19. package/agents/gsd-roadmapper.md +15 -11
  20. package/agents/gsd-ui-checker.md +63 -4
  21. package/agents/gsd-ui-researcher.md +41 -3
  22. package/agents/gsd-user-profiler.md +3 -0
  23. package/agents/gsd-verifier.md +13 -4
  24. package/bin/install.js +1448 -1103
  25. package/commands/gsd/code-review.md +1 -1
  26. package/commands/gsd/discuss-phase.md +1 -1
  27. package/commands/gsd/execute-phase.md +1 -1
  28. package/commands/gsd/import.md +1 -1
  29. package/commands/gsd/map-codebase.md +1 -1
  30. package/commands/gsd/mempalace-capture.md +1 -1
  31. package/commands/gsd/mempalace-recall.md +1 -1
  32. package/commands/gsd/new-milestone.md +1 -1
  33. package/commands/gsd/quick.md +9 -5
  34. package/commands/gsd/review-backlog.md +2 -1
  35. package/commands/gsd/verify-work.md +1 -1
  36. package/gsd-core/bin/gsd-tools.cjs +1035 -138
  37. package/gsd-core/bin/lib/active-workstream-store.cjs +146 -22
  38. package/gsd-core/bin/lib/adr-parser.cjs +13 -7
  39. package/gsd-core/bin/lib/agent-install-check.cjs +392 -32
  40. package/gsd-core/bin/lib/api-coverage.cjs +33 -14
  41. package/gsd-core/bin/lib/artifacts.cjs +5 -0
  42. package/gsd-core/bin/lib/assumption-delta.cjs +32 -15
  43. package/gsd-core/bin/lib/audit-command-router.cjs +9 -2
  44. package/gsd-core/bin/lib/audit.cjs +1026 -268
  45. package/gsd-core/bin/lib/broken-windows.cjs +306 -28
  46. package/gsd-core/bin/lib/capability-consent.cjs +149 -15
  47. package/gsd-core/bin/lib/capability-lifecycle.cjs +45 -0
  48. package/gsd-core/bin/lib/capability-lock.cjs +10 -4
  49. package/gsd-core/bin/lib/capability-registry.cjs +845 -130
  50. package/gsd-core/bin/lib/capability-source.cjs +92 -0
  51. package/gsd-core/bin/lib/capability-state.cjs +18 -3
  52. package/gsd-core/bin/lib/capability-trust.cjs +444 -25
  53. package/gsd-core/bin/lib/capability-validator.cjs +700 -40
  54. package/gsd-core/bin/lib/capability-writer.cjs +3 -2
  55. package/gsd-core/bin/lib/check-command-router.cjs +216 -42
  56. package/gsd-core/bin/lib/claude-orchestration.cjs +56 -3
  57. package/gsd-core/bin/lib/cli-exit.cjs +496 -10
  58. package/gsd-core/bin/lib/code-review-depth.cjs +288 -0
  59. package/gsd-core/bin/lib/codex-agent-toml.cjs +735 -0
  60. package/gsd-core/bin/lib/command-aliases.cjs +22 -0
  61. package/gsd-core/bin/lib/command-arg-projection.cjs +144 -14
  62. package/gsd-core/bin/lib/command-roster.cjs +44 -1
  63. package/gsd-core/bin/lib/command-routing-hub.cjs +31 -2
  64. package/gsd-core/bin/lib/commands.cjs +1172 -108
  65. package/gsd-core/bin/lib/commonjs-marker.cjs +12 -6
  66. package/gsd-core/bin/lib/complexity-trigger.cjs +1192 -0
  67. package/gsd-core/bin/lib/config-loader.cjs +187 -23
  68. package/gsd-core/bin/lib/config.cjs +102 -3
  69. package/gsd-core/bin/lib/configuration.cjs +129 -37
  70. package/gsd-core/bin/lib/core-utils.cjs +208 -33
  71. package/gsd-core/bin/lib/decisions.cjs +23 -0
  72. package/gsd-core/bin/lib/edge-probe.cjs +9 -1
  73. package/gsd-core/bin/lib/estimate-cli.cjs +55 -11
  74. package/gsd-core/bin/lib/exit-code-registry.cjs +98 -0
  75. package/gsd-core/bin/lib/fallow-runner.cjs +20 -44
  76. package/gsd-core/bin/lib/frontmatter.cjs +899 -229
  77. package/gsd-core/bin/lib/gap-checker.cjs +95 -10
  78. package/gsd-core/bin/lib/git-base-branch.cjs +276 -39
  79. package/gsd-core/bin/lib/gsd2-import.cjs +10 -1
  80. package/gsd-core/bin/lib/health-diagnostic-rules/agent-install.cjs +101 -0
  81. package/gsd-core/bin/lib/health-diagnostic-rules/config-validation.cjs +348 -0
  82. package/gsd-core/bin/lib/health-diagnostic-rules/consistency.cjs +149 -0
  83. package/gsd-core/bin/lib/health-diagnostic-rules/install-surface-shadowing.cjs +98 -0
  84. package/gsd-core/bin/lib/health-diagnostic-rules/milestone-archive-hygiene.cjs +100 -0
  85. package/gsd-core/bin/lib/health-diagnostic-rules/phase-structure.cjs +222 -0
  86. package/gsd-core/bin/lib/health-diagnostic-rules/roadmap-disk-consistency.cjs +268 -0
  87. package/gsd-core/bin/lib/health-diagnostic-rules/root-existence.cjs +161 -0
  88. package/gsd-core/bin/lib/health-diagnostic-rules/state-consistency.cjs +303 -0
  89. package/gsd-core/bin/lib/health-diagnostic-rules/worktree-health.cjs +187 -0
  90. package/gsd-core/bin/lib/health-diagnostic-types.cjs +68 -0
  91. package/gsd-core/bin/lib/health-diagnostic.cjs +451 -0
  92. package/gsd-core/bin/lib/host-integration.cjs +39 -6
  93. package/gsd-core/bin/lib/host-runtime-detection.cjs +134 -0
  94. package/gsd-core/bin/lib/init-command-router.cjs +118 -21
  95. package/gsd-core/bin/lib/init.cjs +439 -168
  96. package/gsd-core/bin/lib/install-effort-resolver.cjs +73 -30
  97. package/gsd-core/bin/lib/install-engine.cjs +811 -259
  98. package/gsd-core/bin/lib/install-fs-adapter.cjs +262 -0
  99. package/gsd-core/bin/lib/install-model-override-resolver.cjs +235 -0
  100. package/gsd-core/bin/lib/install-profiles.cjs +212 -61
  101. package/gsd-core/bin/lib/install-scope.cjs +270 -0
  102. package/gsd-core/bin/lib/install-shadow-report.cjs +385 -0
  103. package/gsd-core/bin/lib/installed-surface-resolver.cjs +381 -0
  104. package/gsd-core/bin/lib/installer-migration-report.cjs +3 -0
  105. package/gsd-core/bin/lib/installer-migrations/010-antigravity-retire-confighome-artifacts.cjs +169 -0
  106. package/gsd-core/bin/lib/installer-migrations.cjs +148 -38
  107. package/gsd-core/bin/lib/intel.cjs +101 -26
  108. package/gsd-core/bin/lib/io.cjs +170 -15
  109. package/gsd-core/bin/lib/learnings.cjs +85 -14
  110. package/gsd-core/bin/lib/legacy-cleanup.cjs +8 -2
  111. package/gsd-core/bin/lib/markdown-sectionizer.cjs +2 -1
  112. package/gsd-core/bin/lib/markdown-table.cjs +183 -22
  113. package/gsd-core/bin/lib/milestone-lock.cjs +248 -0
  114. package/gsd-core/bin/lib/milestone.cjs +842 -73
  115. package/gsd-core/bin/lib/model-catalog.cjs +232 -16
  116. package/gsd-core/bin/lib/model-resolver.cjs +193 -68
  117. package/gsd-core/bin/lib/normalize-test-command.cjs +1 -1
  118. package/gsd-core/bin/lib/onboard-projection.cjs +5 -1
  119. package/gsd-core/bin/lib/pattern.cjs +122 -0
  120. package/gsd-core/bin/lib/phase-estimation.cjs +18 -9
  121. package/gsd-core/bin/lib/phase-id.cjs +514 -40
  122. package/gsd-core/bin/lib/phase-lifecycle.cjs +52 -19
  123. package/gsd-core/bin/lib/phase-locator.cjs +262 -34
  124. package/gsd-core/bin/lib/phase.cjs +1038 -214
  125. package/gsd-core/bin/lib/plan-dependency-graph.cjs +72 -1
  126. package/gsd-core/bin/lib/plan-document.cjs +263 -0
  127. package/gsd-core/bin/lib/plan-drift-guard.cjs +120 -0
  128. package/gsd-core/bin/lib/plan-scan.cjs +98 -3
  129. package/gsd-core/bin/lib/planning-command-router.cjs +61 -0
  130. package/gsd-core/bin/lib/planning-inspect.cjs +1168 -0
  131. package/gsd-core/bin/lib/planning-scope.cjs +31 -0
  132. package/gsd-core/bin/lib/planning-snapshot.cjs +894 -0
  133. package/gsd-core/bin/lib/planning-workspace.cjs +112 -6
  134. package/gsd-core/bin/lib/probe-core.cjs +5 -2
  135. package/gsd-core/bin/lib/profile-output.cjs +1 -1
  136. package/gsd-core/bin/lib/profile-pipeline-command-router.cjs +50 -7
  137. package/gsd-core/bin/lib/profile-pipeline.cjs +6 -3
  138. package/gsd-core/bin/lib/real-home-guard.cjs +419 -0
  139. package/gsd-core/bin/lib/refactor-trigger-command-router.cjs +766 -0
  140. package/gsd-core/bin/lib/retired-artifact-cleanup.cjs +11 -6
  141. package/gsd-core/bin/lib/review-lane-descriptor.cjs +22 -13
  142. package/gsd-core/bin/lib/review-lane-invocation.cjs +30 -0
  143. package/gsd-core/bin/lib/review-lane-runner.cjs +421 -66
  144. package/gsd-core/bin/lib/review-reviewer-selection.cjs +13 -18
  145. package/gsd-core/bin/lib/roadmap-command-router.cjs +59 -11
  146. package/gsd-core/bin/lib/roadmap-parser.cjs +1006 -184
  147. package/gsd-core/bin/lib/roadmap-upgrade.cjs +37 -10
  148. package/gsd-core/bin/lib/roadmap.cjs +442 -96
  149. package/gsd-core/bin/lib/runtime-artifact-conversion.cjs +702 -52
  150. package/gsd-core/bin/lib/runtime-artifact-install-plan.cjs +14 -2
  151. package/gsd-core/bin/lib/runtime-artifact-layout.cjs +459 -55
  152. package/gsd-core/bin/lib/runtime-config-adapter-registry.cjs +3 -2
  153. package/gsd-core/bin/lib/runtime-homes.cjs +69 -3
  154. package/gsd-core/bin/lib/runtime-hooks-surface.cjs +402 -58
  155. package/gsd-core/bin/lib/runtime-identity.cjs +234 -0
  156. package/gsd-core/bin/lib/runtime-name-policy.cjs +3 -1
  157. package/gsd-core/bin/lib/runtime-slash.cjs +96 -8
  158. package/gsd-core/bin/lib/security.cjs +104 -5
  159. package/gsd-core/bin/lib/shell-command-projection.cjs +342 -7
  160. package/gsd-core/bin/lib/smart-entry.cjs +133 -23
  161. package/gsd-core/bin/lib/spec-section.cjs +12 -7
  162. package/gsd-core/bin/lib/state-command-router.cjs +52 -19
  163. package/gsd-core/bin/lib/state-contract.cjs +359 -0
  164. package/gsd-core/bin/lib/state-document.cjs +338 -8
  165. package/gsd-core/bin/lib/state-md-schema.cjs +221 -0
  166. package/gsd-core/bin/lib/state-transition.cjs +846 -176
  167. package/gsd-core/bin/lib/state.cjs +2589 -369
  168. package/gsd-core/bin/lib/surface.cjs +33 -11
  169. package/gsd-core/bin/lib/task-command-router.cjs +111 -1
  170. package/gsd-core/bin/lib/task-content-resolution.cjs +368 -0
  171. package/gsd-core/bin/lib/teams-status.cjs +4 -1
  172. package/gsd-core/bin/lib/text-lines.cjs +80 -0
  173. package/gsd-core/bin/lib/token-scanner.cjs +76 -0
  174. package/gsd-core/bin/lib/uat-predicate.cjs +67 -23
  175. package/gsd-core/bin/lib/uat.cjs +1761 -167
  176. package/gsd-core/bin/lib/ui-consideration-probe.cjs +9 -1
  177. package/gsd-core/bin/lib/ui-frontend-evidence.cjs +157 -0
  178. package/gsd-core/bin/lib/ui-safety-gate.cjs +51 -12
  179. package/gsd-core/bin/lib/unusable-input.cjs +37 -0
  180. package/gsd-core/bin/lib/update-context.cjs +8 -2
  181. package/gsd-core/bin/lib/user-artifact-staging.cjs +705 -0
  182. package/gsd-core/bin/lib/validate-command-router.cjs +2 -2
  183. package/gsd-core/bin/lib/validate.cjs +20 -6
  184. package/gsd-core/bin/lib/vendor/README.md +75 -0
  185. package/gsd-core/bin/lib/vendor/js-yaml.cjs +3014 -0
  186. package/gsd-core/bin/lib/vendor/re2js.cjs +6480 -0
  187. package/gsd-core/bin/lib/vendor/re2js.d.cts +938 -0
  188. package/gsd-core/bin/lib/verification-command-router.cjs +2 -1
  189. package/gsd-core/bin/lib/verification.cjs +272 -9
  190. package/gsd-core/bin/lib/verify-command-grounding.cjs +846 -0
  191. package/gsd-core/bin/lib/verify.cjs +453 -918
  192. package/gsd-core/bin/lib/workstream-inventory-builder.cjs +53 -32
  193. package/gsd-core/bin/lib/workstream-inventory.cjs +63 -10
  194. package/gsd-core/bin/lib/workstream-name-policy.cjs +25 -4
  195. package/gsd-core/bin/lib/workstream.cjs +2 -2
  196. package/gsd-core/bin/lib/worktree-base-ref.cjs +66 -12
  197. package/gsd-core/bin/lib/worktree-safety.cjs +341 -18
  198. package/gsd-core/bin/shared/config-defaults.manifest.json +8 -1
  199. package/gsd-core/bin/shared/config-schema.manifest.json +12 -1
  200. package/gsd-core/bin/shared/exit-codes.json +8 -0
  201. package/gsd-core/bin/shared/exit-codes.sh +20 -0
  202. package/gsd-core/bin/shared/model-catalog.json +8 -1
  203. package/gsd-core/references/agent-contracts.md +44 -26
  204. package/gsd-core/references/api-coverage.md +24 -2
  205. package/gsd-core/references/autonomous-smart-discuss.md +3 -3
  206. package/gsd-core/references/checkpoints.md +39 -21
  207. package/gsd-core/references/context-budget.md +1 -1
  208. package/gsd-core/references/decimal-phase-calculation.md +5 -5
  209. package/gsd-core/references/dispatch-isolation-gate.md +138 -0
  210. package/gsd-core/references/doc-conflict-engine.md +1 -1
  211. package/gsd-core/references/edge-probe.md +8 -0
  212. package/gsd-core/references/execute-mvp-tdd.md +4 -6
  213. package/gsd-core/references/execute-phase-between-wave-reset.md +15 -14
  214. package/gsd-core/references/execute-phase-context-guard.md +1 -1
  215. package/gsd-core/references/execute-phase-response-language.md +1 -1
  216. package/gsd-core/references/execute-phase-wave-guard.md +17 -11
  217. package/gsd-core/references/failing-direction.md +78 -0
  218. package/gsd-core/references/gate-prompts.md +1 -1
  219. package/gsd-core/references/git-integration.md +5 -5
  220. package/gsd-core/references/git-planning-commit.md +5 -4
  221. package/gsd-core/references/gsd-run-resolver.md +1 -1
  222. package/gsd-core/references/loop-hook-dispatch.md +61 -2
  223. package/gsd-core/references/model-profiles.md +12 -4
  224. package/gsd-core/references/mvp-concepts.md +9 -9
  225. package/gsd-core/references/nyquist-compliance.md +74 -0
  226. package/gsd-core/references/offer-next.md +3 -5
  227. package/gsd-core/references/phase-argument-parsing.md +3 -3
  228. package/gsd-core/references/planner-failing-direction.md +53 -0
  229. package/gsd-core/references/planner-guidance.md +3 -9
  230. package/gsd-core/references/planner-human-verify-mode.md +15 -1
  231. package/gsd-core/references/planner-preconditions.md +1 -1
  232. package/gsd-core/references/planner-reviews.md +1 -1
  233. package/gsd-core/references/planner-revision.md +1 -1
  234. package/gsd-core/references/planner-verify-command-grounding.md +17 -0
  235. package/gsd-core/references/planning-config.md +44 -13
  236. package/gsd-core/references/reviewer-instances.md +31 -0
  237. package/gsd-core/references/revision-loop.md +1 -1
  238. package/gsd-core/references/runtime-aware-dispatch.md +1 -1
  239. package/gsd-core/references/specless-probe-fallback.md +1 -1
  240. package/gsd-core/references/tdd.md +1 -3
  241. package/gsd-core/references/ui-brand.md +65 -21
  242. package/gsd-core/references/ui-consideration-probe.md +1 -1
  243. package/gsd-core/references/universal-anti-patterns.md +5 -5
  244. package/gsd-core/references/verifier-phase-gates.md +192 -0
  245. package/gsd-core/references/verify-command-path-resolvability.md +42 -0
  246. package/gsd-core/references/verify-mvp-mode.md +2 -2
  247. package/gsd-core/references/workstream-flag.md +33 -17
  248. package/gsd-core/templates/README.md +1 -1
  249. package/gsd-core/templates/SECURITY.md +3 -3
  250. package/gsd-core/templates/UI-SPEC.md +25 -3
  251. package/gsd-core/templates/VALIDATION.md +3 -3
  252. package/gsd-core/templates/discussion-log.md +1 -1
  253. package/gsd-core/templates/phase-prompt.md +5 -4
  254. package/gsd-core/templates/state.md +11 -4
  255. package/gsd-core/templates/verification-report.md +9 -1
  256. package/gsd-core/workflows/_runtime-launcher.snippet.sh +1 -1
  257. package/gsd-core/workflows/add-backlog.md +1 -1
  258. package/gsd-core/workflows/add-phase.md +3 -3
  259. package/gsd-core/workflows/add-tests.md +3 -8
  260. package/gsd-core/workflows/add-todo.md +1 -1
  261. package/gsd-core/workflows/ai-integration-phase.md +13 -20
  262. package/gsd-core/workflows/audit-fix.md +12 -3
  263. package/gsd-core/workflows/audit-milestone.md +9 -9
  264. package/gsd-core/workflows/audit-uat.md +17 -2
  265. package/gsd-core/workflows/autonomous/steps/converge-fail-fast.md +2 -2
  266. package/gsd-core/workflows/autonomous.md +11 -27
  267. package/gsd-core/workflows/check-todos.md +1 -1
  268. package/gsd-core/workflows/cleanup.md +64 -5
  269. package/gsd-core/workflows/code-review/steps/structural-pre-pass.md +14 -4
  270. package/gsd-core/workflows/code-review-fix.md +38 -11
  271. package/gsd-core/workflows/code-review.md +159 -52
  272. package/gsd-core/workflows/complete-milestone.md +151 -23
  273. package/gsd-core/workflows/debug.md +12 -8
  274. package/gsd-core/workflows/diagnose-issues.md +47 -15
  275. package/gsd-core/workflows/discuss-phase/modes/advisor.md +1 -1
  276. package/gsd-core/workflows/discuss-phase/modes/chain.md +5 -8
  277. package/gsd-core/workflows/discuss-phase/modes/default.md +1 -1
  278. package/gsd-core/workflows/discuss-phase/modes/text.md +1 -1
  279. package/gsd-core/workflows/discuss-phase-assumptions/steps/auto-advance-dispatch.md +1 -3
  280. package/gsd-core/workflows/discuss-phase-assumptions.md +4 -3
  281. package/gsd-core/workflows/discuss-phase.md +1 -1
  282. package/gsd-core/workflows/do.md +3 -6
  283. package/gsd-core/workflows/docs-update.md +5 -4
  284. package/gsd-core/workflows/edit-phase.md +27 -2
  285. package/gsd-core/workflows/eval-review.md +7 -14
  286. package/gsd-core/workflows/execute-phase/steps/codebase-drift-gate.md +1 -1
  287. package/gsd-core/workflows/execute-phase/steps/executor-isolation-dispatch.md +142 -15
  288. package/gsd-core/workflows/execute-phase/steps/gap-closure-artifacts.md +1 -1
  289. package/gsd-core/workflows/execute-phase/steps/partial-wave.md +1 -1
  290. package/gsd-core/workflows/execute-phase/steps/per-plan-executor-routing.md +77 -0
  291. package/gsd-core/workflows/execute-phase/steps/per-plan-worktree-gate.md +24 -4
  292. package/gsd-core/workflows/execute-phase/steps/post-merge-gate.md +2 -2
  293. package/gsd-core/workflows/execute-phase/steps/protected-branch.md +21 -0
  294. package/gsd-core/workflows/execute-phase/steps/regression-gate-run.md +2 -2
  295. package/gsd-core/workflows/execute-phase/steps/wave-post-gate-hooks.md +39 -0
  296. package/gsd-core/workflows/execute-phase.md +72 -100
  297. package/gsd-core/workflows/execute-plan.md +52 -15
  298. package/gsd-core/workflows/explore.md +131 -4
  299. package/gsd-core/workflows/extract-learnings.md +1 -1
  300. package/gsd-core/workflows/fast.md +10 -2
  301. package/gsd-core/workflows/forensics.md +1 -1
  302. package/gsd-core/workflows/graduation.md +5 -5
  303. package/gsd-core/workflows/health.md +76 -10
  304. package/gsd-core/workflows/import.md +18 -15
  305. package/gsd-core/workflows/inbox.md +4 -5
  306. package/gsd-core/workflows/ingest-docs.md +49 -16
  307. package/gsd-core/workflows/insert-phase.md +5 -5
  308. package/gsd-core/workflows/list-seeds.md +5 -3
  309. package/gsd-core/workflows/list-workspaces.md +1 -1
  310. package/gsd-core/workflows/manager.md +12 -23
  311. package/gsd-core/workflows/map-codebase.md +1 -1
  312. package/gsd-core/workflows/milestone-summary.md +1 -1
  313. package/gsd-core/workflows/mvp-phase.md +8 -5
  314. package/gsd-core/workflows/new-milestone.md +22 -29
  315. package/gsd-core/workflows/new-project/steps/auto-mode-config.md +1 -1
  316. package/gsd-core/workflows/new-project.md +26 -40
  317. package/gsd-core/workflows/new-workspace.md +1 -1
  318. package/gsd-core/workflows/next.md +14 -2
  319. package/gsd-core/workflows/pause-work.md +1 -1
  320. package/gsd-core/workflows/plan-phase/steps/adr-ingest-express-path.md +1 -1
  321. package/gsd-core/workflows/plan-phase/steps/chunked-planning-mode.md +1 -1
  322. package/gsd-core/workflows/plan-phase/steps/prd-express-path.md +2 -4
  323. package/gsd-core/workflows/plan-phase/steps/stall-detection-helpers.md +3 -3
  324. package/gsd-core/workflows/plan-phase.md +162 -59
  325. package/gsd-core/workflows/plan-review-convergence.md +96 -11
  326. package/gsd-core/workflows/plant-seed.md +2 -2
  327. package/gsd-core/workflows/pr-branch.md +187 -51
  328. package/gsd-core/workflows/profile-user.md +16 -14
  329. package/gsd-core/workflows/progress.md +61 -18
  330. package/gsd-core/workflows/quick/steps/discussion-phase.md +1 -3
  331. package/gsd-core/workflows/quick/steps/plan-checker-loop.md +5 -7
  332. package/gsd-core/workflows/quick/steps/quick-verification.md +28 -9
  333. package/gsd-core/workflows/quick/steps/research-phase.md +4 -6
  334. package/gsd-core/workflows/quick/steps/worktree-pre-dispatch-commit.md +3 -3
  335. package/gsd-core/workflows/quick.md +55 -44
  336. package/gsd-core/workflows/remove-phase.md +4 -4
  337. package/gsd-core/workflows/remove-workspace.md +2 -2
  338. package/gsd-core/workflows/resume-project.md +8 -12
  339. package/gsd-core/workflows/review.md +219 -20
  340. package/gsd-core/workflows/scan.md +1 -1
  341. package/gsd-core/workflows/secure-phase.md +3 -3
  342. package/gsd-core/workflows/session-report.md +2 -1
  343. package/gsd-core/workflows/settings-advanced.md +7 -9
  344. package/gsd-core/workflows/settings-integrations.md +64 -31
  345. package/gsd-core/workflows/settings.md +69 -7
  346. package/gsd-core/workflows/ship.md +116 -50
  347. package/gsd-core/workflows/sketch-wrap-up.md +11 -17
  348. package/gsd-core/workflows/sketch.md +12 -18
  349. package/gsd-core/workflows/smart-entry.md +3 -5
  350. package/gsd-core/workflows/spec-phase.md +53 -13
  351. package/gsd-core/workflows/spike-wrap-up.md +7 -11
  352. package/gsd-core/workflows/spike.md +20 -31
  353. package/gsd-core/workflows/stats.md +2 -2
  354. package/gsd-core/workflows/sync-skills.md +64 -9
  355. package/gsd-core/workflows/thread.md +11 -7
  356. package/gsd-core/workflows/transition.md +49 -14
  357. package/gsd-core/workflows/ui-phase.md +15 -21
  358. package/gsd-core/workflows/ui-review.md +8 -12
  359. package/gsd-core/workflows/ultraplan-phase.md +5 -13
  360. package/gsd-core/workflows/undo.md +8 -16
  361. package/gsd-core/workflows/update.md +7 -11
  362. package/gsd-core/workflows/validate-phase.md +3 -3
  363. package/gsd-core/workflows/verify-work/steps/automated-ui-verification.md +25 -1
  364. package/gsd-core/workflows/verify-work/steps/mvp-uat-framing.md +1 -1
  365. package/gsd-core/workflows/verify-work.md +66 -25
  366. package/hooks/dist/gsd-agent-isolation-guard.js +158 -30
  367. package/hooks/dist/gsd-check-update-worker.js +56 -13
  368. package/hooks/dist/gsd-check-update.js +19 -1
  369. package/hooks/dist/gsd-config-reload.js +18 -12
  370. package/hooks/dist/gsd-context-monitor.js +19 -10
  371. package/hooks/dist/gsd-cursor-post-tool.js +3 -1
  372. package/hooks/dist/gsd-cursor-pre-tool.js +2 -3
  373. package/hooks/dist/gsd-cursor-session-start.js +2 -1
  374. package/hooks/dist/gsd-cursor-stop.js +2 -1
  375. package/hooks/dist/gsd-cursor-subagent-start.js +83 -3
  376. package/hooks/dist/gsd-cursor-subagent-stop.js +6 -3
  377. package/hooks/dist/gsd-ensure-canonical-path.js +2 -1
  378. package/hooks/dist/gsd-graphify-update.sh +22 -18
  379. package/hooks/dist/gsd-node-runner.sh +76 -0
  380. package/hooks/dist/gsd-phase-boundary.sh +1 -0
  381. package/hooks/dist/gsd-prompt-guard.js +37 -27
  382. package/hooks/dist/gsd-read-guard.js +16 -7
  383. package/hooks/dist/gsd-read-injection-scanner.js +55 -32
  384. package/hooks/dist/gsd-session-state.sh +1 -0
  385. package/hooks/dist/gsd-statusline.js +231 -24
  386. package/hooks/dist/gsd-update-banner.js +22 -1
  387. package/hooks/dist/gsd-validate-commit.sh +80 -6
  388. package/hooks/dist/gsd-windsurf-pre-command.js +16 -11
  389. package/hooks/dist/gsd-windsurf-pre-write.js +22 -13
  390. package/hooks/dist/gsd-workflow-guard.js +162 -46
  391. package/hooks/dist/gsd-worktree-path-guard.js +36 -21
  392. package/hooks/dist/gsd-write-guard.js +35 -25
  393. package/hooks/dist/lib/cli-exit.js +560 -0
  394. package/hooks/dist/lib/exit-code-registry.js +98 -0
  395. package/hooks/dist/lib/git-cmd.js +92 -59
  396. package/hooks/dist/lib/git-probe.js +84 -0
  397. package/hooks/dist/lib/hook-exit.js +81 -0
  398. package/hooks/dist/lib/injection-patterns.js +45 -0
  399. package/hooks/dist/lib/isolation-deny-reason.js +39 -0
  400. package/hooks/dist/lib/isolation-sentinel.js +9 -0
  401. package/hooks/dist/managed-hooks-registry.cjs +3 -0
  402. package/hooks/gsd-agent-isolation-guard.js +158 -30
  403. package/hooks/gsd-check-update-worker.js +56 -13
  404. package/hooks/gsd-check-update.js +19 -1
  405. package/hooks/gsd-config-reload.js +18 -12
  406. package/hooks/gsd-context-monitor.js +19 -10
  407. package/hooks/gsd-cursor-post-tool.js +3 -1
  408. package/hooks/gsd-cursor-pre-tool.js +2 -3
  409. package/hooks/gsd-cursor-session-start.js +2 -1
  410. package/hooks/gsd-cursor-stop.js +2 -1
  411. package/hooks/gsd-cursor-subagent-start.js +83 -3
  412. package/hooks/gsd-cursor-subagent-stop.js +6 -3
  413. package/hooks/gsd-ensure-canonical-path.js +2 -1
  414. package/hooks/gsd-graphify-update.sh +22 -18
  415. package/hooks/gsd-node-runner.sh +76 -0
  416. package/hooks/gsd-phase-boundary.sh +1 -0
  417. package/hooks/gsd-prompt-guard.js +37 -27
  418. package/hooks/gsd-read-guard.js +16 -7
  419. package/hooks/gsd-read-injection-scanner.js +55 -32
  420. package/hooks/gsd-session-state.sh +1 -0
  421. package/hooks/gsd-statusline.js +231 -24
  422. package/hooks/gsd-update-banner.js +22 -1
  423. package/hooks/gsd-validate-commit.sh +80 -6
  424. package/hooks/gsd-windsurf-pre-command.js +16 -11
  425. package/hooks/gsd-windsurf-pre-write.js +22 -13
  426. package/hooks/gsd-workflow-guard.js +162 -46
  427. package/hooks/gsd-worktree-path-guard.js +36 -21
  428. package/hooks/gsd-write-guard.js +35 -25
  429. package/hooks/lib/cli-exit.js +560 -0
  430. package/hooks/lib/exit-code-registry.js +98 -0
  431. package/hooks/lib/git-cmd.js +92 -59
  432. package/hooks/lib/git-probe.js +84 -0
  433. package/hooks/lib/hook-exit.js +81 -0
  434. package/hooks/lib/injection-patterns.js +45 -0
  435. package/hooks/lib/isolation-deny-reason.js +39 -0
  436. package/hooks/lib/isolation-sentinel.js +9 -0
  437. package/hooks/managed-hooks-registry.cjs +3 -0
  438. package/package.json +28 -11
  439. package/pi/gsd.cjs +19 -5
  440. package/scripts/base64-scan.sh +74 -12
  441. package/scripts/baselines/planning-prompt-drift-baseline.json +4 -0
  442. package/scripts/baselines/planning-snapshot-bypass-baseline.json +12 -0
  443. package/scripts/baselines/unreachable-guard-drift-baseline.json +4 -0
  444. package/scripts/build-hooks.js +5 -0
  445. package/scripts/changeset/lint.cjs +60 -5
  446. package/scripts/check-alias-drift.cjs +7 -43
  447. package/scripts/check-contract-drift.cjs +297 -0
  448. package/scripts/check-glossary-refs.cjs +77 -15
  449. package/scripts/check-mutation-score-ratchet.cjs +156 -0
  450. package/scripts/ci-check-job-near-cap.cjs +49 -0
  451. package/scripts/ci-pr-mergeability.cjs +262 -0
  452. package/scripts/ci-test-scope.cjs +64 -14
  453. package/scripts/ci-timeout-report.cjs +230 -0
  454. package/scripts/command-contract-helpers.cjs +903 -1
  455. package/scripts/docs-guard-registry.cjs +396 -0
  456. package/scripts/gen-adr-index.cjs +728 -38
  457. package/scripts/gen-capability-registry.cjs +11 -21
  458. package/scripts/gen-context-index.cjs +2 -11
  459. package/scripts/gen-exit-code-docs.cjs +318 -0
  460. package/scripts/gen-exit-code-registry.cjs +891 -0
  461. package/scripts/gen-features.cjs +836 -0
  462. package/scripts/gen-health-docs.cjs +390 -0
  463. package/scripts/gen-hooks-cli-exit.cjs +239 -0
  464. package/scripts/gen-install-tree-fixtures.cjs +2 -2
  465. package/scripts/gen-inventory-manifest.cjs +50 -4
  466. package/scripts/gen-loop-host-contract.cjs +138 -25
  467. package/scripts/gen-registry.cjs +3 -14
  468. package/scripts/gen-scripts-cli-exit.cjs +185 -0
  469. package/scripts/gen-state-md-docs.cjs +727 -0
  470. package/scripts/{test-failure-reasons.cjs → gsd-test-gate-reasons.cjs} +6 -0
  471. package/scripts/lib/alias-drift-families.cjs +46 -0
  472. package/scripts/lib/ci-job-timing.cjs +72 -0
  473. package/scripts/lib/cli-exit.cjs +546 -44
  474. package/scripts/lib/drift-scan.cjs +308 -0
  475. package/scripts/lib/exit-code-registry.cjs +98 -0
  476. package/scripts/lib/ndjson-reporter.cjs +119 -0
  477. package/scripts/lint-allow-test-rule-refs.allowlist.json +1 -26
  478. package/scripts/lint-allow-test-rule-refs.effective-ceiling.json +4 -0
  479. package/scripts/lint-allow-test-rule-refs.unverified-ceiling.json +3 -0
  480. package/scripts/lint-canary-version-leak.cjs +73 -0
  481. package/scripts/lint-command-contract.cjs +96 -13
  482. package/scripts/lint-completion-predicate-drift.cjs +933 -0
  483. package/scripts/lint-completion-ratio-drift.cjs +214 -0
  484. package/scripts/lint-default-flip-documentation.cjs +193 -0
  485. package/scripts/lint-docs-guard-registration.cjs +495 -0
  486. package/scripts/lint-docs-guard-registration.exempt-baseline.cjs +193 -0
  487. package/scripts/lint-eslint-glob-coverage.allowlist.json +38 -0
  488. package/scripts/lint-eslint-glob-coverage.cjs +340 -0
  489. package/scripts/{lint-fix-has-regression-test.cjs → lint-fix-has-regression-tests.cjs} +12 -6
  490. package/scripts/lint-frontmatter-scalar-broad-grep.cjs +237 -0
  491. package/scripts/lint-health-diagnostic-rule-table.cjs +461 -0
  492. package/scripts/lint-hooks-runtime-build-seam.cjs +262 -0
  493. package/scripts/lint-milestone-window-drift.cjs +468 -0
  494. package/scripts/lint-mutation-test-derivation-drift.cjs +86 -0
  495. package/scripts/lint-phase-enumeration-drift.cjs +492 -0
  496. package/scripts/lint-plan-count-drift.cjs +318 -0
  497. package/scripts/lint-planning-artifact-writer-drift.cjs +398 -0
  498. package/scripts/lint-planning-prompt-drift.cjs +471 -0
  499. package/scripts/lint-planning-snapshot-bypass-drift.cjs +544 -0
  500. package/scripts/lint-regression-test-names.cjs +15 -13
  501. package/scripts/lint-removed-but-needed.cjs +488 -0
  502. package/scripts/lint-seam-enforcement.cjs +182 -0
  503. package/scripts/lint-slug-derivation-drift.cjs +921 -0
  504. package/scripts/lint-source-test-name-collision.cjs +241 -0
  505. package/scripts/lint-state-field-drift.cjs +805 -0
  506. package/scripts/lint-state-write-path-drift.cjs +950 -0
  507. package/scripts/lint-test-file-count.allowlist.json +137 -8
  508. package/scripts/lint-test-file-count.cjs +25 -3
  509. package/scripts/lint-unreachable-guard-drift.cjs +830 -0
  510. package/scripts/lint-vendored-deps.cjs +297 -0
  511. package/scripts/mutation-matrix.cjs +599 -50
  512. package/scripts/pr-changed-files.cjs +63 -0
  513. package/scripts/pr-template-policy.cjs +14 -4
  514. package/scripts/prompt-injection-scan.sh +100 -14
  515. package/scripts/require-issue-link-policy.cjs +192 -0
  516. package/scripts/secret-scan.sh +75 -13
  517. package/scripts/select-docs-guards.cjs +56 -0
  518. package/scripts/sync-runtime-launcher.cjs +24 -7
  519. package/skills/gsd-autonomous/SKILL.md +0 -1
  520. package/skills/gsd-code-review/SKILL.md +1 -1
  521. package/skills/gsd-discuss-phase/SKILL.md +1 -1
  522. package/skills/gsd-execute-phase/SKILL.md +1 -2
  523. package/skills/gsd-import/SKILL.md +1 -1
  524. package/skills/gsd-map-codebase/SKILL.md +1 -1
  525. package/skills/gsd-mempalace-capture/SKILL.md +1 -1
  526. package/skills/gsd-mempalace-recall/SKILL.md +1 -1
  527. package/skills/gsd-new-milestone/SKILL.md +1 -1
  528. package/skills/gsd-next/SKILL.md +0 -1
  529. package/skills/gsd-plan-phase/SKILL.md +0 -1
  530. package/skills/gsd-progress/SKILL.md +0 -1
  531. package/skills/gsd-quick/SKILL.md +9 -5
  532. package/skills/gsd-review-backlog/SKILL.md +2 -1
  533. package/skills/gsd-stats/SKILL.md +0 -1
  534. package/skills/gsd-verify-work/SKILL.md +1 -1
  535. package/vscode/package.json +1 -1
  536. package/bin/lib/ui-safety-gate.cjs +0 -107
  537. package/gsd-core/workflows/discovery-phase.md +0 -298
  538. package/gsd-core/workflows/plan-milestone-gaps.md +0 -281
  539. package/gsd-core/workflows/verify-phase.md +0 -574
  540. package/scripts/affected-tests-lib.cjs +0 -554
  541. package/scripts/lint-allow-test-rule-refs.cjs +0 -162
  542. package/scripts/lint-emitted-drift-ack.cjs +0 -344
  543. package/scripts/run-affected-tests.cjs +0 -7
  544. package/scripts/run-tests.cjs +0 -1051
@@ -0,0 +1,381 @@
1
+ "use strict";
2
+ /**
3
+ * installed-surface-resolver.cts — Installed Surface Resolver Module (#2872,
4
+ * ADR-2866, Phase 3 — governed by
5
+ * `.gsd/phase/feat-2872-manifest-scope-runtime/40-design.md`).
6
+ *
7
+ * `resolveInstalledSurfaces(runtime?, opts?)` answers a question no existing
8
+ * module answers: "which surfaces actually exist on THIS machine, across
9
+ * BOTH install scopes, right now?" `capability-state.cts` answers "which
10
+ * capabilities are enabled in THIS config dir" — a different question at a
11
+ * different altitude. This module is a new leaf: it reads two scopes at
12
+ * once, composing three already-shipped, already-tested pieces
13
+ * (`resolveScope`, Phase 1; `resolveTriggerSurface`, Phase 2; and
14
+ * `readInstallManifest`, widened in this same phase) rather than
15
+ * re-implementing any of their rules.
16
+ *
17
+ * ── Probe-not-declared keying ───────────────────────────────────────────────
18
+ * A scope RECORD is keyed by the PROBED scope (`resolveScope`'s own `id`),
19
+ * never by what the manifest itself claims. `manifestVersion`/`runtime`/
20
+ * `scope` recorded inside a v2 manifest are corroboration, not identity: a
21
+ * manifest copied between config dirs, or a `--config-dir` install, must
22
+ * still be reported at the scope this machine actually resolves to.
23
+ *
24
+ * ── Report, don't correct ───────────────────────────────────────────────────
25
+ * When a declared `runtime`/`scope` disagrees with the probe, this module
26
+ * reports the mismatch (`declaredScopeMatchesProbe: false` /
27
+ * `declaredRuntimeMatchesProbe: false`) and otherwise proceeds exactly as it
28
+ * would for an undeclared (v1) manifest. It never silently substitutes the
29
+ * declared value for the probed one, and never throws on a mismatch — see
30
+ * B-row "Postel's Law" discussion in the design doc.
31
+ *
32
+ * ── One trigger call over installed scopes only ─────────────────────────────
33
+ * `resolveTriggerSurface` is called AT MOST once per runtime, with the
34
+ * scopes that are actually installed on this machine (per manifest
35
+ * presence — never per the new corroboration fields, which is what keeps a
36
+ * v1-only install fully functional with no reinstall required). A
37
+ * hypothetical "what if both scopes were installed" answer is deliberately
38
+ * not offered; #2218 is a fact about THIS machine, not a simulation.
39
+ *
40
+ * ── Installed-ness is manifest PRESENCE, never the new fields ───────────────
41
+ * `installed` is `manifestVersion !== null`. A v1 manifest (no
42
+ * `manifestVersion` key at all, `manifestVersion: 1` after normalization) is
43
+ * a correct manifest written by an older GSD — never a broken one, never
44
+ * grounds for `installed: false`, a warning, or a reinstall prompt.
45
+ *
46
+ * ── Stems come from the manifest, not the source tree ───────────────────────
47
+ * `resolveTriggerSurface` needs `stems`. They are derived from the
48
+ * INSTALLED manifest's own `files` keys (see the private stem-derivation
49
+ * helpers below), never from a roster read of the source tree — a global
50
+ * `claude` install ships no `commands/gsd` source, so a roster read would
51
+ * return `[]` in exactly the configuration #2218 is about. The derivation
52
+ * consumes `isNamespacedByDir` and `composeCommandFilename`
53
+ * (`runtime-artifact-layout.cjs`, #2871 Phase 2's exported helpers) rather
54
+ * than re-deriving either rule as a fourth independent copy.
55
+ */
56
+ var __importDefault = (this && this.__importDefault) || function (mod) {
57
+ return (mod && mod.__esModule) ? mod : { "default": mod };
58
+ };
59
+ Object.defineProperty(exports, "__esModule", { value: true });
60
+ exports.resolveInstalledSurfaces = resolveInstalledSurfaces;
61
+ const node_fs_1 = __importDefault(require("node:fs"));
62
+ const node_path_1 = __importDefault(require("node:path"));
63
+ const install_scope_cjs_1 = require("./install-scope.cjs");
64
+ const shell_command_projection_cjs_1 = require("./shell-command-projection.cjs");
65
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
66
+ const runtimeArtifactLayoutMod = require("./runtime-artifact-layout.cjs");
67
+ const { resolveRuntimeArtifactLayout, resolveRuntimeArtifactLayoutFromRegistry, resolveTriggerSurface, isNamespacedByDir, composeCommandFilename, } = runtimeArtifactLayoutMod;
68
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
69
+ const installerMigrationsMod = require("./installer-migrations.cjs");
70
+ const { readInstallManifest, MANIFEST_NAME } = installerMigrationsMod;
71
+ // In .cts (CommonJS output) files, `require` is available as a global.
72
+ const _require = require;
73
+ // ── Internals ───────────────────────────────────────────────────────────
74
+ /**
75
+ * A trigger stem is a kebab-case token and nothing else. Verified against the
76
+ * real roster: all 71 `commands/gsd/*.md` stems match this, so it has no false
77
+ * negatives today.
78
+ *
79
+ * This is a SECURITY boundary, not cosmetics. A stem is derived from a manifest
80
+ * key — attacker-influenceable text, since a project-local
81
+ * `gsd-file-manifest.json` lives inside a repository a user may merely have
82
+ * cloned — and Phase 4 (#2873) renders it back to the user as `/gsd-<stem>`.
83
+ * Without this, `skills/gsd-../../../x` yields the stem `..`, and control
84
+ * characters, newlines, ANSI escapes and RTL-override codepoints all survive
85
+ * into that rendered trigger. The `commands` branch happened to be protected by
86
+ * its `composeCommandFilename` round-trip; the `skills` branch had no
87
+ * equivalent, so the rule is stated once here and applied to both.
88
+ */
89
+ const SAFE_STEM = /^[a-z0-9][a-z0-9-]*$/;
90
+ function getDefaultRuntimeRegistry() {
91
+ return _require('./capability-registry.cjs');
92
+ }
93
+ /** C7: every registered runtime id, sorted for determinism. Reads
94
+ * `opts.registry` when provided (so a sweep is assertable without the real
95
+ * capability registry), else the real one. */
96
+ function listRegisteredRuntimeIds(opts) {
97
+ const registry = opts.registry ?? getDefaultRuntimeRegistry();
98
+ return Object.keys(registry.runtimes).sort();
99
+ }
100
+ /**
101
+ * D — the stem inverse for one `commands`/`skills` layout kind entry.
102
+ * Consumes `isNamespacedByDir` (to decide the commands filename shape) and
103
+ * `composeCommandFilename` (to VERIFY a candidate stem round-trips to the
104
+ * exact filename seen) rather than re-deriving either rule locally (design
105
+ * "Rejected" #6). Manifest keys are normalized with an unconditional
106
+ * `.replace(/\\/g, '/')` (D7) — never gated on `path.sep` — matching this
107
+ * repo's recorded path-separator-normalization defect class.
108
+ */
109
+ function deriveStemsForKindEntry(kind, destSubpath, prefix, fileKeys) {
110
+ const destSubpathNorm = (0, shell_command_projection_cjs_1.posixNormalize)(destSubpath);
111
+ const boundary = `${destSubpathNorm}/`;
112
+ const namespacedByDir = isNamespacedByDir(kind, destSubpath, prefix);
113
+ const stems = new Set();
114
+ for (const rawKey of fileKeys) {
115
+ const key = rawKey.replace(/\\/g, '/');
116
+ if (!key.startsWith(boundary))
117
+ continue; // D4: key not under this declared subpath
118
+ const rest = key.slice(boundary.length);
119
+ if (rest === '')
120
+ continue;
121
+ const segments = rest.split('/');
122
+ if (kind === 'skills') {
123
+ const dirSegment = segments[0];
124
+ if (!dirSegment.startsWith(prefix))
125
+ continue; // D5: subpath matches, prefix does not
126
+ const stem = dirSegment.slice(prefix.length);
127
+ if (stem === '')
128
+ continue; // D7/B7: empty stem never emitted
129
+ if (!SAFE_STEM.test(stem))
130
+ continue; // security: reject anything but a kebab-case token
131
+ stems.add(stem); // D6: several files under one dir -> one stem
132
+ continue;
133
+ }
134
+ // commands: exactly one path segment — the composed filename itself.
135
+ if (segments.length !== 1)
136
+ continue;
137
+ const filename = segments[0];
138
+ if (!filename.endsWith('.md'))
139
+ continue;
140
+ const base = filename.slice(0, -3);
141
+ const candidateStem = namespacedByDir
142
+ ? base
143
+ : (base.startsWith(prefix) ? base.slice(prefix.length) : '');
144
+ if (candidateStem === '')
145
+ continue;
146
+ if (composeCommandFilename(namespacedByDir, prefix, candidateStem) !== filename)
147
+ continue;
148
+ if (!SAFE_STEM.test(candidateStem))
149
+ continue; // security: reject anything but a kebab-case token
150
+ stems.add(candidateStem);
151
+ }
152
+ return [...stems];
153
+ }
154
+ /** D — full stem set for one scope: every `commands`/`skills` layout kind
155
+ * entry, unioned. Empty `files` (C13) short-circuits to `[]` without
156
+ * resolving a layout at all. */
157
+ function deriveStemsFromManifest(runtime, scopeId, configHome, files, opts) {
158
+ const fileKeys = Object.keys(files);
159
+ if (fileKeys.length === 0)
160
+ return [];
161
+ const layout = opts.registry !== undefined
162
+ ? resolveRuntimeArtifactLayoutFromRegistry(opts.registry, runtime, configHome, scopeId)
163
+ : resolveRuntimeArtifactLayout(runtime, configHome, scopeId);
164
+ const stems = new Set();
165
+ for (const kindEntry of layout.kinds) {
166
+ if (kindEntry.kind !== 'commands' && kindEntry.kind !== 'skills')
167
+ continue; // excludes agents/kimi-agents (D4)
168
+ for (const stem of deriveStemsForKindEntry(kindEntry.kind, kindEntry.destSubpath, kindEntry.prefix, fileKeys)) {
169
+ stems.add(stem);
170
+ }
171
+ }
172
+ return [...stems].sort();
173
+ }
174
+ /**
175
+ * True when `p` is a symlink. An `lstatSync` throw (ENOENT — nothing at this
176
+ * path) is NOT evidence of a symlink; it is treated as "not a symlink" here
177
+ * and left for `readManifest` to classify (it already owns the absent-file
178
+ * case, per C14 above).
179
+ */
180
+ function isSymlinkPath(p, lstatSync) {
181
+ try {
182
+ return lstatSync(p).isSymbolicLink();
183
+ }
184
+ catch {
185
+ return false;
186
+ }
187
+ }
188
+ /**
189
+ * The shared "not installed" degraded shape (C14's EACCES path, and this
190
+ * phase's new symlink-guard path). A FACTORY, not a module-level constant
191
+ * object: a `const` object spread at each return site would still share the
192
+ * same `stems` ARRAY reference across every call (`...` shallow-copies the
193
+ * object but not the array a property points at), which would violate this
194
+ * module's own "builds fresh arrays/objects on every call" contract (C15) —
195
+ * a caller mutating one degraded record's `stems` must never be visible on
196
+ * another's.
197
+ */
198
+ function notInstalledScopeRecordFields() {
199
+ return {
200
+ installed: false,
201
+ manifestVersion: null,
202
+ declaredRuntime: null,
203
+ declaredScope: null,
204
+ declaredScopeMatchesProbe: null,
205
+ declaredRuntimeMatchesProbe: null,
206
+ stems: [],
207
+ };
208
+ }
209
+ /**
210
+ * Build one scope's record. `resolvedConfigHome` has already been probed
211
+ * successfully by the time this is called (a `resolveScope` `TypeError` is
212
+ * handled by the caller, per C8 — it is never this function's concern).
213
+ *
214
+ * Two distinct failure modes are handled with two distinct, narrowly-scoped
215
+ * try/catches — NOT one catch-all around the whole function:
216
+ *
217
+ * - The manifest READ (`readManifest`) is the only thing that can justify
218
+ * `installed: false` (C14, e.g. EACCES). A failure here means "we could
219
+ * not even tell whether this scope is installed".
220
+ * - The stem DERIVATION (`deriveStemsFromManifest`, which resolves a
221
+ * runtime artifact layout) is a separate concern. A `TypeError` thrown
222
+ * while deriving stems is a layout-lookup failure, not evidence the
223
+ * manifest is absent — the manifest was already read successfully, so
224
+ * `installed` and every declared/*MatchesProbe field stay exactly as the
225
+ * manifest reported. Conflating the two would report a genuinely
226
+ * installed runtime as `installed: false`, hiding a real install from
227
+ * #2218 shadow detection precisely when this module exists to surface it.
228
+ */
229
+ function buildScopeRecord(runtime, scopeId, resolvedConfigHome, opts) {
230
+ // Hardening requirement 2 (#2873 design doc, "Hardening requirements
231
+ // claimed from #2873's comment"): `readInstallManifest` -> `readJsonIfPresent`
232
+ // uses `existsSync` + `readFileSync` and therefore FOLLOWS symlinks, and
233
+ // this module resolves `local` against `process.cwd()` — a directory that,
234
+ // as of this phase, becomes reachable from an arbitrary cloned repository
235
+ // (this is the same phase that makes the local scope's manifest a first
236
+ // read target, not merely a write target). The in-tree precedent is
237
+ // `getAgentsDir` (`agent-install-check.cts`), which probes with
238
+ // `fs.lstatSync(...).isDirectory()`/`.isFile()` and deliberately does not
239
+ // follow. #2872 left this resolver's read un-guarded only because the path
240
+ // had zero callers at the time; refusing to follow a symlinked config dir
241
+ // or manifest here closes that asymmetry rather than carrying it forward.
242
+ // Degrading to `installed: false` reuses the SAME shape the EACCES catch
243
+ // below already returns — no new failure shape is introduced.
244
+ const lstatSync = opts.lstatSync ?? node_fs_1.default.lstatSync;
245
+ const manifestPath = node_path_1.default.join(resolvedConfigHome, MANIFEST_NAME);
246
+ if (isSymlinkPath(resolvedConfigHome, lstatSync) || isSymlinkPath(manifestPath, lstatSync)) {
247
+ return { scope: scopeId, configHome: resolvedConfigHome, ...notInstalledScopeRecordFields() };
248
+ }
249
+ let manifest;
250
+ try {
251
+ const readManifest = opts.readManifest ?? readInstallManifest;
252
+ manifest = readManifest(resolvedConfigHome);
253
+ }
254
+ catch {
255
+ // C14: manifest read/probe failure degrades to not-installed, never throws.
256
+ // Deliberately a BARE catch, unlike the stem-derivation catch below: any
257
+ // read failure at all (EACCES, ENOENT-after-race, a corrupt filesystem)
258
+ // legitimately means "cannot tell whether installed" (design row C14), so
259
+ // there is no error TYPE here that should instead propagate.
260
+ return { scope: scopeId, configHome: resolvedConfigHome, ...notInstalledScopeRecordFields() };
261
+ }
262
+ const installed = manifest.manifestVersion !== null; // C9: presence, never the new fields
263
+ const declaredRuntime = manifest.runtime;
264
+ const declaredScope = manifest.scope;
265
+ const declaredRuntimeMatchesProbe = declaredRuntime === null ? null : declaredRuntime === runtime;
266
+ const declaredScopeMatchesProbe = declaredScope === null ? null : declaredScope === scopeId;
267
+ let stems = [];
268
+ if (installed) {
269
+ try {
270
+ stems = deriveStemsFromManifest(runtime, scopeId, resolvedConfigHome, manifest.files, opts);
271
+ }
272
+ catch (error) {
273
+ if (!(error instanceof TypeError))
274
+ throw error;
275
+ // A layout-lookup failure means "we could not enumerate this scope's
276
+ // triggers", NOT "this scope is not installed" — the manifest read
277
+ // already succeeded above, so `installed` and the declared fields
278
+ // stay as reported. Conflating the two would hide a real install.
279
+ // Anything that is not the expected `TypeError` (a genuine bug in
280
+ // `deriveStemsFromManifest`/`resolveRuntimeArtifactLayout`) is
281
+ // rethrown rather than silently degrading to `stems: []` — this
282
+ // matches `resolveInstalledSurfaces`'s own `TypeError` narrowing
283
+ // below, so the two catches cannot drift apart.
284
+ stems = [];
285
+ }
286
+ }
287
+ return {
288
+ scope: scopeId,
289
+ configHome: resolvedConfigHome,
290
+ installed,
291
+ manifestVersion: manifest.manifestVersion,
292
+ declaredRuntime,
293
+ declaredScope,
294
+ declaredScopeMatchesProbe,
295
+ declaredRuntimeMatchesProbe,
296
+ stems,
297
+ };
298
+ }
299
+ /**
300
+ * Resolve one runtime's full installed surface. A `resolveScope` `TypeError`
301
+ * (unknown runtime, or `configHome.kind === 'none'`, e.g. vscode) propagates
302
+ * from here uncaught — `resolveInstalledSurfaces` decides whether that
303
+ * means "skip" (C7 sweep) or "propagate" (explicit single-runtime ask, C8).
304
+ */
305
+ function resolveOneRuntime(runtime, opts) {
306
+ const scopes = install_scope_cjs_1.SCOPE_ORDER.map((scopeId) => {
307
+ const resolved = (0, install_scope_cjs_1.resolveScope)({
308
+ id: scopeId,
309
+ runtime,
310
+ env: opts.env,
311
+ home: opts.home,
312
+ existsSync: opts.existsSync,
313
+ cwd: opts.cwd,
314
+ });
315
+ return buildScopeRecord(runtime, scopeId, resolved.configHome, opts);
316
+ });
317
+ // C12: dedupe by resolved configHome BEFORE the trigger call, keeping the
318
+ // higher-ranked (global, first in SCOPE_ORDER) scope. Both scope RECORDS
319
+ // above are unaffected — only the scope list handed to resolveTriggerSurface
320
+ // is deduped.
321
+ const seenConfigHomes = new Set();
322
+ const triggerScopeIds = [];
323
+ for (const record of scopes) {
324
+ if (!record.installed)
325
+ continue;
326
+ if (seenConfigHomes.has(record.configHome))
327
+ continue;
328
+ seenConfigHomes.add(record.configHome);
329
+ triggerScopeIds.push(record.scope);
330
+ }
331
+ const stemUnion = new Set();
332
+ for (const scopeId of triggerScopeIds) {
333
+ const record = scopes.find((s) => s.scope === scopeId);
334
+ for (const stem of record?.stems ?? [])
335
+ stemUnion.add(stem);
336
+ }
337
+ const triggers = triggerScopeIds.length > 0
338
+ ? resolveTriggerSurface(runtime, triggerScopeIds, {
339
+ stems: [...stemUnion].sort(),
340
+ registry: opts.registry,
341
+ })
342
+ : [];
343
+ return { runtime, scopes, triggers };
344
+ }
345
+ /**
346
+ * Read-only. Probes both install scopes for a runtime (or every registered
347
+ * runtime, sorted by id, when `runtime` is omitted), reads each scope's
348
+ * manifest, and resolves the trigger surface across the scopes that are
349
+ * actually installed on this machine. See the module-level comment for the
350
+ * non-obvious choices (probe-not-declared keying, report-don't-correct, one
351
+ * trigger call over installed scopes only).
352
+ *
353
+ * Pure with respect to caller-visible state: builds fresh arrays/objects on
354
+ * every call (C15) and performs no writes. Filesystem reads happen only via
355
+ * `resolveScope`'s injected `existsSync`/`env`/`home`/`cwd` and via
356
+ * `readManifest` (default: `readInstallManifest`).
357
+ *
358
+ * @throws {TypeError} when `runtime` is given explicitly and it is unknown,
359
+ * or has no installable config directory (`configHome.kind === 'none'`,
360
+ * e.g. vscode) — same contract `resolveScope` throws. In the all-runtimes
361
+ * sweep (`runtime` omitted), a runtime that would throw this same
362
+ * `TypeError` is skipped instead, so one non-installable runtime cannot
363
+ * kill the sweep (C7/C8). Any other error type is never swallowed here.
364
+ */
365
+ function resolveInstalledSurfaces(runtime, opts = {}) {
366
+ if (typeof runtime === 'string') {
367
+ return [resolveOneRuntime(runtime, opts)];
368
+ }
369
+ const results = [];
370
+ for (const runtimeId of listRegisteredRuntimeIds(opts)) {
371
+ try {
372
+ results.push(resolveOneRuntime(runtimeId, opts));
373
+ }
374
+ catch (error) {
375
+ if (error instanceof TypeError)
376
+ continue; // C8: sweep skips, never dies
377
+ throw error;
378
+ }
379
+ }
380
+ return results;
381
+ }
@@ -48,6 +48,9 @@ exports.BUNDLED_GSD_HOOK_FILES = Object.freeze(new Set([
48
48
  'hooks/gsd-windsurf-pre-command.js',
49
49
  'hooks/gsd-ensure-canonical-path.js',
50
50
  'hooks/gsd-graphify-update.sh',
51
+ // #3662: portable node resolver staged into hooks/ (not itself a lifecycle
52
+ // hook — managed JS hook commands route through it under --portable-hooks).
53
+ 'hooks/gsd-node-runner.sh',
51
54
  'hooks/gsd-phase-boundary.sh',
52
55
  'hooks/gsd-prompt-guard.js',
53
56
  'hooks/gsd-read-guard.js',
@@ -0,0 +1,169 @@
1
+ "use strict";
2
+ /**
3
+ * Installer migration: retire Antigravity's configHome skills/agents surfaces (#3738).
4
+ *
5
+ * Antigravity's machine-local discovery scans ~/.gemini/config/{skills,agents}
6
+ * (antigravity.google/docs/skills, /docs/subagents); the configHome
7
+ * (~/.gemini/antigravity{,-ide,-cli}) is not scanned for global artifacts, so
8
+ * skills installed there are silently ignored. Since #3738 the global layout
9
+ * declares a `home: ".gemini/config"` override for both kinds, and new
10
+ * installs land in the scanned dir. This migration converges an existing
11
+ * installation: manifest-managed files under the configHome's skills/ and
12
+ * agents/ subtrees are removed (modified ones backed up first), unmanifested
13
+ * files are preserved, and now-empty container directories are retired.
14
+ *
15
+ * Scope is GLOBAL only: the local workspace layout (.agents/skills,
16
+ * .agents/agents) is the documented, still-live surface and is never touched.
17
+ *
18
+ * Is the action safe in non-interactive install?
19
+ * Yes. Every emitted action type (`remove-managed`, `backup-and-remove`,
20
+ * `remove-empty-dir`) is non-interactive and journaled; none requires a
21
+ * user choice, and unknown files never produce an action.
22
+ *
23
+ * See docs/installer-migrations.md#shipped-migrations and the antigravity row
24
+ * of docs/installer-migrations.md#runtime-configuration-contract-registry.
25
+ */
26
+ var __importDefault = (this && this.__importDefault) || function (mod) {
27
+ return (mod && mod.__esModule) ? mod : { "default": mod };
28
+ };
29
+ const node_fs_1 = __importDefault(require("node:fs"));
30
+ const node_path_1 = __importDefault(require("node:path"));
31
+ /** The two retired configHome-relative artifact subpaths. */
32
+ const RETIRED_SUBPATHS = ['skills', 'agents'];
33
+ /** Only GSD-owned top-level entries are retirement candidates. */
34
+ const GSD_PREFIX = 'gsd-';
35
+ const FILE_REASON = 'Antigravity scans ~/.gemini/config/{skills,agents} for global discovery and does not scan the ' +
36
+ 'configHome, so these artifacts are invisible to the runtime (#3738); the same artifacts reinstall ' +
37
+ "under the global layout's .gemini/config home override";
38
+ const FILE_OWNERSHIP_EVIDENCE = 'pre-#3738 antigravity installs record skills/gsd-*/** and agents/gsd-*.md keys in ' +
39
+ 'gsd-file-manifest.json at the configHome root; the migration only walks gsd--prefixed entries ' +
40
+ 'under the two retired subpaths';
41
+ const DIR_REASON = 'the retired container directory is removed only once every GSD-owned entry inside it is gone; a ' +
42
+ 'directory that still holds an unmanifested user file — or any file-level action that failed to ' +
43
+ 'apply — is left in place by the emptiness re-check';
44
+ const DIR_OWNERSHIP_EVIDENCE = 'skills/ and agents/ at the antigravity configHome root are GSD-installed container directories ' +
45
+ 'from the pre-#3738 layout; removal is gated on emptiness by the shared remove-empty-dir action';
46
+ /**
47
+ * Recursively collect files and directories under `root/relDir`, never
48
+ * following a symlink (whether it names a file or a directory) and never
49
+ * emitting a path that resolves outside `baseResolved`. Mirrors the traversal
50
+ * guard in migration 009 (`walkPiHooksTree`).
51
+ */
52
+ function walkTree(root, relDir, baseResolved, files, dirs) {
53
+ const dir = node_path_1.default.join(root, relDir);
54
+ const entries = node_fs_1.default.readdirSync(dir, { withFileTypes: true });
55
+ for (const entry of entries) {
56
+ // Never follow a symlink into or through: it must not be traversed,
57
+ // hashed, or removed, regardless of what it points at.
58
+ if (entry.isSymbolicLink())
59
+ continue;
60
+ const relPath = node_path_1.default.posix.join(relDir, entry.name);
61
+ const resolved = node_path_1.default.resolve(root, relPath);
62
+ if (resolved !== baseResolved && !resolved.startsWith(baseResolved + node_path_1.default.sep))
63
+ continue;
64
+ if (entry.isDirectory()) {
65
+ dirs.push(relPath);
66
+ walkTree(root, relPath, baseResolved, files, dirs);
67
+ }
68
+ else if (entry.isFile()) {
69
+ files.push(relPath);
70
+ }
71
+ }
72
+ }
73
+ const migration = {
74
+ id: '2026-08-26-antigravity-retire-confighome-artifacts',
75
+ title: "Retire Antigravity's configHome skills/agents surfaces",
76
+ description: 'Remove manifest-managed skills/gsd-*/ and agents/gsd-*.md under the Antigravity configHome ' +
77
+ '(~/.gemini/antigravity{,-ide,-cli}) — a location Antigravity does not scan for global discovery — ' +
78
+ 'and retire the now-empty container directories, now that the global layout installs both kinds ' +
79
+ 'under the ~/.gemini/config home override (#3738). Global scope only; the local .agents workspace ' +
80
+ 'surface is untouched.',
81
+ introducedIn: '1.11.0',
82
+ runtimes: ['antigravity'],
83
+ scopes: ['global'],
84
+ destructive: true,
85
+ plan: (ctx) => {
86
+ // Defense in depth ahead of the framework's own runtimes/scope filters:
87
+ // a claude/kimi/etc. skills/ or agents/ directory is a live install
88
+ // surface, never a retirement target, and so is antigravity's LOCAL
89
+ // .agents/skills layout.
90
+ if (ctx.runtime !== 'antigravity')
91
+ return [];
92
+ if (ctx.scope !== 'global')
93
+ return [];
94
+ const actions = [];
95
+ for (const subpath of RETIRED_SUBPATHS) {
96
+ const surfaceRoot = node_path_1.default.join(ctx.configDir, subpath);
97
+ let rootLstat;
98
+ try {
99
+ rootLstat = node_fs_1.default.lstatSync(surfaceRoot);
100
+ }
101
+ catch {
102
+ continue; // absent -> nothing to retire for this surface, idempotent
103
+ }
104
+ // Never follow a symlinked surface root: walking through it could plan
105
+ // actions against paths outside the config directory entirely.
106
+ if (rootLstat.isSymbolicLink() || !rootLstat.isDirectory())
107
+ continue;
108
+ const baseResolved = node_path_1.default.resolve(ctx.configDir);
109
+ const files = [];
110
+ const dirs = [];
111
+ try {
112
+ const entries = node_fs_1.default.readdirSync(surfaceRoot, { withFileTypes: true });
113
+ for (const entry of entries) {
114
+ if (entry.isSymbolicLink() || !entry.name.startsWith(GSD_PREFIX))
115
+ continue;
116
+ const relPath = node_path_1.default.posix.join(subpath, entry.name);
117
+ if (entry.isDirectory()) {
118
+ dirs.push(relPath);
119
+ walkTree(ctx.configDir, relPath, baseResolved, files, dirs);
120
+ }
121
+ else if (entry.isFile()) {
122
+ files.push(relPath);
123
+ }
124
+ }
125
+ }
126
+ catch {
127
+ // Unreadable directory: nothing safe to plan for this surface.
128
+ continue;
129
+ }
130
+ for (const relPath of files) {
131
+ const { classification } = ctx.classifyArtifact(relPath);
132
+ if (classification === 'managed-pristine') {
133
+ actions.push({ type: 'remove-managed', relPath, reason: FILE_REASON, ownershipEvidence: FILE_OWNERSHIP_EVIDENCE });
134
+ }
135
+ else if (classification === 'managed-modified') {
136
+ actions.push({ type: 'backup-and-remove', relPath, reason: FILE_REASON, ownershipEvidence: FILE_OWNERSHIP_EVIDENCE });
137
+ }
138
+ // 'unknown' (user-added, not manifest-recorded): no action, preserved.
139
+ // 'missing' / 'managed-missing': impossible here — relPath was just
140
+ // discovered by walking the live filesystem, so it currently exists.
141
+ }
142
+ // Deepest directories first, so a child has already been evaluated
143
+ // (and possibly removed) before its parent's own emptiness is
144
+ // re-checked by the executor. The surface root itself is appended
145
+ // last, unconditionally: the executor's own emptiness re-check is what
146
+ // actually decides whether it goes, not this ordering.
147
+ const orderedDirs = [...dirs].sort((a, b) => b.split('/').length - a.split('/').length);
148
+ orderedDirs.push(subpath);
149
+ for (const relPath of orderedDirs) {
150
+ actions.push({
151
+ type: 'remove-empty-dir',
152
+ relPath,
153
+ reason: DIR_REASON,
154
+ ownershipEvidence: DIR_OWNERSHIP_EVIDENCE,
155
+ // Declared, not derived: classifyArtifact() hashes file contents
156
+ // via sha256File(), which throws EISDIR against a directory path.
157
+ // These relPaths name directories, so classification is stated
158
+ // directly (never 'unknown', so the planner's
159
+ // unknown-classification block never fires for them).
160
+ classification: 'managed-pristine',
161
+ originalHash: null,
162
+ currentHash: null,
163
+ });
164
+ }
165
+ }
166
+ return actions;
167
+ },
168
+ };
169
+ module.exports = migration;