@opengsd/gsd-core 1.14.0 → 1.15.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 (283) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/README.ja-JP.md +3 -3
  4. package/README.ko-KR.md +3 -3
  5. package/README.pt-BR.md +3 -3
  6. package/README.zh-CN.md +3 -3
  7. package/agents/gsd-code-fixer.compact.md +7 -6
  8. package/agents/gsd-code-fixer.md +9 -8
  9. package/agents/gsd-debug-session-manager.compact.md +17 -2
  10. package/agents/gsd-debug-session-manager.md +17 -2
  11. package/agents/gsd-debugger.md +2 -2
  12. package/agents/gsd-eval-auditor.compact.md +1 -1
  13. package/agents/gsd-eval-auditor.md +1 -1
  14. package/agents/gsd-executor.md +13 -8
  15. package/agents/gsd-intel-updater.compact.md +1 -1
  16. package/agents/gsd-intel-updater.md +1 -1
  17. package/agents/gsd-phase-researcher.md +19 -11
  18. package/agents/gsd-plan-checker.md +8 -7
  19. package/agents/gsd-planner.md +12 -8
  20. package/agents/gsd-project-researcher.compact.md +1 -1
  21. package/agents/gsd-project-researcher.md +1 -1
  22. package/agents/gsd-research-synthesizer.compact.md +1 -1
  23. package/agents/gsd-research-synthesizer.md +1 -1
  24. package/agents/gsd-ui-auditor.md +155 -17
  25. package/agents/gsd-ui-researcher.compact.md +1 -1
  26. package/agents/gsd-ui-researcher.md +1 -1
  27. package/agents/gsd-verifier.md +10 -9
  28. package/bin/install.js +642 -95
  29. package/commands/gsd/autonomous.md +2 -2
  30. package/commands/gsd/capture.md +1 -1
  31. package/commands/gsd/mempalace-capture.md +7 -3
  32. package/commands/gsd/plan-review-convergence.md +6 -6
  33. package/commands/gsd/progress.md +1 -1
  34. package/commands/gsd/quick-batch.md +1 -1
  35. package/commands/gsd/review.md +2 -3
  36. package/gsd-core/bin/gsd-tools.cjs +335 -22
  37. package/gsd-core/bin/lib/adr-parser.cjs +3 -1
  38. package/gsd-core/bin/lib/audit.cjs +81 -13
  39. package/gsd-core/bin/lib/capability-registry.cjs +82 -187
  40. package/gsd-core/bin/lib/capability-validator.cjs +0 -1
  41. package/gsd-core/bin/lib/check-command-router.cjs +101 -14
  42. package/gsd-core/bin/lib/codex-agent-toml.cjs +21 -25
  43. package/gsd-core/bin/lib/commands.cjs +175 -42
  44. package/gsd-core/bin/lib/config-loader.cjs +65 -4
  45. package/gsd-core/bin/lib/config.cjs +33 -7
  46. package/gsd-core/bin/lib/decisions.cjs +30 -14
  47. package/gsd-core/bin/lib/frontmatter.cjs +13 -0
  48. package/gsd-core/bin/lib/graphify.cjs +10 -2
  49. package/gsd-core/bin/lib/host-runtime-detection.cjs +9 -0
  50. package/gsd-core/bin/lib/init.cjs +207 -41
  51. package/gsd-core/bin/lib/install-engine.cjs +13 -0
  52. package/gsd-core/bin/lib/installer-migrations.cjs +8 -1
  53. package/gsd-core/bin/lib/milestone.cjs +18 -5
  54. package/gsd-core/bin/lib/model-resolver.cjs +159 -50
  55. package/gsd-core/bin/lib/phase-command-router.cjs +9 -1
  56. package/gsd-core/bin/lib/phase-id-card.cjs +32 -0
  57. package/gsd-core/bin/lib/phase-id-display.cjs +78 -0
  58. package/gsd-core/bin/lib/phase-id.cjs +109 -7
  59. package/gsd-core/bin/lib/phase-locator.cjs +29 -10
  60. package/gsd-core/bin/lib/phase.cjs +227 -26
  61. package/gsd-core/bin/lib/plan-document.cjs +49 -1
  62. package/gsd-core/bin/lib/planning-document.cjs +459 -0
  63. package/gsd-core/bin/lib/planning-inspect.cjs +18 -1
  64. package/gsd-core/bin/lib/planning-workspace.cjs +8 -3
  65. package/gsd-core/bin/lib/pr-branch-patterns.cjs +57 -0
  66. package/gsd-core/bin/lib/probe-core.cjs +7 -1
  67. package/gsd-core/bin/lib/project-root.cjs +41 -2
  68. package/gsd-core/bin/lib/review-lane-descriptor.cjs +10 -30
  69. package/gsd-core/bin/lib/review-reviewer-selection.cjs +2 -2
  70. package/gsd-core/bin/lib/roadmap-command-router.cjs +12 -4
  71. package/gsd-core/bin/lib/roadmap-parser.cjs +163 -3
  72. package/gsd-core/bin/lib/roadmap-upgrade.cjs +1539 -13
  73. package/gsd-core/bin/lib/roadmap.cjs +251 -31
  74. package/gsd-core/bin/lib/runtime-artifact-conversion.cjs +283 -31
  75. package/gsd-core/bin/lib/runtime-artifact-install-plan.cjs +3 -1
  76. package/gsd-core/bin/lib/runtime-homes.cjs +4 -0
  77. package/gsd-core/bin/lib/runtime-hooks-surface.cjs +215 -33
  78. package/gsd-core/bin/lib/runtime-name-policy.cjs +111 -1
  79. package/gsd-core/bin/lib/shell-command-projection.cjs +10 -6
  80. package/gsd-core/bin/lib/state-transition.cjs +39 -2
  81. package/gsd-core/bin/lib/state.cjs +42 -0
  82. package/gsd-core/bin/lib/surface.cjs +17 -1
  83. package/gsd-core/bin/lib/tdd-red-evidence.cjs +78 -5
  84. package/gsd-core/bin/lib/uat-predicate.cjs +47 -4
  85. package/gsd-core/bin/lib/uat.cjs +8 -0
  86. package/gsd-core/bin/lib/ui-consideration-probe.cjs +15 -2
  87. package/gsd-core/bin/lib/ui-frontend-evidence.cjs +100 -9
  88. package/gsd-core/bin/lib/undo-commit-selection.cjs +131 -0
  89. package/gsd-core/bin/lib/verification.cjs +268 -15
  90. package/gsd-core/bin/lib/verify-command-grounding.cjs +46 -2
  91. package/gsd-core/bin/lib/verify.cjs +132 -25
  92. package/gsd-core/bin/lib/worktree-base-ref.cjs +482 -73
  93. package/gsd-core/bin/lib/worktree-safety.cjs +784 -51
  94. package/gsd-core/bin/shared/config-defaults.manifest.json +3 -0
  95. package/gsd-core/bin/shared/config-schema.manifest.json +1 -0
  96. package/gsd-core/references/checkpoints.md +5 -3
  97. package/gsd-core/references/edge-probe-fixtures/01-round-half-even/expected-coverage.json +28 -3
  98. package/gsd-core/references/edge-probe-fixtures/02-merge-intervals/expected-coverage.json +37 -4
  99. package/gsd-core/references/edge-probe-fixtures/03-truncate-graphemes/expected-coverage.json +28 -3
  100. package/gsd-core/references/edge-probe-fixtures/04-money-rounding/expected-coverage.json +28 -3
  101. package/gsd-core/references/edge-probe-fixtures/05-list-dedupe/expected-coverage.json +37 -4
  102. package/gsd-core/references/edge-probe-fixtures/06-resolved-mixed/expected-coverage.json +37 -4
  103. package/gsd-core/references/edge-probe.md +195 -21
  104. package/gsd-core/references/execute-phase-between-wave-reset.md +7 -6
  105. package/gsd-core/references/execute-phase-wave-guard.md +22 -11
  106. package/gsd-core/references/gsd-run-resolver.md +1 -1
  107. package/gsd-core/references/model-profiles.md +1 -1
  108. package/gsd-core/references/phase-argument-parsing.md +9 -7
  109. package/gsd-core/references/phase-id-convention.md +28 -0
  110. package/gsd-core/references/planner-gap-closure.md +2 -0
  111. package/gsd-core/references/planner-load-graph-context.md +24 -13
  112. package/gsd-core/references/planner-verify-command-grounding.md +14 -0
  113. package/gsd-core/references/planning-config.md +11 -2
  114. package/gsd-core/references/tdd.md +27 -4
  115. package/gsd-core/references/ui-consideration-probe.md +10 -5
  116. package/gsd-core/references/verify-command-path-resolvability.md +10 -2
  117. package/gsd-core/references/worktree-path-safety.md +321 -0
  118. package/gsd-core/templates/verification-report.md +1 -1
  119. package/gsd-core/workflows/_runtime-launcher.snippet.sh +1 -1
  120. package/gsd-core/workflows/add-backlog.md +1 -1
  121. package/gsd-core/workflows/add-phase.md +1 -1
  122. package/gsd-core/workflows/add-tests.md +2 -2
  123. package/gsd-core/workflows/add-todo.md +3 -3
  124. package/gsd-core/workflows/ai-integration-phase.md +11 -3
  125. package/gsd-core/workflows/audit-fix.md +1 -1
  126. package/gsd-core/workflows/audit-milestone.md +1 -1
  127. package/gsd-core/workflows/audit-uat.md +1 -1
  128. package/gsd-core/workflows/autonomous/steps/converge-fail-fast.md +9 -18
  129. package/gsd-core/workflows/autonomous.md +16 -6
  130. package/gsd-core/workflows/check-todos.md +2 -2
  131. package/gsd-core/workflows/cleanup.md +2 -2
  132. package/gsd-core/workflows/code-review/steps/dispatch-fix.md +4 -3
  133. package/gsd-core/workflows/code-review/steps/structural-pre-pass.md +1 -1
  134. package/gsd-core/workflows/code-review-fix.md +108 -22
  135. package/gsd-core/workflows/code-review.md +63 -46
  136. package/gsd-core/workflows/complete-milestone/detail/elaboration.md +1 -1
  137. package/gsd-core/workflows/complete-milestone.md +2 -2
  138. package/gsd-core/workflows/debug.md +3 -3
  139. package/gsd-core/workflows/diagnose-issues.md +1 -1
  140. package/gsd-core/workflows/discuss-phase/modes/advisor.md +1 -1
  141. package/gsd-core/workflows/discuss-phase/modes/chain.md +1 -1
  142. package/gsd-core/workflows/discuss-phase-assumptions.md +1 -1
  143. package/gsd-core/workflows/discuss-phase.md +1 -1
  144. package/gsd-core/workflows/do.md +2 -2
  145. package/gsd-core/workflows/docs-update.md +3 -3
  146. package/gsd-core/workflows/edit-phase.md +1 -1
  147. package/gsd-core/workflows/eval-review.md +10 -3
  148. package/gsd-core/workflows/execute-phase/detail/elaboration.md +2 -2
  149. package/gsd-core/workflows/execute-phase/steps/code-review-disposition.md +1017 -0
  150. package/gsd-core/workflows/execute-phase/steps/codebase-drift-gate.md +1 -1
  151. package/gsd-core/workflows/execute-phase/steps/completion-reconciliation.md +3 -3
  152. package/gsd-core/workflows/execute-phase/steps/executor-isolation-dispatch.md +37 -3
  153. package/gsd-core/workflows/execute-phase/steps/gap-closure-artifacts.md +1 -1
  154. package/gsd-core/workflows/execute-phase/steps/partial-wave.md +1 -1
  155. package/gsd-core/workflows/execute-phase/steps/per-plan-executor-routing.md +1 -1
  156. package/gsd-core/workflows/execute-phase/steps/per-plan-worktree-gate.md +1 -1
  157. package/gsd-core/workflows/execute-phase/steps/post-merge-gate.md +46 -9
  158. package/gsd-core/workflows/execute-phase/steps/protected-branch.md +1 -1
  159. package/gsd-core/workflows/execute-phase/steps/ready-wave-gate.md +37 -0
  160. package/gsd-core/workflows/execute-phase/steps/regression-gate-run.md +1 -1
  161. package/gsd-core/workflows/execute-phase/steps/stale-reverification.md +24 -0
  162. package/gsd-core/workflows/execute-phase/steps/tdd-applicability-resolution.md +1 -1
  163. package/gsd-core/workflows/execute-phase/steps/threat-id-gate.md +28 -0
  164. package/gsd-core/workflows/execute-phase/steps/wave-post-gate-hooks.md +1 -1
  165. package/gsd-core/workflows/execute-phase/steps/worktree-base-check.md +25 -0
  166. package/gsd-core/workflows/execute-phase.md +36 -26
  167. package/gsd-core/workflows/execute-plan.md +5 -4
  168. package/gsd-core/workflows/explore.md +3 -3
  169. package/gsd-core/workflows/extract-learnings.md +2 -1
  170. package/gsd-core/workflows/fast.md +1 -1
  171. package/gsd-core/workflows/forensics.md +1 -1
  172. package/gsd-core/workflows/graduation.md +1 -1
  173. package/gsd-core/workflows/health.md +2 -2
  174. package/gsd-core/workflows/help/modes/full.compact.md +3 -3
  175. package/gsd-core/workflows/help/modes/full.md +5 -5
  176. package/gsd-core/workflows/help/modes/topic.md +15 -5
  177. package/gsd-core/workflows/import.md +2 -2
  178. package/gsd-core/workflows/inbox.md +2 -2
  179. package/gsd-core/workflows/ingest-docs.md +3 -3
  180. package/gsd-core/workflows/insert-phase.md +1 -1
  181. package/gsd-core/workflows/list-seeds.md +1 -1
  182. package/gsd-core/workflows/list-workspaces.md +1 -1
  183. package/gsd-core/workflows/manager.md +2 -2
  184. package/gsd-core/workflows/map-codebase.md +2 -2
  185. package/gsd-core/workflows/milestone-summary.md +1 -1
  186. package/gsd-core/workflows/mvp-phase.md +1 -1
  187. package/gsd-core/workflows/new-milestone.md +2 -2
  188. package/gsd-core/workflows/new-project/steps/auto-mode-config.md +3 -3
  189. package/gsd-core/workflows/new-project/steps/codebase-map-offer.md +1 -1
  190. package/gsd-core/workflows/new-project.md +7 -7
  191. package/gsd-core/workflows/new-workspace.md +2 -2
  192. package/gsd-core/workflows/next.md +1 -1
  193. package/gsd-core/workflows/note.md +1 -1
  194. package/gsd-core/workflows/onboard.md +1 -1
  195. package/gsd-core/workflows/pause-work.md +1 -1
  196. package/gsd-core/workflows/plan-phase/detail/elaboration.md +1 -1
  197. package/gsd-core/workflows/plan-phase/steps/chunked-planning-mode.md +17 -5
  198. package/gsd-core/workflows/plan-phase/steps/prd-express-path.md +1 -1
  199. package/gsd-core/workflows/plan-phase/steps/stall-detection-helpers.md +23 -5
  200. package/gsd-core/workflows/plan-phase.md +24 -7
  201. package/gsd-core/workflows/plan-review-convergence.md +21 -5
  202. package/gsd-core/workflows/plant-seed.md +62 -20
  203. package/gsd-core/workflows/pr-branch.md +113 -13
  204. package/gsd-core/workflows/profile-user.md +2 -2
  205. package/gsd-core/workflows/progress.md +1 -1
  206. package/gsd-core/workflows/quick/steps/plan-checker-loop.md +25 -0
  207. package/gsd-core/workflows/quick/steps/quick-verification.md +1 -1
  208. package/gsd-core/workflows/quick/steps/worktree-pre-dispatch-commit.md +1 -1
  209. package/gsd-core/workflows/quick-batch/steps/batch-init.md +1 -1
  210. package/gsd-core/workflows/quick-batch/steps/completion.md +1 -1
  211. package/gsd-core/workflows/quick-batch/steps/merge-wave.md +1 -1
  212. package/gsd-core/workflows/quick-batch/steps/planner-wave.md +1 -1
  213. package/gsd-core/workflows/quick-batch/steps/research-phase.md +1 -1
  214. package/gsd-core/workflows/quick-batch/steps/resume-mode.md +1 -1
  215. package/gsd-core/workflows/quick-batch/steps/verification-wave.md +1 -1
  216. package/gsd-core/workflows/quick-batch/steps/worktree-dispatch.md +1 -1
  217. package/gsd-core/workflows/quick-batch.md +1 -1
  218. package/gsd-core/workflows/quick.md +21 -9
  219. package/gsd-core/workflows/reapply-patches.md +9 -3
  220. package/gsd-core/workflows/remove-phase.md +1 -1
  221. package/gsd-core/workflows/remove-workspace.md +2 -2
  222. package/gsd-core/workflows/resume-project.md +1 -1
  223. package/gsd-core/workflows/review.md +31 -16
  224. package/gsd-core/workflows/scan.md +1 -1
  225. package/gsd-core/workflows/secure-phase.md +3 -2
  226. package/gsd-core/workflows/settings-advanced.md +30 -10
  227. package/gsd-core/workflows/settings-integrations.md +2 -3
  228. package/gsd-core/workflows/settings.md +4 -4
  229. package/gsd-core/workflows/ship.md +3 -2
  230. package/gsd-core/workflows/sketch-wrap-up.md +1 -1
  231. package/gsd-core/workflows/sketch.md +1 -1
  232. package/gsd-core/workflows/smart-entry.md +2 -2
  233. package/gsd-core/workflows/spec-phase.md +15 -5
  234. package/gsd-core/workflows/spike-wrap-up.md +1 -1
  235. package/gsd-core/workflows/spike.md +1 -1
  236. package/gsd-core/workflows/stats.md +1 -1
  237. package/gsd-core/workflows/sync-skills.md +5 -5
  238. package/gsd-core/workflows/thread.md +1 -1
  239. package/gsd-core/workflows/transition.md +1 -1
  240. package/gsd-core/workflows/ui-phase.md +44 -8
  241. package/gsd-core/workflows/ui-review.md +18 -4
  242. package/gsd-core/workflows/ultraplan-phase.md +1 -1
  243. package/gsd-core/workflows/undo.md +339 -20
  244. package/gsd-core/workflows/update.md +7 -7
  245. package/gsd-core/workflows/validate-phase.md +3 -2
  246. package/gsd-core/workflows/verify-work/steps/automated-ui-verification.md +1 -1
  247. package/gsd-core/workflows/verify-work/steps/mvp-uat-framing.md +1 -1
  248. package/gsd-core/workflows/verify-work.md +81 -16
  249. package/hooks/dist/gsd-agent-isolation-guard.js +24 -0
  250. package/hooks/dist/gsd-secret-read-guard.js +27 -1
  251. package/hooks/dist/gsd-statusline.js +70 -13
  252. package/hooks/dist/gsd-validate-commit.sh +63 -4
  253. package/hooks/gsd-agent-isolation-guard.js +24 -0
  254. package/hooks/gsd-secret-read-guard.js +27 -1
  255. package/hooks/gsd-statusline.js +70 -13
  256. package/hooks/gsd-validate-commit.sh +63 -4
  257. package/package.json +3 -2
  258. package/scripts/build-hooks.js +15 -6
  259. package/scripts/check-contract-drift.cjs +127 -11
  260. package/scripts/command-contract-helpers.cjs +3 -0
  261. package/scripts/docs-guard-registry.cjs +28 -0
  262. package/scripts/gen-loop-host-contract.cjs +69 -0
  263. package/scripts/lib/macos-conformance-tier.generated.cjs +14 -0
  264. package/scripts/lib/ndjson-reporter.cjs +3 -2
  265. package/scripts/lib/platform-conformance-tier.generated.cjs +11 -0
  266. package/scripts/lint-docs-guard-registration.exempt-baseline.cjs +28 -1
  267. package/scripts/lint-phase-arg-assignment.cjs +257 -0
  268. package/scripts/lint-phase-id-drift.cjs +290 -5
  269. package/scripts/lint-pr-branch-pattern-drift.cjs +148 -0
  270. package/scripts/lint-retired-runtime-name.cjs +619 -0
  271. package/scripts/lint-state-write-path-drift.cjs +93 -0
  272. package/scripts/lint-test-file-count.allowlist.json +28 -9
  273. package/scripts/lint-workflow-shellcheck-baseline.json +15 -0
  274. package/scripts/prompt-injection-scan.sh +4 -0
  275. package/scripts/release-tarball-smoke.cjs +194 -1
  276. package/skills/gsd-autonomous/SKILL.md +2 -2
  277. package/skills/gsd-capture/SKILL.md +1 -1
  278. package/skills/gsd-mempalace-capture/SKILL.md +7 -3
  279. package/skills/gsd-plan-review-convergence/SKILL.md +5 -5
  280. package/skills/gsd-progress/SKILL.md +1 -1
  281. package/skills/gsd-quick-batch/SKILL.md +1 -1
  282. package/skills/gsd-review/SKILL.md +2 -3
  283. package/vscode/package.json +1 -1
@@ -457,7 +457,10 @@ function convertClaudeCommandToClaudeSkill(content, skillName, runtime = null, c
457
457
  // calls fall back to reading the list.
458
458
  const names = cmdNames || readGsdCommandNames();
459
459
  const normalizedBody = transformContentToHyphen(body, names);
460
- const description = extractFrontmatterField(frontmatter, 'description') || '';
460
+ // #4324: the description is the text the host's skill picker renders, so it
461
+ // needs the same hyphen normalisation the body gets — otherwise a `/gsd:<cmd>`
462
+ // mention in a command description ships the retired colon form to the user.
463
+ const description = transformContentToHyphen(extractFrontmatterField(frontmatter, 'description') || '', names);
461
464
  const argumentHint = extractFrontmatterField(frontmatter, 'argument-hint');
462
465
  const agent = extractFrontmatterField(frontmatter, 'agent');
463
466
  // #769: preserve context: from source command files so it is emitted into
@@ -1670,6 +1673,8 @@ function convertClaudeCommandToClineSkill(content, skillName, _runtime = null, c
1670
1673
  if (!description)
1671
1674
  description = `Run GSD workflow ${skillName}.`;
1672
1675
  description = toSingleLine(description);
1676
+ // #4324: same reason as the Claude skill converter above.
1677
+ description = transformContentToHyphen(description, names);
1673
1678
  // Cline documented max is 1024 code points (not UTF-16 code units).
1674
1679
  // Use Array.from to iterate by code point so that multibyte characters
1675
1680
  // (e.g. emoji, astral-plane chars) are never split, which would produce
@@ -1818,6 +1823,22 @@ Typed mapping (agent_type-capable schema only):
1818
1823
  never fabricate a manual worktree protocol — route through the negotiated
1819
1824
  isolation adapter, which still fails closed for hosts declaring \`none\` (#3360).
1820
1825
 
1826
+ Foreground handoffs:
1827
+ - spawn_agent is asynchronous. When the source Agent(...) or Task(...) declares
1828
+ run_in_background=false, call collaboration.wait_agent(timeout_ms=...) immediately after
1829
+ spawn and keep the parent turn active until that child returns a terminal result.
1830
+ - collaboration.wait_agent is a mailbox wakeup, NOT a completion oracle: "Wait completed"
1831
+ can mean only that a child sent an interim MESSAGE or status update. After every wakeup,
1832
+ inspect the named child's update/status. Only a FINAL_ANSWER or a terminal agent status
1833
+ (completed, failed, or cancelled) ends the foreground handoff.
1834
+ - On an interim MESSAGE or any non-terminal status, do not report an outcome, send a
1835
+ continuation, start parent work, or end the parent turn. Call collaboration.wait_agent
1836
+ again for the same child. If a terminal response is absent after an abnormal end, reconcile
1837
+ the workflow's durable artifacts before classifying the child.
1838
+ - This applies to one foreground child as well as fan-out. The child retains its workflow's
1839
+ own checkpoint loop; do not report an outcome or start any further parent work before its
1840
+ terminal result is available.
1841
+
1821
1842
  Generic-agent workaround (multi_agent_v1 schema — NO agent_type field):
1822
1843
  When only the generic \`multi_agent_v1\` schema is available, typed GSD agent dispatch
1823
1844
  (\`gsd-planner\`, \`gsd-executor\`, etc.) is NOT possible. This is a known Codex limitation
@@ -1845,6 +1866,9 @@ Spawn restriction:
1845
1866
  defaulting to inline execution.
1846
1867
 
1847
1868
  Parallel fan-out:
1869
+ - For each child, loop on collaboration.wait_agent(timeout_ms=...) until its own terminal
1870
+ result is observed. A mailbox update from one child never completes another child, and an
1871
+ interim MESSAGE never completes its sender.
1848
1872
  - Spawn multiple agents → collect agent IDs → \`collaboration.wait_agent(timeout_ms=...)\` for each to complete
1849
1873
  - Do NOT use \`functions.wait(cell_id=...)\` — that is an unrelated exec-cell tool, not the collaboration wait
1850
1874
 
@@ -2273,38 +2297,45 @@ const claudeToCopilotTools = {
2273
2297
  AskUserQuestion: 'ask_user',
2274
2298
  SlashCommand: 'skill',
2275
2299
  };
2276
- // Tool name mapping from Claude Code to Gemini CLI
2277
- // Gemini CLI uses snake_case built-in tool names
2278
- const claudeToGeminiTools = {
2279
- Read: 'read_file',
2300
+ // Tool name mapping from Claude Code to Antigravity
2301
+ // Antigravity uses Gemini's snake_case built-in tool names
2302
+ // #4705: values are Antigravity-NATIVE tool names per the documented subagent
2303
+ // contract (antigravity.google/docs/subagents: view_file, replace_file_content,
2304
+ // grep_search, run_command are the documented examples; the catalog is
2305
+ // non-exhaustive, so unmapped entries keep their best-known grant rather than
2306
+ // being dropped — dropping would silently remove a restriction). The old
2307
+ // values were Gemini CLI dialect names, which Antigravity's tool validation
2308
+ // does not document and may hang the subagent on.
2309
+ const claudeToAntigravityTools = {
2310
+ Read: 'view_file',
2280
2311
  Write: 'write_file',
2281
- Edit: 'replace',
2282
- Bash: 'run_shell_command',
2312
+ Edit: 'replace_file_content',
2313
+ Bash: 'run_command',
2283
2314
  Glob: 'glob',
2284
- Grep: 'search_file_content',
2315
+ Grep: 'grep_search',
2285
2316
  WebSearch: 'google_web_search',
2286
2317
  WebFetch: 'web_fetch',
2287
2318
  TodoWrite: 'write_todos',
2288
2319
  };
2289
2320
  /**
2290
- * Convert a Claude Code tool name to Gemini CLI format
2291
- * - Applies Claude→Gemini mapping (Read→read_file, Bash→run_shell_command, etc.)
2292
- * - Filters out MCP tools (mcp__*) — they are auto-discovered at runtime in Gemini
2293
- * - Filters out Task/Agent — agents are auto-registered as tools in Gemini
2294
- * @returns {string|null} Gemini tool name, or null if tool should be excluded
2321
+ * Convert a Claude Code tool name to Antigravity format
2322
+ * - Applies Claude→Antigravity mapping (Read→read_file, Bash→run_shell_command, etc.)
2323
+ * - Filters out MCP tools (mcp__*) — they are auto-discovered at runtime in Antigravity
2324
+ * - Filters out Task/Agent — agents are auto-registered as tools in Antigravity
2325
+ * @returns {string|null} Antigravity tool name, or null if tool should be excluded
2295
2326
  */
2296
- function convertGeminiToolName(claudeTool) {
2327
+ function convertAntigravityToolName(claudeTool) {
2297
2328
  // MCP tools: exclude — auto-discovered from mcpServers config at runtime
2298
2329
  if (claudeTool.startsWith('mcp__')) {
2299
2330
  return null;
2300
2331
  }
2301
2332
  // Task/Agent: exclude — agents are auto-registered as callable tools.
2302
- // AskUserQuestion: exclude — Gemini CLI does not expose an ask_user tool;
2303
- // emitting it causes frontmatter validation errors (#3362).
2304
- // Skill/SlashCommand: exclude — Gemini CLI has no 'skill' built-in tool;
2305
- // the lowercase fallback would emit an invalid 'skill'/'slashcommand' name
2306
- // that fails frontmatter validation (tools.N: Invalid tool name) and aborts
2307
- // the entire agent load (#1394).
2333
+ // AskUserQuestion: exclude — Antigravity (Gemini tool dialect) does not expose
2334
+ // an ask_user tool; emitting it causes frontmatter validation errors (#3362).
2335
+ // Skill/SlashCommand: exclude — Antigravity (Gemini tool dialect) has no 'skill'
2336
+ // built-in tool; the lowercase fallback would emit an invalid
2337
+ // 'skill'/'slashcommand' name that fails frontmatter validation
2338
+ // (tools.N: Invalid tool name) and aborts the entire agent load (#1394).
2308
2339
  if (claudeTool === 'Task' ||
2309
2340
  claudeTool === 'Agent' ||
2310
2341
  claudeTool === 'AskUserQuestion' ||
@@ -2314,8 +2345,8 @@ function convertGeminiToolName(claudeTool) {
2314
2345
  return null;
2315
2346
  }
2316
2347
  // Check for explicit mapping
2317
- if (claudeToGeminiTools[claudeTool]) {
2318
- return claudeToGeminiTools[claudeTool];
2348
+ if (claudeToAntigravityTools[claudeTool]) {
2349
+ return claudeToAntigravityTools[claudeTool];
2319
2350
  }
2320
2351
  // Default: lowercase
2321
2352
  return claudeTool.toLowerCase();
@@ -2371,7 +2402,7 @@ function convertClaudeAgentToCopilotAgent(content, isGlobal = false) {
2371
2402
  }
2372
2403
  /**
2373
2404
  * Convert a Claude agent (.md) to an Antigravity agent.
2374
- * Uses Gemini tool names since Antigravity runs on Gemini 3 backend.
2405
+ * Uses Antigravity's Gemini tool dialect since Antigravity runs on Gemini 3 backend.
2375
2406
  */
2376
2407
  function convertClaudeAgentToAntigravityAgent(content, isGlobal = false) {
2377
2408
  const converted = convertClaudeToAntigravityContent(content, isGlobal);
@@ -2382,11 +2413,17 @@ function convertClaudeAgentToAntigravityAgent(content, isGlobal = false) {
2382
2413
  const description = extractFrontmatterField(frontmatter, 'description') || '';
2383
2414
  const color = extractFrontmatterField(frontmatter, 'color');
2384
2415
  const toolsRaw = extractFrontmatterField(frontmatter, 'tools') || '';
2385
- // Map tools to Gemini equivalents (reuse existing convertGeminiToolName)
2416
+ // Map tools to Antigravity equivalents (reuse existing convertAntigravityToolName)
2386
2417
  const claudeTools = toolsRaw.split(',').map(t => t.trim()).filter(Boolean);
2387
- const mappedTools = claudeTools.map(t => convertGeminiToolName(t)).filter(Boolean);
2418
+ const mappedTools = claudeTools.map(t => convertAntigravityToolName(t)).filter(Boolean);
2388
2419
  // #2876: quote description for the same reason as the skill variant.
2389
- let fm = `---\nname: ${name}\ndescription: ${yamlQuote(description)}\ntools: ${mappedTools.join(', ')}\n`;
2420
+ // #4705: tools is a YAML SEQUENCE of native names (one `- name` item per
2421
+ // line), not a comma-separated scalar. Empty mapped set -> `tools: []` so an
2422
+ // agent whose every tool was filtered stays explicitly restricted.
2423
+ const toolsBlock = mappedTools.length > 0
2424
+ ? `tools:\n${mappedTools.map((t) => `- ${t}`).join('\n')}\n`
2425
+ : 'tools: []\n';
2426
+ let fm = `---\nname: ${name}\ndescription: ${yamlQuote(description)}\n${toolsBlock}`;
2390
2427
  if (color)
2391
2428
  fm += `color: ${color}\n`;
2392
2429
  fm += '---';
@@ -2769,15 +2806,53 @@ function convertClaudeCommandToKiloSkill(content, skillName) {
2769
2806
  // Relocated from bin/install.js (#1511). Behavior is byte-for-behavior identical
2770
2807
  // to the originals; the only change is the injected `attribution` 5th param in
2771
2808
  // _applyRuntimeRewrites (replacing the internal getCommitAttribution() call).
2809
+ /**
2810
+ * #4377: is the project-relative include style opted in?
2811
+ *
2812
+ * Dual-sourced exactly like `--portable-hooks`/`GSD_PORTABLE_HOOKS`:
2813
+ * `bin/install.js` sets the variable when the flag is passed, so the flag and
2814
+ * the environment cannot disagree, and every seam that computes a path prefix
2815
+ * (the installer copy path, the install engine, the two rewrite entry points,
2816
+ * the install plan, and `applySurface`) reads the same answer without six signatures having to
2817
+ * grow a parameter each and stay in sync.
2818
+ *
2819
+ * Opt-in, not the new default. Making relative the default would change every
2820
+ * existing single-checkout local install — which works today — to fix a
2821
+ * multi-worktree case those users do not have.
2822
+ *
2823
+ * @param env - Environment to read (injectable for tests).
2824
+ * @returns Whether local installs should emit project-relative includes.
2825
+ */
2826
+ function relativeIncludesEnabled(env = process.env) {
2827
+ return env.GSD_RELATIVE_INCLUDES === '1';
2828
+ }
2772
2829
  /**
2773
2830
  * Compute the path prefix for a runtime install.
2774
2831
  * Global installs under $HOME use $HOME/... form; others use the resolved target.
2775
2832
  * isOpencode excludes OpenCode (uses ~/.config/opencode which breaks $HOME shorthand).
2776
2833
  * isWindowsHost is not used today but reserved for future Windows-specific logic.
2777
2834
  *
2835
+ * #4377: a LOCAL install can instead emit a project-relative prefix, so a repo
2836
+ * worked from several git worktrees does not get every worktree's `@` includes
2837
+ * baked to whichever checkout happened to run the installer. Absolute is still
2838
+ * the default; `projectRelative` opts in.
2839
+ *
2840
+ * `localDirName` is the runtime's own `localConfigDir` descriptor value
2841
+ * (via `getDirName`), never a hardcoded literal — the same value the rewrite
2842
+ * engine already uses for its `./.claude/` -> `./<dir>/` substitutions, and
2843
+ * exactly what `resolveScope` joins onto the cwd to produce `resolvedTarget`
2844
+ * for a local install. Copilot and Antigravity have shipped this shape for
2845
+ * local installs since they were added, with hardcoded `.github/` and
2846
+ * `.agents/`; this is the same behavior, derived instead of written down.
2847
+ *
2848
+ * Fails safe to the absolute prefix: no opt-in, a global install, a missing
2849
+ * dir name, or the `configHome.kind === 'none'` sentinel all fall through. A
2850
+ * wrong-but-absolute include still resolves to a real file; a wrong relative
2851
+ * one silently resolves against whatever the reader's cwd happens to be.
2852
+ *
2778
2853
  * @private — exported as `_computePathPrefix` for tests.
2779
2854
  */
2780
- function computePathPrefix({ isGlobal, isOpencode, isWindowsHost: _isWindowsHost, resolvedTarget, homeDir }) {
2855
+ function computePathPrefix({ isGlobal, isOpencode, isWindowsHost: _isWindowsHost, resolvedTarget, homeDir, projectRelative = relativeIncludesEnabled(), localDirName, projectRoot = process.cwd(), projectRelativePath, }) {
2781
2856
  // #1615: normalize Windows backslashes to forward slashes. This prefix is
2782
2857
  // substituted into markdown @-references (e.g. Windsurf workflow files),
2783
2858
  // which use POSIX paths universally. Idempotent on POSIX (no backslashes).
@@ -2789,8 +2864,62 @@ function computePathPrefix({ isGlobal, isOpencode, isWindowsHost: _isWindowsHost
2789
2864
  if (isGlobal && posixTarget.startsWith(posixHome) && !isOpencode) {
2790
2865
  return '$HOME' + posixTarget.slice(posixHome.length) + '/';
2791
2866
  }
2867
+ if (!isGlobal && projectRelative) {
2868
+ // An explicit local config dir need not be the descriptor's conventional
2869
+ // `.claude`-style directory. Derive from the resolved target first; only
2870
+ // use the descriptor as the legacy fallback when no project root exists.
2871
+ const relative = projectRelativePrefix(projectRelativePath)
2872
+ || projectRelativePrefixFromProjectRoot(projectRoot, resolvedTarget)
2873
+ || projectRelativePrefix(localDirName);
2874
+ if (relative)
2875
+ return relative;
2876
+ }
2792
2877
  return `${posixTarget}/`;
2793
2878
  }
2879
+ /** Return a safe project-relative prefix for a resolved install target. */
2880
+ function projectRelativePrefixFromProjectRoot(projectRoot, resolvedTarget) {
2881
+ if (typeof projectRoot !== 'string' || typeof resolvedTarget !== 'string')
2882
+ return '';
2883
+ const relative = (0, shell_command_projection_cjs_1.posixNormalize)(node_path_1.default.relative(projectRoot, resolvedTarget));
2884
+ if (!relative || relative === '.' || relative === '..' || relative.startsWith('../') || node_path_1.default.isAbsolute(relative))
2885
+ return '';
2886
+ return projectRelativePrefix(relative);
2887
+ }
2888
+ /**
2889
+ * A runtime installed directly at the project root cannot use its descriptor
2890
+ * directory in a project-relative include: that directory was never created.
2891
+ */
2892
+ function localIncludeDirName(runtime) {
2893
+ return _hostBehaviors(runtime).localTargetIsProjectRoot === true ? undefined : getDirName(runtime);
2894
+ }
2895
+ /**
2896
+ * #4377: the project-relative prefix for a local install, or `''` when the
2897
+ * runtime cannot express one and the caller must fall back to absolute.
2898
+ *
2899
+ * Rejects the `configHome.kind === 'none'` sentinel (a runtime with no local
2900
+ * config dir at all — interpolating it would produce a literal
2901
+ * `(no-local-config-dir)/` path segment), anything absolute, and anything that
2902
+ * climbs out of the project with `..`. Trailing slashes are normalized so a
2903
+ * descriptor value written either way yields one prefix.
2904
+ *
2905
+ * @param localDirName - The runtime's `localConfigDir` descriptor value.
2906
+ * @returns A `dir/` prefix, or `''` to signal "use the absolute form".
2907
+ */
2908
+ function projectRelativePrefix(localDirName) {
2909
+ if (typeof localDirName !== 'string' || localDirName.length === 0)
2910
+ return '';
2911
+ if (localDirName === runtimeNamePolicy.NO_LOCAL_CONFIG_DIR_SENTINEL)
2912
+ return '';
2913
+ const normalized = (0, shell_command_projection_cjs_1.posixNormalize)(localDirName).replace(/\/+$/, '');
2914
+ if (!normalized || normalized.startsWith('/') || /^[A-Za-z]:/.test(normalized))
2915
+ return '';
2916
+ // Reject a climb in ANY segment, not only at the beginning. posixNormalize
2917
+ // deliberately normalizes separators rather than resolving path segments,
2918
+ // so `nested/../../outside` must be caught explicitly here.
2919
+ if (normalized.split('/').includes('..'))
2920
+ return '';
2921
+ return `${normalized}/`;
2922
+ }
2794
2923
  /**
2795
2924
  * Canonical list of every non-Claude runtime that gsd-core emits artifacts for.
2796
2925
  * DERIVED from the capability registry (ADR-1239 Phase B, #1679) — the registry's
@@ -2957,7 +3086,108 @@ function restoreClaudeGlobalAtRefTilde(content, pathPrefix) {
2957
3086
  *
2958
3087
  * @private — exported as `_applyRuntimeRewrites` for tests.
2959
3088
  */
3089
+ /**
3090
+ * #4377: is this prefix a project-relative one?
3091
+ *
3092
+ * Anything not rooted -- no leading `/`, no `$HOME`, no `~`, no drive letter.
3093
+ * Used only to decide whether the shell-default guard below needs to run, so
3094
+ * an absolute install is byte-for-byte untouched by any of this.
3095
+ *
3096
+ * @param pathPrefix - The computed prefix.
3097
+ * @returns Whether it resolves relative to something.
3098
+ */
3099
+ function isRelativePathPrefix(pathPrefix) {
3100
+ if (typeof pathPrefix !== 'string' || pathPrefix.length === 0)
3101
+ return false;
3102
+ return !(pathPrefix.startsWith('/')
3103
+ || pathPrefix.startsWith('$HOME')
3104
+ || pathPrefix.startsWith('~')
3105
+ || /^[A-Za-z]:/.test(pathPrefix));
3106
+ }
3107
+ /**
3108
+ * #4377: shield `${VAR:-default}` shell defaults from a RELATIVE path prefix.
3109
+ *
3110
+ * The runtime launcher snippet probes for gsd-tools through a chain of shell
3111
+ * defaults -- `${CLAUDE_CONFIG_DIR:-$HOME/.claude}/gsd-core/bin/...`, one per
3112
+ * runtime. Those are shell word expansions, not markdown `@` includes, and
3113
+ * they are the one place where substituting a project-relative prefix makes
3114
+ * things WORSE rather than better: `$HOME/.claude` resolves the same from
3115
+ * anywhere, while a bare `.claude` resolves against whatever directory the
3116
+ * shell happens to be sitting in. Trading an include that points at the wrong
3117
+ * checkout for a path that points at nothing is not a fix.
3118
+ *
3119
+ * The issue asked for project-relative INCLUDES, and this keeps the change to
3120
+ * exactly that. The launcher already handles the multi-worktree case on its
3121
+ * own, and better -- it probes `$(git rev-parse --show-toplevel)/.claude/...`
3122
+ * first, so it finds the current worktree's copy long before it reaches these
3123
+ * defaults.
3124
+ *
3125
+ * The mask token is `@@GSD4377:<n>@@`. It has to survive every substitution in
3126
+ * the rewrite body untouched, so it deliberately contains no `.claude`, no
3127
+ * `~`, no `$HOME` and no path separator -- there is nothing in it for those
3128
+ * regexes to match. A collision would need that literal to already exist in
3129
+ * the shipped corpus, which is asserted against in the tests.
3130
+ *
3131
+ * Only runs when the prefix is relative, so an absolute install never sees
3132
+ * this transformation at all.
3133
+ *
3134
+ * @param content - The body being rewritten.
3135
+ * @param rewrite - The substitution pass to run on the unguarded remainder.
3136
+ * @returns The rewritten body, with every shell default restored verbatim.
3137
+ */
3138
+ function withShellDefaultsPreserved(content, rewrite) {
3139
+ const preserved = [];
3140
+ let masked = '';
3141
+ let copiedThrough = 0;
3142
+ let searchFrom = 0;
3143
+ // Scan balanced `${...}` expansions instead of stopping at the first `}`.
3144
+ // The launcher has nested defaults such as `${A:-${B:-$HOME/.x}}`; a
3145
+ // single `[^}]*` regex only recognizes a prefix of that expression and
3146
+ // makes preservation depend accidentally on where the rewritten text sits.
3147
+ while (searchFrom < content.length) {
3148
+ const start = content.indexOf('${', searchFrom);
3149
+ if (start === -1)
3150
+ break;
3151
+ const opener = /^\$\{[A-Za-z_][A-Za-z0-9_]*:-/.exec(content.slice(start));
3152
+ if (!opener) {
3153
+ searchFrom = start + 2;
3154
+ continue;
3155
+ }
3156
+ let depth = 1;
3157
+ let end = start + opener[0].length;
3158
+ while (end < content.length && depth > 0) {
3159
+ if (content.startsWith('${', end)) {
3160
+ depth += 1;
3161
+ end += 2;
3162
+ continue;
3163
+ }
3164
+ if (content[end] === '}')
3165
+ depth -= 1;
3166
+ end += 1;
3167
+ }
3168
+ if (depth !== 0) {
3169
+ searchFrom = start + 2;
3170
+ continue;
3171
+ }
3172
+ masked += content.slice(copiedThrough, start);
3173
+ preserved.push(content.slice(start, end));
3174
+ masked += `@@GSD4377:${preserved.length - 1}@@`;
3175
+ copiedThrough = end;
3176
+ searchFrom = end;
3177
+ }
3178
+ masked += content.slice(copiedThrough);
3179
+ return rewrite(masked).replace(/@@GSD4377:(\d+)@@/g, (_m, i) => preserved[Number(i)]);
3180
+ }
2960
3181
  function _applyRuntimeRewrites(content, runtime, pathPrefix, isGlobal = false, attribution = undefined) {
3182
+ // #4377: with a project-relative prefix, run the whole substitution body
3183
+ // with `${VAR:-default}` shell defaults masked out, so the launcher shim
3184
+ // keeps its absolute fallbacks. A no-op for the absolute (default) prefix.
3185
+ if (isRelativePathPrefix(pathPrefix)) {
3186
+ return withShellDefaultsPreserved(content, (masked) => _applyRuntimeRewritesInner(masked, runtime, pathPrefix, isGlobal, attribution));
3187
+ }
3188
+ return _applyRuntimeRewritesInner(content, runtime, pathPrefix, isGlobal, attribution);
3189
+ }
3190
+ function _applyRuntimeRewritesInner(content, runtime, pathPrefix, isGlobal = false, attribution = undefined) {
2961
3191
  const dirName = getDirName(runtime);
2962
3192
  const normalizedPathPrefix = pathPrefix.replace(/\/$/, '');
2963
3193
  content = filterRuntimeNotesForTarget(content, runtime);
@@ -3296,7 +3526,9 @@ function rewriteStagedSkillBodies(stagedDir, opts) {
3296
3526
  const isGlobal = (0, install_scope_cjs_1.isGlobalScope)(scope);
3297
3527
  const isOpencode = false; // #2087: opencode installs via the combined-family engine path, never through the generic rewrite
3298
3528
  const isWindowsHost = platform === 'win32';
3299
- const pathPrefix = computePathPrefix({ isGlobal, isOpencode, isWindowsHost, resolvedTarget, homeDir });
3529
+ // #4377: localDirName lets a local install emit a project-relative prefix
3530
+ // when opted in; ignored for a global install and when the opt-in is off.
3531
+ const pathPrefix = computePathPrefix({ isGlobal, isOpencode, isWindowsHost, resolvedTarget, homeDir, localDirName: localIncludeDirName(runtime) });
3300
3532
  const attribution = resolveAttribution ? resolveAttribution(runtime) : undefined;
3301
3533
  applyRuntimeContentRewritesInPlace(stagedDir, runtime, pathPrefix, isGlobal, attribution);
3302
3534
  // #2873 (4b): claude, global scope only — see
@@ -3339,7 +3571,9 @@ function rewriteStagedCommandBodies(stagedDir, opts) {
3339
3571
  const isGlobal = (0, install_scope_cjs_1.isGlobalScope)(scope);
3340
3572
  const isOpencode = false; // #2087: opencode installs via the combined-family engine path, never through the generic rewrite
3341
3573
  const isWindowsHost = platform === 'win32';
3342
- const pathPrefix = computePathPrefix({ isGlobal, isOpencode, isWindowsHost, resolvedTarget, homeDir });
3574
+ // #4377: localDirName lets a local install emit a project-relative prefix
3575
+ // when opted in; ignored for a global install and when the opt-in is off.
3576
+ const pathPrefix = computePathPrefix({ isGlobal, isOpencode, isWindowsHost, resolvedTarget, homeDir, localDirName: localIncludeDirName(runtime) });
3343
3577
  const attribution = resolveAttribution ? resolveAttribution(runtime) : undefined;
3344
3578
  return applyRuntimeContentRewritesForCommandsInPlace(stagedDir, runtime, pathPrefix, isGlobal, attribution);
3345
3579
  }
@@ -3389,6 +3623,18 @@ function normalizeAgentBodyForRuntime(content, runtime, cmdNames) {
3389
3623
  function applyAgentPathRewrites(content, runtime, pathPrefix) {
3390
3624
  if (_hostBehaviors(runtime).noPathRewrite === true)
3391
3625
  return content;
3626
+ // #4377: the agents pipeline is the third emit path that substitutes this
3627
+ // prefix (skills/commands via _applyRuntimeRewrites, the gsd-core spec tree
3628
+ // via copyWithPathReplacement, and here). All three carry the same guard:
3629
+ // with a project-relative prefix, `${VAR:-default}` shell defaults are
3630
+ // masked out so the runtime launcher keeps its absolute fallbacks. A no-op
3631
+ // for the absolute prefix. See withShellDefaultsPreserved for why.
3632
+ if (isRelativePathPrefix(pathPrefix)) {
3633
+ return withShellDefaultsPreserved(content, (masked) => applyAgentPathRewritesInner(masked, runtime, pathPrefix));
3634
+ }
3635
+ return applyAgentPathRewritesInner(content, runtime, pathPrefix);
3636
+ }
3637
+ function applyAgentPathRewritesInner(content, runtime, pathPrefix) {
3392
3638
  const normalizedPathPrefix = pathPrefix.replace(/\/$/, '');
3393
3639
  content = content.replace(/~\/\.claude\//g, pathPrefix);
3394
3640
  content = content.replace(/\$HOME\/\.claude\//g, pathPrefix);
@@ -3645,8 +3891,8 @@ module.exports = {
3645
3891
  // #1182: agent converters + tool-name table dependency closure
3646
3892
  claudeToCopilotTools,
3647
3893
  convertCopilotToolName,
3648
- claudeToGeminiTools,
3649
- convertGeminiToolName,
3894
+ claudeToAntigravityTools,
3895
+ convertAntigravityToolName,
3650
3896
  convertClaudeAgentToCopilotAgent,
3651
3897
  convertClaudeAgentToAntigravityAgent,
3652
3898
  convertClaudeAgentToCursorAgent,
@@ -3690,6 +3936,12 @@ module.exports = {
3690
3936
  READONLY_AGENT_DISALLOWED_TOOLS,
3691
3937
  applyAgentFrontmatterExtensions,
3692
3938
  _computePathPrefix: computePathPrefix,
3939
+ _withShellDefaultsPreserved: withShellDefaultsPreserved,
3940
+ _isRelativePathPrefix: isRelativePathPrefix,
3941
+ _relativeIncludesEnabled: relativeIncludesEnabled,
3942
+ _projectRelativePrefix: projectRelativePrefix,
3943
+ _projectRelativePrefixFromProjectRoot: projectRelativePrefixFromProjectRoot,
3944
+ _localIncludeDirName: localIncludeDirName,
3693
3945
  _restoreClaudeGlobalAtRefTilde: restoreClaudeGlobalAtRefTilde,
3694
3946
  _applyRuntimeRewrites,
3695
3947
  _stampNonClaudeRuntimeDefaults,
@@ -92,7 +92,9 @@ function createRuntimeArtifactInstallPlan(args) {
92
92
  const isGlobal = (0, install_scope_cjs_1.isGlobalScope)(scope);
93
93
  const isOpencode = layout.runtime === 'opencode';
94
94
  const isWindowsHost = (platform ?? process.platform) === 'win32';
95
- const pathPrefix = conversionExports._computePathPrefix({ isGlobal, isOpencode, isWindowsHost, resolvedTarget, homeDir });
95
+ // #4377: descriptor-derived local dir name, so an opted-in local install
96
+ // emits a project-relative prefix instead of this checkout's absolute path.
97
+ const pathPrefix = conversionExports._computePathPrefix({ isGlobal, isOpencode, isWindowsHost, resolvedTarget, homeDir, localDirName: conversionExports._localIncludeDirName(layout.runtime) });
96
98
  const attribution = resolveAttribution ? resolveAttribution(layout.runtime) : undefined;
97
99
  // #2875 Part 2 (row I1): layout.configDir IS the install root the inline
98
100
  // agent loop called `targetDir` — same value, same resolution.
@@ -49,6 +49,7 @@ exports.getGlobalSkillDisplayPath = getGlobalSkillDisplayPath;
49
49
  const node_os_1 = __importDefault(require("node:os"));
50
50
  const node_path_1 = __importDefault(require("node:path"));
51
51
  const node_fs_1 = __importDefault(require("node:fs"));
52
+ const runtime_name_policy_cjs_1 = require("./runtime-name-policy.cjs");
52
53
  /**
53
54
  * Expand a leading ~ to the given home directory (defaults to os.homedir()).
54
55
  * Every call site inside resolveConfigHomeFromDescriptor threads its
@@ -455,6 +456,9 @@ function resolveKimiHooksTomlDir(opts = {}) {
455
456
  * the behaviour of bin/install.js getGlobalDir(runtime, explicitDir).
456
457
  */
457
458
  function getGlobalConfigDir(runtime, explicitDir) {
459
+ // A retired runtime id must never resolve — checked before `explicitDir` so
460
+ // an explicit directory cannot mask the fact that the runtime itself is gone.
461
+ (0, runtime_name_policy_cjs_1.assertNotRetiredRuntime)(runtime);
458
462
  if (explicitDir)
459
463
  return expandTilde(explicitDir);
460
464
  // ── Grok: not in the registry — hardcoded branch ─────────────────────────