@opengsd/gsd-core 1.15.0 → 1.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/.opencode/plugins/gsd-core.js +85 -5
- package/agents/gsd-code-fixer.compact.md +1 -1
- package/agents/gsd-code-fixer.md +1 -1
- package/agents/gsd-code-reviewer.compact.md +5 -3
- package/agents/gsd-code-reviewer.md +8 -6
- package/agents/gsd-debug-session-manager.compact.md +1 -1
- package/agents/gsd-debug-session-manager.md +1 -1
- 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 +4 -4
- package/agents/gsd-intel-updater.compact.md +1 -1
- package/agents/gsd-intel-updater.md +1 -1
- package/agents/gsd-mempalace-curator.md +2 -2
- package/agents/gsd-phase-researcher.md +1 -1
- package/agents/gsd-plan-checker.md +7 -2
- package/agents/gsd-planner.md +3 -3
- 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.compact.md +21 -30
- package/agents/gsd-ui-auditor.md +42 -51
- package/agents/gsd-ui-researcher.compact.md +1 -1
- package/agents/gsd-ui-researcher.md +1 -1
- package/agents/gsd-verifier.md +31 -9
- package/bin/install.js +126 -196
- package/commands/gsd/add-tests.md +6 -1
- package/commands/gsd/ai-integration-phase.md +6 -1
- package/commands/gsd/audit-fix.md +5 -0
- package/commands/gsd/audit-milestone.md +6 -1
- package/commands/gsd/autonomous.md +5 -0
- package/commands/gsd/capture.md +8 -4
- package/commands/gsd/code-review.md +7 -2
- package/commands/gsd/complete-milestone.md +4 -0
- package/commands/gsd/config.md +7 -3
- package/commands/gsd/debug.md +11 -7
- package/commands/gsd/discuss-phase.md +7 -3
- package/commands/gsd/docs-update.md +12 -7
- package/commands/gsd/eval-review.md +6 -1
- package/commands/gsd/execute-phase.md +12 -7
- package/commands/gsd/extract-learnings.md +5 -0
- package/commands/gsd/fast.md +4 -0
- package/commands/gsd/forensics.md +5 -1
- package/commands/gsd/graphify.md +10 -6
- package/commands/gsd/health.md +5 -0
- package/commands/gsd/help.md +7 -2
- package/commands/gsd/import.md +7 -3
- package/commands/gsd/inbox.md +5 -0
- package/commands/gsd/ingest-docs.md +5 -1
- package/commands/gsd/manager.md +6 -1
- package/commands/gsd/map-codebase.md +7 -3
- package/commands/gsd/mempalace-capture.md +5 -1
- package/commands/gsd/mempalace-recall.md +5 -1
- package/commands/gsd/milestone-summary.md +5 -1
- package/commands/gsd/mvp-phase.md +8 -3
- package/commands/gsd/new-milestone.md +6 -1
- package/commands/gsd/new-project.md +5 -0
- package/commands/gsd/next.md +6 -1
- package/commands/gsd/ns-context.md +4 -0
- package/commands/gsd/ns-ideate.md +4 -0
- package/commands/gsd/ns-manage.md +4 -0
- package/commands/gsd/ns-project.md +4 -0
- package/commands/gsd/ns-review.md +4 -0
- package/commands/gsd/ns-workflow.md +4 -0
- package/commands/gsd/onboard.md +6 -1
- package/commands/gsd/pause-work.md +5 -1
- package/commands/gsd/phase.md +8 -4
- package/commands/gsd/plan-phase.md +6 -1
- package/commands/gsd/plan-review-convergence.md +5 -1
- package/commands/gsd/pr-branch.md +4 -0
- package/commands/gsd/profile-user.md +5 -1
- package/commands/gsd/progress.md +6 -1
- package/commands/gsd/quick-batch.md +20 -8
- package/commands/gsd/quick.md +12 -7
- package/commands/gsd/review.md +5 -1
- package/commands/gsd/secure-phase.md +6 -1
- package/commands/gsd/ship.md +5 -0
- package/commands/gsd/sketch.md +7 -2
- package/commands/gsd/spec-phase.md +5 -1
- package/commands/gsd/spike.md +8 -3
- package/commands/gsd/surface.md +5 -1
- package/commands/gsd/thread.md +4 -0
- package/commands/gsd/ui-phase.md +6 -1
- package/commands/gsd/ui-review.md +6 -1
- package/commands/gsd/ultraplan-phase.md +5 -1
- package/commands/gsd/undo.md +5 -1
- package/commands/gsd/update.md +6 -2
- package/commands/gsd/validate-phase.md +6 -1
- package/commands/gsd/verify-work.md +6 -1
- package/commands/gsd/workspace.md +7 -3
- package/gsd-core/bin/gsd-tools.cjs +142 -56
- package/gsd-core/bin/lib/active-workstream-store.cjs +15 -0
- package/gsd-core/bin/lib/agent-install-check.cjs +4 -1
- package/gsd-core/bin/lib/audit.cjs +78 -44
- package/gsd-core/bin/lib/broken-windows.cjs +13 -13
- package/gsd-core/bin/lib/capability-activation.cjs +9 -4
- package/gsd-core/bin/lib/capability-registry.cjs +183 -103
- package/gsd-core/bin/lib/capability-validator.cjs +16 -0
- package/gsd-core/bin/lib/check-auto-mode.cjs +35 -0
- package/gsd-core/bin/lib/check-command-router.cjs +164 -1712
- package/gsd-core/bin/lib/cjs-command-router-adapter.cjs +13 -2
- package/gsd-core/bin/lib/cli-exit.cjs +12 -0
- package/gsd-core/bin/lib/codex-agent-toml.cjs +11 -8
- package/gsd-core/bin/lib/command-aliases.cjs +7 -0
- package/gsd-core/bin/lib/command-routing-hub.cjs +48 -1
- package/gsd-core/bin/lib/commands.cjs +173 -170
- package/gsd-core/bin/lib/complexity-trigger.cjs +8 -7
- package/gsd-core/bin/lib/config.cjs +43 -12
- package/gsd-core/bin/lib/core-utils.cjs +6 -1
- package/gsd-core/bin/lib/coverage.cjs +4 -8
- package/gsd-core/bin/lib/decision-coverage-support.cjs +259 -0
- package/gsd-core/bin/lib/drift.cjs +177 -42
- package/gsd-core/bin/lib/frontmatter-fence.cjs +90 -0
- package/gsd-core/bin/lib/frontmatter-splice.cjs +494 -0
- package/gsd-core/bin/lib/frontmatter.cjs +413 -234
- package/gsd-core/bin/lib/gap-checker.cjs +72 -29
- package/gsd-core/bin/lib/gate-api-coverage-verify-pre.cjs +381 -0
- package/gsd-core/bin/lib/gate-args.cjs +53 -0
- package/gsd-core/bin/lib/gate-codebase-drift.cjs +285 -0
- package/gsd-core/bin/lib/gate-config.cjs +46 -0
- package/gsd-core/bin/lib/gate-context-drift.cjs +141 -0
- package/gsd-core/bin/lib/gate-decision-coverage-plan.cjs +169 -0
- package/gsd-core/bin/lib/gate-decision-coverage-verify.cjs +126 -0
- package/gsd-core/bin/lib/gate-evaluation-scope.cjs +555 -0
- package/gsd-core/bin/lib/gate-evidence.cjs +138 -0
- package/gsd-core/bin/lib/gate-exit.cjs +27 -0
- package/gsd-core/bin/lib/gate-gap-analysis-plan-post.cjs +61 -0
- package/gsd-core/bin/lib/gate-phase-context.cjs +170 -0
- package/gsd-core/bin/lib/gate-predicate-evaluator.cjs +1 -1
- package/gsd-core/bin/lib/gate-predicate.cjs +165 -0
- package/gsd-core/bin/lib/gate-prohibition-enforcement.cjs +94 -0
- package/gsd-core/bin/lib/gate-schema-drift.cjs +165 -0
- package/gsd-core/bin/lib/gate-tdd-red-evidence.cjs +100 -0
- package/gsd-core/bin/lib/gate-tdd-review-checkpoint.cjs +182 -0
- package/gsd-core/bin/lib/gate-ui-plan.cjs +86 -0
- package/gsd-core/bin/lib/gate-ui-safety.cjs +80 -0
- package/gsd-core/bin/lib/gate-verdict.cjs +64 -0
- package/gsd-core/bin/lib/gate-verify-command-paths.cjs +78 -0
- package/gsd-core/bin/lib/gate-verify-failure-directions.cjs +41 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/phase-structure.cjs +43 -47
- package/gsd-core/bin/lib/health-diagnostic.cjs +45 -8
- package/gsd-core/bin/lib/init.cjs +162 -96
- package/gsd-core/bin/lib/install-engine.cjs +19 -35
- package/gsd-core/bin/lib/install-profiles.cjs +7 -4
- package/gsd-core/bin/lib/io.cjs +122 -3
- package/gsd-core/bin/lib/loop-resolver.cjs +95 -0
- package/gsd-core/bin/lib/markdown-sectionizer.cjs +75 -1
- package/gsd-core/bin/lib/milestone.cjs +19 -1
- package/gsd-core/bin/lib/model-resolver.cjs +18 -18
- package/gsd-core/bin/lib/observability/event.cjs +1 -1
- package/gsd-core/bin/lib/observability/logger.cjs +46 -1
- package/gsd-core/bin/lib/pattern.cjs +10 -0
- package/gsd-core/bin/lib/phase-command-router.cjs +11 -4
- package/gsd-core/bin/lib/phase-estimation.cjs +5 -4
- package/gsd-core/bin/lib/phase-id.cjs +1 -1
- package/gsd-core/bin/lib/phase-lifecycle.cjs +9 -2
- package/gsd-core/bin/lib/phase-status.cjs +360 -0
- package/gsd-core/bin/lib/phase.cjs +280 -80
- package/gsd-core/bin/lib/plan-document.cjs +93 -19
- package/gsd-core/bin/lib/plan-drift-guard.cjs +5 -0
- package/gsd-core/bin/lib/planning-document.cjs +273 -40
- package/gsd-core/bin/lib/planning-inspect.cjs +42 -8
- package/gsd-core/bin/lib/planning-snapshot.cjs +18 -0
- package/gsd-core/bin/lib/planning-workspace.cjs +76 -53
- package/gsd-core/bin/lib/pristine-baseline.cjs +10 -0
- package/gsd-core/bin/lib/profile-output.cjs +6 -3
- package/gsd-core/bin/lib/prohibition-enforcement.cjs +0 -55
- package/gsd-core/bin/lib/quick-batch-command-router.cjs +35 -9
- package/gsd-core/bin/lib/quick-batch-dispatch.cjs +11 -8
- package/gsd-core/bin/lib/real-home-guard.cjs +9 -1
- package/gsd-core/bin/lib/report-parser.cjs +269 -0
- package/gsd-core/bin/lib/roadmap-command-router.cjs +13 -15
- package/gsd-core/bin/lib/roadmap-parser.cjs +82 -15
- package/gsd-core/bin/lib/roadmap-upgrade.cjs +127 -65
- package/gsd-core/bin/lib/roadmap.cjs +169 -72
- package/gsd-core/bin/lib/runtime-artifact-conversion.cjs +91 -157
- package/gsd-core/bin/lib/runtime-artifact-install-plan.cjs +2 -1
- package/gsd-core/bin/lib/runtime-artifact-layout.cjs +57 -1
- package/gsd-core/bin/lib/runtime-homes.cjs +13 -10
- package/gsd-core/bin/lib/runtime-hooks-surface.cjs +307 -591
- package/gsd-core/bin/lib/runtime-name-policy.cjs +142 -27
- package/gsd-core/bin/lib/runtime-slash.cjs +47 -30
- package/gsd-core/bin/lib/shell-command-projection.cjs +37 -2
- package/gsd-core/bin/lib/smart-entry.cjs +19 -3
- package/gsd-core/bin/lib/stale-bake-guard.cjs +32 -48
- package/gsd-core/bin/lib/state-contract.cjs +15 -18
- package/gsd-core/bin/lib/state-document.cjs +100 -22
- package/gsd-core/bin/lib/state.cjs +214 -105
- package/gsd-core/bin/lib/surface.cjs +2 -1
- package/gsd-core/bin/lib/tdd-red-evidence.cjs +48 -152
- package/gsd-core/bin/lib/uat-predicate.cjs +313 -35
- package/gsd-core/bin/lib/uat.cjs +424 -7
- package/gsd-core/bin/lib/ui-frontend-evidence.cjs +94 -58
- package/gsd-core/bin/lib/vendor/README.md +31 -9
- package/gsd-core/bin/lib/vendor/saxes.cjs +1934 -0
- package/gsd-core/bin/lib/vendor/saxes.cjs.LICENSE.txt +92 -0
- package/gsd-core/bin/lib/vendor/tap-parser.cjs +8927 -0
- package/gsd-core/bin/lib/vendor/tap-parser.cjs.LICENSE.txt +152 -0
- package/gsd-core/bin/lib/verification-command-router.cjs +2 -1
- package/gsd-core/bin/lib/verification.cjs +1165 -314
- package/gsd-core/bin/lib/verify-command-router.cjs +18 -7
- package/gsd-core/bin/lib/verify.cjs +286 -567
- package/gsd-core/bin/lib/workstream-inventory-builder.cjs +14 -6
- package/gsd-core/bin/lib/workstream-inventory.cjs +31 -21
- package/gsd-core/bin/lib/workstream-name-policy.cjs +31 -1
- package/gsd-core/bin/lib/workstream.cjs +11 -2
- package/gsd-core/bin/shared/config-defaults.manifest.json +5 -0
- package/gsd-core/bin/shared/config-schema.manifest.json +4 -0
- package/gsd-core/references/autonomous-smart-discuss.md +2 -1
- package/gsd-core/references/autonomous-ui-design-contract.md +3 -3
- package/gsd-core/references/execute-mvp-tdd.md +5 -10
- package/gsd-core/references/execute-phase-between-wave-reset.md +3 -0
- package/gsd-core/references/execute-phase-response-language.md +1 -1
- package/gsd-core/references/gsd-run-resolver.md +1 -1
- package/gsd-core/references/loop-hook-dispatch.md +7 -1
- package/gsd-core/references/offer-next.md +1 -1
- package/gsd-core/references/planning-config.md +1 -1
- package/gsd-core/references/spidr-splitting.md +1 -1
- package/gsd-core/references/tdd.md +10 -4
- package/gsd-core/references/verifier-phase-gates.md +5 -2
- package/gsd-core/references/verify-mvp-mode.md +2 -2
- package/gsd-core/references/workstream-flag.md +33 -3
- package/gsd-core/templates/README.md +1 -1
- package/gsd-core/templates/UAT.md +17 -1
- package/gsd-core/templates/config.json +2 -11
- 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 +8 -7
- package/gsd-core/workflows/add-tests.md +3 -2
- package/gsd-core/workflows/add-todo.md +4 -3
- package/gsd-core/workflows/ai-integration-phase.md +3 -2
- package/gsd-core/workflows/audit-fix.md +1 -1
- package/gsd-core/workflows/audit-milestone.md +4 -3
- package/gsd-core/workflows/audit-uat.md +1 -1
- package/gsd-core/workflows/autonomous.md +28 -18
- package/gsd-core/workflows/check-todos.md +6 -5
- package/gsd-core/workflows/cleanup.md +1 -1
- package/gsd-core/workflows/code-review/steps/structural-pre-pass.md +20 -13
- package/gsd-core/workflows/code-review-fix.md +5 -4
- package/gsd-core/workflows/code-review.md +84 -90
- package/gsd-core/workflows/complete-milestone/detail/elaboration.md +4 -3
- package/gsd-core/workflows/complete-milestone.md +12 -7
- package/gsd-core/workflows/debug.md +30 -5
- package/gsd-core/workflows/diagnose-issues.md +3 -2
- 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 +4 -3
- package/gsd-core/workflows/discuss-phase.md +4 -3
- package/gsd-core/workflows/do.md +1 -1
- package/gsd-core/workflows/docs-update.md +4 -3
- package/gsd-core/workflows/edit-phase.md +4 -3
- package/gsd-core/workflows/eval-review.md +5 -3
- package/gsd-core/workflows/execute-phase/detail/elaboration.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/code-review-disposition.md +4 -2
- package/gsd-core/workflows/execute-phase/steps/codebase-drift-gate.md +15 -4
- package/gsd-core/workflows/execute-phase/steps/completion-reconciliation.md +10 -7
- package/gsd-core/workflows/execute-phase/steps/executor-isolation-dispatch.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/gap-closure-artifacts.md +3 -1
- package/gsd-core/workflows/execute-phase/steps/partial-wave.md +2 -2
- 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 +1 -1
- package/gsd-core/workflows/execute-phase/steps/protected-branch.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/regression-gate-run.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/regression-gate.md +2 -0
- package/gsd-core/workflows/execute-phase/steps/tdd-applicability-resolution.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/verify-phase-goal.md +187 -0
- package/gsd-core/workflows/execute-phase/steps/wave-post-gate-hooks.md +2 -3
- package/gsd-core/workflows/execute-phase.md +78 -170
- package/gsd-core/workflows/execute-plan.md +13 -19
- package/gsd-core/workflows/explore.md +2 -2
- package/gsd-core/workflows/extract-learnings.md +3 -2
- 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 -1
- package/gsd-core/workflows/import.md +3 -2
- package/gsd-core/workflows/inbox.md +1 -1
- package/gsd-core/workflows/ingest-docs.md +1 -1
- package/gsd-core/workflows/insert-phase.md +4 -3
- package/gsd-core/workflows/list-seeds.md +1 -1
- package/gsd-core/workflows/list-workspaces.md +1 -1
- package/gsd-core/workflows/manager.md +5 -3
- package/gsd-core/workflows/map-codebase.md +4 -3
- package/gsd-core/workflows/milestone-summary.md +3 -2
- package/gsd-core/workflows/mvp-phase.md +14 -14
- package/gsd-core/workflows/new-milestone.md +10 -10
- package/gsd-core/workflows/new-project/steps/auto-mode-config.md +1 -1
- package/gsd-core/workflows/new-project.md +1 -1
- package/gsd-core/workflows/new-workspace.md +1 -1
- package/gsd-core/workflows/next.md +1 -1
- package/gsd-core/workflows/pause-work.md +2 -2
- package/gsd-core/workflows/plan-phase/detail/elaboration.md +1 -1
- package/gsd-core/workflows/plan-phase/steps/chunked-planning-mode.md +1 -1
- package/gsd-core/workflows/plan-phase/steps/closed-phase-gate.md +1 -1
- package/gsd-core/workflows/plan-phase/steps/prd-express-path.md +1 -1
- package/gsd-core/workflows/plan-phase/steps/stall-detection-helpers.md +1 -1
- package/gsd-core/workflows/plan-phase.md +27 -18
- package/gsd-core/workflows/plan-review-convergence.md +1 -1
- package/gsd-core/workflows/plant-seed.md +1 -1
- package/gsd-core/workflows/pr-branch.md +1 -1
- package/gsd-core/workflows/profile-user.md +1 -1
- package/gsd-core/workflows/progress.md +19 -49
- package/gsd-core/workflows/quick/steps/plan-checker-loop.md +4 -2
- package/gsd-core/workflows/quick/steps/quick-verification.md +4 -4
- package/gsd-core/workflows/quick/steps/worktree-pre-dispatch-commit.md +30 -11
- 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 +9 -3
- package/gsd-core/workflows/quick-batch/steps/worktree-dispatch.md +1 -1
- package/gsd-core/workflows/quick-batch.md +15 -10
- package/gsd-core/workflows/quick.md +42 -31
- package/gsd-core/workflows/remove-phase.md +3 -2
- package/gsd-core/workflows/remove-workspace.md +1 -1
- package/gsd-core/workflows/resume-project.md +3 -2
- package/gsd-core/workflows/review.md +3 -2
- package/gsd-core/workflows/scan.md +3 -2
- package/gsd-core/workflows/secure-phase.md +11 -12
- package/gsd-core/workflows/settings-advanced.md +1 -1
- package/gsd-core/workflows/settings-integrations.md +1 -1
- package/gsd-core/workflows/settings.md +1 -1
- package/gsd-core/workflows/ship.md +12 -12
- 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 +1 -1
- package/gsd-core/workflows/spec-phase.md +1 -1
- 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 +1 -1
- package/gsd-core/workflows/thread.md +2 -2
- package/gsd-core/workflows/transition.md +13 -23
- package/gsd-core/workflows/ui-phase.md +5 -4
- package/gsd-core/workflows/ui-review.md +4 -3
- package/gsd-core/workflows/ultraplan-phase.md +3 -2
- package/gsd-core/workflows/undo.md +1 -1
- package/gsd-core/workflows/validate-phase.md +10 -12
- package/gsd-core/workflows/verify-work/detail/elaboration.md +43 -3
- package/gsd-core/workflows/verify-work/steps/automated-ui-verification.md +1 -1
- package/gsd-core/workflows/verify-work/steps/mvp-uat-framing.md +5 -3
- package/gsd-core/workflows/verify-work.md +68 -59
- package/hooks/dist/gsd-agent-isolation-guard.js +8 -0
- package/hooks/dist/gsd-check-update-worker.js +8 -0
- package/hooks/dist/gsd-check-update.js +8 -0
- package/hooks/dist/gsd-context-monitor.js +31 -8
- package/hooks/dist/gsd-cursor-subagent-start.js +8 -0
- package/hooks/dist/gsd-secret-read-guard.js +147 -16
- package/hooks/dist/gsd-statusline.js +15 -7
- package/hooks/dist/gsd-update-banner.js +8 -0
- package/hooks/dist/gsd-windsurf-pre-write.js +11 -2
- package/hooks/dist/gsd-workflow-guard.js +5 -4
- package/hooks/dist/gsd-worktree-path-guard.js +6 -2
- package/hooks/dist/lib/cli-exit.js +12 -0
- package/hooks/dist/lib/git-probe.js +17 -1
- package/hooks/dist/lib/isolation-sentinel.js +2 -2
- package/hooks/gsd-agent-isolation-guard.js +8 -0
- package/hooks/gsd-check-update-worker.js +8 -0
- package/hooks/gsd-check-update.js +8 -0
- package/hooks/gsd-context-monitor.js +31 -8
- package/hooks/gsd-cursor-subagent-start.js +8 -0
- package/hooks/gsd-secret-read-guard.js +147 -16
- package/hooks/gsd-statusline.js +15 -7
- package/hooks/gsd-update-banner.js +8 -0
- package/hooks/gsd-windsurf-pre-write.js +11 -2
- package/hooks/gsd-workflow-guard.js +5 -4
- package/hooks/gsd-worktree-path-guard.js +6 -2
- package/hooks/hooks.json +5 -5
- package/hooks/lib/cli-exit.js +12 -0
- package/hooks/lib/git-probe.js +17 -1
- package/hooks/lib/isolation-sentinel.js +2 -2
- package/package.json +21 -4
- package/scripts/changeset/parse.cjs +52 -4
- package/scripts/ci-timeout-report.cjs +770 -4
- package/scripts/command-contract-helpers.cjs +12 -8
- package/scripts/docs-guard-registry.cjs +6 -0
- package/scripts/gen-features.cjs +13 -8
- package/scripts/gen-hooks-cli-exit.cjs +12 -28
- package/scripts/gen-loop-host-contract.cjs +10 -1
- package/scripts/gen-platform-conformance-tier.cjs +187 -1
- package/scripts/gen-plugin-skills.cjs +87 -1
- package/scripts/gen-research-agents.cjs +24 -31
- package/scripts/gen-scripts-cli-exit.cjs +30 -3
- package/scripts/gen-test-timings.cjs +32 -7
- package/scripts/lib/cli-exit.cjs +12 -0
- package/scripts/lib/macos-conformance-tier.generated.cjs +20 -2
- package/scripts/lib/ndjson-reporter.cjs +28 -3
- package/scripts/lib/platform-conformance-tier.generated.cjs +34 -5
- package/scripts/lib/registration-ledger-preload.cjs +155 -0
- package/scripts/lib/vendor-bundle.cjs +59 -0
- package/scripts/lib/vendor-licenses/saxes-6.0.0.txt +64 -0
- package/scripts/lint-allow-test-rule-refs.effective-ceiling.json +1 -1
- package/scripts/lint-allow-test-rule-refs.unverified-ceiling.json +1 -1
- package/scripts/lint-completion-predicate-drift.cjs +18 -19
- package/scripts/lint-descriptions.cjs +7 -3
- package/scripts/lint-docs-guard-registration.exempt-baseline.cjs +10 -0
- package/scripts/lint-eslint-glob-coverage.allowlist.json +20 -0
- package/scripts/lint-frontmatter-fence-drift.cjs +313 -0
- package/scripts/lint-frontmatter-scalar-broad-grep.cjs +122 -16
- package/scripts/lint-phase-enumeration-drift.cjs +12 -8
- package/scripts/lint-phase-id-drift.cjs +29 -0
- package/scripts/lint-planning-document-positive-control.cjs +329 -0
- package/scripts/lint-response-language-coverage.cjs +3 -0
- package/scripts/lint-skill-deps.cjs +7 -3
- package/scripts/lint-test-file-count.allowlist.json +11 -1
- package/scripts/lint-test-file-count.cjs +34 -1
- package/scripts/lint-vendored-deps.cjs +41 -5
- package/scripts/lint-workflow-shellcheck-baseline.json +10 -10
- package/scripts/mutation-matrix.cjs +50 -5
- package/scripts/require-issue-link-policy.cjs +6 -2
- package/scripts/sync-runtime-launcher.cjs +184 -2
- package/scripts/verify-npm-publish.cjs +76 -20
- package/skills/gsd-add-tests/SKILL.md +6 -1
- package/skills/gsd-ai-integration-phase/SKILL.md +6 -1
- package/skills/gsd-audit-fix/SKILL.md +5 -0
- package/skills/gsd-audit-milestone/SKILL.md +6 -1
- package/skills/gsd-autonomous/SKILL.md +5 -0
- package/skills/gsd-capture/SKILL.md +8 -4
- package/skills/gsd-code-review/SKILL.md +7 -2
- package/skills/gsd-complete-milestone/SKILL.md +4 -0
- package/skills/gsd-config/SKILL.md +8 -4
- package/skills/gsd-debug/SKILL.md +11 -7
- package/skills/gsd-discuss-phase/SKILL.md +7 -3
- package/skills/gsd-docs-update/SKILL.md +12 -7
- package/skills/gsd-eval-review/SKILL.md +6 -1
- package/skills/gsd-execute-phase/SKILL.md +12 -7
- package/skills/gsd-extract-learnings/SKILL.md +5 -0
- package/skills/gsd-fast/SKILL.md +4 -0
- package/skills/gsd-forensics/SKILL.md +5 -1
- package/skills/gsd-graphify/SKILL.md +10 -6
- package/skills/gsd-health/SKILL.md +5 -0
- package/skills/gsd-help/SKILL.md +7 -2
- package/skills/gsd-import/SKILL.md +7 -3
- package/skills/gsd-inbox/SKILL.md +5 -0
- package/skills/gsd-ingest-docs/SKILL.md +5 -1
- package/skills/gsd-manager/SKILL.md +6 -1
- package/skills/gsd-map-codebase/SKILL.md +7 -3
- package/skills/gsd-mempalace-capture/SKILL.md +5 -1
- package/skills/gsd-mempalace-recall/SKILL.md +5 -1
- package/skills/gsd-milestone-summary/SKILL.md +5 -1
- package/skills/gsd-mvp-phase/SKILL.md +8 -3
- package/skills/gsd-new-milestone/SKILL.md +6 -1
- package/skills/gsd-new-project/SKILL.md +5 -0
- package/skills/gsd-next/SKILL.md +6 -1
- package/skills/gsd-ns-context/SKILL.md +4 -0
- package/skills/gsd-ns-ideate/SKILL.md +4 -0
- package/skills/gsd-ns-manage/SKILL.md +4 -0
- package/skills/gsd-ns-project/SKILL.md +4 -0
- package/skills/gsd-ns-review/SKILL.md +4 -0
- package/skills/gsd-ns-workflow/SKILL.md +4 -0
- package/skills/gsd-onboard/SKILL.md +6 -1
- package/skills/gsd-pause-work/SKILL.md +5 -1
- package/skills/gsd-phase/SKILL.md +8 -4
- package/skills/gsd-plan-phase/SKILL.md +6 -1
- package/skills/gsd-plan-review-convergence/SKILL.md +5 -1
- package/skills/gsd-pr-branch/SKILL.md +4 -0
- package/skills/gsd-profile-user/SKILL.md +5 -1
- package/skills/gsd-progress/SKILL.md +6 -1
- package/skills/gsd-quick/SKILL.md +16 -10
- package/skills/gsd-quick-batch/SKILL.md +20 -8
- package/skills/gsd-review/SKILL.md +5 -1
- package/skills/gsd-review-backlog/SKILL.md +3 -2
- package/skills/gsd-secure-phase/SKILL.md +6 -1
- package/skills/gsd-ship/SKILL.md +5 -0
- package/skills/gsd-sketch/SKILL.md +7 -2
- package/skills/gsd-spec-phase/SKILL.md +5 -1
- package/skills/gsd-spike/SKILL.md +8 -3
- package/skills/gsd-surface/SKILL.md +5 -1
- package/skills/gsd-thread/SKILL.md +4 -0
- package/skills/gsd-ui-phase/SKILL.md +6 -1
- package/skills/gsd-ui-review/SKILL.md +6 -1
- package/skills/gsd-ultraplan-phase/SKILL.md +5 -1
- package/skills/gsd-undo/SKILL.md +5 -1
- package/skills/gsd-update/SKILL.md +6 -2
- package/skills/gsd-validate-phase/SKILL.md +6 -1
- package/skills/gsd-verify-work/SKILL.md +6 -1
- package/skills/gsd-workspace/SKILL.md +7 -3
- package/skills/gsd-workstreams/SKILL.md +6 -6
- package/vscode/package.json +1 -1
- package/gsd-core/workflows/execute-phase/steps/stale-reverification.md +0 -24
package/bin/install.js
CHANGED
|
@@ -49,7 +49,7 @@ const { isTestHomeGuardRefusal } = require('../gsd-core/bin/lib/real-home-guard.
|
|
|
49
49
|
// (getConfigDirFromHome and the runtime-content-rewrite loops below) — #2876
|
|
50
50
|
// retired the re-export; tests now import getDirName directly from
|
|
51
51
|
// gsd-core/bin/lib/runtime-name-policy.cjs.
|
|
52
|
-
const { getDirName, getRuntimeLabel, getGlobalConfigHomeFragment, runtimeFlags,
|
|
52
|
+
const { getDirName, getRuntimeLabel, getGlobalConfigHomeFragment, runtimeFlags, hostBehaviorsFor } = require('../gsd-core/bin/lib/runtime-name-policy.cjs');
|
|
53
53
|
const {
|
|
54
54
|
applyWorktreeBaseRef,
|
|
55
55
|
readBaseRefFromSettings,
|
|
@@ -104,7 +104,7 @@ const hooksSurface = require('../gsd-core/bin/lib/runtime-hooks-surface.cjs');
|
|
|
104
104
|
*/
|
|
105
105
|
function shouldNormalizeHyphenNamespaceInAgentBody(runtime) {
|
|
106
106
|
if (typeof runtime !== 'string' || runtime === '') return false;
|
|
107
|
-
return
|
|
107
|
+
return hostBehaviorsFor(runtime).hyphenNameAgentBody === true;
|
|
108
108
|
}
|
|
109
109
|
|
|
110
110
|
/**
|
|
@@ -436,7 +436,7 @@ const GSD_CHANGESET_FILES = [
|
|
|
436
436
|
'github-release-notes.cjs', 'lint.cjs', 'new.cjs',
|
|
437
437
|
'README.md', // documentation only — not user-authored
|
|
438
438
|
];
|
|
439
|
-
const GSD_SCRIPTS_LIB_FILES = ['cli-exit.cjs', 'allowlist-ratchet.cjs', 'drift-scan.cjs', 'alias-drift-families.cjs', 'exit-code-registry.cjs', 'ndjson-reporter.cjs', 'ci-job-timing.cjs', 'shellcheck-fetch.cjs', 'npm-version-check-diagnosis.cjs', 'platform-conformance-tier.generated.cjs', 'suite-detection.cjs', 'macos-conformance-tier.generated.cjs'];
|
|
439
|
+
const GSD_SCRIPTS_LIB_FILES = ['cli-exit.cjs', 'allowlist-ratchet.cjs', 'drift-scan.cjs', 'alias-drift-families.cjs', 'exit-code-registry.cjs', 'ndjson-reporter.cjs', 'ci-job-timing.cjs', 'shellcheck-fetch.cjs', 'npm-version-check-diagnosis.cjs', 'platform-conformance-tier.generated.cjs', 'suite-detection.cjs', 'macos-conformance-tier.generated.cjs', 'vendor-bundle.cjs', 'registration-ledger-preload.cjs'];
|
|
440
440
|
|
|
441
441
|
// #4544 — the Codex hook payload the install stages into <targetDir>/hooks/.
|
|
442
442
|
// Hoisted to module scope (the #3184 precedent above) so the rollback's
|
|
@@ -473,7 +473,7 @@ const CODEX_HOOKS_TO_COPY = [
|
|
|
473
473
|
* @returns {string}
|
|
474
474
|
*/
|
|
475
475
|
function resolveSharedHooksDirName(runtime) {
|
|
476
|
-
const raw =
|
|
476
|
+
const raw = hostBehaviorsFor(runtime).sharedHooksDirName;
|
|
477
477
|
if (typeof raw !== 'string') return SHARED_HOOKS_DIR_DEFAULT;
|
|
478
478
|
const name = raw.trim();
|
|
479
479
|
if (name === '') return SHARED_HOOKS_DIR_DEFAULT;
|
|
@@ -628,68 +628,6 @@ try {
|
|
|
628
628
|
_installedCapabilityRegistry = _capabilityRegistry;
|
|
629
629
|
}
|
|
630
630
|
|
|
631
|
-
// Fail-safe floor for the reference host's #338-privacy-critical behaviors, used
|
|
632
|
-
// ONLY when the first-party capability registry cannot be loaded (a broken bundle).
|
|
633
|
-
// Without it, a registry-load failure would make `_hostBehaviors('claude')` return
|
|
634
|
-
// {} and silently route a claude LOCAL install to the repo-shared, committed
|
|
635
|
-
// `settings.json` instead of the gitignored `settings.local.json` (#338) — leaking
|
|
636
|
-
// engineer-specific absolute paths. Keyed by runtime id (a DATA lookup, not a
|
|
637
|
-
// hardcoded string-equality branch) so behavior degrades CLOSED (safe), never open.
|
|
638
|
-
// The live descriptor (capabilities/claude/capability.json) remains the source of
|
|
639
|
-
// truth; this mirrors only the privacy-load-bearing subset. (ADR-1239 / #2086)
|
|
640
|
-
//
|
|
641
|
-
// #2870: NOT routed through the Install Scope Module (resolveScope,
|
|
642
|
-
// src/install-scope.cts) despite that module owning per-scope settings-file
|
|
643
|
-
// resolution elsewhere in this file. resolveScope's own descriptor lookup
|
|
644
|
-
// goes through the SAME capability registry require this floor exists to
|
|
645
|
-
// survive the failure of (see getRegistry() in install-scope.cts) — so on
|
|
646
|
-
// exactly the "registry failed to load" path this constant is for,
|
|
647
|
-
// resolveScope would throw too. Routing through it here would trade a
|
|
648
|
-
// graceful, documented degrade for a crash in the one case this floor was
|
|
649
|
-
// added to prevent. This hardcoded literal is the correct, honest answer,
|
|
650
|
-
// not an un-migrated leftover.
|
|
651
|
-
const FALLBACK_HOST_BEHAVIORS = Object.freeze({
|
|
652
|
-
claude: Object.freeze({
|
|
653
|
-
settingsFileByScope: Object.freeze({ local: 'settings.local.json', global: 'settings.json' }),
|
|
654
|
-
permissionsSchema: 'claude',
|
|
655
|
-
sourceMarkerFile: '.gsd-source',
|
|
656
|
-
hyphenNameAgentBody: true,
|
|
657
|
-
legacyCommandsGsdInstallMigration: true,
|
|
658
|
-
legacyCommandsGsdUninstall: 'global',
|
|
659
|
-
}),
|
|
660
|
-
// antigravity's global config dir is resolved dynamically (env-overridable,
|
|
661
|
-
// multi-segment) via resolveAntigravityGlobalDir in getConfigDirFromHome. If the
|
|
662
|
-
// registry fails to load, this floor keeps that routing intact instead of
|
|
663
|
-
// silently falling through to the generic getGlobalConfigHomeFragment default
|
|
664
|
-
// (which would return the wrong '.claude' fragment). (ADR-1239 / #2096)
|
|
665
|
-
antigravity: Object.freeze({ globalDirResolver: 'antigravity' }),
|
|
666
|
-
});
|
|
667
|
-
|
|
668
|
-
/**
|
|
669
|
-
* Resolve a runtime's host behaviors from a capability registry, with the
|
|
670
|
-
* #338-privacy fail-safe floor when the registry (or the runtime's descriptor)
|
|
671
|
-
* is unavailable. Registry is passed in so this is unit-testable under a
|
|
672
|
-
* simulated registry-load failure. (ADR-1239 / #2086)
|
|
673
|
-
*/
|
|
674
|
-
function _resolveHostBehaviors(runtime, registry) {
|
|
675
|
-
const cap = registry && registry.runtimes && registry.runtimes[runtime];
|
|
676
|
-
const declared = cap && cap.runtime && cap.runtime.hostBehaviors;
|
|
677
|
-
if (declared) return declared;
|
|
678
|
-
return FALLBACK_HOST_BEHAVIORS[runtime] || {};
|
|
679
|
-
}
|
|
680
|
-
|
|
681
|
-
/**
|
|
682
|
-
* Host-specific install behaviors, declared on the runtime descriptor
|
|
683
|
-
* (capabilities/<runtime>/capability.json -> runtime.hostBehaviors) instead of
|
|
684
|
-
* scattered `runtime === '<id>'` string checks (ADR-1239 / #2086). Returns {}
|
|
685
|
-
* for runtimes that declare none, so every behavior branch degrades to the
|
|
686
|
-
* generic path by default — EXCEPT the reference host's #338-critical keys, which
|
|
687
|
-
* fall back to FALLBACK_HOST_BEHAVIORS if the registry failed to load.
|
|
688
|
-
*/
|
|
689
|
-
function _hostBehaviors(runtime) {
|
|
690
|
-
return _resolveHostBehaviors(runtime, _capabilityRegistry);
|
|
691
|
-
}
|
|
692
|
-
|
|
693
631
|
/**
|
|
694
632
|
* Read a runtime's documentation-sourced `hostIntegration.dispatch` axes
|
|
695
633
|
* (ADR-1239 Phase A — `capabilities/<runtime>/capability.json`
|
|
@@ -697,7 +635,7 @@ function _hostBehaviors(runtime) {
|
|
|
697
635
|
* background, backgroundDispatch, subagentToolkit}`. These are validated,
|
|
698
636
|
* closed-vocabulary FACTS about what the runtime's real dispatch primitive
|
|
699
637
|
* supports (never inferred) — see `docs/reference/host-integration-capability-
|
|
700
|
-
* matrix.md` for citations. Unlike `
|
|
638
|
+
* matrix.md` for citations. Unlike `hostBehaviorsFor` (install *policy*), this is
|
|
701
639
|
* the negotiated *capability* surface; #2284 is its first content-projection
|
|
702
640
|
* consumer (previously read only by `shouldFlattenDispatch`). Returns `{}` if
|
|
703
641
|
* the registry or the runtime's descriptor is unavailable, so callers must
|
|
@@ -833,6 +771,7 @@ const {
|
|
|
833
771
|
} = require(path.join(_gsdLibDir, 'installer-migration-report.cjs'));
|
|
834
772
|
const {
|
|
835
773
|
resolveRuntimeArtifactLayout,
|
|
774
|
+
resolveAdvertisedNewProject,
|
|
836
775
|
} = require(path.join(_gsdLibDir, 'runtime-artifact-layout.cjs'));
|
|
837
776
|
const {
|
|
838
777
|
readSurface,
|
|
@@ -1178,13 +1117,13 @@ function getConfigDirFromHome(runtime, isGlobal) {
|
|
|
1178
1117
|
// !isGlobal returns at the top of this function.)
|
|
1179
1118
|
// Descriptor-driven (ADR-1239 / #2096): folded from a hardcoded
|
|
1180
1119
|
// `runtime === 'antigravity'` literal into a read of the runtime's
|
|
1181
|
-
// `hostBehaviors.globalDirResolver` descriptor field (via
|
|
1182
|
-
// also degrades to
|
|
1120
|
+
// `hostBehaviors.globalDirResolver` descriptor field (via hostBehaviorsFor, which
|
|
1121
|
+
// also degrades to its #338 floor on registry-load failure). This is
|
|
1183
1122
|
// antigravity-unique: unlike `configHome.kind === 'dot-home-nested'` (which
|
|
1184
1123
|
// windsurf also declares — see capabilities/windsurf/capability.json — and
|
|
1185
1124
|
// would wrongly route windsurf's global dir through
|
|
1186
1125
|
// resolveAntigravityGlobalDir), `globalDirResolver` is only set by antigravity.
|
|
1187
|
-
if (
|
|
1126
|
+
if (hostBehaviorsFor(runtime).globalDirResolver === 'antigravity') {
|
|
1188
1127
|
const antigravityDir = resolveAntigravityGlobalDir();
|
|
1189
1128
|
const rel = path.relative(os.homedir(), antigravityDir);
|
|
1190
1129
|
const segments = rel.split(path.sep).filter(Boolean);
|
|
@@ -1594,12 +1533,12 @@ function getCommitAttribution(runtime) {
|
|
|
1594
1533
|
|
|
1595
1534
|
let result;
|
|
1596
1535
|
|
|
1597
|
-
const _attrResolverKey =
|
|
1536
|
+
const _attrResolverKey = hostBehaviorsFor(runtime).attributionConfigResolver;
|
|
1598
1537
|
if (_attrResolverKey && ATTRIBUTION_CONFIG_RESOLVERS[_attrResolverKey]) {
|
|
1599
1538
|
const resolveConfigPath = ATTRIBUTION_CONFIG_RESOLVERS[_attrResolverKey];
|
|
1600
1539
|
const config = readSettings(resolveConfigPath(getGlobalConfigDir(runtime, null)));
|
|
1601
1540
|
result = (config && config.disable_ai_attribution === true) ? null : undefined;
|
|
1602
|
-
} else if (
|
|
1541
|
+
} else if (hostBehaviorsFor(runtime).attributionSource === 'settings-json-commit') {
|
|
1603
1542
|
// Claude Code
|
|
1604
1543
|
const settings = readSettings(path.join(getGlobalConfigDir(runtime, explicitConfigDir), 'settings.json'));
|
|
1605
1544
|
if (!settings || !settings.attribution || settings.attribution.commit === undefined) {
|
|
@@ -2084,13 +2023,13 @@ function convertClaudeCommandToClaudeSkill(content, skillName, runtime = null, c
|
|
|
2084
2023
|
// Hermes' SKILL.md spec lists `version` as a required frontmatter field.
|
|
2085
2024
|
// Track GSD's package version so Hermes' skill_view() reports a stable
|
|
2086
2025
|
// identifier per install.
|
|
2087
|
-
if (
|
|
2026
|
+
if (hostBehaviorsFor(runtime).skillFrontmatterVersion) fm += `version: ${yamlQuote(pkg.version)}\n`;
|
|
2088
2027
|
// #778 (b) — numeric priority for /skills ordering, declared on the runtime
|
|
2089
2028
|
// descriptor (runtime.hostBehaviors.skillPriorityFrontmatter). Scoped to
|
|
2090
2029
|
// runtimes that declare the flag so Claude/Hermes skill frontmatter is
|
|
2091
2030
|
// unchanged (they ignore the field, but we keep their output byte-stable).
|
|
2092
2031
|
// skillName is the `gsd-<stem>` dir name. (ADR-1239 / #2086)
|
|
2093
|
-
if (
|
|
2032
|
+
if (hostBehaviorsFor(runtime).skillPriorityFrontmatter) {
|
|
2094
2033
|
const stem = typeof skillName === 'string' && skillName.startsWith('gsd-')
|
|
2095
2034
|
? skillName.slice(4)
|
|
2096
2035
|
: skillName;
|
|
@@ -2555,20 +2494,11 @@ function yamlIdentifier(value) {
|
|
|
2555
2494
|
return yamlQuote(text);
|
|
2556
2495
|
}
|
|
2557
2496
|
|
|
2497
|
+
// The frontmatter block is the one the one fence owner (`locateFrontmatterFence`) finds, read
|
|
2498
|
+
// through the conversion module's reader — never a local `indexOf('---', 3)` scan, which ended
|
|
2499
|
+
// the block at the first `---` anywhere, even inside a value (found while implementing #5105).
|
|
2558
2500
|
function extractFrontmatterAndBody(content) {
|
|
2559
|
-
|
|
2560
|
-
return { frontmatter: null, body: content };
|
|
2561
|
-
}
|
|
2562
|
-
|
|
2563
|
-
const endIndex = content.indexOf('---', 3);
|
|
2564
|
-
if (endIndex === -1) {
|
|
2565
|
-
return { frontmatter: null, body: content };
|
|
2566
|
-
}
|
|
2567
|
-
|
|
2568
|
-
return {
|
|
2569
|
-
frontmatter: content.substring(3, endIndex).trim(),
|
|
2570
|
-
body: content.substring(endIndex + 3),
|
|
2571
|
-
};
|
|
2501
|
+
return runtimeArtifactConversion.extractFrontmatterAndBody(content);
|
|
2572
2502
|
}
|
|
2573
2503
|
|
|
2574
2504
|
function extractFrontmatterField(frontmatter, fieldName) {
|
|
@@ -2813,7 +2743,7 @@ function convertClaudeCommandToTraeSkill(content, skillName) {
|
|
|
2813
2743
|
// is not formally documented (thin SPA docs) — descriptor-driven, single
|
|
2814
2744
|
// fixed GSD-side value (runtime.hostBehaviors.soloStageMetadata), inferred/
|
|
2815
2745
|
// best-effort.
|
|
2816
|
-
const soloStage =
|
|
2746
|
+
const soloStage = hostBehaviorsFor('trae').soloStageMetadata;
|
|
2817
2747
|
if (soloStage) fm += `stage: ${soloStage}\n`;
|
|
2818
2748
|
fm += '---';
|
|
2819
2749
|
return `${fm}\n${body}`;
|
|
@@ -3806,7 +3736,7 @@ const HERMES_DISPATCH_TOOL_CONFIG = Object.freeze({
|
|
|
3806
3736
|
*/
|
|
3807
3737
|
function convertClaudeToHermesMarkdown(content, ctx) {
|
|
3808
3738
|
const runtime = (ctx && ctx.runtime) || 'hermes';
|
|
3809
|
-
const b =
|
|
3739
|
+
const b = hostBehaviorsFor(runtime).brandingRewrites;
|
|
3810
3740
|
let converted = content;
|
|
3811
3741
|
if (b) {
|
|
3812
3742
|
converted = converted.replace(/CLAUDE\.md/g, b['CLAUDE.md']);
|
|
@@ -7040,7 +6970,7 @@ function writeCopilotHookConfig(targetDir) {
|
|
|
7040
6970
|
* model aliases). Preserves an explicit `true` opt-in and existing values.
|
|
7041
6971
|
*/
|
|
7042
6972
|
function writeNonClaudeDefaults(runtime) {
|
|
7043
|
-
if (
|
|
6973
|
+
if (hostBehaviorsFor(runtime).nativeModelAliases || process.env.GSD_TEST_MODE) return;
|
|
7044
6974
|
const gsdDir = path.join(os.homedir(), '.gsd');
|
|
7045
6975
|
const defaultsPath = path.join(gsdDir, 'defaults.json');
|
|
7046
6976
|
let releaseLock = null;
|
|
@@ -7271,20 +7201,12 @@ function convertClaudeToOpencodeFrontmatter(content, { isAgent = false, modelOve
|
|
|
7271
7201
|
// Runtime-neutral agent name replacement (#766)
|
|
7272
7202
|
convertedContent = neutralizeAgentReferences(convertedContent, 'AGENTS.md');
|
|
7273
7203
|
|
|
7274
|
-
//
|
|
7275
|
-
|
|
7276
|
-
|
|
7277
|
-
}
|
|
7278
|
-
|
|
7279
|
-
// Find the end of frontmatter
|
|
7280
|
-
const endIndex = convertedContent.indexOf('---', 3);
|
|
7281
|
-
if (endIndex === -1) {
|
|
7204
|
+
// The frontmatter block, as the one fence owner finds it (none → nothing to convert).
|
|
7205
|
+
const { frontmatter, body } = extractFrontmatterAndBody(convertedContent);
|
|
7206
|
+
if (frontmatter === null) {
|
|
7282
7207
|
return convertedContent;
|
|
7283
7208
|
}
|
|
7284
7209
|
|
|
7285
|
-
const frontmatter = convertedContent.substring(3, endIndex).trim();
|
|
7286
|
-
const body = convertedContent.substring(endIndex + 3);
|
|
7287
|
-
|
|
7288
7210
|
// Parse frontmatter line by line (simple YAML parsing)
|
|
7289
7211
|
const lines = frontmatter.split('\n');
|
|
7290
7212
|
const newLines = [];
|
|
@@ -7438,20 +7360,12 @@ function convertClaudeToKiloFrontmatter(content, { isAgent = false, modelOverrid
|
|
|
7438
7360
|
// Runtime-neutral agent name replacement (#766)
|
|
7439
7361
|
convertedContent = neutralizeAgentReferences(convertedContent, 'AGENTS.md');
|
|
7440
7362
|
|
|
7441
|
-
//
|
|
7442
|
-
|
|
7443
|
-
|
|
7444
|
-
}
|
|
7445
|
-
|
|
7446
|
-
// Find the end of frontmatter
|
|
7447
|
-
const endIndex = convertedContent.indexOf('---', 3);
|
|
7448
|
-
if (endIndex === -1) {
|
|
7363
|
+
// The frontmatter block, as the one fence owner finds it (none → nothing to convert).
|
|
7364
|
+
const { frontmatter, body } = extractFrontmatterAndBody(convertedContent);
|
|
7365
|
+
if (frontmatter === null) {
|
|
7449
7366
|
return convertedContent;
|
|
7450
7367
|
}
|
|
7451
7368
|
|
|
7452
|
-
const frontmatter = convertedContent.substring(3, endIndex).trim();
|
|
7453
|
-
const body = convertedContent.substring(endIndex + 3);
|
|
7454
|
-
|
|
7455
7369
|
// Parse frontmatter line by line (simple YAML parsing)
|
|
7456
7370
|
const lines = frontmatter.split('\n');
|
|
7457
7371
|
const newLines = [];
|
|
@@ -7825,7 +7739,7 @@ const RUNTIME_CONTENT_DISPATCH = {
|
|
|
7825
7739
|
},
|
|
7826
7740
|
},
|
|
7827
7741
|
// qwen/hermes: brand VALUES are descriptor-driven (ADR-1239 / #2092) via
|
|
7828
|
-
//
|
|
7742
|
+
// hostBehaviorsFor(ctx.runtime).brandingRewrites — EXACT regexes/ordering
|
|
7829
7743
|
// preserved from the prior hardcoded-literal versions (including the
|
|
7830
7744
|
// qwen-specific `.claude/skills/` -> `.qwen/skills/` pre-rewrite, whose
|
|
7831
7745
|
// target is derived as `${b['.claude/']}skills/`).
|
|
@@ -7833,7 +7747,7 @@ const RUNTIME_CONTENT_DISPATCH = {
|
|
|
7833
7747
|
md: (content, ctx) => {
|
|
7834
7748
|
// Guarded (post-review #2092): degrade closed to a no-op if the
|
|
7835
7749
|
// registry fails to load, instead of throwing on `b['CLAUDE.md']`.
|
|
7836
|
-
const b =
|
|
7750
|
+
const b = hostBehaviorsFor(ctx.runtime).brandingRewrites;
|
|
7837
7751
|
if (b) {
|
|
7838
7752
|
content = content.replace(/CLAUDE\.md/g, b['CLAUDE.md']);
|
|
7839
7753
|
// #2284(b): skips <runtime_compatibility> comparison-table content (protected region).
|
|
@@ -7843,7 +7757,7 @@ const RUNTIME_CONTENT_DISPATCH = {
|
|
|
7843
7757
|
return content;
|
|
7844
7758
|
},
|
|
7845
7759
|
js: (content, ctx) => {
|
|
7846
|
-
const b =
|
|
7760
|
+
const b = hostBehaviorsFor(ctx.runtime).brandingRewrites;
|
|
7847
7761
|
if (b) {
|
|
7848
7762
|
content = content.replace(/\.claude\/skills\//g, `${b['.claude/']}skills/`);
|
|
7849
7763
|
content = content.replace(/\.claude\//g, b['.claude/']);
|
|
@@ -7862,7 +7776,7 @@ const RUNTIME_CONTENT_DISPATCH = {
|
|
|
7862
7776
|
// hostIntegration.dispatch facts.
|
|
7863
7777
|
md: (content, ctx) => convertClaudeToHermesMarkdown(content, ctx),
|
|
7864
7778
|
js: (content, ctx) => {
|
|
7865
|
-
const b =
|
|
7779
|
+
const b = hostBehaviorsFor(ctx.runtime).brandingRewrites;
|
|
7866
7780
|
if (b) {
|
|
7867
7781
|
content = content.replace(/\.claude\/skills\//g, `${b['.claude/']}skills/`);
|
|
7868
7782
|
content = content.replace(/\.claude\//g, b['.claude/']);
|
|
@@ -8025,7 +7939,7 @@ function copyWithPathReplacement(srcDir, destDir, pathPrefix, runtime, isCommand
|
|
|
8025
7939
|
// emit path, which never had it: every @~/.claude/gsd-core/… include
|
|
8026
7940
|
// in a global install's workflows/references tree silently resolved
|
|
8027
7941
|
// to nothing (54 includes across 22 files on a live install).
|
|
8028
|
-
if (runtime
|
|
7942
|
+
if (hostBehaviorsFor(runtime).restoreAtRefTildeInSpecTree) {
|
|
8029
7943
|
content = runtimeArtifactConversion._restoreClaudeGlobalAtRefTilde(content, pathPrefix);
|
|
8030
7944
|
}
|
|
8031
7945
|
return content;
|
|
@@ -8041,7 +7955,7 @@ function copyWithPathReplacement(srcDir, destDir, pathPrefix, runtime, isCommand
|
|
|
8041
7955
|
// copyWithPathReplacement is the emit path for gsd-core/workflows/*.md;
|
|
8042
7956
|
// _applyRuntimeRewrites is NOT invoked here, so this is what makes the fix
|
|
8043
7957
|
// live in real installs (it is a no-op for files without those lines).
|
|
8044
|
-
if (!
|
|
7958
|
+
if (!hostBehaviorsFor(runtime).authorsCanonicalWorkflow) {
|
|
8045
7959
|
content = _stampNonClaudeRuntimeDefaults(content, runtime);
|
|
8046
7960
|
}
|
|
8047
7961
|
|
|
@@ -8391,7 +8305,7 @@ function uninstall(isGlobal, runtime = DEFAULT_RUNTIME) {
|
|
|
8391
8305
|
// `runtime === 'cline'` branch into hostBehaviors.localTargetIsProjectRoot.
|
|
8392
8306
|
const targetDir = isGlobal
|
|
8393
8307
|
? getGlobalConfigDir(runtime, explicitConfigDir)
|
|
8394
|
-
:
|
|
8308
|
+
: hostBehaviorsFor(runtime).localTargetIsProjectRoot
|
|
8395
8309
|
? process.cwd()
|
|
8396
8310
|
: path.join(process.cwd(), dirName);
|
|
8397
8311
|
|
|
@@ -8499,7 +8413,7 @@ function uninstall(isGlobal, runtime = DEFAULT_RUNTIME) {
|
|
|
8499
8413
|
}
|
|
8500
8414
|
|
|
8501
8415
|
// 1a. Non-layout Codex side-effects: agent .toml files, config.toml sections, hooks.json
|
|
8502
|
-
if (
|
|
8416
|
+
if (hostBehaviorsFor(runtime).tomlConfigInstall) {
|
|
8503
8417
|
const codexAgentsDir = path.join(targetDir, 'agents');
|
|
8504
8418
|
if (fs.existsSync(codexAgentsDir)) {
|
|
8505
8419
|
const tomlFiles = fs.readdirSync(codexAgentsDir);
|
|
@@ -8613,7 +8527,7 @@ function uninstall(isGlobal, runtime = DEFAULT_RUNTIME) {
|
|
|
8613
8527
|
// global cross-tool ~/.agents/AGENTS.md target.
|
|
8614
8528
|
// Descriptor-driven (ADR-1239 / #2090): folded from `runtime === 'cline'`
|
|
8615
8529
|
// into hostBehaviors.clineRulesSurface.
|
|
8616
|
-
if (
|
|
8530
|
+
if (hostBehaviorsFor(runtime).clineRulesSurface) {
|
|
8617
8531
|
const clinerulesDir = path.join(targetDir, '.clinerules');
|
|
8618
8532
|
for (const rel of ['gsd.md', path.join('hooks', 'PreToolUse')]) {
|
|
8619
8533
|
const p = path.join(clinerulesDir, rel);
|
|
@@ -8663,7 +8577,7 @@ function uninstall(isGlobal, runtime = DEFAULT_RUNTIME) {
|
|
|
8663
8577
|
// GSD-managed hook entries from hooks.json and clean up the managed hook
|
|
8664
8578
|
// scripts. Gated by the hostBehaviors.hooksJsonSurface descriptor axis, not a
|
|
8665
8579
|
// hardcoded `isCursor` branch.
|
|
8666
|
-
if (
|
|
8580
|
+
if (hostBehaviorsFor(runtime).hooksJsonSurface) {
|
|
8667
8581
|
const hooksJsonCleanup = removeCursorHooksJson(targetDir);
|
|
8668
8582
|
if (hooksJsonCleanup.changed) {
|
|
8669
8583
|
removedCount++;
|
|
@@ -8723,7 +8637,7 @@ function uninstall(isGlobal, runtime = DEFAULT_RUNTIME) {
|
|
|
8723
8637
|
|
|
8724
8638
|
// 1c. Claude local: remove flat gsd-*.md commands from commands/ (current layout,
|
|
8725
8639
|
// #1367 fix). Also remove legacy commands/gsd/ subdirectory from prior installs.
|
|
8726
|
-
if (!isGlobal &&
|
|
8640
|
+
if (!isGlobal && hostBehaviorsFor(runtime).localInstallStyle === 'legacy-flat') {
|
|
8727
8641
|
const commandsDir = path.join(targetDir, 'commands');
|
|
8728
8642
|
// Remove flat gsd-*.md files (current layout after #1367 fix)
|
|
8729
8643
|
if (fs.existsSync(commandsDir)) {
|
|
@@ -8789,7 +8703,7 @@ function uninstall(isGlobal, runtime = DEFAULT_RUNTIME) {
|
|
|
8789
8703
|
// removes the directory; we must preserve/restore user artifacts before that path.
|
|
8790
8704
|
// This block runs AFTER uninstallRuntimeArtifacts, so we check if the directory
|
|
8791
8705
|
// was already removed and skip if so (idempotent).
|
|
8792
|
-
if (
|
|
8706
|
+
if (hostBehaviorsFor(runtime).legacyCommandsGsdCleanup === true) {
|
|
8793
8707
|
// dev-preferences may have survived in skills/ as SKILL.md — nothing to do for
|
|
8794
8708
|
// that case. If a stale commands/gsd/ still exists (e.g. legacy was not removed),
|
|
8795
8709
|
// attempt migration. In practice _runLegacyUninstallCleanup removes it first,
|
|
@@ -9004,7 +8918,7 @@ function uninstall(isGlobal, runtime = DEFAULT_RUNTIME) {
|
|
|
9004
8918
|
// that declares the block (OpenCode, Kilo, ...), not just OpenCode. Only
|
|
9005
8919
|
// GSD's own plugin file is removed; the plugins/ dir is pruned only if it
|
|
9006
8920
|
// becomes empty, preserving any user-authored plugins for that host.
|
|
9007
|
-
const _np =
|
|
8921
|
+
const _np = hostBehaviorsFor(runtime).nativePlugin;
|
|
9008
8922
|
if (_np) {
|
|
9009
8923
|
const pluginsDir = path.join(targetDir, _np.dir);
|
|
9010
8924
|
const pluginPath = path.join(pluginsDir, _np.file);
|
|
@@ -9169,7 +9083,7 @@ function uninstall(isGlobal, runtime = DEFAULT_RUNTIME) {
|
|
|
9169
9083
|
// to preserve any user-added allow/deny entries.
|
|
9170
9084
|
// Uses a local flag to avoid the shared `settingsModified` producing a false
|
|
9171
9085
|
// "Removed GSD permissions" message when only hooks/statusline changed.
|
|
9172
|
-
if (
|
|
9086
|
+
if (hostBehaviorsFor(runtime).permissionsSchema === 'claude' && settings.permissions) {
|
|
9173
9087
|
let permissionsModified = false;
|
|
9174
9088
|
if (Array.isArray(settings.permissions.allow)) {
|
|
9175
9089
|
const before = settings.permissions.allow.length;
|
|
@@ -9240,7 +9154,7 @@ function uninstall(isGlobal, runtime = DEFAULT_RUNTIME) {
|
|
|
9240
9154
|
// runtimes that host MCP there (Augment), symmetric to the mcp_config.json
|
|
9241
9155
|
// removal for Antigravity below. Only the GSD-owned mcpServers.gsd key is
|
|
9242
9156
|
// removed — any other user-configured MCP servers are preserved.
|
|
9243
|
-
if (
|
|
9157
|
+
if (hostBehaviorsFor(runtime).mcpCompanion === 'settings-json' &&
|
|
9244
9158
|
settings.mcpServers && typeof settings.mcpServers === 'object' &&
|
|
9245
9159
|
settings.mcpServers.gsd !== undefined) {
|
|
9246
9160
|
delete settings.mcpServers.gsd;
|
|
@@ -9929,7 +9843,7 @@ function writeManifest(configDir, runtime = DEFAULT_RUNTIME, options = {}) {
|
|
|
9929
9843
|
// #1367: Claude local now writes flat gsd-*.md files at commands/ (not commands/gsd/).
|
|
9930
9844
|
// Claude local uses flatCommandsDir instead for manifest recording.
|
|
9931
9845
|
const flatCommandsDir = path.join(configDir, 'commands');
|
|
9932
|
-
const opencodeCommandDir = path.join(configDir,
|
|
9846
|
+
const opencodeCommandDir = path.join(configDir, hostBehaviorsFor(runtime).flatCommandDir || 'command');
|
|
9933
9847
|
// Hermes nests GSD skills under skills/gsd/ as a single category (#2841) —
|
|
9934
9848
|
// already encoded in its layout descriptor's destSubpath ('skills/gsd').
|
|
9935
9849
|
// All other runtimes that use the Codex-style skills layout use a flat skills/ root.
|
|
@@ -9944,7 +9858,7 @@ function writeManifest(configDir, runtime = DEFAULT_RUNTIME, options = {}) {
|
|
|
9944
9858
|
// `options.scope` could drift; one cannot.
|
|
9945
9859
|
const resolvedScope = options.scope === 'local' ? 'local' : 'global';
|
|
9946
9860
|
const codexSkillsDir = _resolveSkillsRootDir(runtime, configDir, resolvedScope);
|
|
9947
|
-
const codexSkillsManifestPrefix =
|
|
9861
|
+
const codexSkillsManifestPrefix = hostBehaviorsFor(runtime).skillsManifestPrefix || 'skills/';
|
|
9948
9862
|
// #3738: resolve the ACTUAL agents-install dir honoring an agents-kind `home`
|
|
9949
9863
|
// override (antigravity global → $HOME/.gemini/config/agents), mirroring
|
|
9950
9864
|
// _resolveSkillsRootDir for skills. Hardcoding configDir/agents left the
|
|
@@ -9996,26 +9910,26 @@ function writeManifest(configDir, runtime = DEFAULT_RUNTIME, options = {}) {
|
|
|
9996
9910
|
// Claude local (#1367): flat gsd-*.md files at commands/ level.
|
|
9997
9911
|
// Only claude local writes gsd-*.md here; global installs don't emit commands,
|
|
9998
9912
|
// so this branch is a no-op for global (no matching files to find).
|
|
9999
|
-
if (
|
|
9913
|
+
if (hostBehaviorsFor(runtime).localInstallStyle === 'legacy-flat' && fs.existsSync(flatCommandsDir)) {
|
|
10000
9914
|
for (const file of fs.readdirSync(flatCommandsDir)) {
|
|
10001
9915
|
if (file.startsWith('gsd-') && file.endsWith('.md')) {
|
|
10002
9916
|
manifest.files['commands/' + file] = fileHash(path.join(flatCommandsDir, file));
|
|
10003
9917
|
}
|
|
10004
9918
|
}
|
|
10005
9919
|
}
|
|
10006
|
-
if (
|
|
9920
|
+
if (hostBehaviorsFor(runtime).flatCommandDir && fs.existsSync(opencodeCommandDir)) {
|
|
10007
9921
|
// #2329: derive the manifest key prefix from the SAME descriptor value used
|
|
10008
9922
|
// to compute opencodeCommandDir above, instead of a separately-hardcoded
|
|
10009
9923
|
// literal — a divergence here would silently break the manifest even after
|
|
10010
9924
|
// the destSubpath descriptor is corrected (Generative Fix Divergence guard).
|
|
10011
|
-
const flatCommandDirPrefix =
|
|
9925
|
+
const flatCommandDirPrefix = hostBehaviorsFor(runtime).flatCommandDir || 'command';
|
|
10012
9926
|
for (const file of fs.readdirSync(opencodeCommandDir)) {
|
|
10013
9927
|
if (file.startsWith('gsd-') && file.endsWith('.md')) {
|
|
10014
9928
|
manifest.files[flatCommandDirPrefix + '/' + file] = fileHash(path.join(opencodeCommandDir, file));
|
|
10015
9929
|
}
|
|
10016
9930
|
}
|
|
10017
9931
|
}
|
|
10018
|
-
if (!
|
|
9932
|
+
if (!hostBehaviorsFor(runtime).skipCodexSkillsManifest && fs.existsSync(codexSkillsDir)) {
|
|
10019
9933
|
// All runtimes (including Hermes post-#947) use the canonical 'gsd-' prefix.
|
|
10020
9934
|
const skillListPrefix = 'gsd-';
|
|
10021
9935
|
for (const skillName of listCodexSkillNames(codexSkillsDir, skillListPrefix)) {
|
|
@@ -10026,14 +9940,14 @@ function writeManifest(configDir, runtime = DEFAULT_RUNTIME, options = {}) {
|
|
|
10026
9940
|
}
|
|
10027
9941
|
}
|
|
10028
9942
|
// Descriptor-driven (#2090): hash the category DESCRIPTION.md so reinstall detects drift.
|
|
10029
|
-
if (
|
|
9943
|
+
if (hostBehaviorsFor(runtime).trackCategoryDescription) {
|
|
10030
9944
|
const descPath = path.join(codexSkillsDir, 'DESCRIPTION.md');
|
|
10031
9945
|
if (fs.existsSync(descPath)) {
|
|
10032
9946
|
manifest.files['skills/gsd/DESCRIPTION.md'] = fileHash(descPath);
|
|
10033
9947
|
}
|
|
10034
9948
|
}
|
|
10035
9949
|
}
|
|
10036
|
-
if (
|
|
9950
|
+
if (hostBehaviorsFor(runtime).agentManifestStyle === 'kimi-nested' && fs.existsSync(agentsDir)) {
|
|
10037
9951
|
const agentHashes = generateManifest(agentsDir);
|
|
10038
9952
|
for (const [rel, hash] of Object.entries(agentHashes)) {
|
|
10039
9953
|
const isRootAgent = rel === 'gsd.yaml' || rel === 'gsd.md';
|
|
@@ -10054,7 +9968,7 @@ function writeManifest(configDir, runtime = DEFAULT_RUNTIME, options = {}) {
|
|
|
10054
9968
|
// marker block, not the per-configDir manifest, since it lives outside it.)
|
|
10055
9969
|
// Descriptor-driven (ADR-1239 / #2090): folded from `isCline` into
|
|
10056
9970
|
// hostBehaviors.clineRulesSurface.
|
|
10057
|
-
if (
|
|
9971
|
+
if (hostBehaviorsFor(runtime).clineRulesSurface) {
|
|
10058
9972
|
for (const rel of ['.clinerules/gsd.md', '.clinerules/hooks/PreToolUse']) {
|
|
10059
9973
|
const dest = path.join(configDir, rel);
|
|
10060
9974
|
if (fs.existsSync(dest)) {
|
|
@@ -10075,7 +9989,7 @@ function writeManifest(configDir, runtime = DEFAULT_RUNTIME, options = {}) {
|
|
|
10075
9989
|
// skipSharedHooksInstall:true) — the redundant `&& !isCopilot` was removed.
|
|
10076
9990
|
// #2100: Windsurf's exclusion is likewise descriptor-driven (windsurf declares
|
|
10077
9991
|
// skipSharedHooksInstall:true) — the redundant `&& !isWindsurf` was removed.
|
|
10078
|
-
if (!isCodex &&
|
|
9992
|
+
if (!isCodex && hostBehaviorsFor(runtime).skipSharedHooksInstall !== true) {
|
|
10079
9993
|
// #3023: manifest keys must track the bundle wherever the descriptor put it,
|
|
10080
9994
|
// or uninstall/saveLocalPatches silently orphan the tree.
|
|
10081
9995
|
const sharedHooksDirName = resolveSharedHooksDirName(runtime);
|
|
@@ -10142,7 +10056,7 @@ function writeManifest(configDir, runtime = DEFAULT_RUNTIME, options = {}) {
|
|
|
10142
10056
|
|
|
10143
10057
|
// Track the OpenCode native plugin adapter (#1914) so update/drift detection
|
|
10144
10058
|
// and uninstall can account for it.
|
|
10145
|
-
const _npM =
|
|
10059
|
+
const _npM = hostBehaviorsFor(runtime).nativePlugin;
|
|
10146
10060
|
if (_npM) {
|
|
10147
10061
|
const pluginInstallPath = path.join(configDir, _npM.dir, _npM.file);
|
|
10148
10062
|
if (fs.existsSync(pluginInstallPath)) {
|
|
@@ -10373,7 +10287,7 @@ function saveLocalPatches(configDir, pristineCtx) {
|
|
|
10373
10287
|
skillsRoot !== resolvedConfig &&
|
|
10374
10288
|
!skillsRoot.startsWith(resolvedConfig + path.sep)
|
|
10375
10289
|
) {
|
|
10376
|
-
const prefix =
|
|
10290
|
+
const prefix = hostBehaviorsFor(patchRuntime).skillsManifestPrefix || 'skills/';
|
|
10377
10291
|
skillsRedirect = { root: skillsRoot, prefix };
|
|
10378
10292
|
}
|
|
10379
10293
|
}
|
|
@@ -10596,7 +10510,7 @@ function reportLocalPatches(configDir, runtime = DEFAULT_RUNTIME) {
|
|
|
10596
10510
|
try { meta = JSON.parse(fs.readFileSync(metaPath, 'utf8')); } catch { return []; }
|
|
10597
10511
|
|
|
10598
10512
|
if (meta.files && meta.files.length > 0) {
|
|
10599
|
-
const reapplyCommand =
|
|
10513
|
+
const reapplyCommand = hostBehaviorsFor(runtime).reapplyCommand || '/gsd-update --reapply';
|
|
10600
10514
|
console.log('');
|
|
10601
10515
|
console.log(' ' + yellow + 'Local patches detected' + reset + ' (from v' + meta.from_version + '):');
|
|
10602
10516
|
for (const f of meta.files) {
|
|
@@ -10624,12 +10538,12 @@ function reportInstallerMigrationResult(result) {
|
|
|
10624
10538
|
|
|
10625
10539
|
function install(isGlobal, runtime = DEFAULT_RUNTIME, options = {}) {
|
|
10626
10540
|
// #2093: isKilo dropped — Kilo's agent/model-override handling below reads
|
|
10627
|
-
//
|
|
10541
|
+
// hostBehaviorsFor(runtime).frontmatterDialect === 'kilo' instead of this flag.
|
|
10628
10542
|
// #2095: isKimi dropped — kimi is now a hooks/ consumer like every other
|
|
10629
10543
|
// settings-json-adjacent runtime; the two `&& !isKimi` hooks-copy guards
|
|
10630
10544
|
// below were removed, leaving isKimi unused in this function (the kimi
|
|
10631
10545
|
// local-install-deferred branch above already reads
|
|
10632
|
-
//
|
|
10546
|
+
// hostBehaviorsFor(runtime).localInstallDeferred instead of this flag).
|
|
10633
10547
|
// #2096: isAntigravity dropped — antigravity's agents were already
|
|
10634
10548
|
// descriptor-driven (installRuntimeArtifacts), so its two legacy-agent-loop
|
|
10635
10549
|
// branches (the path-rewrite skip and the converter dispatch) were
|
|
@@ -10669,7 +10583,7 @@ function install(isGlobal, runtime = DEFAULT_RUNTIME, options = {}) {
|
|
|
10669
10583
|
// re-running install()) can warn again if the same condition recurs.
|
|
10670
10584
|
_codexResolverModelOmittedWarned = false;
|
|
10671
10585
|
|
|
10672
|
-
if (
|
|
10586
|
+
if (hostBehaviorsFor(runtime).localInstallDeferred && !isGlobal) {
|
|
10673
10587
|
console.log(` ${yellow}⚠${reset} Kimi local install is deferred for Phase 2.`);
|
|
10674
10588
|
console.log(` No .kimi-code/skills or .agents/skills project artifacts were written.`);
|
|
10675
10589
|
console.log(` Project-level Kimi install semantics remain deferred.`);
|
|
@@ -10740,7 +10654,7 @@ function install(isGlobal, runtime = DEFAULT_RUNTIME, options = {}) {
|
|
|
10740
10654
|
// auto-removed on reinstall (dual-read fallback per issue #791 spec).
|
|
10741
10655
|
const targetDir = isGlobal
|
|
10742
10656
|
? getGlobalConfigDir(runtime, explicitConfigDir)
|
|
10743
|
-
:
|
|
10657
|
+
: hostBehaviorsFor(runtime).localTargetIsProjectRoot
|
|
10744
10658
|
? process.cwd()
|
|
10745
10659
|
: path.join(process.cwd(), dirName);
|
|
10746
10660
|
|
|
@@ -10855,7 +10769,7 @@ function install(isGlobal, runtime = DEFAULT_RUNTIME, options = {}) {
|
|
|
10855
10769
|
const isWindowsHost = process.platform === 'win32';
|
|
10856
10770
|
const pathPrefix = computePathPrefix({
|
|
10857
10771
|
isGlobal,
|
|
10858
|
-
isOpencode:
|
|
10772
|
+
isOpencode: hostBehaviorsFor(runtime).skipHomePrefixSubstitution === true,
|
|
10859
10773
|
isWindowsHost,
|
|
10860
10774
|
resolvedTarget,
|
|
10861
10775
|
homeDir,
|
|
@@ -10863,7 +10777,7 @@ function install(isGlobal, runtime = DEFAULT_RUNTIME, options = {}) {
|
|
|
10863
10777
|
// copyWithPathReplacement, i.e. the one actually written into every
|
|
10864
10778
|
// emitted command/skill/workflow body — the rewrite-engine seams below
|
|
10865
10779
|
// handle re-applied surfaces, not the first install.
|
|
10866
|
-
localDirName:
|
|
10780
|
+
localDirName: hostBehaviorsFor(runtime).localTargetIsProjectRoot === true ? undefined : getDirName(runtime),
|
|
10867
10781
|
});
|
|
10868
10782
|
|
|
10869
10783
|
// runtimeLabel is now the single-source getRuntimeLabel lookup (ADR-1239
|
|
@@ -10967,7 +10881,7 @@ function install(isGlobal, runtime = DEFAULT_RUNTIME, options = {}) {
|
|
|
10967
10881
|
// a core/--minimal install too (#2695), and its pass-2 sweeps remove every
|
|
10968
10882
|
// gsd-* skill dir / agent file the snapshot does not claim — so an empty
|
|
10969
10883
|
// minimal-mode snapshot deleted the whole surface with nothing to restore.
|
|
10970
|
-
if (
|
|
10884
|
+
if (hostBehaviorsFor(runtime).tomlConfigInstall) {
|
|
10971
10885
|
codexManagedSnapshotCaptured = true;
|
|
10972
10886
|
const _preSkillsDir = _resolveSkillsRootDir(runtime, targetDir, _installScopeId);
|
|
10973
10887
|
if (fs.existsSync(_preSkillsDir)) {
|
|
@@ -11216,7 +11130,7 @@ function install(isGlobal, runtime = DEFAULT_RUNTIME, options = {}) {
|
|
|
11216
11130
|
// The full restoreCodexSnapshot() (defined inside the config block) additionally
|
|
11217
11131
|
// handles config.toml and the staged hooks/ tree, which are not yet touched
|
|
11218
11132
|
// at this point in the pipeline.
|
|
11219
|
-
const _codexPreConfigRollback = !
|
|
11133
|
+
const _codexPreConfigRollback = !hostBehaviorsFor(runtime).tomlConfigInstall || isMinimalMode(_effectiveInstallMode) ? null : () => {
|
|
11220
11134
|
rollbackInstallerMigrations();
|
|
11221
11135
|
// skills/gsd-* — pass 1: restore snapshot entries (may be absent if deleted mid-install).
|
|
11222
11136
|
const _earlySkillsDir = _resolveSkillsRootDir(runtime, targetDir, _installScopeId);
|
|
@@ -11406,7 +11320,7 @@ function install(isGlobal, runtime = DEFAULT_RUNTIME, options = {}) {
|
|
|
11406
11320
|
// used to describe. Claude-local remains the one special-cased path
|
|
11407
11321
|
// (copyWithPathReplacement + stale-skills cleanup).
|
|
11408
11322
|
const _isSkillsRuntime = (() => {
|
|
11409
|
-
if (
|
|
11323
|
+
if (hostBehaviorsFor(runtime).localInstallStyle === 'legacy-flat' && !isGlobal) return false; // legacy flat local path (descriptor-driven; #2086)
|
|
11410
11324
|
// #2875 Part 2 defect fix: a runtime whose LOCAL commands are embedded in a
|
|
11411
11325
|
// rules file rather than materialized as files (hostBehaviors.localCommandsViaRules
|
|
11412
11326
|
// — cline is the only declarant, capabilities/cline/capability.json) must not
|
|
@@ -11417,7 +11331,7 @@ function install(isGlobal, runtime = DEFAULT_RUNTIME, options = {}) {
|
|
|
11417
11331
|
// spuriously fail; the `localCommandsViaRules` branch below (unchanged
|
|
11418
11332
|
// messaging) and the unconditional agents-materialization block further down
|
|
11419
11333
|
// (installAgentsKindStandalone) already cover this runtime/scope correctly.
|
|
11420
|
-
if (!isGlobal &&
|
|
11334
|
+
if (!isGlobal && hostBehaviorsFor(runtime).localCommandsViaRules) return false;
|
|
11421
11335
|
const cap = _capabilityRegistry && _capabilityRegistry.runtimes && _capabilityRegistry.runtimes[runtime];
|
|
11422
11336
|
const layout = cap && cap.runtime && cap.runtime.artifactLayout;
|
|
11423
11337
|
if (!layout) return false;
|
|
@@ -11456,13 +11370,13 @@ function install(isGlobal, runtime = DEFAULT_RUNTIME, options = {}) {
|
|
|
11456
11370
|
// marker. Write failure is non-fatal (install proceeds; warn so /gsd-surface breakage is
|
|
11457
11371
|
// diagnosable) — the same contract the late write had.
|
|
11458
11372
|
function _writeGsdSourceMarker(runtime, targetDir, src, isGlobal) {
|
|
11459
|
-
if (
|
|
11373
|
+
if (hostBehaviorsFor(runtime).sourceMarkerFile && isGlobal) {
|
|
11460
11374
|
const gsdSourceCommands = path.join(src, 'commands', 'gsd');
|
|
11461
11375
|
if (fs.existsSync(gsdSourceCommands)) {
|
|
11462
11376
|
try {
|
|
11463
11377
|
// ADR-1239 Phase B write-confinement: the descriptor-sourced marker filename
|
|
11464
11378
|
// must resolve under targetDir (parity with the other descriptor-driven writes).
|
|
11465
|
-
const _markerPath = assertDestWithinConfigHome(targetDir,
|
|
11379
|
+
const _markerPath = assertDestWithinConfigHome(targetDir, hostBehaviorsFor(runtime).sourceMarkerFile);
|
|
11466
11380
|
if (hasExistingSymlinkBetween(path.resolve(targetDir), _markerPath, { allowOptInFollow: isSymlinkedDestOptIn() })) {
|
|
11467
11381
|
throw new Error(`compatibility marker "${_markerPath}" contains an untrusted symlink`);
|
|
11468
11382
|
}
|
|
@@ -11537,7 +11451,7 @@ function install(isGlobal, runtime = DEFAULT_RUNTIME, options = {}) {
|
|
|
11537
11451
|
// index BOTH SKILL.md and the sidecar, causing each GSD skill to appear twice
|
|
11538
11452
|
// in autocomplete. Cleaning them up fixes the duplication; SKILL.md alone is
|
|
11539
11453
|
// sufficient for Codex discovery. User-owned dirs are never touched.
|
|
11540
|
-
if (
|
|
11454
|
+
if (hostBehaviorsFor(runtime).cleanupSkillSidecars) {
|
|
11541
11455
|
cleanupCodexSkillMetadataSidecars(_skillsRootDir);
|
|
11542
11456
|
}
|
|
11543
11457
|
|
|
@@ -11563,7 +11477,7 @@ function install(isGlobal, runtime = DEFAULT_RUNTIME, options = {}) {
|
|
|
11563
11477
|
// Descriptor-driven (ADR-1239 / #2100): folded from `isWindsurf` into
|
|
11564
11478
|
// hostBehaviors.legacyDevinSkillsCleanup (windsurf is the only runtime that
|
|
11565
11479
|
// declares it, so this is byte-parity).
|
|
11566
|
-
if (
|
|
11480
|
+
if (hostBehaviorsFor(runtime).legacyDevinSkillsCleanup && !isGlobal) {
|
|
11567
11481
|
const removedCount = cleanupWindsurfLegacyDevinSkills(process.cwd());
|
|
11568
11482
|
if (removedCount > 0) {
|
|
11569
11483
|
console.log(` ${green}✓${reset} Removed ${removedCount} legacy .devin/skills/gsd-* dir(s) (pre-#1615 Windsurf layout)`);
|
|
@@ -11571,12 +11485,12 @@ function install(isGlobal, runtime = DEFAULT_RUNTIME, options = {}) {
|
|
|
11571
11485
|
}
|
|
11572
11486
|
|
|
11573
11487
|
// Descriptor-driven (#2090): write DESCRIPTION.md for the gsd/ category after layout install
|
|
11574
|
-
if (
|
|
11488
|
+
if (hostBehaviorsFor(runtime).writeCategoryDescription) {
|
|
11575
11489
|
writeHermesCategoryDescription(path.join(targetDir, 'skills', 'gsd'));
|
|
11576
11490
|
}
|
|
11577
11491
|
|
|
11578
11492
|
// Verify installed artifacts and report
|
|
11579
|
-
if (
|
|
11493
|
+
if (hostBehaviorsFor(runtime).reportSkillsCount) {
|
|
11580
11494
|
const hermesSkillsDir = path.join(targetDir, 'skills', 'gsd');
|
|
11581
11495
|
if (fs.existsSync(hermesSkillsDir)) {
|
|
11582
11496
|
// Hermes layout uses prefix: 'gsd-' (#947) — skill dirs have gsd-<stem> names
|
|
@@ -11590,7 +11504,7 @@ function install(isGlobal, runtime = DEFAULT_RUNTIME, options = {}) {
|
|
|
11590
11504
|
} else {
|
|
11591
11505
|
failures.push('skills/gsd/*');
|
|
11592
11506
|
}
|
|
11593
|
-
} else if (
|
|
11507
|
+
} else if (hostBehaviorsFor(runtime).verificationStyle === 'kimi') {
|
|
11594
11508
|
const skillsDir = path.join(targetDir, 'skills');
|
|
11595
11509
|
const rootAgentPath = path.join(targetDir, 'agents', 'gsd.yaml');
|
|
11596
11510
|
if (fs.existsSync(skillsDir)) {
|
|
@@ -11614,7 +11528,7 @@ function install(isGlobal, runtime = DEFAULT_RUNTIME, options = {}) {
|
|
|
11614
11528
|
// hostBehaviors.verificationStyle === 'windsurf-workflows' (extends the
|
|
11615
11529
|
// same mechanism the 'kimi' verificationStyle branch above uses; windsurf
|
|
11616
11530
|
// is the only runtime that declares this value, so this is byte-parity).
|
|
11617
|
-
} else if (
|
|
11531
|
+
} else if (hostBehaviorsFor(runtime).verificationStyle === 'windsurf-workflows') {
|
|
11618
11532
|
if (isGlobal) {
|
|
11619
11533
|
console.log(` ${green}✓${reset} Windsurf global install skipped workflow artifacts (workspace-only)`);
|
|
11620
11534
|
} else {
|
|
@@ -11663,7 +11577,7 @@ function install(isGlobal, runtime = DEFAULT_RUNTIME, options = {}) {
|
|
|
11663
11577
|
// Descriptor-driven commands/ output report (currently CodeBuddy).
|
|
11664
11578
|
// Cursor retired this parallel surface in #2644 because its skills are
|
|
11665
11579
|
// already slash-menu entries as well as model-invocable context.
|
|
11666
|
-
if (
|
|
11580
|
+
if (hostBehaviorsFor(runtime).reportCommandsDir) {
|
|
11667
11581
|
const commandsDir = path.join(targetDir, 'commands');
|
|
11668
11582
|
if (fs.existsSync(commandsDir)) {
|
|
11669
11583
|
const cmdCount = fs.readdirSync(commandsDir)
|
|
@@ -11678,14 +11592,14 @@ function install(isGlobal, runtime = DEFAULT_RUNTIME, options = {}) {
|
|
|
11678
11592
|
}
|
|
11679
11593
|
}
|
|
11680
11594
|
}
|
|
11681
|
-
} else if (
|
|
11595
|
+
} else if (hostBehaviorsFor(runtime).localCommandsViaRules) {
|
|
11682
11596
|
// Cline local install: rules-based only — commands are embedded in .clinerules (generated below).
|
|
11683
11597
|
// No skills/commands directory needed for local installs.
|
|
11684
11598
|
// Global installs are handled above by _isSkillsRuntime (#782).
|
|
11685
11599
|
// Descriptor-driven (ADR-1239 / #2090): folded from `isCline` into
|
|
11686
11600
|
// hostBehaviors.localCommandsViaRules.
|
|
11687
11601
|
console.log(` ${green}✓${reset} Cline: commands will be available via .clinerules`);
|
|
11688
|
-
} else if (
|
|
11602
|
+
} else if (hostBehaviorsFor(runtime).pluginOnlyInstall) {
|
|
11689
11603
|
// pi (ADR-1239 / #2102 Stage 1): plugin-only install — pi's /gsd command is
|
|
11690
11604
|
// registered programmatically by the native extension (pi/gsd.cjs →
|
|
11691
11605
|
// extensions/gsd.js, staged separately below; the dest suffix must be
|
|
@@ -11793,8 +11707,8 @@ function install(isGlobal, runtime = DEFAULT_RUNTIME, options = {}) {
|
|
|
11793
11707
|
// double-stages their plugin file. A runtime like pi, whose artifactLayout is
|
|
11794
11708
|
// intentionally empty for both scopes (`_isSkillsRuntime` is false), still
|
|
11795
11709
|
// needs its declared hostBehaviors.nativePlugin file copied into targetDir.
|
|
11796
|
-
if (!_isSkillsRuntime &&
|
|
11797
|
-
_installNativePluginIfDeclared(runtime, targetDir,
|
|
11710
|
+
if (!_isSkillsRuntime && hostBehaviorsFor(runtime).nativePlugin) {
|
|
11711
|
+
_installNativePluginIfDeclared(runtime, targetDir, hostBehaviorsFor(runtime), src);
|
|
11798
11712
|
}
|
|
11799
11713
|
|
|
11800
11714
|
// #2624: the .gsd-source marker is now written by _writeGsdSourceMarker()
|
|
@@ -11815,7 +11729,7 @@ function install(isGlobal, runtime = DEFAULT_RUNTIME, options = {}) {
|
|
|
11815
11729
|
// hostBehaviors.installsCommandBodiesForWorkflowDelegation (windsurf is the
|
|
11816
11730
|
// only runtime that declares it, so this is byte-parity — the #1629 fix
|
|
11817
11731
|
// itself is unchanged).
|
|
11818
|
-
if (
|
|
11732
|
+
if (hostBehaviorsFor(runtime).installsCommandBodiesForWorkflowDelegation && !isGlobal) {
|
|
11819
11733
|
const commandsSrc = path.join(src, 'commands', 'gsd');
|
|
11820
11734
|
const commandsDest = path.join(skillDest, 'commands', 'gsd');
|
|
11821
11735
|
if (fs.existsSync(commandsSrc)) {
|
|
@@ -11879,7 +11793,7 @@ function install(isGlobal, runtime = DEFAULT_RUNTIME, options = {}) {
|
|
|
11879
11793
|
// scopes (programmatic dispatch, no named-dispatch subagent toolkit, no
|
|
11880
11794
|
// host-read markdown surface), so the resolved layout has no `agents` kind
|
|
11881
11795
|
// to stage and the function returns `null` without writing anything.
|
|
11882
|
-
if (
|
|
11796
|
+
if (hostBehaviorsFor(runtime).pluginOnlyInstall) {
|
|
11883
11797
|
console.log(` ${green}✓${reset} pi: no subagent files (programmatic dispatch, no named-dispatch toolkit)`);
|
|
11884
11798
|
} else if (_isSkillsRuntime) {
|
|
11885
11799
|
console.log(` ${dim}↳${reset} Agents installed via descriptor-driven layout (${runtime})`);
|
|
@@ -11914,7 +11828,7 @@ function install(isGlobal, runtime = DEFAULT_RUNTIME, options = {}) {
|
|
|
11914
11828
|
// advertising the old full agent surface even though the descriptor-driven
|
|
11915
11829
|
// write above already skipped writing the .md files for a minimal-tier
|
|
11916
11830
|
// resolvedProfile. Reuse the same helper that powers `--uninstall`.
|
|
11917
|
-
if (isMinimalMode(_effectiveInstallMode) &&
|
|
11831
|
+
if (isMinimalMode(_effectiveInstallMode) && hostBehaviorsFor(runtime).tomlConfigInstall) {
|
|
11918
11832
|
const codexConfigPath = path.join(targetDir, 'config.toml');
|
|
11919
11833
|
if (fs.existsSync(codexConfigPath)) {
|
|
11920
11834
|
const existing = fs.readFileSync(codexConfigPath, 'utf8');
|
|
@@ -12033,7 +11947,7 @@ function install(isGlobal, runtime = DEFAULT_RUNTIME, options = {}) {
|
|
|
12033
11947
|
// runtime.hostBehaviors.brandingRewrites. This site only
|
|
12034
11948
|
// rewrites the two brand-name keys (no `.claude/` here — the
|
|
12035
11949
|
// config-dir replace above already handled path fragments).
|
|
12036
|
-
const _b2 =
|
|
11950
|
+
const _b2 = hostBehaviorsFor(runtime).brandingRewrites;
|
|
12037
11951
|
if (_b2) {
|
|
12038
11952
|
content = content.replace(/CLAUDE\.md/g, _b2['CLAUDE.md']);
|
|
12039
11953
|
content = content.replace(/\bClaude Code\b/g, _b2['Claude Code']);
|
|
@@ -12192,7 +12106,7 @@ function install(isGlobal, runtime = DEFAULT_RUNTIME, options = {}) {
|
|
|
12192
12106
|
// skipSharedHooksInstall:true) — the redundant `&& !isCopilot` was removed.
|
|
12193
12107
|
// #2100: Windsurf's exclusion is likewise descriptor-driven (windsurf declares
|
|
12194
12108
|
// skipSharedHooksInstall:true) — the redundant `&& !isWindsurf` was removed.
|
|
12195
|
-
if (!isCodex &&
|
|
12109
|
+
if (!isCodex && hostBehaviorsFor(runtime).skipSharedHooksInstall !== true) {
|
|
12196
12110
|
if (!installSharedHooksBundle(targetDir)) {
|
|
12197
12111
|
failures.push('hooks');
|
|
12198
12112
|
}
|
|
@@ -12359,7 +12273,7 @@ function install(isGlobal, runtime = DEFAULT_RUNTIME, options = {}) {
|
|
|
12359
12273
|
}
|
|
12360
12274
|
|
|
12361
12275
|
// Verify no leaked .claude paths in non-Claude runtimes (manifest-scoped)
|
|
12362
|
-
if (!
|
|
12276
|
+
if (!hostBehaviorsFor(runtime).ownsClaudePaths) {
|
|
12363
12277
|
const leakedPaths = [];
|
|
12364
12278
|
// Only scan files that were written by this install (manifest-tracked).
|
|
12365
12279
|
// Scanning the entire targetDir can match user-authored content that
|
|
@@ -12392,7 +12306,7 @@ function install(isGlobal, runtime = DEFAULT_RUNTIME, options = {}) {
|
|
|
12392
12306
|
// verification backstop. The `_GSD_RUNTIME_ROOT`/`$PREFERRED_CONFIG_DIR`
|
|
12393
12307
|
// fallback chains and prose `.claude` mentions carry no `@~/` prefix and
|
|
12394
12308
|
// are deliberately untouched, as is CHANGELOG.md.
|
|
12395
|
-
if (runtime
|
|
12309
|
+
if (hostBehaviorsFor(runtime).rewriteClaudeAtIncludes) {
|
|
12396
12310
|
for (const relPath of manifestFiles) {
|
|
12397
12311
|
const fileName = path.basename(relPath);
|
|
12398
12312
|
if (!(fileName.endsWith('.md') || fileName.endsWith('.toml'))) continue;
|
|
@@ -13041,7 +12955,7 @@ function install(isGlobal, runtime = DEFAULT_RUNTIME, options = {}) {
|
|
|
13041
12955
|
// stop, subagentStart, subagentStop) via runtime-hooks-surface.cts, which reads
|
|
13042
12956
|
// the event list from the descriptor-driven adapter module.
|
|
13043
12957
|
const cursorHookResult = writeCursorHooksJson(targetDir, src, {
|
|
13044
|
-
managedHookEvents:
|
|
12958
|
+
managedHookEvents: hostBehaviorsFor(runtime).managedHookEvents,
|
|
13045
12959
|
});
|
|
13046
12960
|
if (cursorHookResult.changed) {
|
|
13047
12961
|
console.log(` ${green}✓${reset} Configured Cursor lifecycle hooks (sessionStart, postToolUse, preToolUse, stop, subagentStart, subagentStop)`);
|
|
@@ -13134,9 +13048,9 @@ function install(isGlobal, runtime = DEFAULT_RUNTIME, options = {}) {
|
|
|
13134
13048
|
// reports success and the user is left with the very breakage the opt-in
|
|
13135
13049
|
// exists to prevent. Verified reproducible before this guard existed.
|
|
13136
13050
|
const kimiInstalledThisRun = selectedRuntimes.includes('kimi');
|
|
13137
|
-
if (hasReclaimKimiLegacy && runtime
|
|
13051
|
+
if (hasReclaimKimiLegacy && hostBehaviorsFor(runtime).reclaimsKimiLegacyHooksRoot && kimiInstalledThisRun) {
|
|
13138
13052
|
console.log(` ${dim}•${reset} Skipped --reclaim-kimi-legacy: this run also installs --kimi, so ${resolveKimiHooksTomlDir({ runtime: 'kimi' })} is a live Kimi CLI install`);
|
|
13139
|
-
} else if (hasReclaimKimiLegacy && runtime
|
|
13053
|
+
} else if (hasReclaimKimiLegacy && hostBehaviorsFor(runtime).reclaimsKimiLegacyHooksRoot) {
|
|
13140
13054
|
const legacyKimiRoot = resolveKimiHooksTomlDir({ runtime: 'kimi' });
|
|
13141
13055
|
// Both roots honor their own env override (KIMI_SHARE_DIR /
|
|
13142
13056
|
// KIMI_CODE_HOME). A user who points both at ONE directory collapses
|
|
@@ -13212,15 +13126,15 @@ function install(isGlobal, runtime = DEFAULT_RUNTIME, options = {}) {
|
|
|
13212
13126
|
// #2870: the CURRENT scope's settings filename is sourced from the Install
|
|
13213
13127
|
// Scope Module (_installScope.settingsFile, resolveScope's per-scope field)
|
|
13214
13128
|
// instead of indexing _scopedSettings by hand. _scopedSettings itself is
|
|
13215
|
-
// retained unchanged as the #338-privacy fail-safe path:
|
|
13216
|
-
// already degrades to
|
|
13217
|
-
//
|
|
13129
|
+
// retained unchanged as the #338-privacy fail-safe path: hostBehaviorsFor
|
|
13130
|
+
// already degrades to its #338 floor (see runtime-name-policy.cts)
|
|
13131
|
+
// when the registry fails to load, whereas resolveScope's registry
|
|
13218
13132
|
// lookup throws in that same scenario (_installScope is null when it did).
|
|
13219
13133
|
// Falling back to _scopedSettings[_installScopeId] there — and keeping the
|
|
13220
13134
|
// non-local-claude branch's expression untouched — means this is
|
|
13221
13135
|
// byte-identical to the pre-migration computation in every case, including
|
|
13222
13136
|
// the broken-registry fail-safe floor.
|
|
13223
|
-
const _scopedSettings =
|
|
13137
|
+
const _scopedSettings = hostBehaviorsFor(runtime).settingsFileByScope || null;
|
|
13224
13138
|
const _currentScopeSettingsFile = _installScope
|
|
13225
13139
|
? _installScope.settingsFile
|
|
13226
13140
|
: (_scopedSettings ? (_scopedSettings[_installScopeId] ?? null) : null);
|
|
@@ -13346,7 +13260,7 @@ function install(isGlobal, runtime = DEFAULT_RUNTIME, options = {}) {
|
|
|
13346
13260
|
// Descriptor-driven (ADR-1239 / #2096): hookPathStyle comes from the
|
|
13347
13261
|
// runtime's hostBehaviors instead of a hardcoded `runtime === 'antigravity'`
|
|
13348
13262
|
// check inside projectLocalHookPrefix.
|
|
13349
|
-
const localPrefix = projectLocalHookPrefix({ runtime, dirName, hookPathStyle:
|
|
13263
|
+
const localPrefix = projectLocalHookPrefix({ runtime, dirName, hookPathStyle: hostBehaviorsFor(runtime).hookPathStyle });
|
|
13350
13264
|
const settingsEntrypoints = [];
|
|
13351
13265
|
const hookOpts = {
|
|
13352
13266
|
portableHooks: hasPortableHooks,
|
|
@@ -13449,7 +13363,7 @@ function install(isGlobal, runtime = DEFAULT_RUNTIME, options = {}) {
|
|
|
13449
13363
|
// installAllRuntimes can register it at finalize time when the user opts
|
|
13450
13364
|
// in (#2795). Computed here (not in finishInstall) so the same buildHookCommand
|
|
13451
13365
|
// / localCmd resolution logic is shared with the other JS hooks.
|
|
13452
|
-
const updateBannerCommand =
|
|
13366
|
+
const updateBannerCommand = hostBehaviorsFor(runtime).skipUpdateBannerCommand
|
|
13453
13367
|
? null
|
|
13454
13368
|
: (isGlobal
|
|
13455
13369
|
? buildHookCommand(targetDir, 'gsd-update-banner.js', hookOpts)
|
|
@@ -13612,7 +13526,7 @@ function finishInstall(settingsPath, settings, statuslineCommand, shouldInstallS
|
|
|
13612
13526
|
// on plan.finishPermissionWriter === 'kilo' (descriptor-driven), not this flag.
|
|
13613
13527
|
// #2094: isTrae dropped — unused in this function.
|
|
13614
13528
|
// #2095: isKimi dropped — the Kimi "Done!" banner below reads
|
|
13615
|
-
//
|
|
13529
|
+
// hostBehaviorsFor(runtime).doneBannerStyle === 'kimi-agent-file' (descriptor-driven), not this flag.
|
|
13616
13530
|
// #2096: isAntigravity dropped — unused in this function.
|
|
13617
13531
|
// #2098: isCodebuddy dropped — unused in this function.
|
|
13618
13532
|
// #2099: isCopilot dropped — unused in this function.
|
|
@@ -13633,7 +13547,7 @@ function finishInstall(settingsPath, settings, statuslineCommand, shouldInstallS
|
|
|
13633
13547
|
// runtime — kept for a caller that invokes finishInstall directly.
|
|
13634
13548
|
assertConfiguredEntrypoints(bannerOpts.configuredEntrypoints);
|
|
13635
13549
|
|
|
13636
|
-
if (shouldInstallStatusline && plan.writesSharedSettings && !
|
|
13550
|
+
if (shouldInstallStatusline && plan.writesSharedSettings && !hostBehaviorsFor(runtime).skipSettingsUi) {
|
|
13637
13551
|
if (!isGlobal && !forceStatusline) {
|
|
13638
13552
|
// Local installs skip statusLine by default: repo settings.json takes precedence over
|
|
13639
13553
|
// profile-level settings.json in Claude Code, so writing here would silently clobber
|
|
@@ -13659,7 +13573,7 @@ function finishInstall(settingsPath, settings, statuslineCommand, shouldInstallS
|
|
|
13659
13573
|
// settings.json hooks block — opencode/kilo/codex/cursor/windsurf/trae/
|
|
13660
13574
|
// cline either lack the surface or use a different config schema.
|
|
13661
13575
|
const { shouldInstallBanner, bannerCommand } = bannerOpts;
|
|
13662
|
-
if (shouldInstallBanner && settings && plan.writesSharedSettings && !
|
|
13576
|
+
if (shouldInstallBanner && settings && plan.writesSharedSettings && !hostBehaviorsFor(runtime).skipSettingsUi) {
|
|
13663
13577
|
if (!bannerCommand) {
|
|
13664
13578
|
console.warn(` ${yellow}⚠${reset} Skipped update banner registration — Node executable path unavailable. See #2979 / #3002.`);
|
|
13665
13579
|
} else {
|
|
@@ -13688,13 +13602,13 @@ function finishInstall(settingsPath, settings, statuslineCommand, shouldInstallS
|
|
|
13688
13602
|
// Merges GSD-owned entries non-destructively (preserves existing user permissions).
|
|
13689
13603
|
// Scoped to Claude only: antigravity/qwen/hermes/codebuddy also write
|
|
13690
13604
|
// settings.json but use different runtimes and do not use these permission strings.
|
|
13691
|
-
if (
|
|
13605
|
+
if (hostBehaviorsFor(runtime).permissionsSchema === 'claude') {
|
|
13692
13606
|
mergeClaudePermissions(settings);
|
|
13693
13607
|
}
|
|
13694
13608
|
|
|
13695
13609
|
// #2097 UPGRADE 3 (transport:mcp): companion MCP server for runtimes that host
|
|
13696
13610
|
// MCP in settings.json (Augment). settings.json is golden-excluded, so no golden change.
|
|
13697
|
-
if (
|
|
13611
|
+
if (hostBehaviorsFor(runtime).mcpCompanion === 'settings-json' && settings && plan.writesSharedSettings) {
|
|
13698
13612
|
mergeGsdMcpServerIntoSettings(settings);
|
|
13699
13613
|
}
|
|
13700
13614
|
|
|
@@ -13734,18 +13648,29 @@ function finishInstall(settingsPath, settings, statuslineCommand, shouldInstallS
|
|
|
13734
13648
|
// generation reads it). This call is idempotent (preserves existing values).
|
|
13735
13649
|
writeNonClaudeDefaults(runtime);
|
|
13736
13650
|
|
|
13737
|
-
// program
|
|
13738
|
-
//
|
|
13739
|
-
//
|
|
13651
|
+
// program is the runtime display label (ADR-1239 Phase B / #1679). The command
|
|
13652
|
+
// is generated from the surface this runtime registered in this install scope
|
|
13653
|
+
// (#5215, ADR-5057 §5 Phase 12) — a runtime that registers no new-project
|
|
13654
|
+
// trigger is told so instead of being sent to a command that does not exist (#4567).
|
|
13740
13655
|
const program = getRuntimeLabel(runtime);
|
|
13741
|
-
const
|
|
13656
|
+
const advertised = resolveAdvertisedNewProject(runtime, isGlobal ? 'global' : 'local');
|
|
13657
|
+
const command = advertised.kind === 'command' ? advertised.command : null;
|
|
13658
|
+
// Host-specific launch/restart steps below stay; only the new-project clause
|
|
13659
|
+
// changes when the runtime registered no such command.
|
|
13660
|
+
const noNewProject = advertised.kind === 'unregistered'
|
|
13661
|
+
? `${program} registers no new-project command in this scope${advertised.nativeCommand ? ` (its native extension registers ${cyan}${advertised.nativeCommand}${reset})` : ''}.`
|
|
13662
|
+
: '';
|
|
13742
13663
|
|
|
13743
13664
|
// Claude Code global installs use the skills/ format (CC 2.1.88+).
|
|
13744
13665
|
// Restart is required for CC to pick up newly-installed skills, and the
|
|
13745
13666
|
// slash-menu surface depends on CC version — so the instruction needs to
|
|
13746
13667
|
// cover both invocation paths to avoid #2957-style "no commands appear".
|
|
13747
|
-
if (
|
|
13748
|
-
console.log(`
|
|
13668
|
+
if (hostBehaviorsFor(runtime).skillsGlobalOnboarding && isGlobal) {
|
|
13669
|
+
console.log(command === null ? `
|
|
13670
|
+
${green}Done!${reset} Restart ${program}. ${noNewProject}
|
|
13671
|
+
|
|
13672
|
+
${cyan}Join the community:${reset} https://discord.gg/mYgfVNfA2r
|
|
13673
|
+
` : `
|
|
13749
13674
|
${green}Done!${reset} Restart ${program}, then in any directory either type ${cyan}${command}${reset} or ask Claude to run the ${cyan}gsd-new-project${reset} skill.
|
|
13750
13675
|
|
|
13751
13676
|
${cyan}Join the community:${reset} https://discord.gg/mYgfVNfA2r
|
|
@@ -13753,9 +13678,13 @@ function finishInstall(settingsPath, settings, statuslineCommand, shouldInstallS
|
|
|
13753
13678
|
return;
|
|
13754
13679
|
}
|
|
13755
13680
|
|
|
13756
|
-
if (
|
|
13681
|
+
if (hostBehaviorsFor(runtime).doneBannerStyle === 'kimi-agent-file') {
|
|
13757
13682
|
const agentPath = configDir ? path.join(configDir, 'agents', 'gsd.yaml') : 'agents/gsd.yaml';
|
|
13758
|
-
console.log(`
|
|
13683
|
+
console.log(command === null ? `
|
|
13684
|
+
${green}Done!${reset} Start ${program} with ${cyan}kimi --agent-file ${agentPath}${reset}. ${noNewProject}
|
|
13685
|
+
|
|
13686
|
+
${cyan}Join the community:${reset} https://discord.gg/mYgfVNfA2r
|
|
13687
|
+
` : `
|
|
13759
13688
|
${green}Done!${reset} Start ${program} with ${cyan}kimi --agent-file ${agentPath}${reset}, then run ${cyan}${command}${reset}.
|
|
13760
13689
|
|
|
13761
13690
|
${cyan}Join the community:${reset} https://discord.gg/mYgfVNfA2r
|
|
@@ -13763,7 +13692,11 @@ function finishInstall(settingsPath, settings, statuslineCommand, shouldInstallS
|
|
|
13763
13692
|
return;
|
|
13764
13693
|
}
|
|
13765
13694
|
|
|
13766
|
-
console.log(`
|
|
13695
|
+
console.log(command === null ? `
|
|
13696
|
+
${green}Done!${reset} GSD is installed for ${program}, which registers no new-project command in this scope${advertised.nativeCommand ? ` (its native extension registers ${cyan}${advertised.nativeCommand}${reset})` : ''}.
|
|
13697
|
+
|
|
13698
|
+
${cyan}Join the community:${reset} https://discord.gg/mYgfVNfA2r
|
|
13699
|
+
` : `
|
|
13767
13700
|
${green}Done!${reset} Open a blank directory in ${program} and run ${cyan}${command}${reset}.
|
|
13768
13701
|
|
|
13769
13702
|
${cyan}Join the community:${reset} https://discord.gg/mYgfVNfA2r
|
|
@@ -14713,9 +14646,6 @@ module.exports = {
|
|
|
14713
14646
|
install,
|
|
14714
14647
|
installAllRuntimes,
|
|
14715
14648
|
uninstall,
|
|
14716
|
-
// #2086 — host-behavior resolution + the #338 privacy fail-safe floor (exported for tests)
|
|
14717
|
-
_resolveHostBehaviors,
|
|
14718
|
-
FALLBACK_HOST_BEHAVIORS,
|
|
14719
14649
|
// #3023 — shared hook bundle directory name, descriptor-driven
|
|
14720
14650
|
SHARED_HOOKS_DIR_DEFAULT,
|
|
14721
14651
|
resolveSharedHooksDirName,
|