@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.
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/README.ja-JP.md +3 -3
- package/README.ko-KR.md +3 -3
- package/README.pt-BR.md +3 -3
- package/README.zh-CN.md +3 -3
- package/agents/gsd-code-fixer.compact.md +7 -6
- package/agents/gsd-code-fixer.md +9 -8
- package/agents/gsd-debug-session-manager.compact.md +17 -2
- package/agents/gsd-debug-session-manager.md +17 -2
- package/agents/gsd-debugger.md +2 -2
- package/agents/gsd-eval-auditor.compact.md +1 -1
- package/agents/gsd-eval-auditor.md +1 -1
- package/agents/gsd-executor.md +13 -8
- package/agents/gsd-intel-updater.compact.md +1 -1
- package/agents/gsd-intel-updater.md +1 -1
- package/agents/gsd-phase-researcher.md +19 -11
- package/agents/gsd-plan-checker.md +8 -7
- package/agents/gsd-planner.md +12 -8
- package/agents/gsd-project-researcher.compact.md +1 -1
- package/agents/gsd-project-researcher.md +1 -1
- package/agents/gsd-research-synthesizer.compact.md +1 -1
- package/agents/gsd-research-synthesizer.md +1 -1
- package/agents/gsd-ui-auditor.md +155 -17
- package/agents/gsd-ui-researcher.compact.md +1 -1
- package/agents/gsd-ui-researcher.md +1 -1
- package/agents/gsd-verifier.md +10 -9
- package/bin/install.js +642 -95
- package/commands/gsd/autonomous.md +2 -2
- package/commands/gsd/capture.md +1 -1
- package/commands/gsd/mempalace-capture.md +7 -3
- package/commands/gsd/plan-review-convergence.md +6 -6
- package/commands/gsd/progress.md +1 -1
- package/commands/gsd/quick-batch.md +1 -1
- package/commands/gsd/review.md +2 -3
- package/gsd-core/bin/gsd-tools.cjs +335 -22
- package/gsd-core/bin/lib/adr-parser.cjs +3 -1
- package/gsd-core/bin/lib/audit.cjs +81 -13
- package/gsd-core/bin/lib/capability-registry.cjs +82 -187
- package/gsd-core/bin/lib/capability-validator.cjs +0 -1
- package/gsd-core/bin/lib/check-command-router.cjs +101 -14
- package/gsd-core/bin/lib/codex-agent-toml.cjs +21 -25
- package/gsd-core/bin/lib/commands.cjs +175 -42
- package/gsd-core/bin/lib/config-loader.cjs +65 -4
- package/gsd-core/bin/lib/config.cjs +33 -7
- package/gsd-core/bin/lib/decisions.cjs +30 -14
- package/gsd-core/bin/lib/frontmatter.cjs +13 -0
- package/gsd-core/bin/lib/graphify.cjs +10 -2
- package/gsd-core/bin/lib/host-runtime-detection.cjs +9 -0
- package/gsd-core/bin/lib/init.cjs +207 -41
- package/gsd-core/bin/lib/install-engine.cjs +13 -0
- package/gsd-core/bin/lib/installer-migrations.cjs +8 -1
- package/gsd-core/bin/lib/milestone.cjs +18 -5
- package/gsd-core/bin/lib/model-resolver.cjs +159 -50
- package/gsd-core/bin/lib/phase-command-router.cjs +9 -1
- package/gsd-core/bin/lib/phase-id-card.cjs +32 -0
- package/gsd-core/bin/lib/phase-id-display.cjs +78 -0
- package/gsd-core/bin/lib/phase-id.cjs +109 -7
- package/gsd-core/bin/lib/phase-locator.cjs +29 -10
- package/gsd-core/bin/lib/phase.cjs +227 -26
- package/gsd-core/bin/lib/plan-document.cjs +49 -1
- package/gsd-core/bin/lib/planning-document.cjs +459 -0
- package/gsd-core/bin/lib/planning-inspect.cjs +18 -1
- package/gsd-core/bin/lib/planning-workspace.cjs +8 -3
- package/gsd-core/bin/lib/pr-branch-patterns.cjs +57 -0
- package/gsd-core/bin/lib/probe-core.cjs +7 -1
- package/gsd-core/bin/lib/project-root.cjs +41 -2
- package/gsd-core/bin/lib/review-lane-descriptor.cjs +10 -30
- package/gsd-core/bin/lib/review-reviewer-selection.cjs +2 -2
- package/gsd-core/bin/lib/roadmap-command-router.cjs +12 -4
- package/gsd-core/bin/lib/roadmap-parser.cjs +163 -3
- package/gsd-core/bin/lib/roadmap-upgrade.cjs +1539 -13
- package/gsd-core/bin/lib/roadmap.cjs +251 -31
- package/gsd-core/bin/lib/runtime-artifact-conversion.cjs +283 -31
- package/gsd-core/bin/lib/runtime-artifact-install-plan.cjs +3 -1
- package/gsd-core/bin/lib/runtime-homes.cjs +4 -0
- package/gsd-core/bin/lib/runtime-hooks-surface.cjs +215 -33
- package/gsd-core/bin/lib/runtime-name-policy.cjs +111 -1
- package/gsd-core/bin/lib/shell-command-projection.cjs +10 -6
- package/gsd-core/bin/lib/state-transition.cjs +39 -2
- package/gsd-core/bin/lib/state.cjs +42 -0
- package/gsd-core/bin/lib/surface.cjs +17 -1
- package/gsd-core/bin/lib/tdd-red-evidence.cjs +78 -5
- package/gsd-core/bin/lib/uat-predicate.cjs +47 -4
- package/gsd-core/bin/lib/uat.cjs +8 -0
- package/gsd-core/bin/lib/ui-consideration-probe.cjs +15 -2
- package/gsd-core/bin/lib/ui-frontend-evidence.cjs +100 -9
- package/gsd-core/bin/lib/undo-commit-selection.cjs +131 -0
- package/gsd-core/bin/lib/verification.cjs +268 -15
- package/gsd-core/bin/lib/verify-command-grounding.cjs +46 -2
- package/gsd-core/bin/lib/verify.cjs +132 -25
- package/gsd-core/bin/lib/worktree-base-ref.cjs +482 -73
- package/gsd-core/bin/lib/worktree-safety.cjs +784 -51
- package/gsd-core/bin/shared/config-defaults.manifest.json +3 -0
- package/gsd-core/bin/shared/config-schema.manifest.json +1 -0
- package/gsd-core/references/checkpoints.md +5 -3
- package/gsd-core/references/edge-probe-fixtures/01-round-half-even/expected-coverage.json +28 -3
- package/gsd-core/references/edge-probe-fixtures/02-merge-intervals/expected-coverage.json +37 -4
- package/gsd-core/references/edge-probe-fixtures/03-truncate-graphemes/expected-coverage.json +28 -3
- package/gsd-core/references/edge-probe-fixtures/04-money-rounding/expected-coverage.json +28 -3
- package/gsd-core/references/edge-probe-fixtures/05-list-dedupe/expected-coverage.json +37 -4
- package/gsd-core/references/edge-probe-fixtures/06-resolved-mixed/expected-coverage.json +37 -4
- package/gsd-core/references/edge-probe.md +195 -21
- package/gsd-core/references/execute-phase-between-wave-reset.md +7 -6
- package/gsd-core/references/execute-phase-wave-guard.md +22 -11
- package/gsd-core/references/gsd-run-resolver.md +1 -1
- package/gsd-core/references/model-profiles.md +1 -1
- package/gsd-core/references/phase-argument-parsing.md +9 -7
- package/gsd-core/references/phase-id-convention.md +28 -0
- package/gsd-core/references/planner-gap-closure.md +2 -0
- package/gsd-core/references/planner-load-graph-context.md +24 -13
- package/gsd-core/references/planner-verify-command-grounding.md +14 -0
- package/gsd-core/references/planning-config.md +11 -2
- package/gsd-core/references/tdd.md +27 -4
- package/gsd-core/references/ui-consideration-probe.md +10 -5
- package/gsd-core/references/verify-command-path-resolvability.md +10 -2
- package/gsd-core/references/worktree-path-safety.md +321 -0
- package/gsd-core/templates/verification-report.md +1 -1
- package/gsd-core/workflows/_runtime-launcher.snippet.sh +1 -1
- package/gsd-core/workflows/add-backlog.md +1 -1
- package/gsd-core/workflows/add-phase.md +1 -1
- package/gsd-core/workflows/add-tests.md +2 -2
- package/gsd-core/workflows/add-todo.md +3 -3
- package/gsd-core/workflows/ai-integration-phase.md +11 -3
- package/gsd-core/workflows/audit-fix.md +1 -1
- package/gsd-core/workflows/audit-milestone.md +1 -1
- package/gsd-core/workflows/audit-uat.md +1 -1
- package/gsd-core/workflows/autonomous/steps/converge-fail-fast.md +9 -18
- package/gsd-core/workflows/autonomous.md +16 -6
- package/gsd-core/workflows/check-todos.md +2 -2
- package/gsd-core/workflows/cleanup.md +2 -2
- package/gsd-core/workflows/code-review/steps/dispatch-fix.md +4 -3
- package/gsd-core/workflows/code-review/steps/structural-pre-pass.md +1 -1
- package/gsd-core/workflows/code-review-fix.md +108 -22
- package/gsd-core/workflows/code-review.md +63 -46
- package/gsd-core/workflows/complete-milestone/detail/elaboration.md +1 -1
- package/gsd-core/workflows/complete-milestone.md +2 -2
- package/gsd-core/workflows/debug.md +3 -3
- package/gsd-core/workflows/diagnose-issues.md +1 -1
- package/gsd-core/workflows/discuss-phase/modes/advisor.md +1 -1
- package/gsd-core/workflows/discuss-phase/modes/chain.md +1 -1
- package/gsd-core/workflows/discuss-phase-assumptions.md +1 -1
- package/gsd-core/workflows/discuss-phase.md +1 -1
- package/gsd-core/workflows/do.md +2 -2
- package/gsd-core/workflows/docs-update.md +3 -3
- package/gsd-core/workflows/edit-phase.md +1 -1
- package/gsd-core/workflows/eval-review.md +10 -3
- package/gsd-core/workflows/execute-phase/detail/elaboration.md +2 -2
- package/gsd-core/workflows/execute-phase/steps/code-review-disposition.md +1017 -0
- package/gsd-core/workflows/execute-phase/steps/codebase-drift-gate.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/completion-reconciliation.md +3 -3
- package/gsd-core/workflows/execute-phase/steps/executor-isolation-dispatch.md +37 -3
- package/gsd-core/workflows/execute-phase/steps/gap-closure-artifacts.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/partial-wave.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/per-plan-executor-routing.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/per-plan-worktree-gate.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/post-merge-gate.md +46 -9
- package/gsd-core/workflows/execute-phase/steps/protected-branch.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/ready-wave-gate.md +37 -0
- package/gsd-core/workflows/execute-phase/steps/regression-gate-run.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/stale-reverification.md +24 -0
- package/gsd-core/workflows/execute-phase/steps/tdd-applicability-resolution.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/threat-id-gate.md +28 -0
- package/gsd-core/workflows/execute-phase/steps/wave-post-gate-hooks.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/worktree-base-check.md +25 -0
- package/gsd-core/workflows/execute-phase.md +36 -26
- package/gsd-core/workflows/execute-plan.md +5 -4
- package/gsd-core/workflows/explore.md +3 -3
- package/gsd-core/workflows/extract-learnings.md +2 -1
- package/gsd-core/workflows/fast.md +1 -1
- package/gsd-core/workflows/forensics.md +1 -1
- package/gsd-core/workflows/graduation.md +1 -1
- package/gsd-core/workflows/health.md +2 -2
- package/gsd-core/workflows/help/modes/full.compact.md +3 -3
- package/gsd-core/workflows/help/modes/full.md +5 -5
- package/gsd-core/workflows/help/modes/topic.md +15 -5
- package/gsd-core/workflows/import.md +2 -2
- package/gsd-core/workflows/inbox.md +2 -2
- package/gsd-core/workflows/ingest-docs.md +3 -3
- package/gsd-core/workflows/insert-phase.md +1 -1
- package/gsd-core/workflows/list-seeds.md +1 -1
- package/gsd-core/workflows/list-workspaces.md +1 -1
- package/gsd-core/workflows/manager.md +2 -2
- package/gsd-core/workflows/map-codebase.md +2 -2
- package/gsd-core/workflows/milestone-summary.md +1 -1
- package/gsd-core/workflows/mvp-phase.md +1 -1
- package/gsd-core/workflows/new-milestone.md +2 -2
- package/gsd-core/workflows/new-project/steps/auto-mode-config.md +3 -3
- package/gsd-core/workflows/new-project/steps/codebase-map-offer.md +1 -1
- package/gsd-core/workflows/new-project.md +7 -7
- package/gsd-core/workflows/new-workspace.md +2 -2
- package/gsd-core/workflows/next.md +1 -1
- package/gsd-core/workflows/note.md +1 -1
- package/gsd-core/workflows/onboard.md +1 -1
- package/gsd-core/workflows/pause-work.md +1 -1
- package/gsd-core/workflows/plan-phase/detail/elaboration.md +1 -1
- package/gsd-core/workflows/plan-phase/steps/chunked-planning-mode.md +17 -5
- package/gsd-core/workflows/plan-phase/steps/prd-express-path.md +1 -1
- package/gsd-core/workflows/plan-phase/steps/stall-detection-helpers.md +23 -5
- package/gsd-core/workflows/plan-phase.md +24 -7
- package/gsd-core/workflows/plan-review-convergence.md +21 -5
- package/gsd-core/workflows/plant-seed.md +62 -20
- package/gsd-core/workflows/pr-branch.md +113 -13
- package/gsd-core/workflows/profile-user.md +2 -2
- package/gsd-core/workflows/progress.md +1 -1
- package/gsd-core/workflows/quick/steps/plan-checker-loop.md +25 -0
- package/gsd-core/workflows/quick/steps/quick-verification.md +1 -1
- package/gsd-core/workflows/quick/steps/worktree-pre-dispatch-commit.md +1 -1
- package/gsd-core/workflows/quick-batch/steps/batch-init.md +1 -1
- package/gsd-core/workflows/quick-batch/steps/completion.md +1 -1
- package/gsd-core/workflows/quick-batch/steps/merge-wave.md +1 -1
- package/gsd-core/workflows/quick-batch/steps/planner-wave.md +1 -1
- package/gsd-core/workflows/quick-batch/steps/research-phase.md +1 -1
- package/gsd-core/workflows/quick-batch/steps/resume-mode.md +1 -1
- package/gsd-core/workflows/quick-batch/steps/verification-wave.md +1 -1
- package/gsd-core/workflows/quick-batch/steps/worktree-dispatch.md +1 -1
- package/gsd-core/workflows/quick-batch.md +1 -1
- package/gsd-core/workflows/quick.md +21 -9
- package/gsd-core/workflows/reapply-patches.md +9 -3
- package/gsd-core/workflows/remove-phase.md +1 -1
- package/gsd-core/workflows/remove-workspace.md +2 -2
- package/gsd-core/workflows/resume-project.md +1 -1
- package/gsd-core/workflows/review.md +31 -16
- package/gsd-core/workflows/scan.md +1 -1
- package/gsd-core/workflows/secure-phase.md +3 -2
- package/gsd-core/workflows/settings-advanced.md +30 -10
- package/gsd-core/workflows/settings-integrations.md +2 -3
- package/gsd-core/workflows/settings.md +4 -4
- package/gsd-core/workflows/ship.md +3 -2
- package/gsd-core/workflows/sketch-wrap-up.md +1 -1
- package/gsd-core/workflows/sketch.md +1 -1
- package/gsd-core/workflows/smart-entry.md +2 -2
- package/gsd-core/workflows/spec-phase.md +15 -5
- package/gsd-core/workflows/spike-wrap-up.md +1 -1
- package/gsd-core/workflows/spike.md +1 -1
- package/gsd-core/workflows/stats.md +1 -1
- package/gsd-core/workflows/sync-skills.md +5 -5
- package/gsd-core/workflows/thread.md +1 -1
- package/gsd-core/workflows/transition.md +1 -1
- package/gsd-core/workflows/ui-phase.md +44 -8
- package/gsd-core/workflows/ui-review.md +18 -4
- package/gsd-core/workflows/ultraplan-phase.md +1 -1
- package/gsd-core/workflows/undo.md +339 -20
- package/gsd-core/workflows/update.md +7 -7
- package/gsd-core/workflows/validate-phase.md +3 -2
- package/gsd-core/workflows/verify-work/steps/automated-ui-verification.md +1 -1
- package/gsd-core/workflows/verify-work/steps/mvp-uat-framing.md +1 -1
- package/gsd-core/workflows/verify-work.md +81 -16
- package/hooks/dist/gsd-agent-isolation-guard.js +24 -0
- package/hooks/dist/gsd-secret-read-guard.js +27 -1
- package/hooks/dist/gsd-statusline.js +70 -13
- package/hooks/dist/gsd-validate-commit.sh +63 -4
- package/hooks/gsd-agent-isolation-guard.js +24 -0
- package/hooks/gsd-secret-read-guard.js +27 -1
- package/hooks/gsd-statusline.js +70 -13
- package/hooks/gsd-validate-commit.sh +63 -4
- package/package.json +3 -2
- package/scripts/build-hooks.js +15 -6
- package/scripts/check-contract-drift.cjs +127 -11
- package/scripts/command-contract-helpers.cjs +3 -0
- package/scripts/docs-guard-registry.cjs +28 -0
- package/scripts/gen-loop-host-contract.cjs +69 -0
- package/scripts/lib/macos-conformance-tier.generated.cjs +14 -0
- package/scripts/lib/ndjson-reporter.cjs +3 -2
- package/scripts/lib/platform-conformance-tier.generated.cjs +11 -0
- package/scripts/lint-docs-guard-registration.exempt-baseline.cjs +28 -1
- package/scripts/lint-phase-arg-assignment.cjs +257 -0
- package/scripts/lint-phase-id-drift.cjs +290 -5
- package/scripts/lint-pr-branch-pattern-drift.cjs +148 -0
- package/scripts/lint-retired-runtime-name.cjs +619 -0
- package/scripts/lint-state-write-path-drift.cjs +93 -0
- package/scripts/lint-test-file-count.allowlist.json +28 -9
- package/scripts/lint-workflow-shellcheck-baseline.json +15 -0
- package/scripts/prompt-injection-scan.sh +4 -0
- package/scripts/release-tarball-smoke.cjs +194 -1
- package/skills/gsd-autonomous/SKILL.md +2 -2
- package/skills/gsd-capture/SKILL.md +1 -1
- package/skills/gsd-mempalace-capture/SKILL.md +7 -3
- package/skills/gsd-plan-review-convergence/SKILL.md +5 -5
- package/skills/gsd-progress/SKILL.md +1 -1
- package/skills/gsd-quick-batch/SKILL.md +1 -1
- package/skills/gsd-review/SKILL.md +2 -3
- 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
|
-
|
|
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
|
|
2277
|
-
//
|
|
2278
|
-
|
|
2279
|
-
|
|
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: '
|
|
2282
|
-
Bash: '
|
|
2312
|
+
Edit: 'replace_file_content',
|
|
2313
|
+
Bash: 'run_command',
|
|
2283
2314
|
Glob: 'glob',
|
|
2284
|
-
Grep: '
|
|
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
|
|
2291
|
-
* - Applies Claude→
|
|
2292
|
-
* - Filters out MCP tools (mcp__*) — they are auto-discovered at runtime in
|
|
2293
|
-
* - Filters out Task/Agent — agents are auto-registered as tools in
|
|
2294
|
-
* @returns {string|null}
|
|
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
|
|
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
|
|
2303
|
-
// emitting it causes frontmatter validation errors (#3362).
|
|
2304
|
-
// Skill/SlashCommand: exclude — Gemini
|
|
2305
|
-
// the lowercase fallback would emit an invalid
|
|
2306
|
-
// that fails frontmatter validation
|
|
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 (
|
|
2318
|
-
return
|
|
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
|
|
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
|
|
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 =>
|
|
2418
|
+
const mappedTools = claudeTools.map(t => convertAntigravityToolName(t)).filter(Boolean);
|
|
2388
2419
|
// #2876: quote description for the same reason as the skill variant.
|
|
2389
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
3649
|
-
|
|
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
|
-
|
|
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 ─────────────────────────
|