@opengsd/gsd-core 1.13.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-advisor-researcher.compact.md +85 -0
- package/agents/gsd-ai-researcher.compact.md +96 -0
- package/agents/gsd-assumptions-analyzer.compact.md +81 -0
- package/agents/gsd-code-fixer.compact.md +459 -0
- package/agents/gsd-code-fixer.md +9 -8
- package/agents/gsd-code-reviewer.compact.md +269 -0
- package/agents/gsd-code-reviewer.md +15 -3
- package/agents/gsd-codebase-mapper.compact.md +760 -0
- package/agents/gsd-debug-session-manager.compact.md +360 -0
- package/agents/gsd-debug-session-manager.md +17 -2
- package/agents/gsd-debugger.md +2 -2
- package/agents/gsd-doc-classifier.compact.md +192 -0
- package/agents/gsd-doc-synthesizer.compact.md +200 -0
- package/agents/gsd-doc-verifier.compact.md +143 -0
- package/agents/gsd-doc-writer.compact.md +440 -0
- package/agents/gsd-dom-verifier.compact.md +138 -0
- package/agents/gsd-domain-researcher.compact.md +141 -0
- package/agents/gsd-eval-auditor.compact.md +160 -0
- package/agents/gsd-eval-auditor.md +1 -1
- package/agents/gsd-eval-planner.compact.md +137 -0
- package/agents/gsd-executor.md +13 -8
- package/agents/gsd-framework-selector.compact.md +82 -0
- package/agents/gsd-integration-checker.compact.md +245 -0
- package/agents/gsd-intel-updater.compact.md +226 -0
- package/agents/gsd-intel-updater.md +1 -1
- package/agents/gsd-mempalace-curator.compact.md +45 -0
- package/agents/gsd-nyquist-auditor.compact.md +179 -0
- package/agents/gsd-pattern-mapper.compact.md +275 -0
- 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 +587 -0
- package/agents/gsd-project-researcher.md +1 -1
- package/agents/gsd-research-synthesizer.compact.md +212 -0
- package/agents/gsd-research-synthesizer.md +1 -1
- package/agents/gsd-roadmapper.compact.md +454 -0
- package/agents/gsd-roadmapper.md +13 -0
- package/agents/gsd-security-auditor.compact.md +162 -0
- package/agents/gsd-ui-auditor.compact.md +404 -0
- package/agents/gsd-ui-auditor.md +155 -17
- package/agents/gsd-ui-checker.compact.md +277 -0
- package/agents/gsd-ui-researcher.compact.md +282 -0
- package/agents/gsd-ui-researcher.md +1 -1
- package/agents/gsd-user-profiler.compact.md +108 -0
- package/agents/gsd-verifier.md +10 -9
- package/bin/install.js +848 -163
- package/commands/gsd/autonomous.md +2 -2
- package/commands/gsd/capture.md +1 -1
- package/commands/gsd/cleanup.md +1 -0
- package/commands/gsd/code-review.md +2 -1
- package/commands/gsd/complete-milestone.md +1 -0
- package/commands/gsd/config.md +1 -0
- package/commands/gsd/debug.md +1 -0
- package/commands/gsd/graphify.md +1 -0
- package/commands/gsd/health.md +1 -0
- package/commands/gsd/mempalace-capture.md +8 -3
- package/commands/gsd/mempalace-recall.md +1 -0
- package/commands/gsd/new-milestone.md +1 -0
- package/commands/gsd/new-project.md +1 -0
- package/commands/gsd/next.md +1 -0
- package/commands/gsd/pause-work.md +1 -0
- package/commands/gsd/phase.md +1 -0
- package/commands/gsd/plan-review-convergence.md +6 -6
- package/commands/gsd/pr-branch.md +1 -0
- package/commands/gsd/progress.md +1 -1
- package/commands/gsd/quick-batch.md +1 -1
- package/commands/gsd/resume-work.md +1 -0
- package/commands/gsd/review-backlog.md +1 -0
- package/commands/gsd/review.md +2 -3
- package/commands/gsd/settings.md +2 -1
- package/commands/gsd/stats.md +1 -0
- package/commands/gsd/thread.md +1 -0
- package/commands/gsd/workspace.md +1 -0
- package/commands/gsd/workstreams.md +1 -0
- package/gsd-core/bin/check-latest-version.cjs +8 -3
- package/gsd-core/bin/gsd-tools.cjs +672 -146
- package/gsd-core/bin/lib/adr-parser.cjs +4 -2
- package/gsd-core/bin/lib/artifacts.cjs +2 -1
- package/gsd-core/bin/lib/audit.cjs +119 -34
- package/gsd-core/bin/lib/broken-windows.cjs +168 -49
- package/gsd-core/bin/lib/capability-lifecycle.cjs +10 -6
- package/gsd-core/bin/lib/capability-loader.cjs +135 -1
- package/gsd-core/bin/lib/capability-registry.cjs +96 -189
- package/gsd-core/bin/lib/capability-source.cjs +19 -2
- package/gsd-core/bin/lib/capability-validator.cjs +14 -2
- package/gsd-core/bin/lib/check-command-router.cjs +213 -49
- package/gsd-core/bin/lib/code-review-depth.cjs +2 -2
- package/gsd-core/bin/lib/codex-agent-toml.cjs +21 -25
- package/gsd-core/bin/lib/commands.cjs +823 -112
- package/gsd-core/bin/lib/config-loader.cjs +66 -4
- package/gsd-core/bin/lib/config.cjs +186 -45
- package/gsd-core/bin/lib/coverage.cjs +1 -1
- package/gsd-core/bin/lib/decisions.cjs +164 -45
- package/gsd-core/bin/lib/external-descriptor-trust.cjs +29 -14
- package/gsd-core/bin/lib/frontmatter.cjs +13 -0
- package/gsd-core/bin/lib/graphify.cjs +10 -2
- package/gsd-core/bin/lib/gsd2-import.cjs +1 -2
- package/gsd-core/bin/lib/health-diagnostic-rules/state-consistency.cjs +12 -1
- package/gsd-core/bin/lib/health-diagnostic-rules/worktree-health.cjs +1 -1
- package/gsd-core/bin/lib/host-runtime-detection.cjs +9 -0
- package/gsd-core/bin/lib/init.cjs +614 -86
- package/gsd-core/bin/lib/install-engine.cjs +29 -3
- package/gsd-core/bin/lib/install-profiles.cjs +14 -0
- package/gsd-core/bin/lib/installer-migrations.cjs +41 -5
- package/gsd-core/bin/lib/loop-resolver.cjs +50 -31
- package/gsd-core/bin/lib/mcp-catalog.cjs +2 -2
- package/gsd-core/bin/lib/milestone.cjs +37 -13
- package/gsd-core/bin/lib/model-resolver.cjs +253 -53
- package/gsd-core/bin/lib/phase-command-router.cjs +16 -2
- 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 +268 -27
- package/gsd-core/bin/lib/phase-lifecycle.cjs +61 -0
- package/gsd-core/bin/lib/phase-locator.cjs +29 -10
- package/gsd-core/bin/lib/phase.cjs +393 -88
- 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 +52 -19
- package/gsd-core/bin/lib/planning-snapshot.cjs +61 -12
- package/gsd-core/bin/lib/planning-workspace.cjs +57 -3
- package/gsd-core/bin/lib/pr-branch-patterns.cjs +57 -0
- package/gsd-core/bin/lib/pristine-baseline.cjs +182 -0
- package/gsd-core/bin/lib/probe-core.cjs +7 -1
- package/gsd-core/bin/lib/prohibition-enforcement.cjs +91 -4
- package/gsd-core/bin/lib/project-root.cjs +41 -2
- package/gsd-core/bin/lib/quick-batch.cjs +1 -1
- package/gsd-core/bin/lib/refactor-trigger-command-router.cjs +61 -2
- package/gsd-core/bin/lib/research-store.cjs +11 -12
- package/gsd-core/bin/lib/review-lane-descriptor.cjs +10 -30
- package/gsd-core/bin/lib/review-lane-invocation.cjs +23 -0
- package/gsd-core/bin/lib/review-reviewer-selection.cjs +2 -2
- package/gsd-core/bin/lib/reviewer-step-dispatch.cjs +337 -0
- package/gsd-core/bin/lib/roadmap-command-router.cjs +12 -4
- package/gsd-core/bin/lib/roadmap-parser.cjs +219 -18
- package/gsd-core/bin/lib/roadmap-upgrade.cjs +1539 -13
- package/gsd-core/bin/lib/roadmap.cjs +356 -42
- package/gsd-core/bin/lib/runtime-artifact-conversion.cjs +310 -41
- package/gsd-core/bin/lib/runtime-artifact-install-plan.cjs +15 -4
- package/gsd-core/bin/lib/runtime-artifact-layout.cjs +13 -5
- package/gsd-core/bin/lib/runtime-homes.cjs +4 -0
- package/gsd-core/bin/lib/runtime-hooks-surface.cjs +408 -37
- package/gsd-core/bin/lib/runtime-name-policy.cjs +111 -1
- package/gsd-core/bin/lib/security.cjs +126 -7
- package/gsd-core/bin/lib/shell-command-projection.cjs +10 -6
- package/gsd-core/bin/lib/state-document.cjs +130 -28
- package/gsd-core/bin/lib/state-md-schema.cjs +21 -14
- package/gsd-core/bin/lib/state-transition.cjs +181 -30
- package/gsd-core/bin/lib/state.cjs +265 -27
- package/gsd-core/bin/lib/surface.cjs +77 -3
- package/gsd-core/bin/lib/task-command-router.cjs +12 -6
- 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 +9 -1
- 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/update-context.cjs +30 -24
- package/gsd-core/bin/lib/vendor/js-yaml.cjs +11 -3
- package/gsd-core/bin/lib/verification.cjs +315 -30
- package/gsd-core/bin/lib/verify-command-grounding.cjs +47 -3
- package/gsd-core/bin/lib/verify.cjs +320 -48
- package/gsd-core/bin/lib/workstream-inventory.cjs +1 -0
- package/gsd-core/bin/lib/worktree-base-ref.cjs +482 -73
- package/gsd-core/bin/lib/worktree-safety.cjs +797 -58
- package/gsd-core/bin/shared/config-defaults.manifest.json +4 -0
- package/gsd-core/bin/shared/config-schema.manifest.json +6 -0
- package/gsd-core/bin/verify-reapply-patches.cjs +439 -80
- package/gsd-core/references/checkpoints.md +5 -3
- package/gsd-core/references/compact-content-gate.md +66 -0
- 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/loop-hook-dispatch.md +18 -0
- package/gsd-core/references/model-profiles.md +13 -4
- 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 +14 -2
- package/gsd-core/references/tdd.md +30 -4
- package/gsd-core/references/thinking-models-planning.md +18 -2
- package/gsd-core/references/ui-consideration-probe.md +10 -5
- package/gsd-core/references/verification-patterns.md +17 -4
- package/gsd-core/references/verify-command-path-resolvability.md +10 -2
- package/gsd-core/references/worktree-path-safety.md +433 -2
- package/gsd-core/templates/README.md +7 -1
- package/gsd-core/templates/state.md +6 -3
- package/gsd-core/templates/summary.compact.md +212 -0
- package/gsd-core/templates/user-setup.compact.md +199 -0
- package/gsd-core/templates/user-setup.md +0 -9
- 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 +6 -5
- 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 +29 -16
- package/gsd-core/workflows/check-todos.md +6 -4
- package/gsd-core/workflows/cleanup.md +5 -3
- package/gsd-core/workflows/code-review/steps/dispatch-fix.md +4 -3
- package/gsd-core/workflows/code-review/steps/structural-pre-pass.md +8 -1
- package/gsd-core/workflows/code-review-fix.md +108 -22
- package/gsd-core/workflows/code-review.md +216 -73
- package/gsd-core/workflows/complete-milestone/detail/elaboration.md +274 -0
- package/gsd-core/workflows/complete-milestone.md +41 -264
- 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/detail/elaboration.md +179 -0
- package/gsd-core/workflows/docs-update.md +17 -158
- 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 +124 -0
- package/gsd-core/workflows/execute-phase/steps/code-review-disposition.md +1017 -0
- package/gsd-core/workflows/execute-phase/steps/codebase-drift-gate.md +19 -4
- package/gsd-core/workflows/execute-phase/steps/completion-reconciliation.md +56 -0
- package/gsd-core/workflows/execute-phase/steps/executor-isolation-dispatch.md +43 -4
- package/gsd-core/workflows/execute-phase/steps/executor-progress-policy.md +43 -0
- 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/sequential-root-pin.md +35 -0
- 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 +83 -172
- package/gsd-core/workflows/execute-plan.md +24 -10
- 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 +398 -0
- package/gsd-core/workflows/help/modes/full.md +5 -5
- package/gsd-core/workflows/help/modes/topic.md +15 -5
- package/gsd-core/workflows/help.md +1 -1
- 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 +52 -5
- 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 +56 -14
- package/gsd-core/workflows/new-project/detail/elaboration.md +216 -0
- 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 +39 -209
- 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 +209 -0
- 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 +45 -187
- 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 +132 -20
- 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 +29 -10
- package/gsd-core/workflows/reapply-patches.md +86 -6
- 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 +22 -9
- 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 +14 -12
- package/gsd-core/workflows/validate-phase.md +3 -2
- package/gsd-core/workflows/verify-work/detail/elaboration.md +230 -0
- 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 +101 -196
- package/hooks/dist/gsd-agent-isolation-guard.js +66 -16
- package/hooks/dist/gsd-context-monitor.js +88 -15
- package/hooks/dist/gsd-cursor-subagent-start.js +34 -14
- package/hooks/dist/gsd-secret-read-guard.js +71 -19
- package/hooks/dist/gsd-statusline.js +81 -20
- package/hooks/dist/gsd-validate-commit.sh +97 -8
- package/hooks/dist/gsd-worktree-path-guard.js +25 -14
- package/hooks/dist/gsd-write-guard.js +46 -1
- package/hooks/dist/lib/dispatch-identity.js +187 -0
- package/hooks/dist/lib/filename-classification.js +64 -0
- package/hooks/dist/lib/isolation-deny-reason.js +53 -1
- package/hooks/dist/lib/isolation-sentinel.js +58 -19
- package/hooks/gsd-agent-isolation-guard.js +66 -16
- package/hooks/gsd-context-monitor.js +88 -15
- package/hooks/gsd-cursor-subagent-start.js +34 -14
- package/hooks/gsd-secret-read-guard.js +71 -19
- package/hooks/gsd-statusline.js +81 -20
- package/hooks/gsd-validate-commit.sh +97 -8
- package/hooks/gsd-worktree-path-guard.js +25 -14
- package/hooks/gsd-write-guard.js +46 -1
- package/hooks/lib/dispatch-identity.js +187 -0
- package/hooks/lib/filename-classification.js +64 -0
- package/hooks/lib/isolation-deny-reason.js +53 -1
- package/hooks/lib/isolation-sentinel.js +58 -19
- package/package.json +11 -6
- package/scripts/benchmark-compact-content-variants.cjs +298 -0
- package/scripts/benchmark-compact-content.cjs +368 -0
- package/scripts/build-hooks.js +15 -6
- package/scripts/check-contract-drift.cjs +131 -12
- package/scripts/check-env.cjs +36 -8
- package/scripts/check-glossary-refs.cjs +25 -21
- package/scripts/ci-next-health.cjs +271 -0
- package/scripts/ci-prepare-test-scope.cjs +7 -7
- package/scripts/ci-test-scope.cjs +126 -20
- package/scripts/ci-timeout-report.cjs +1 -1
- package/scripts/command-contract-helpers.cjs +3 -0
- package/scripts/diff-touches-shipped-paths.cjs +1 -1
- package/scripts/docs-guard-registry.cjs +35 -2
- package/scripts/gen-adr-index.cjs +8 -2
- package/scripts/gen-inventory-manifest.cjs +12 -0
- package/scripts/gen-loop-host-contract.cjs +69 -0
- package/scripts/gen-platform-conformance-tier.cjs +557 -0
- package/scripts/lib/drift-scan.cjs +1 -1
- package/scripts/lib/macos-conformance-tier.generated.cjs +224 -0
- package/scripts/lib/ndjson-reporter.cjs +3 -2
- package/scripts/lib/npm-version-check-diagnosis.cjs +59 -0
- package/scripts/lib/platform-conformance-tier.generated.cjs +287 -0
- package/scripts/lib/suite-detection.cjs +32 -0
- package/scripts/lint-allowed-tools-parity.cjs +221 -0
- package/scripts/lint-docs-guard-registration.exempt-baseline.cjs +47 -3
- package/scripts/lint-phase-arg-assignment.cjs +257 -0
- package/scripts/lint-phase-id-drift.cjs +623 -13
- package/scripts/lint-pr-branch-pattern-drift.cjs +148 -0
- package/scripts/lint-response-language-coverage.cjs +9 -3
- package/scripts/lint-retired-runtime-name.cjs +619 -0
- package/scripts/lint-source-test-name-collision.cjs +1 -1
- package/scripts/lint-state-write-path-drift.cjs +93 -0
- package/scripts/lint-test-file-count.allowlist.json +29 -9
- package/scripts/lint-vendored-deps.cjs +128 -17
- package/scripts/lint-workflow-shellcheck-baseline.json +100 -0
- package/scripts/prompt-injection-scan.sh +18 -0
- package/scripts/release-tarball-smoke.cjs +194 -1
- package/scripts/workflow-size.cjs +139 -0
- package/skills/gsd-autonomous/SKILL.md +2 -2
- package/skills/gsd-capture/SKILL.md +1 -1
- package/skills/gsd-cleanup/SKILL.md +1 -0
- package/skills/gsd-code-review/SKILL.md +2 -1
- package/skills/gsd-complete-milestone/SKILL.md +1 -0
- package/skills/gsd-config/SKILL.md +1 -0
- package/skills/gsd-debug/SKILL.md +1 -0
- package/skills/gsd-graphify/SKILL.md +1 -0
- package/skills/gsd-health/SKILL.md +1 -0
- package/skills/gsd-mempalace-capture/SKILL.md +8 -3
- package/skills/gsd-mempalace-recall/SKILL.md +1 -0
- package/skills/gsd-new-milestone/SKILL.md +1 -0
- package/skills/gsd-new-project/SKILL.md +1 -0
- package/skills/gsd-next/SKILL.md +1 -0
- package/skills/gsd-pause-work/SKILL.md +1 -0
- package/skills/gsd-phase/SKILL.md +1 -0
- package/skills/gsd-plan-review-convergence/SKILL.md +5 -5
- package/skills/gsd-pr-branch/SKILL.md +1 -0
- package/skills/gsd-progress/SKILL.md +1 -1
- package/skills/gsd-quick-batch/SKILL.md +1 -1
- package/skills/gsd-resume-work/SKILL.md +1 -0
- package/skills/gsd-review/SKILL.md +2 -3
- package/skills/gsd-review-backlog/SKILL.md +1 -0
- package/skills/gsd-settings/SKILL.md +2 -1
- package/skills/gsd-stats/SKILL.md +1 -0
- package/skills/gsd-thread/SKILL.md +1 -0
- package/skills/gsd-workspace/SKILL.md +1 -0
- package/skills/gsd-workstreams/SKILL.md +1 -0
- package/vscode/package.json +1 -1
- package/gsd-core/templates/claude-md.md +0 -145
- package/gsd-core/templates/codebase/concerns.md +0 -310
- package/gsd-core/templates/codebase/conventions.md +0 -307
- package/gsd-core/templates/codebase/integrations.md +0 -280
- package/gsd-core/templates/codebase/structure.md +0 -285
- package/gsd-core/templates/codebase/testing.md +0 -480
- package/gsd-core/templates/debug-subagent-prompt.md +0 -91
- package/gsd-core/templates/discovery.md +0 -146
|
@@ -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
|
|
@@ -1011,7 +1014,7 @@ function buildKimiAgentArtifacts({ rootAgent = '', subagents = [], requestedSuba
|
|
|
1011
1014
|
* @param {boolean} [isGlobal=false] - Whether this is a global install
|
|
1012
1015
|
*/
|
|
1013
1016
|
function convertClaudeToAntigravityContent(content, isGlobal = false) {
|
|
1014
|
-
let c = content;
|
|
1017
|
+
let c = filterRuntimeNotesForTarget(content, 'antigravity');
|
|
1015
1018
|
if (isGlobal) {
|
|
1016
1019
|
// #3738: global skills install under ~/.gemini/config/skills (the dir AGY
|
|
1017
1020
|
// scans for global discovery), so skills-path references must divert there
|
|
@@ -1103,7 +1106,7 @@ function convertSlashCommandsToCursorSkillMentions(content) {
|
|
|
1103
1106
|
return content.replace(/gsd:/gi, 'gsd-');
|
|
1104
1107
|
}
|
|
1105
1108
|
function convertClaudeToCursorMarkdown(content) {
|
|
1106
|
-
let converted = convertSlashCommandsToCursorSkillMentions(content);
|
|
1109
|
+
let converted = convertSlashCommandsToCursorSkillMentions(filterRuntimeNotesForTarget(content, 'cursor'));
|
|
1107
1110
|
// Replace tool name references in body text
|
|
1108
1111
|
converted = converted.replace(/\bBash\(/g, 'Shell(');
|
|
1109
1112
|
converted = converted.replace(/\bEdit\(/g, 'StrReplace(');
|
|
@@ -1203,7 +1206,7 @@ function convertSlashCommandsToWindsurfSkillMentions(content) {
|
|
|
1203
1206
|
return content.replace(/gsd:/gi, 'gsd-');
|
|
1204
1207
|
}
|
|
1205
1208
|
function convertClaudeToWindsurfMarkdown(content) {
|
|
1206
|
-
let converted = convertSlashCommandsToWindsurfSkillMentions(content);
|
|
1209
|
+
let converted = convertSlashCommandsToWindsurfSkillMentions(filterRuntimeNotesForTarget(content, 'windsurf'));
|
|
1207
1210
|
// Replace tool name references in body text
|
|
1208
1211
|
converted = converted.replace(/\bBash\(/g, 'Shell(');
|
|
1209
1212
|
converted = converted.replace(/\bEdit\(/g, 'StrReplace(');
|
|
@@ -1362,7 +1365,7 @@ function convertSlashCommandsToAugmentSkillMentions(content) {
|
|
|
1362
1365
|
return content.replace(/gsd:/gi, 'gsd-');
|
|
1363
1366
|
}
|
|
1364
1367
|
function convertClaudeToAugmentMarkdown(content) {
|
|
1365
|
-
let converted = convertSlashCommandsToAugmentSkillMentions(content);
|
|
1368
|
+
let converted = convertSlashCommandsToAugmentSkillMentions(filterRuntimeNotesForTarget(content, 'augment'));
|
|
1366
1369
|
converted = converted.replace(/\bBash\(/g, 'launch-process(');
|
|
1367
1370
|
converted = converted.replace(/\bEdit\(/g, 'str-replace-editor(');
|
|
1368
1371
|
converted = converted.replace(/\bRead\(/g, 'view(');
|
|
@@ -1440,7 +1443,7 @@ function convertSlashCommandsToTraeSkillMentions(content) {
|
|
|
1440
1443
|
});
|
|
1441
1444
|
}
|
|
1442
1445
|
function convertClaudeToTraeMarkdown(content) {
|
|
1443
|
-
let converted = convertSlashCommandsToTraeSkillMentions(content);
|
|
1446
|
+
let converted = convertSlashCommandsToTraeSkillMentions(filterRuntimeNotesForTarget(content, 'trae'));
|
|
1444
1447
|
converted = converted.replace(/\bBash\(/g, 'Shell(');
|
|
1445
1448
|
converted = converted.replace(/\bEdit\(/g, 'StrReplace(');
|
|
1446
1449
|
// Replace general-purpose subagent type with Trae's equivalent "general_purpose_task"
|
|
@@ -1548,7 +1551,7 @@ function convertSlashCommandsToCodebuddySkillMentions(content) {
|
|
|
1548
1551
|
});
|
|
1549
1552
|
}
|
|
1550
1553
|
function convertClaudeToCodebuddyMarkdown(content) {
|
|
1551
|
-
let converted = convertSlashCommandsToCodebuddySkillMentions(content);
|
|
1554
|
+
let converted = convertSlashCommandsToCodebuddySkillMentions(filterRuntimeNotesForTarget(content, 'codebuddy'));
|
|
1552
1555
|
// CodeBuddy uses the same tool names as Claude Code (Bash, Edit, Read, Write, etc.)
|
|
1553
1556
|
// No tool name conversion needed
|
|
1554
1557
|
converted = converted.replace(/\$ARGUMENTS\b/g, '{{GSD_ARGS}}');
|
|
@@ -1625,7 +1628,7 @@ function convertClaudeCommandToCodebuddyCommand(content, commandName) {
|
|
|
1625
1628
|
}
|
|
1626
1629
|
// ── Cline converters ────────────────────────────────────────────────────────
|
|
1627
1630
|
function convertClaudeToCliineMarkdown(content) {
|
|
1628
|
-
let converted = content;
|
|
1631
|
+
let converted = filterRuntimeNotesForTarget(content, 'cline');
|
|
1629
1632
|
// Cline uses the same tool names as Claude Code — no tool name conversion needed
|
|
1630
1633
|
converted = converted.replace(/`\.\/CLAUDE\.md`/g, '`.clinerules`');
|
|
1631
1634
|
converted = converted.replace(/\.\/CLAUDE\.md/g, '.clinerules');
|
|
@@ -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
|
|
@@ -1712,7 +1717,7 @@ function rewriteBareGsdToolsCommandsForCodex(content) {
|
|
|
1712
1717
|
.replace(/((?:&&|\|\||[;|])\s*)gsd-tools(?=\s)/g, `$1${CODEX_GSD_TOOLS_INVOCATION}`);
|
|
1713
1718
|
}
|
|
1714
1719
|
function convertClaudeToCodexMarkdown(content) {
|
|
1715
|
-
let converted = convertSlashCommandsToCodexSkillMentions(content);
|
|
1720
|
+
let converted = convertSlashCommandsToCodexSkillMentions(filterRuntimeNotesForTarget(content, 'codex'));
|
|
1716
1721
|
converted = converted.replace(/\$ARGUMENTS\b/g, '{{GSD_ARGS}}');
|
|
1717
1722
|
// Remove /clear references — Codex has no equivalent command
|
|
1718
1723
|
// Handle backtick-wrapped: `\/clear` then: → (removed)
|
|
@@ -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
|
|
|
@@ -1901,9 +1925,24 @@ function frontmatterScalar(key, value) {
|
|
|
1901
1925
|
? `${key} "${frontmatterModule.escapeDoubleQuotedScalar(value)}"`
|
|
1902
1926
|
: `${key} ${value}`;
|
|
1903
1927
|
}
|
|
1928
|
+
const RUNTIME_NOTE_AUDIENCE_BY_HEADING = new Map([
|
|
1929
|
+
['copilot (vs code)', 'copilot'],
|
|
1930
|
+
]);
|
|
1931
|
+
function filterRuntimeNotesForTarget(content, targetRuntime) {
|
|
1932
|
+
return content.replace(/<runtime_note(?:\s+runtime=["']([^"']+)["'])?>([\s\S]*?)<\/runtime_note>/g, (whole, declaredAudience, inner) => {
|
|
1933
|
+
if (declaredAudience && declaredAudience.toLowerCase() !== targetRuntime)
|
|
1934
|
+
return '';
|
|
1935
|
+
const remaining = inner.replace(/(?:^|\n)[ \t]*\*\*([^*\n]+):\*\*[^\n]*(?:\n(?![ \t]*\n)[^\n]*)*/g, (section, heading) => {
|
|
1936
|
+
const audience = RUNTIME_NOTE_AUDIENCE_BY_HEADING.get(heading.trim().toLowerCase());
|
|
1937
|
+
return audience && audience !== targetRuntime ? '' : section;
|
|
1938
|
+
});
|
|
1939
|
+
const body = remaining.trim();
|
|
1940
|
+
return body ? `<runtime_note>\n${body}\n</runtime_note>` : '';
|
|
1941
|
+
});
|
|
1942
|
+
}
|
|
1904
1943
|
function convertClaudeToOpencodeFrontmatter(content, { isAgent = false, modelOverride = null, variant = null } = {}) {
|
|
1905
1944
|
// Replace tool name references in content (applies to all files)
|
|
1906
|
-
let convertedContent = content;
|
|
1945
|
+
let convertedContent = filterRuntimeNotesForTarget(content, 'opencode');
|
|
1907
1946
|
convertedContent = convertedContent.replace(/\bAskUserQuestion\b/g, 'question');
|
|
1908
1947
|
convertedContent = convertedContent.replace(/\bSlashCommand\b/g, 'skill');
|
|
1909
1948
|
convertedContent = convertedContent.replace(/\bTodoWrite\b/g, 'todowrite');
|
|
@@ -2064,7 +2103,7 @@ function convertClaudeToOpencodeFrontmatter(content, { isAgent = false, modelOve
|
|
|
2064
2103
|
// (#2093).
|
|
2065
2104
|
function convertClaudeToKiloFrontmatter(content, { isAgent = false, modelOverride = null } = {}) {
|
|
2066
2105
|
// Replace tool name references in content (applies to all files)
|
|
2067
|
-
let convertedContent = content;
|
|
2106
|
+
let convertedContent = filterRuntimeNotesForTarget(content, 'kilo');
|
|
2068
2107
|
convertedContent = convertedContent.replace(/\bAskUserQuestion\b/g, 'question');
|
|
2069
2108
|
convertedContent = convertedContent.replace(/\bSlashCommand\b/g, 'skill');
|
|
2070
2109
|
convertedContent = convertedContent.replace(/\bTodoWrite\b/g, 'todowrite');
|
|
@@ -2258,38 +2297,45 @@ const claudeToCopilotTools = {
|
|
|
2258
2297
|
AskUserQuestion: 'ask_user',
|
|
2259
2298
|
SlashCommand: 'skill',
|
|
2260
2299
|
};
|
|
2261
|
-
// Tool name mapping from Claude Code to
|
|
2262
|
-
//
|
|
2263
|
-
|
|
2264
|
-
|
|
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',
|
|
2265
2311
|
Write: 'write_file',
|
|
2266
|
-
Edit: '
|
|
2267
|
-
Bash: '
|
|
2312
|
+
Edit: 'replace_file_content',
|
|
2313
|
+
Bash: 'run_command',
|
|
2268
2314
|
Glob: 'glob',
|
|
2269
|
-
Grep: '
|
|
2315
|
+
Grep: 'grep_search',
|
|
2270
2316
|
WebSearch: 'google_web_search',
|
|
2271
2317
|
WebFetch: 'web_fetch',
|
|
2272
2318
|
TodoWrite: 'write_todos',
|
|
2273
2319
|
};
|
|
2274
2320
|
/**
|
|
2275
|
-
* Convert a Claude Code tool name to
|
|
2276
|
-
* - Applies Claude→
|
|
2277
|
-
* - Filters out MCP tools (mcp__*) — they are auto-discovered at runtime in
|
|
2278
|
-
* - Filters out Task/Agent — agents are auto-registered as tools in
|
|
2279
|
-
* @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
|
|
2280
2326
|
*/
|
|
2281
|
-
function
|
|
2327
|
+
function convertAntigravityToolName(claudeTool) {
|
|
2282
2328
|
// MCP tools: exclude — auto-discovered from mcpServers config at runtime
|
|
2283
2329
|
if (claudeTool.startsWith('mcp__')) {
|
|
2284
2330
|
return null;
|
|
2285
2331
|
}
|
|
2286
2332
|
// Task/Agent: exclude — agents are auto-registered as callable tools.
|
|
2287
|
-
// AskUserQuestion: exclude — Gemini
|
|
2288
|
-
// emitting it causes frontmatter validation errors (#3362).
|
|
2289
|
-
// Skill/SlashCommand: exclude — Gemini
|
|
2290
|
-
// the lowercase fallback would emit an invalid
|
|
2291
|
-
// that fails frontmatter validation
|
|
2292
|
-
// 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).
|
|
2293
2339
|
if (claudeTool === 'Task' ||
|
|
2294
2340
|
claudeTool === 'Agent' ||
|
|
2295
2341
|
claudeTool === 'AskUserQuestion' ||
|
|
@@ -2299,8 +2345,8 @@ function convertGeminiToolName(claudeTool) {
|
|
|
2299
2345
|
return null;
|
|
2300
2346
|
}
|
|
2301
2347
|
// Check for explicit mapping
|
|
2302
|
-
if (
|
|
2303
|
-
return
|
|
2348
|
+
if (claudeToAntigravityTools[claudeTool]) {
|
|
2349
|
+
return claudeToAntigravityTools[claudeTool];
|
|
2304
2350
|
}
|
|
2305
2351
|
// Default: lowercase
|
|
2306
2352
|
return claudeTool.toLowerCase();
|
|
@@ -2356,7 +2402,7 @@ function convertClaudeAgentToCopilotAgent(content, isGlobal = false) {
|
|
|
2356
2402
|
}
|
|
2357
2403
|
/**
|
|
2358
2404
|
* Convert a Claude agent (.md) to an Antigravity agent.
|
|
2359
|
-
* Uses Gemini tool
|
|
2405
|
+
* Uses Antigravity's Gemini tool dialect since Antigravity runs on Gemini 3 backend.
|
|
2360
2406
|
*/
|
|
2361
2407
|
function convertClaudeAgentToAntigravityAgent(content, isGlobal = false) {
|
|
2362
2408
|
const converted = convertClaudeToAntigravityContent(content, isGlobal);
|
|
@@ -2367,11 +2413,17 @@ function convertClaudeAgentToAntigravityAgent(content, isGlobal = false) {
|
|
|
2367
2413
|
const description = extractFrontmatterField(frontmatter, 'description') || '';
|
|
2368
2414
|
const color = extractFrontmatterField(frontmatter, 'color');
|
|
2369
2415
|
const toolsRaw = extractFrontmatterField(frontmatter, 'tools') || '';
|
|
2370
|
-
// Map tools to
|
|
2416
|
+
// Map tools to Antigravity equivalents (reuse existing convertAntigravityToolName)
|
|
2371
2417
|
const claudeTools = toolsRaw.split(',').map(t => t.trim()).filter(Boolean);
|
|
2372
|
-
const mappedTools = claudeTools.map(t =>
|
|
2418
|
+
const mappedTools = claudeTools.map(t => convertAntigravityToolName(t)).filter(Boolean);
|
|
2373
2419
|
// #2876: quote description for the same reason as the skill variant.
|
|
2374
|
-
|
|
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}`;
|
|
2375
2427
|
if (color)
|
|
2376
2428
|
fm += `color: ${color}\n`;
|
|
2377
2429
|
fm += '---';
|
|
@@ -2754,15 +2806,53 @@ function convertClaudeCommandToKiloSkill(content, skillName) {
|
|
|
2754
2806
|
// Relocated from bin/install.js (#1511). Behavior is byte-for-behavior identical
|
|
2755
2807
|
// to the originals; the only change is the injected `attribution` 5th param in
|
|
2756
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
|
+
}
|
|
2757
2829
|
/**
|
|
2758
2830
|
* Compute the path prefix for a runtime install.
|
|
2759
2831
|
* Global installs under $HOME use $HOME/... form; others use the resolved target.
|
|
2760
2832
|
* isOpencode excludes OpenCode (uses ~/.config/opencode which breaks $HOME shorthand).
|
|
2761
2833
|
* isWindowsHost is not used today but reserved for future Windows-specific logic.
|
|
2762
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
|
+
*
|
|
2763
2853
|
* @private — exported as `_computePathPrefix` for tests.
|
|
2764
2854
|
*/
|
|
2765
|
-
function computePathPrefix({ isGlobal, isOpencode, isWindowsHost: _isWindowsHost, resolvedTarget, homeDir }) {
|
|
2855
|
+
function computePathPrefix({ isGlobal, isOpencode, isWindowsHost: _isWindowsHost, resolvedTarget, homeDir, projectRelative = relativeIncludesEnabled(), localDirName, projectRoot = process.cwd(), projectRelativePath, }) {
|
|
2766
2856
|
// #1615: normalize Windows backslashes to forward slashes. This prefix is
|
|
2767
2857
|
// substituted into markdown @-references (e.g. Windsurf workflow files),
|
|
2768
2858
|
// which use POSIX paths universally. Idempotent on POSIX (no backslashes).
|
|
@@ -2774,8 +2864,62 @@ function computePathPrefix({ isGlobal, isOpencode, isWindowsHost: _isWindowsHost
|
|
|
2774
2864
|
if (isGlobal && posixTarget.startsWith(posixHome) && !isOpencode) {
|
|
2775
2865
|
return '$HOME' + posixTarget.slice(posixHome.length) + '/';
|
|
2776
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
|
+
}
|
|
2777
2877
|
return `${posixTarget}/`;
|
|
2778
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
|
+
}
|
|
2779
2923
|
/**
|
|
2780
2924
|
* Canonical list of every non-Claude runtime that gsd-core emits artifacts for.
|
|
2781
2925
|
* DERIVED from the capability registry (ADR-1239 Phase B, #1679) — the registry's
|
|
@@ -2942,9 +3086,111 @@ function restoreClaudeGlobalAtRefTilde(content, pathPrefix) {
|
|
|
2942
3086
|
*
|
|
2943
3087
|
* @private — exported as `_applyRuntimeRewrites` for tests.
|
|
2944
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
|
+
}
|
|
2945
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) {
|
|
2946
3191
|
const dirName = getDirName(runtime);
|
|
2947
3192
|
const normalizedPathPrefix = pathPrefix.replace(/\/$/, '');
|
|
3193
|
+
content = filterRuntimeNotesForTarget(content, runtime);
|
|
2948
3194
|
// #1521: stamp runtime identity + use_worktrees=false for every non-Claude runtime
|
|
2949
3195
|
// before brand-specific path rewrites, so the replace operates on the pristine
|
|
2950
3196
|
// source line and is idempotent regardless of subsequent path substitutions.
|
|
@@ -3280,7 +3526,9 @@ function rewriteStagedSkillBodies(stagedDir, opts) {
|
|
|
3280
3526
|
const isGlobal = (0, install_scope_cjs_1.isGlobalScope)(scope);
|
|
3281
3527
|
const isOpencode = false; // #2087: opencode installs via the combined-family engine path, never through the generic rewrite
|
|
3282
3528
|
const isWindowsHost = platform === 'win32';
|
|
3283
|
-
|
|
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) });
|
|
3284
3532
|
const attribution = resolveAttribution ? resolveAttribution(runtime) : undefined;
|
|
3285
3533
|
applyRuntimeContentRewritesInPlace(stagedDir, runtime, pathPrefix, isGlobal, attribution);
|
|
3286
3534
|
// #2873 (4b): claude, global scope only — see
|
|
@@ -3323,7 +3571,9 @@ function rewriteStagedCommandBodies(stagedDir, opts) {
|
|
|
3323
3571
|
const isGlobal = (0, install_scope_cjs_1.isGlobalScope)(scope);
|
|
3324
3572
|
const isOpencode = false; // #2087: opencode installs via the combined-family engine path, never through the generic rewrite
|
|
3325
3573
|
const isWindowsHost = platform === 'win32';
|
|
3326
|
-
|
|
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) });
|
|
3327
3577
|
const attribution = resolveAttribution ? resolveAttribution(runtime) : undefined;
|
|
3328
3578
|
return applyRuntimeContentRewritesForCommandsInPlace(stagedDir, runtime, pathPrefix, isGlobal, attribution);
|
|
3329
3579
|
}
|
|
@@ -3373,6 +3623,18 @@ function normalizeAgentBodyForRuntime(content, runtime, cmdNames) {
|
|
|
3373
3623
|
function applyAgentPathRewrites(content, runtime, pathPrefix) {
|
|
3374
3624
|
if (_hostBehaviors(runtime).noPathRewrite === true)
|
|
3375
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) {
|
|
3376
3638
|
const normalizedPathPrefix = pathPrefix.replace(/\/$/, '');
|
|
3377
3639
|
content = content.replace(/~\/\.claude\//g, pathPrefix);
|
|
3378
3640
|
content = content.replace(/\$HOME\/\.claude\//g, pathPrefix);
|
|
@@ -3613,6 +3875,7 @@ module.exports = {
|
|
|
3613
3875
|
neutralizeAgentReferences,
|
|
3614
3876
|
convertClaudeCommandToOpencodeSkill,
|
|
3615
3877
|
convertClaudeCommandToKiloSkill,
|
|
3878
|
+
filterRuntimeNotesForTarget,
|
|
3616
3879
|
// #2087 — opencode/kilo command-frontmatter converters, exported so the
|
|
3617
3880
|
// layout-driven `convertedCommandsKind` can resolve them by name (routes the
|
|
3618
3881
|
// opencode/kilo command install through the engine instead of the bespoke path).
|
|
@@ -3628,8 +3891,8 @@ module.exports = {
|
|
|
3628
3891
|
// #1182: agent converters + tool-name table dependency closure
|
|
3629
3892
|
claudeToCopilotTools,
|
|
3630
3893
|
convertCopilotToolName,
|
|
3631
|
-
|
|
3632
|
-
|
|
3894
|
+
claudeToAntigravityTools,
|
|
3895
|
+
convertAntigravityToolName,
|
|
3633
3896
|
convertClaudeAgentToCopilotAgent,
|
|
3634
3897
|
convertClaudeAgentToAntigravityAgent,
|
|
3635
3898
|
convertClaudeAgentToCursorAgent,
|
|
@@ -3673,6 +3936,12 @@ module.exports = {
|
|
|
3673
3936
|
READONLY_AGENT_DISALLOWED_TOOLS,
|
|
3674
3937
|
applyAgentFrontmatterExtensions,
|
|
3675
3938
|
_computePathPrefix: computePathPrefix,
|
|
3939
|
+
_withShellDefaultsPreserved: withShellDefaultsPreserved,
|
|
3940
|
+
_isRelativePathPrefix: isRelativePathPrefix,
|
|
3941
|
+
_relativeIncludesEnabled: relativeIncludesEnabled,
|
|
3942
|
+
_projectRelativePrefix: projectRelativePrefix,
|
|
3943
|
+
_projectRelativePrefixFromProjectRoot: projectRelativePrefixFromProjectRoot,
|
|
3944
|
+
_localIncludeDirName: localIncludeDirName,
|
|
3676
3945
|
_restoreClaudeGlobalAtRefTilde: restoreClaudeGlobalAtRefTilde,
|
|
3677
3946
|
_applyRuntimeRewrites,
|
|
3678
3947
|
_stampNonClaudeRuntimeDefaults,
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
// In .cts (CommonJS output) files, `require` is available as a global.
|
|
10
10
|
const _require = require;
|
|
11
11
|
const path = _require('node:path');
|
|
12
|
+
const { tryWithinRootLexical } = _require('./security.cjs');
|
|
12
13
|
// #2870: InstallScope is owned by install-scope.cts, not re-declared here.
|
|
13
14
|
// `isGlobalScope` centralizes the `scope === 'global'` boolean projection
|
|
14
15
|
// this module needs at `_computePathPrefix`'s `isGlobal: boolean` boundary
|
|
@@ -33,11 +34,19 @@ function assertDestWithinConfigHome(configDir, destSubpath) {
|
|
|
33
34
|
throw new Error(`destSubpath "${destSubpath}" contains a NUL byte and is not valid`);
|
|
34
35
|
}
|
|
35
36
|
const root = path.resolve(configDir);
|
|
36
|
-
|
|
37
|
-
|
|
37
|
+
// `resolved === root` is a DELIBERATE ADDITIONAL rejection, separate from
|
|
38
|
+
// the containment decision: `tryWithinRootLexical` treats target === root
|
|
39
|
+
// as CONTAINED, but a destSubpath of "" (or one that resolves to configDir
|
|
40
|
+
// itself) must never be accepted here — this is the strict-subpath
|
|
41
|
+
// requirement Phase B of ADR-1239 imposes on third-party descriptors, and
|
|
42
|
+
// it prevents a descriptor from writing at configHome itself. Kept as its
|
|
43
|
+
// own check per ADR-4650 decision 6 (a wrapper may add its own conditions
|
|
44
|
+
// on top of the canonical predicate, never invert it).
|
|
45
|
+
const contained = tryWithinRootLexical(destSubpath, configDir);
|
|
46
|
+
if (contained === null || contained === root) {
|
|
38
47
|
throw new Error(`destSubpath "${destSubpath}" must be a strict subpath of configHome "${configDir}" — not configHome itself or outside it (escapes configHome)`);
|
|
39
48
|
}
|
|
40
|
-
return
|
|
49
|
+
return contained;
|
|
41
50
|
}
|
|
42
51
|
function errorMessage(err) {
|
|
43
52
|
if (err instanceof Error)
|
|
@@ -83,7 +92,9 @@ function createRuntimeArtifactInstallPlan(args) {
|
|
|
83
92
|
const isGlobal = (0, install_scope_cjs_1.isGlobalScope)(scope);
|
|
84
93
|
const isOpencode = layout.runtime === 'opencode';
|
|
85
94
|
const isWindowsHost = (platform ?? process.platform) === 'win32';
|
|
86
|
-
|
|
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) });
|
|
87
98
|
const attribution = resolveAttribution ? resolveAttribution(layout.runtime) : undefined;
|
|
88
99
|
// #2875 Part 2 (row I1): layout.configDir IS the install root the inline
|
|
89
100
|
// agent loop called `targetDir` — same value, same resolution.
|