@opengsd/gsd-core 1.9.1 → 1.11.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 +2 -3
- package/.opencode/plugins/gsd-core.js +8 -1
- package/agents/gsd-code-fixer.md +27 -3
- package/agents/gsd-debug-session-manager.md +11 -0
- package/agents/gsd-debugger.md +12 -246
- package/agents/gsd-doc-synthesizer.md +2 -4
- package/agents/gsd-executor.md +12 -10
- package/agents/gsd-integration-checker.md +3 -0
- package/agents/gsd-mempalace-curator.md +5 -2
- package/agents/gsd-phase-researcher.md +20 -1
- package/agents/gsd-plan-checker.md +46 -0
- package/agents/gsd-planner.md +49 -54
- package/agents/gsd-roadmapper.md +21 -3
- package/agents/gsd-user-profiler.md +3 -0
- package/agents/gsd-verifier.md +26 -73
- package/bin/install.js +1272 -1238
- package/bin/lib/ui-safety-gate.cjs +2 -0
- package/commands/gsd/code-review.md +1 -1
- package/commands/gsd/execute-phase.md +1 -1
- package/commands/gsd/map-codebase.md +1 -1
- package/commands/gsd/mempalace-capture.md +2 -2
- package/commands/gsd/mempalace-recall.md +1 -1
- package/commands/gsd/new-milestone.md +2 -2
- package/commands/gsd/plan-phase.md +1 -1
- package/commands/gsd/quick.md +1 -1
- package/commands/gsd/review-backlog.md +2 -1
- package/commands/gsd/verify-work.md +1 -1
- package/gsd-core/bin/gsd-tools.cjs +1009 -115
- package/gsd-core/bin/lib/active-workstream-store.cjs +153 -12
- package/gsd-core/bin/lib/agent-install-check.cjs +268 -38
- package/gsd-core/bin/lib/api-coverage.cjs +123 -5
- package/gsd-core/bin/lib/artifacts.cjs +3 -0
- package/gsd-core/bin/lib/assumption-delta.cjs +2 -4
- package/gsd-core/bin/lib/audit-command-router.cjs +9 -2
- package/gsd-core/bin/lib/audit.cjs +926 -202
- package/gsd-core/bin/lib/broken-windows.cjs +36 -6
- package/gsd-core/bin/lib/capability-consent.cjs +149 -15
- package/gsd-core/bin/lib/capability-lifecycle.cjs +45 -0
- package/gsd-core/bin/lib/capability-registry.cjs +608 -148
- package/gsd-core/bin/lib/capability-source.cjs +92 -0
- package/gsd-core/bin/lib/capability-trust.cjs +444 -25
- package/gsd-core/bin/lib/capability-validator.cjs +507 -24
- package/gsd-core/bin/lib/capability-writer.cjs +3 -2
- package/gsd-core/bin/lib/check-command-router.cjs +114 -38
- package/gsd-core/bin/lib/claude-orchestration.cjs +56 -3
- package/gsd-core/bin/lib/codex-agent-toml.cjs +329 -0
- package/gsd-core/bin/lib/command-aliases.cjs +94 -0
- package/gsd-core/bin/lib/command-roster.cjs +44 -1
- package/gsd-core/bin/lib/commands.cjs +665 -99
- package/gsd-core/bin/lib/commonjs-marker.cjs +142 -0
- package/gsd-core/bin/lib/complexity-trigger.cjs +1172 -0
- package/gsd-core/bin/lib/config-loader.cjs +76 -0
- package/gsd-core/bin/lib/config.cjs +22 -2
- package/gsd-core/bin/lib/context-composer.cjs +278 -0
- package/gsd-core/bin/lib/context-predicates.cjs +506 -0
- package/gsd-core/bin/lib/core-utils.cjs +217 -40
- package/gsd-core/bin/lib/decisions.cjs +23 -0
- package/gsd-core/bin/lib/docs.cjs +3 -2
- package/gsd-core/bin/lib/external-job.cjs +19 -4
- package/gsd-core/bin/lib/fallow-runner.cjs +20 -44
- package/gsd-core/bin/lib/frontmatter.cjs +239 -32
- package/gsd-core/bin/lib/gap-checker.cjs +68 -7
- package/gsd-core/bin/lib/gate-predicate-evaluator.cjs +57 -6
- package/gsd-core/bin/lib/git-base-branch.cjs +160 -15
- package/gsd-core/bin/lib/graphify.cjs +142 -27
- package/gsd-core/bin/lib/gsd2-import.cjs +37 -5
- package/gsd-core/bin/lib/health-diagnostic-rules/agent-install.cjs +101 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/config-validation.cjs +348 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/consistency.cjs +145 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/install-surface-shadowing.cjs +98 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/milestone-archive-hygiene.cjs +100 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/phase-structure.cjs +222 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/roadmap-disk-consistency.cjs +265 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/root-existence.cjs +161 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/state-consistency.cjs +303 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/worktree-health.cjs +173 -0
- package/gsd-core/bin/lib/health-diagnostic-types.cjs +68 -0
- package/gsd-core/bin/lib/health-diagnostic.cjs +431 -0
- package/gsd-core/bin/lib/host-integration.cjs +13 -1
- package/gsd-core/bin/lib/host-runtime-detection.cjs +134 -0
- package/gsd-core/bin/lib/init-command-router.cjs +83 -8
- package/gsd-core/bin/lib/init.cjs +1325 -169
- package/gsd-core/bin/lib/install-effort-resolver.cjs +73 -30
- package/gsd-core/bin/lib/install-engine.cjs +805 -264
- package/gsd-core/bin/lib/install-fs-adapter.cjs +262 -0
- package/gsd-core/bin/lib/install-model-override-resolver.cjs +203 -0
- package/gsd-core/bin/lib/install-profiles.cjs +160 -57
- package/gsd-core/bin/lib/install-scope.cjs +270 -0
- package/gsd-core/bin/lib/install-shadow-report.cjs +385 -0
- package/gsd-core/bin/lib/installed-surface-resolver.cjs +381 -0
- package/gsd-core/bin/lib/installer-migration-authoring.cjs +3 -1
- package/gsd-core/bin/lib/installer-migration-report.cjs +4 -0
- package/gsd-core/bin/lib/installer-migrations/007-retire-config-root-commonjs-marker.cjs +149 -0
- package/gsd-core/bin/lib/installer-migrations/008-cursor-retire-commands-surface.cjs +55 -0
- package/gsd-core/bin/lib/installer-migrations/009-pi-retire-reserved-hooks-dir.cjs +199 -0
- package/gsd-core/bin/lib/installer-migrations.cjs +206 -13
- package/gsd-core/bin/lib/io.cjs +38 -3
- package/gsd-core/bin/lib/markdown-sectionizer.cjs +8 -1
- package/gsd-core/bin/lib/markdown-table.cjs +133 -20
- package/gsd-core/bin/lib/mcp-catalog.cjs +518 -0
- package/gsd-core/bin/lib/mcp-server.cjs +135 -3
- package/gsd-core/bin/lib/milestone-lock.cjs +248 -0
- package/gsd-core/bin/lib/milestone.cjs +821 -109
- package/gsd-core/bin/lib/model-catalog.cjs +59 -1
- package/gsd-core/bin/lib/model-resolver.cjs +183 -40
- package/gsd-core/bin/lib/normalize-test-command.cjs +1 -1
- package/gsd-core/bin/lib/pattern.cjs +122 -0
- package/gsd-core/bin/lib/phase-estimation.cjs +1 -1
- package/gsd-core/bin/lib/phase-id.cjs +507 -36
- package/gsd-core/bin/lib/phase-lifecycle.cjs +28 -3
- package/gsd-core/bin/lib/phase-locator.cjs +258 -58
- package/gsd-core/bin/lib/phase.cjs +891 -156
- package/gsd-core/bin/lib/plan-dependency-graph.cjs +303 -0
- package/gsd-core/bin/lib/plan-drift-guard.cjs +120 -0
- package/gsd-core/bin/lib/plan-scan.cjs +86 -2
- package/gsd-core/bin/lib/planning-scope.cjs +31 -0
- package/gsd-core/bin/lib/planning-snapshot.cjs +890 -0
- package/gsd-core/bin/lib/planning-workspace.cjs +60 -6
- package/gsd-core/bin/lib/probe-core.cjs +1 -1
- package/gsd-core/bin/lib/profile-output.cjs +1 -1
- package/gsd-core/bin/lib/prompt-budget.cjs +128 -165
- package/gsd-core/bin/lib/refactor-trigger-command-router.cjs +740 -0
- package/gsd-core/bin/lib/retired-artifact-cleanup.cjs +85 -0
- package/gsd-core/bin/lib/review-lane-descriptor.cjs +108 -0
- package/gsd-core/bin/lib/review-lane-invocation.cjs +30 -0
- package/gsd-core/bin/lib/review-lane-runner.cjs +447 -68
- package/gsd-core/bin/lib/review-reviewer-selection.cjs +13 -18
- package/gsd-core/bin/lib/roadmap-command-router.cjs +76 -9
- package/gsd-core/bin/lib/roadmap-parser.cjs +1035 -194
- package/gsd-core/bin/lib/roadmap-upgrade.cjs +37 -10
- package/gsd-core/bin/lib/roadmap.cjs +405 -84
- package/gsd-core/bin/lib/runtime-artifact-conversion.cjs +795 -100
- package/gsd-core/bin/lib/runtime-artifact-install-plan.cjs +14 -2
- package/gsd-core/bin/lib/runtime-artifact-layout.cjs +440 -57
- package/gsd-core/bin/lib/runtime-config-adapter-registry.cjs +3 -2
- package/gsd-core/bin/lib/runtime-homes.cjs +220 -41
- package/gsd-core/bin/lib/runtime-hooks-surface.cjs +220 -44
- package/gsd-core/bin/lib/runtime-name-policy.cjs +3 -1
- package/gsd-core/bin/lib/runtime-slash.cjs +27 -9
- package/gsd-core/bin/lib/section-manifest.cjs +209 -0
- package/gsd-core/bin/lib/security.cjs +104 -5
- package/gsd-core/bin/lib/shell-command-projection.cjs +388 -30
- package/gsd-core/bin/lib/smart-entry.cjs +154 -22
- package/gsd-core/bin/lib/state-command-router.cjs +5 -1
- package/gsd-core/bin/lib/state-document.cjs +152 -8
- package/gsd-core/bin/lib/state-transition.cjs +424 -105
- package/gsd-core/bin/lib/state.cjs +1927 -401
- package/gsd-core/bin/lib/surface.cjs +35 -10
- package/gsd-core/bin/lib/text-lines.cjs +80 -0
- package/gsd-core/bin/lib/token-scanner.cjs +76 -0
- package/gsd-core/bin/lib/uat-predicate.cjs +20 -4
- package/gsd-core/bin/lib/uat.cjs +706 -64
- package/gsd-core/bin/lib/ui-frontend-evidence.cjs +157 -0
- package/gsd-core/bin/lib/ui-safety-gate.cjs +14 -5
- package/gsd-core/bin/lib/unusable-input.cjs +33 -0
- package/gsd-core/bin/lib/update-context.cjs +8 -2
- package/gsd-core/bin/lib/user-artifact-staging.cjs +705 -0
- package/gsd-core/bin/lib/validate.cjs +20 -6
- package/gsd-core/bin/lib/vendor/README.md +37 -0
- package/gsd-core/bin/lib/vendor/re2js.cjs +6480 -0
- package/gsd-core/bin/lib/vendor/re2js.d.cts +938 -0
- package/gsd-core/bin/lib/verification-command-router.cjs +2 -1
- package/gsd-core/bin/lib/verification.cjs +287 -20
- package/gsd-core/bin/lib/verify.cjs +368 -880
- package/gsd-core/bin/lib/workflow-fragments.cjs +557 -0
- package/gsd-core/bin/lib/workstream-inventory-builder.cjs +203 -19
- package/gsd-core/bin/lib/workstream-inventory.cjs +576 -31
- package/gsd-core/bin/lib/workstream.cjs +8 -2
- package/gsd-core/bin/lib/worktree-base-ref.cjs +50 -6
- package/gsd-core/bin/lib/worktree-safety.cjs +450 -125
- package/gsd-core/bin/shared/config-defaults.manifest.json +1 -0
- package/gsd-core/bin/shared/config-schema.manifest.json +9 -1
- package/gsd-core/references/agent-contracts.md +43 -26
- package/gsd-core/references/artifact-types.md +10 -3
- package/gsd-core/references/autonomous-ui-design-contract.md +42 -0
- package/gsd-core/references/checkpoints.md +2 -2
- package/gsd-core/references/context-budget.md +1 -1
- package/gsd-core/references/debugger-techniques.md +255 -0
- package/gsd-core/references/dispatch-isolation-gate.md +138 -0
- package/gsd-core/references/doc-conflict-engine.md +1 -1
- package/gsd-core/references/execute-mvp-tdd.md +3 -3
- package/gsd-core/references/execute-phase-between-wave-reset.md +6 -2
- package/gsd-core/references/execute-phase-context-guard.md +1 -1
- package/gsd-core/references/execute-phase-response-language.md +1 -1
- package/gsd-core/references/execute-phase-wave-guard.md +6 -2
- package/gsd-core/references/gate-prompts.md +1 -1
- package/gsd-core/references/git-planning-commit.md +2 -1
- package/gsd-core/references/loop-hook-dispatch.md +39 -2
- package/gsd-core/references/model-profiles.md +12 -4
- package/gsd-core/references/mvp-concepts.md +9 -9
- package/gsd-core/references/planner-guidance.md +3 -9
- package/gsd-core/references/planner-preconditions.md +1 -1
- package/gsd-core/references/planner-reviews.md +1 -1
- package/gsd-core/references/planning-config.md +8 -6
- package/gsd-core/references/research-documentation-lookup.md +5 -3
- package/gsd-core/references/revision-loop.md +1 -1
- package/gsd-core/references/specless-probe-fallback.md +8 -7
- package/gsd-core/references/universal-anti-patterns.md +3 -3
- package/gsd-core/references/verifier-phase-gates.md +192 -0
- package/gsd-core/references/verifier-wiring-patterns.md +100 -0
- package/gsd-core/references/verify-mvp-mode.md +1 -1
- package/gsd-core/references/workstream-flag.md +22 -6
- package/gsd-core/references/worktree-branch-check.md +2 -2
- package/gsd-core/templates/discussion-log.md +1 -1
- package/gsd-core/templates/phase-prompt.md +2 -4
- package/gsd-core/templates/state.md +4 -4
- package/gsd-core/templates/summary-complex.md +2 -0
- package/gsd-core/templates/summary-minimal.md +2 -0
- package/gsd-core/templates/summary-standard.md +2 -0
- package/gsd-core/templates/summary.md +2 -0
- package/gsd-core/templates/verification-report.md +9 -1
- package/gsd-core/workflows/ai-integration-phase.md +9 -11
- package/gsd-core/workflows/audit-milestone.md +3 -0
- package/gsd-core/workflows/autonomous/steps/converge-banner.md +1 -0
- package/gsd-core/workflows/autonomous/steps/converge-dispatch-bg.md +11 -0
- package/gsd-core/workflows/autonomous/steps/converge-dispatch-inline.md +7 -0
- package/gsd-core/workflows/autonomous/steps/converge-fail-fast.md +21 -0
- package/gsd-core/workflows/autonomous/steps/converge-loop.md +7 -0
- package/gsd-core/workflows/autonomous.md +33 -70
- package/gsd-core/workflows/cleanup.md +62 -3
- package/gsd-core/workflows/code-review/steps/dispatch-fix.md +39 -0
- package/gsd-core/workflows/code-review/steps/structural-pre-pass.md +93 -0
- package/gsd-core/workflows/code-review-fix.md +37 -10
- package/gsd-core/workflows/code-review.md +74 -166
- package/gsd-core/workflows/complete-milestone/steps/git-tag.md +29 -0
- package/gsd-core/workflows/complete-milestone.md +160 -95
- package/gsd-core/workflows/debug.md +16 -17
- package/gsd-core/workflows/diagnose-issues.md +56 -8
- package/gsd-core/workflows/discuss-phase/modes/chain.md +2 -1
- package/gsd-core/workflows/discuss-phase/modes/default.md +1 -1
- package/gsd-core/workflows/discuss-phase-assumptions/steps/auto-advance-dispatch.md +15 -0
- package/gsd-core/workflows/discuss-phase-assumptions.md +7 -17
- package/gsd-core/workflows/docs-update/steps/dispatch-monorepo-packages.md +51 -0
- package/gsd-core/workflows/docs-update.md +8 -51
- package/gsd-core/workflows/edit-phase.md +26 -1
- package/gsd-core/workflows/eval-review.md +3 -5
- package/gsd-core/workflows/execute-phase/steps/executor-isolation-dispatch.md +64 -7
- package/gsd-core/workflows/execute-phase/steps/gap-closure-artifacts.md +50 -0
- package/gsd-core/workflows/execute-phase/steps/partial-wave.md +31 -0
- package/gsd-core/workflows/execute-phase/steps/per-plan-executor-routing.md +77 -0
- package/gsd-core/workflows/execute-phase/steps/per-plan-worktree-gate.md +21 -0
- package/gsd-core/workflows/execute-phase/steps/regression-gate-run.md +42 -0
- package/gsd-core/workflows/execute-phase/steps/regression-gate.md +43 -37
- package/gsd-core/workflows/execute-phase.md +103 -187
- package/gsd-core/workflows/execute-plan.md +36 -4
- package/gsd-core/workflows/explore.md +131 -4
- package/gsd-core/workflows/fast.md +10 -2
- package/gsd-core/workflows/health.md +73 -4
- package/gsd-core/workflows/help/modes/full.md +6 -1
- package/gsd-core/workflows/import.md +4 -4
- package/gsd-core/workflows/ingest-docs.md +7 -6
- package/gsd-core/workflows/mvp-phase.md +6 -3
- package/gsd-core/workflows/new-milestone/steps/project-md-milestone-write.md +16 -0
- package/gsd-core/workflows/new-milestone/steps/reset-phase-safety.md +19 -0
- package/gsd-core/workflows/new-milestone.md +35 -47
- package/gsd-core/workflows/new-project/steps/auto-mode-config.md +176 -0
- package/gsd-core/workflows/new-project/steps/auto-mode-detection.md +32 -0
- package/gsd-core/workflows/new-project/steps/codebase-map-offer.md +18 -0
- package/gsd-core/workflows/new-project.md +27 -240
- package/gsd-core/workflows/next.md +12 -0
- package/gsd-core/workflows/plan-phase/steps/adr-ingest-express-path.md +15 -0
- package/gsd-core/workflows/plan-phase/steps/chunked-planning-mode.md +110 -0
- package/gsd-core/workflows/plan-phase/steps/prd-express-gate.md +8 -0
- package/gsd-core/workflows/plan-phase/steps/research-only-early-exit.md +17 -0
- package/gsd-core/workflows/plan-phase/steps/research-only-modifiers.md +16 -0
- package/gsd-core/workflows/plan-phase/steps/reviews-prerequisite.md +17 -0
- package/gsd-core/workflows/plan-phase/steps/stall-detection-helpers.md +149 -0
- package/gsd-core/workflows/plan-phase.md +89 -209
- package/gsd-core/workflows/plan-review-convergence.md +50 -2
- package/gsd-core/workflows/progress/steps/forensic-audit.md +125 -0
- package/gsd-core/workflows/progress/steps/mvp-display.md +18 -0
- package/gsd-core/workflows/progress.md +45 -159
- package/gsd-core/workflows/quick/steps/discussion-phase.md +124 -0
- package/gsd-core/workflows/quick/steps/plan-checker-loop.md +111 -0
- package/gsd-core/workflows/quick/steps/quick-verification.md +67 -0
- package/gsd-core/workflows/quick/steps/research-phase.md +72 -0
- package/gsd-core/workflows/quick/steps/worktree-pre-dispatch-commit.md +37 -0
- package/gsd-core/workflows/quick.md +55 -405
- package/gsd-core/workflows/resume-project.md +3 -0
- package/gsd-core/workflows/review/steps/reviewer-instances-note-1.md +4 -0
- package/gsd-core/workflows/review/steps/reviewer-instances-note-2.md +3 -0
- package/gsd-core/workflows/review.md +41 -13
- package/gsd-core/workflows/section-manifest.json +219 -0
- package/gsd-core/workflows/secure-phase.md +1 -1
- package/gsd-core/workflows/session-report.md +2 -1
- package/gsd-core/workflows/settings.md +66 -2
- package/gsd-core/workflows/ship.md +104 -44
- package/gsd-core/workflows/sketch.md +1 -1
- package/gsd-core/workflows/spec-phase.md +41 -20
- package/gsd-core/workflows/spike-wrap-up.md +20 -5
- package/gsd-core/workflows/spike.md +50 -16
- package/gsd-core/workflows/sync-skills.md +106 -13
- package/gsd-core/workflows/transition/steps/workstream-collision-check.md +17 -0
- package/gsd-core/workflows/transition.md +53 -31
- package/gsd-core/workflows/ui-phase.md +13 -12
- package/gsd-core/workflows/ui-review.md +2 -2
- package/gsd-core/workflows/update/steps/channel-banner.md +7 -0
- package/gsd-core/workflows/update.md +19 -8
- package/gsd-core/workflows/validate-phase.md +1 -1
- package/gsd-core/workflows/verify-work/steps/automated-ui-verification.md +36 -0
- package/gsd-core/workflows/verify-work/steps/mvp-uat-framing.md +21 -0
- package/gsd-core/workflows/verify-work.md +17 -65
- package/hooks/dist/gsd-agent-isolation-guard.js +517 -0
- package/hooks/dist/gsd-check-update-worker.js +64 -12
- package/hooks/dist/gsd-check-update.js +19 -1
- package/hooks/dist/gsd-cursor-pre-tool.js +0 -3
- package/hooks/dist/gsd-cursor-subagent-start.js +607 -26
- package/hooks/dist/gsd-cursor-subagent-stop.js +3 -2
- package/hooks/dist/gsd-prompt-guard.js +21 -20
- package/hooks/dist/gsd-read-injection-scanner.js +45 -24
- package/hooks/dist/gsd-statusline.js +90 -6
- package/hooks/dist/gsd-update-banner.js +22 -1
- package/hooks/dist/gsd-workflow-guard.js +134 -36
- package/hooks/dist/gsd-worktree-path-guard.js +2 -1
- package/hooks/dist/gsd-write-guard.js +359 -0
- package/hooks/dist/lib/git-cmd.js +92 -59
- package/hooks/dist/lib/injection-patterns.js +45 -0
- package/hooks/dist/lib/isolation-deny-reason.js +39 -0
- package/hooks/dist/lib/isolation-sentinel.js +277 -0
- package/hooks/dist/managed-hooks-registry.cjs +2 -0
- package/hooks/gsd-agent-isolation-guard.js +517 -0
- package/hooks/gsd-check-update-worker.js +64 -12
- package/hooks/gsd-check-update.js +19 -1
- package/hooks/gsd-cursor-pre-tool.js +0 -3
- package/hooks/gsd-cursor-subagent-start.js +607 -26
- package/hooks/gsd-cursor-subagent-stop.js +3 -2
- package/hooks/gsd-prompt-guard.js +21 -20
- package/hooks/gsd-read-injection-scanner.js +45 -24
- package/hooks/gsd-statusline.js +90 -6
- package/hooks/gsd-update-banner.js +22 -1
- package/hooks/gsd-workflow-guard.js +134 -36
- package/hooks/gsd-worktree-path-guard.js +2 -1
- package/hooks/gsd-write-guard.js +359 -0
- package/hooks/hooks.json +12 -0
- package/hooks/lib/git-cmd.js +92 -59
- package/hooks/lib/injection-patterns.js +45 -0
- package/hooks/lib/isolation-deny-reason.js +39 -0
- package/hooks/lib/isolation-sentinel.js +277 -0
- package/hooks/managed-hooks-registry.cjs +2 -0
- package/package.json +31 -10
- package/pi/gsd.cjs +71 -12
- package/scripts/baselines/planning-prompt-drift-baseline.json +4 -0
- package/scripts/baselines/planning-snapshot-bypass-baseline.json +12 -0
- package/scripts/baselines/unreachable-guard-drift-baseline.json +4 -0
- package/scripts/build-hooks.js +9 -0
- package/scripts/changeset/lint.cjs +68 -6
- package/scripts/changeset/serialize.cjs +5 -1
- package/scripts/check-alias-drift.cjs +7 -43
- package/scripts/check-contract-drift.cjs +297 -0
- package/scripts/ci-test-scope.cjs +19 -2
- package/scripts/command-contract-helpers.cjs +903 -1
- package/scripts/gen-adr-index.cjs +728 -38
- package/scripts/gen-capability-matrix.cjs +1 -1
- package/scripts/gen-capability-registry.cjs +3 -15
- package/scripts/gen-context-index.cjs +439 -0
- package/scripts/gen-health-docs.cjs +390 -0
- package/scripts/gen-inventory-manifest.cjs +150 -4
- package/scripts/gen-loop-host-contract.cjs +4 -24
- package/scripts/gen-prompt-budget-parity-corpus.cjs +645 -0
- package/scripts/gen-registry.cjs +3 -14
- package/scripts/gen-section-manifest.cjs +638 -0
- package/scripts/generate-package-identity.cjs +4 -2
- package/scripts/lib/alias-drift-families.cjs +46 -0
- package/scripts/lib/drift-scan.cjs +278 -0
- package/scripts/lint-allow-test-rule-refs.allowlist.json +15 -54
- package/scripts/lint-allow-test-rule-refs.effective-ceiling.json +4 -0
- package/scripts/lint-allow-test-rule-refs.unverified-ceiling.json +3 -0
- package/scripts/lint-canary-version-leak.cjs +73 -0
- package/scripts/lint-command-contract.cjs +96 -13
- package/scripts/lint-compiled-artifact-sync.cjs +6 -1
- package/scripts/lint-completion-predicate-drift.cjs +933 -0
- package/scripts/lint-completion-ratio-drift.cjs +214 -0
- package/scripts/lint-default-flip-documentation.cjs +193 -0
- package/scripts/lint-docs-command-form.cjs +195 -0
- package/scripts/lint-docs-required.cjs +9 -1
- package/scripts/lint-emitted-drift-ack.cjs +215 -20
- package/scripts/lint-eslint-glob-coverage.allowlist.json +34 -0
- package/scripts/lint-eslint-glob-coverage.cjs +340 -0
- package/scripts/lint-example-parser-parity.cjs +395 -0
- package/scripts/lint-frontmatter-scalar-broad-grep.cjs +237 -0
- package/scripts/lint-health-diagnostic-rule-table.cjs +404 -0
- package/scripts/lint-hooks-runtime-build-seam.cjs +262 -0
- package/scripts/lint-milestone-window-drift.cjs +468 -0
- package/scripts/lint-phase-enumeration-drift.cjs +479 -0
- package/scripts/lint-plan-count-drift.cjs +318 -0
- package/scripts/lint-planning-artifact-writer-drift.cjs +398 -0
- package/scripts/lint-planning-prompt-drift.cjs +434 -0
- package/scripts/lint-planning-snapshot-bypass-drift.cjs +544 -0
- package/scripts/lint-regression-test-names.cjs +15 -13
- package/scripts/lint-removed-but-needed.cjs +320 -0
- package/scripts/lint-state-field-drift.cjs +805 -0
- package/scripts/lint-state-write-path-drift.cjs +1045 -0
- package/scripts/lint-test-file-count.allowlist.json +40 -3
- package/scripts/lint-unreachable-guard-drift.cjs +843 -0
- package/scripts/lint-vendored-deps.cjs +124 -0
- package/scripts/mutation-matrix.cjs +13 -0
- package/scripts/pr-changed-files.cjs +63 -0
- package/scripts/pr-template-policy.cjs +14 -4
- package/scripts/prompt-injection-scan.sh +52 -6
- package/scripts/require-issue-link-policy.cjs +192 -0
- package/scripts/state-write-path-drift-baseline.json +19 -0
- package/scripts/sync-runtime-launcher.cjs +2 -4
- package/skills/gsd-autonomous/SKILL.md +0 -1
- package/skills/gsd-code-review/SKILL.md +1 -1
- package/skills/gsd-execute-phase/SKILL.md +1 -2
- package/skills/gsd-map-codebase/SKILL.md +1 -1
- package/skills/gsd-mempalace-capture/SKILL.md +2 -2
- package/skills/gsd-mempalace-recall/SKILL.md +1 -1
- package/skills/gsd-new-milestone/SKILL.md +2 -2
- package/skills/gsd-next/SKILL.md +0 -1
- package/skills/gsd-plan-phase/SKILL.md +1 -2
- package/skills/gsd-progress/SKILL.md +0 -1
- package/skills/gsd-quick/SKILL.md +1 -1
- package/skills/gsd-review-backlog/SKILL.md +2 -1
- package/skills/gsd-stats/SKILL.md +0 -1
- package/skills/gsd-verify-work/SKILL.md +1 -1
- package/vscode/package.json +1 -1
- package/gsd-core/workflows/discovery-phase.md +0 -298
- package/gsd-core/workflows/plan-milestone-gaps.md +0 -281
- package/gsd-core/workflows/verify-phase.md +0 -577
- package/scripts/affected-tests-lib.cjs +0 -554
- package/scripts/gen-emitted-baseline.cjs +0 -145
- package/scripts/lint-allow-test-rule-refs.cjs +0 -162
- package/scripts/run-affected-tests.cjs +0 -7
- package/scripts/run-tests.cjs +0 -1050
|
@@ -17,13 +17,31 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
17
17
|
const node_path_1 = __importDefault(require("node:path"));
|
|
18
18
|
const node_fs_1 = __importDefault(require("node:fs"));
|
|
19
19
|
const node_os_1 = __importDefault(require("node:os"));
|
|
20
|
+
// #2874 (ADR-58 cleanup phase): route this module's fs calls through the
|
|
21
|
+
// installRuntimeArtifacts call tree's injectable seam — see
|
|
22
|
+
// install-fs-adapter.cts's module doc. Resolves to real `node:fs` (the
|
|
23
|
+
// `fs` import above stays for type-only references, e.g. `fs.Dirent`)
|
|
24
|
+
// unless the top-level installRuntimeArtifacts call injected a `deps.fs`.
|
|
25
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
26
|
+
const installFsAdapter = require("./install-fs-adapter.cjs");
|
|
27
|
+
const { installFs, mkInstallTempDir } = installFsAdapter;
|
|
20
28
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
21
29
|
const installProfiles = require("./install-profiles.cjs");
|
|
22
|
-
const { stageSkillsForProfile,
|
|
30
|
+
const { stageSkillsForProfile, stageAgentsForRuntimeWithConverter, stageSkillsForRuntimeAsSkills, stageCommandsForRuntimeFlat, } = installProfiles;
|
|
23
31
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
24
32
|
const runtimeArtifactConversion = require("./runtime-artifact-conversion.cjs");
|
|
25
33
|
const conversionExports = runtimeArtifactConversion;
|
|
34
|
+
// #2875 Part 2 (J8): shared model-override precedence resolver — see its
|
|
35
|
+
// module doc for why kilo/opencode MUST resolve through this ONE function
|
|
36
|
+
// rather than re-deriving the chain per runtime.
|
|
37
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
38
|
+
const installModelOverrideResolver = require("./install-model-override-resolver.cjs");
|
|
26
39
|
const shell_command_projection_cjs_1 = require("./shell-command-projection.cjs");
|
|
40
|
+
// #2870: `isGlobalScope` centralizes the `scope === 'global'` boolean
|
|
41
|
+
// projection both kind-builder closures below need at the converters'
|
|
42
|
+
// positional `isGlobal` boundary (see its doc comment in install-scope.cts
|
|
43
|
+
// for why the projection is centralized rather than eliminated).
|
|
44
|
+
const install_scope_cjs_1 = require("./install-scope.cjs");
|
|
27
45
|
// In .cts (CommonJS output) files, `require` is available as a global.
|
|
28
46
|
const _require = require;
|
|
29
47
|
// ---------------------------------------------------------------------------
|
|
@@ -38,24 +56,51 @@ const _require = require;
|
|
|
38
56
|
* 3. Throw a descriptive error if neither succeeds.
|
|
39
57
|
*/
|
|
40
58
|
function findInstallSourceRoot(runtimeConfigDir) {
|
|
41
|
-
// Step 1: marker check
|
|
59
|
+
// Step 1: marker check — reads `<runtimeConfigDir>/.gsd-source`, a path
|
|
60
|
+
// under the INSTALL DESTINATION, so this probe goes through the injected
|
|
61
|
+
// adapter (installFs()).
|
|
42
62
|
if (runtimeConfigDir) {
|
|
43
63
|
const markerPath = node_path_1.default.join(runtimeConfigDir, '.gsd-source');
|
|
44
|
-
if (
|
|
64
|
+
if (installFs().existsSync(markerPath)) {
|
|
45
65
|
try {
|
|
46
|
-
const src =
|
|
47
|
-
if (src &&
|
|
66
|
+
const src = installFs().readFileSync(markerPath, 'utf8').trim();
|
|
67
|
+
if (src && installFs().existsSync(src))
|
|
48
68
|
return src;
|
|
49
69
|
}
|
|
50
70
|
catch { /* fall through */ }
|
|
51
71
|
}
|
|
52
72
|
}
|
|
53
|
-
// Step 2: walk up from __dirname
|
|
73
|
+
// Step 2: walk up from __dirname to locate the GSD PACKAGE'S OWN source
|
|
74
|
+
// tree (commands/gsd/) — this resolves where the installer's own code is
|
|
75
|
+
// running FROM, not anything under the install destination, so it is
|
|
76
|
+
// deliberately NOT routed through the injected fs adapter (#2874): a fake
|
|
77
|
+
// "destination" adapter has no reason to know about the real package's own
|
|
78
|
+
// on-disk layout (an injected adapter's store starts empty and is never
|
|
79
|
+
// seeded with real repo paths), and routing it through would make this
|
|
80
|
+
// resolution unconditionally throw rather than gracefully staging nothing.
|
|
81
|
+
//
|
|
82
|
+
// Uses `fs.statSync` in a try/catch rather than `fs.existsSync` — this is
|
|
83
|
+
// LOAD-BEARING, not a style choice: tests/executed-plan.test.cjs's F2 cases
|
|
84
|
+
// poison every method on the ROUTED fs surface (including `existsSync`,
|
|
85
|
+
// since installFs()'s REAL_ADAPTER also calls it) to prove nothing on the
|
|
86
|
+
// installRuntimeArtifacts call tree reaches real fs. The F2 "nativePlugin
|
|
87
|
+
// runtime: pi" test calls this function (via findInstallSourceRoot()) AFTER
|
|
88
|
+
// installing that poison, specifically to resolve the pi nativePlugin
|
|
89
|
+
// source path against this repo's own real layout — an operation this
|
|
90
|
+
// function must still be able to perform even while `existsSync` is
|
|
91
|
+
// poisoned, because this Step 2 walk is real-fs-only by design and was
|
|
92
|
+
// never meant to be covered by that poison list. `statSync` is not on the
|
|
93
|
+
// poisoned surface, so this probe survives; switching back to `existsSync`
|
|
94
|
+
// makes that F2 test throw (verified: reverting this to `existsSync` trips
|
|
95
|
+
// the poison and breaks the pi nativePlugin case).
|
|
54
96
|
let dir = __dirname;
|
|
55
97
|
for (let i = 0; i < 6; i++) {
|
|
56
98
|
const candidate = node_path_1.default.join(dir, 'commands', 'gsd');
|
|
57
|
-
|
|
99
|
+
try {
|
|
100
|
+
node_fs_1.default.statSync(candidate);
|
|
58
101
|
return candidate;
|
|
102
|
+
}
|
|
103
|
+
catch { /* not here — keep walking up */ }
|
|
59
104
|
const parent = node_path_1.default.dirname(dir);
|
|
60
105
|
if (parent === dir)
|
|
61
106
|
break;
|
|
@@ -72,28 +117,35 @@ function findInstallSourceRoot(runtimeConfigDir) {
|
|
|
72
117
|
* 3. Throw a descriptive error if neither succeeds.
|
|
73
118
|
*/
|
|
74
119
|
function findAgentsSourceRoot(runtimeConfigDir) {
|
|
75
|
-
// Step 1: marker check
|
|
120
|
+
// Step 1: marker check (destination-relative — routed through installFs()).
|
|
76
121
|
if (runtimeConfigDir) {
|
|
77
122
|
const markerPath = node_path_1.default.join(runtimeConfigDir, '.gsd-source');
|
|
78
|
-
if (
|
|
123
|
+
if (installFs().existsSync(markerPath)) {
|
|
79
124
|
try {
|
|
80
|
-
const src =
|
|
81
|
-
if (src &&
|
|
125
|
+
const src = installFs().readFileSync(markerPath, 'utf8').trim();
|
|
126
|
+
if (src && installFs().existsSync(src)) {
|
|
82
127
|
// Marker points to commands/gsd; agents/ is a sibling of commands/
|
|
83
128
|
const agentsCandidate = node_path_1.default.resolve(node_path_1.default.dirname(src), '..', 'agents');
|
|
84
|
-
if (
|
|
129
|
+
if (installFs().existsSync(agentsCandidate))
|
|
85
130
|
return agentsCandidate;
|
|
86
131
|
}
|
|
87
132
|
}
|
|
88
133
|
catch { /* fall through */ }
|
|
89
134
|
}
|
|
90
135
|
}
|
|
91
|
-
// Step 2: walk up from __dirname
|
|
136
|
+
// Step 2: walk up from __dirname — locates THIS package's own agents/
|
|
137
|
+
// source tree, not the install destination. See findInstallSourceRoot's
|
|
138
|
+
// Step 2 comment (#2874) for why this stays unrouted, real-fs-only, and why
|
|
139
|
+
// it uses `statSync` rather than `existsSync` (load-bearing against F2's
|
|
140
|
+
// poison of the routed fs surface, not a style choice).
|
|
92
141
|
let dir = __dirname;
|
|
93
142
|
for (let i = 0; i < 6; i++) {
|
|
94
143
|
const candidate = node_path_1.default.join(dir, 'agents');
|
|
95
|
-
|
|
144
|
+
try {
|
|
145
|
+
node_fs_1.default.statSync(candidate);
|
|
96
146
|
return candidate;
|
|
147
|
+
}
|
|
148
|
+
catch { /* not here — keep walking up */ }
|
|
97
149
|
const parent = node_path_1.default.dirname(dir);
|
|
98
150
|
if (parent === dir)
|
|
99
151
|
break;
|
|
@@ -117,9 +169,63 @@ function agentsKind(destSubpath, prefix, configDir) {
|
|
|
117
169
|
kind: 'agents',
|
|
118
170
|
destSubpath,
|
|
119
171
|
prefix,
|
|
120
|
-
|
|
172
|
+
// #2995: a `converter: null` agents entry (claude local, zcode) previously
|
|
173
|
+
// staged via stageAgentsForProfile — a RAW byte copy that never reads content
|
|
174
|
+
// into JS, so gsd:section markers shipped verbatim. Route through the
|
|
175
|
+
// composing stager with an identity converter instead: same output as the raw
|
|
176
|
+
// copy for an unmarked agent, markers stripped for a marked one. Routing both
|
|
177
|
+
// agent kinds through the stager collapses what were five independent agent
|
|
178
|
+
// read points down to three compose call sites: this stager, bin/install.js's
|
|
179
|
+
// inline agent loop, and installCodexConfig's per-agent .toml writer. The
|
|
180
|
+
// exhaustive per-runtime sweep in tests/agent-fragments-emission.install.test.cjs
|
|
181
|
+
// is what keeps a fourth from appearing uncomposed.
|
|
182
|
+
// #2875 Part 2 (row I2): agentCtx threaded through so a runtime using this
|
|
183
|
+
// converter:null builder (claude, plus any future identity-copy runtime)
|
|
184
|
+
// ALSO gets path-rewrites/attribution/frontmatter-extensions/normalize
|
|
185
|
+
// when a caller supplies agentCtx (createRuntimeArtifactInstallPlan /
|
|
186
|
+
// applySurface's agentCtx build). Previously this closure's `(resolved) =>`
|
|
187
|
+
// signature silently dropped the second arg every caller already passed —
|
|
188
|
+
// a caller with NO agentCtx in scope is unaffected (row I2: converter-only,
|
|
189
|
+
// as today), matching stageAgentsForRuntimeWithConverter's own contract.
|
|
190
|
+
stage: (resolved, agentCtx) => stageAgentsForRuntimeWithConverter(findAgentsSourceRoot(configDir), resolved, (content) => content, false, agentCtx),
|
|
121
191
|
};
|
|
122
192
|
}
|
|
193
|
+
/**
|
|
194
|
+
* Runtime allowlist check for a descriptor-declared `converter` name, applied
|
|
195
|
+
* at DISPATCH time (security fix). `VALID_CONVERTER_NAMES` (capability-
|
|
196
|
+
* validator.cjs) is otherwise enforced ONLY at lint/build time
|
|
197
|
+
* (`check:contract-drift`) — every `conversionExports[converterName]`
|
|
198
|
+
* dynamic-property read below trusted that a `capability.json` reaching this
|
|
199
|
+
* far had already passed that check. It had not, in general: a hand-edited
|
|
200
|
+
* or malformed descriptor naming an Object-prototype member (`"constructor"`,
|
|
201
|
+
* `"toString"`, `"hasOwnProperty"`, ...) resolves to that member instead of
|
|
202
|
+
* throwing, producing garbage staged content rather than a loud failure —
|
|
203
|
+
* pre-existing, but promoted from the `/gsd-surface`-only path to the real
|
|
204
|
+
* install path for seven runtimes by #2875 Part 2's agents-bypass closure.
|
|
205
|
+
* Required lazily (call-time, not module-top) to avoid a load-time circular
|
|
206
|
+
* require, the same pattern install-engine.cts's `_hostBehaviors` already
|
|
207
|
+
* uses for `capability-registry.cjs`. Fails CLOSED: any error loading the
|
|
208
|
+
* allowlist itself (missing module, exotic bundling) is treated as "nothing
|
|
209
|
+
* is allowed", never as "skip the check".
|
|
210
|
+
*/
|
|
211
|
+
function _resolveNamedConverter(converterName, kindLabel) {
|
|
212
|
+
let validNames;
|
|
213
|
+
try {
|
|
214
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
215
|
+
validNames = require('./capability-validator.cjs').VALID_CONVERTER_NAMES;
|
|
216
|
+
}
|
|
217
|
+
catch {
|
|
218
|
+
validNames = undefined;
|
|
219
|
+
}
|
|
220
|
+
if (!validNames || !validNames.has(converterName)) {
|
|
221
|
+
throw new Error(`Unknown converter "${converterName}" declared for a ${kindLabel} kind — refusing to dispatch (not in capability-validator.cjs's VALID_CONVERTER_NAMES allowlist).`);
|
|
222
|
+
}
|
|
223
|
+
const fn = conversionExports[converterName];
|
|
224
|
+
if (typeof fn !== 'function') {
|
|
225
|
+
throw new Error(`Converter "${converterName}" is allowlisted but is not an exported function of runtime-artifact-conversion.cjs.`);
|
|
226
|
+
}
|
|
227
|
+
return fn;
|
|
228
|
+
}
|
|
123
229
|
/**
|
|
124
230
|
* Build a converted-agents kind descriptor for runtimes whose agent `.md` files
|
|
125
231
|
* need runtime-specific frontmatter/body conversion (e.g. Copilot, Cursor, Codex).
|
|
@@ -131,27 +237,80 @@ function agentsKind(destSubpath, prefix, configDir) {
|
|
|
131
237
|
* Agent filenames are preserved verbatim (the prefix is already embedded in the
|
|
132
238
|
* agent stem — e.g. `gsd-planner.md`).
|
|
133
239
|
*
|
|
134
|
-
* #1173 SCOPE
|
|
135
|
-
* the
|
|
136
|
-
*
|
|
137
|
-
*
|
|
138
|
-
*
|
|
139
|
-
*
|
|
140
|
-
*
|
|
141
|
-
*
|
|
142
|
-
* `
|
|
143
|
-
* `
|
|
144
|
-
*
|
|
145
|
-
* (`
|
|
146
|
-
*
|
|
147
|
-
*
|
|
148
|
-
*
|
|
149
|
-
*
|
|
150
|
-
*
|
|
151
|
-
* `
|
|
152
|
-
*
|
|
153
|
-
*
|
|
154
|
-
*
|
|
240
|
+
* #1173 SCOPE, updated by #2875 Part 2 (the agents-bypass closure) — measured
|
|
241
|
+
* against the tree, not the ADR-3574 framing that preceded it:
|
|
242
|
+
*
|
|
243
|
+
* Of the four blockers this comment used to name for wiring `bin/install.js`'s
|
|
244
|
+
* inline agent loop against this resolver, THREE were already stale by the
|
|
245
|
+
* time #2875 measured them and are not re-litigated here: Copilot's
|
|
246
|
+
* `.agent.md` rename (the loop's own `destName = entry.name` comment records
|
|
247
|
+
* the ternary dropped in #2099; the descriptor fold applies it via
|
|
248
|
+
* `hostBehaviors.agentFileExtension`), the cross-cutting path-prefix rewrite +
|
|
249
|
+
* attribution (`stageAgentsForRuntimeWithConverter` already applies
|
|
250
|
+
* `applyAgentPathRewrites` -> `processAttribution` when `agentCtx` is
|
|
251
|
+
* present), and stale-file cleanup (`_removeGsdEntries` prunes every
|
|
252
|
+
* `gsd-`-prefixed entry in a kind's destSubpath, broader than the loop's own
|
|
253
|
+
* extension-gated check).
|
|
254
|
+
*
|
|
255
|
+
* The fourth — config-reading steps — was the real gap, and #2875 Part 2
|
|
256
|
+
* closed it: `stageAgentsForRuntimeWithConverter` now takes a per-file
|
|
257
|
+
* `agentName` (`agentCtx.agentName`, ADR-1235 §1) and a `targetDir`
|
|
258
|
+
* (`agentCtx.targetDir`), which together let it (a) run a post-converter
|
|
259
|
+
* frontmatter-extensions step (`applyAgentFrontmatterExtensions`, driven by
|
|
260
|
+
* `hostBehaviors.agentFrontmatterExtensions` — Claude's `effort` +
|
|
261
|
+
* `disallowedTools` injection) and (b) let THIS function resolve a per-agent
|
|
262
|
+
* model override (`installModelOverrideResolver.resolveAgentModelOverride`,
|
|
263
|
+
* `model_overrides[agent]` > `model_profile_overrides.<rt>.<tier>` > omit)
|
|
264
|
+
* before invoking a converter that needs it (kilo/opencode). Both pieces —
|
|
265
|
+
* plus a data-driven Hermes branding converter
|
|
266
|
+
* (`convertClaudeAgentToHermesAgent`, reading `hostBehaviors.brandingRewrites`
|
|
267
|
+
* rather than a hardcoded string table) — are single-sourced: `bin/install.js`
|
|
268
|
+
* requires the SAME functions this module does, so its inline loop and the
|
|
269
|
+
* descriptor path can no longer independently drift (the CLAUDE.md
|
|
270
|
+
* "Generative Fix Divergence" class the prior duplication risked).
|
|
271
|
+
*
|
|
272
|
+
* `tests/agent-descriptor-parity.test.cjs` proves byte-identical output
|
|
273
|
+
* between the inline loop and a SYNTHETIC descriptor registry (the same
|
|
274
|
+
* override seam `resolveRuntimeArtifactLayoutFromRegistry` exposes) for all
|
|
275
|
+
* six runtimes the inline loop still served: claude, cline, codex, hermes,
|
|
276
|
+
* kilo, opencode.
|
|
277
|
+
*
|
|
278
|
+
* Both findings the prior revision of this comment named as STILL deferred
|
|
279
|
+
* are now CLOSED (#2875 Part 2 Task A/B/C), measured against the real
|
|
280
|
+
* `capability.json` entries and the real production entry points, not
|
|
281
|
+
* argued from this module alone:
|
|
282
|
+
*
|
|
283
|
+
* 1. **kilo/opencode reaching `layout.kinds`.** `installEngine.
|
|
284
|
+
* installAgentsKindStandalone` (install-engine.cts) is called from inside
|
|
285
|
+
* `installOpencodeFamilyArtifacts` and resolves the agents kind through
|
|
286
|
+
* THIS SAME `resolveRuntimeArtifactLayout`/`convertedAgentsKind` path —
|
|
287
|
+
* `installOpencodeFamilyArtifacts` no longer stages only `commands` +
|
|
288
|
+
* `skills`. `bin/install.js`'s legacy-flat local path (claude-local,
|
|
289
|
+
* `hostBehaviors.localInstallStyle === 'legacy-flat'`) reaches the SAME
|
|
290
|
+
* generic loop only via `installRuntimeArtifacts`'s conditional
|
|
291
|
+
* `_isSkillsRuntime` branch; a call to `installAgentsKindStandalone` was
|
|
292
|
+
* added at claude-local's own call site to cover that scope too — the
|
|
293
|
+
* install-tree golden fixture (`tests/fixtures/install-tree/claude-local.json`)
|
|
294
|
+
* is what caught the gap when it was first missed.
|
|
295
|
+
* 2. **`/gsd:surface` / `applySurface` activation.** Confirmed convergent,
|
|
296
|
+
* not merely non-broken: for all six runtimes (claude, cline, codex,
|
|
297
|
+
* hermes, kilo, opencode), staging via `applySurface` into a freshly
|
|
298
|
+
* wiped `agents/` directory produces byte-identical output (including
|
|
299
|
+
* filenames) to `installRuntimeArtifacts`'s own write — verified directly
|
|
300
|
+
* against the built registry, not inferred.
|
|
301
|
+
*
|
|
302
|
+
* The inline loop (`_DESCRIPTOR_AGENTS_RUNTIMES` and the `bin/install.js`
|
|
303
|
+
* agent-staging block it gated) is DELETED — every runtime the registry
|
|
304
|
+
* declares an `agents` kind for is descriptor-driven now, including a
|
|
305
|
+
* seventh runtime (`kimi-code`) this comment's own prior measurement missed
|
|
306
|
+
* (it fell through the inline loop's generic `else if` branch, same as
|
|
307
|
+
* claude, with no dedicated dialect arm — caught by the same golden fixture).
|
|
308
|
+
*
|
|
309
|
+
* Codex's `config.toml [agents.gsd-*]` strip (`bin/install.js`, under
|
|
310
|
+
* `isMinimalMode` + `hostBehaviors.tomlConfigInstall`) remains the one
|
|
311
|
+
* genuinely out-of-scope constraint: it mutates a host config file, not the
|
|
312
|
+
* agents directory, and no descriptor kind models host-config mutation. It
|
|
313
|
+
* stays exactly where it is.
|
|
155
314
|
*
|
|
156
315
|
* Mirrors the `convertedCommandsKind` pattern (#785).
|
|
157
316
|
*
|
|
@@ -166,15 +325,45 @@ function convertedAgentsKind(destSubpath, prefix, converterName, configDir, scop
|
|
|
166
325
|
destSubpath,
|
|
167
326
|
prefix,
|
|
168
327
|
stage: (resolved, agentCtx) => {
|
|
169
|
-
//
|
|
170
|
-
//
|
|
171
|
-
//
|
|
172
|
-
//
|
|
173
|
-
|
|
328
|
+
// #2870: `scope` is this function's own parameter (default `'global'`,
|
|
329
|
+
// so it is never undefined here), sourced upstream from the Install
|
|
330
|
+
// Scope Module's resolved id. `isGlobalScope` projects it to the
|
|
331
|
+
// boolean `stageAgentsForRuntimeWithConverter`'s positional API
|
|
332
|
+
// requires — see its doc comment in install-scope.cts.
|
|
333
|
+
const rawConverter = _resolveNamedConverter(converterName, 'agents');
|
|
334
|
+
// #2875 Part 2 (J5-J8): kilo/opencode agent converters take an options
|
|
335
|
+
// bag (`{isAgent, modelOverride}`), not the `isGlobal` boolean every
|
|
336
|
+
// other agent converter's 2nd positional arg means — mirrors the
|
|
337
|
+
// inline loop's per-runtime `frontmatterDialect === 'opencode' | 'kilo'`
|
|
338
|
+
// branches (bin/install.js), which resolve model_overrides[agent] >
|
|
339
|
+
// model_profile_overrides.<runtime>.<tier> > omit BEFORE calling the
|
|
340
|
+
// converter. Resolved ONCE per stage() call (not per file — a pure
|
|
341
|
+
// function of configDir/targetDir) via the single shared precedence
|
|
342
|
+
// resolver so kilo and opencode can never diverge (J8).
|
|
343
|
+
const needsModelOverride = converterName === 'convertClaudeToOpencodeFrontmatter' || converterName === 'convertClaudeToKiloFrontmatter';
|
|
344
|
+
let converter;
|
|
345
|
+
if (needsModelOverride) {
|
|
346
|
+
const overrideTargetDir = agentCtx?.targetDir ?? configDir;
|
|
347
|
+
const modelOverrides = installModelOverrideResolver.readGsdEffectiveModelOverrides(overrideTargetDir);
|
|
348
|
+
const runtimeResolver = installModelOverrideResolver.readGsdRuntimeProfileResolver(overrideTargetDir);
|
|
349
|
+
converter = (content, _isGlobal, meta) => {
|
|
350
|
+
const modelOverride = meta
|
|
351
|
+
? installModelOverrideResolver.resolveAgentModelOverride(meta.agentName, modelOverrides, runtimeResolver)
|
|
352
|
+
: null;
|
|
353
|
+
return rawConverter(content, { isAgent: true, modelOverride });
|
|
354
|
+
};
|
|
355
|
+
}
|
|
356
|
+
else {
|
|
357
|
+
// isGlobal is threaded so scope-aware agent converters (copilot, antigravity)
|
|
358
|
+
// choose global-home vs workspace-relative paths; converters that only take
|
|
359
|
+
// (content) ignore the extra positional arg. Mirrors skillsKind's scope
|
|
360
|
+
// threading (#1173).
|
|
361
|
+
converter = (content) => rawConverter(content, (0, install_scope_cjs_1.isGlobalScope)(scope));
|
|
362
|
+
}
|
|
174
363
|
// ADR-1235 §1: when agentCtx is provided (by createRuntimeArtifactInstallPlan
|
|
175
364
|
// for descriptor-driven runtimes), thread it through so stageAgentsForRuntimeWithConverter
|
|
176
365
|
// can apply the full pre-converter + post-converter sequence in the correct order.
|
|
177
|
-
return stageAgentsForRuntimeWithConverter(findAgentsSourceRoot(configDir), resolved, converter, scope
|
|
366
|
+
return stageAgentsForRuntimeWithConverter(findAgentsSourceRoot(configDir), resolved, converter, (0, install_scope_cjs_1.isGlobalScope)(scope), agentCtx);
|
|
178
367
|
},
|
|
179
368
|
};
|
|
180
369
|
}
|
|
@@ -185,30 +374,32 @@ function kimiAgentsKind(destSubpath, prefix, configDir) {
|
|
|
185
374
|
prefix,
|
|
186
375
|
stage: (resolved) => {
|
|
187
376
|
const buildKimiAgentArtifacts = conversionExports['buildKimiAgentArtifacts'];
|
|
188
|
-
|
|
377
|
+
// #2995: compose at staging (identity converter) so the readFileSync below
|
|
378
|
+
// sees marker-free content — same single composing stager as agentsKind.
|
|
379
|
+
const stagedAgents = stageAgentsForRuntimeWithConverter(findAgentsSourceRoot(configDir), resolved, (content) => content);
|
|
189
380
|
const subagents = [];
|
|
190
|
-
if (
|
|
191
|
-
for (const entry of
|
|
381
|
+
if (installFs().existsSync(stagedAgents)) {
|
|
382
|
+
for (const entry of installFs().readdirSync(stagedAgents, { withFileTypes: true })) {
|
|
192
383
|
if (!entry.isFile() || !entry.name.endsWith('.md'))
|
|
193
384
|
continue;
|
|
194
385
|
const agentPath = node_path_1.default.join(stagedAgents, entry.name);
|
|
195
386
|
subagents.push({
|
|
196
387
|
path: (0, shell_command_projection_cjs_1.posixNormalize)(node_path_1.default.join('agents', entry.name)),
|
|
197
|
-
content:
|
|
388
|
+
content: installFs().readFileSync(agentPath, 'utf8'),
|
|
198
389
|
});
|
|
199
390
|
}
|
|
200
391
|
}
|
|
201
392
|
const rootAgent = `---\nname: gsd\ndescription: Run GSD workflows in Kimi CLI.\ntools: Agent\n---\n\n# GSD for Kimi CLI\n\nCoordinate installed /skill:gsd-* workflows and route work to generated GSD subagents when a workflow requires an agent handoff.\n`;
|
|
202
393
|
const artifacts = buildKimiAgentArtifacts({ rootAgent, subagents });
|
|
203
|
-
const stageDir =
|
|
394
|
+
const stageDir = mkInstallTempDir('gsd-kimi-agents-');
|
|
204
395
|
installProfiles.STAGED_DIRS.add(stageDir);
|
|
205
|
-
|
|
206
|
-
|
|
396
|
+
installFs().writeFileSync(node_path_1.default.join(stageDir, 'gsd.yaml'), artifacts.root.yaml);
|
|
397
|
+
installFs().writeFileSync(node_path_1.default.join(stageDir, 'gsd.md'), artifacts.root.prompt);
|
|
207
398
|
const subagentsDir = node_path_1.default.join(stageDir, 'subagents');
|
|
208
|
-
|
|
399
|
+
installFs().mkdirSync(subagentsDir, { recursive: true });
|
|
209
400
|
for (const artifact of artifacts.subagents) {
|
|
210
|
-
|
|
211
|
-
|
|
401
|
+
installFs().writeFileSync(node_path_1.default.join(subagentsDir, `${artifact.name}.yaml`), artifact.yaml);
|
|
402
|
+
installFs().writeFileSync(node_path_1.default.join(subagentsDir, `${artifact.name}.md`), artifact.prompt);
|
|
212
403
|
}
|
|
213
404
|
return stageDir;
|
|
214
405
|
},
|
|
@@ -239,7 +430,7 @@ function skillsKind(destSubpath, prefix, converterName, runtime, configDir, nest
|
|
|
239
430
|
prefix,
|
|
240
431
|
converter: converterName,
|
|
241
432
|
stage: (resolved) => {
|
|
242
|
-
const realConverter =
|
|
433
|
+
const realConverter = _resolveNamedConverter(converterName, 'skills');
|
|
243
434
|
// Compute cmdNames once per stage call for performance (#3583).
|
|
244
435
|
// Extra trailing args are ignored by converters that don't need them. The
|
|
245
436
|
// isGlobal flag is the 5th positional (NOT the 3rd): the 3rd positional is
|
|
@@ -249,7 +440,21 @@ function skillsKind(destSubpath, prefix, converterName, runtime, configDir, nest
|
|
|
249
440
|
const cmdNames = conversionExports.readGsdCommandNames
|
|
250
441
|
? conversionExports.readGsdCommandNames()
|
|
251
442
|
: [];
|
|
252
|
-
|
|
443
|
+
// #2870: same judgment as convertedAgentsKind above — `scope` is this
|
|
444
|
+
// function's own parameter (default `'global'`, so it is never
|
|
445
|
+
// undefined here); `isGlobalScope` projects it to the boolean
|
|
446
|
+
// `realConverter`'s positional `isGlobal` arg requires.
|
|
447
|
+
const isGlobal = (0, install_scope_cjs_1.isGlobalScope)(scope);
|
|
448
|
+
// #2873 (4b): spec-root reachability is applied LATER in the pipeline —
|
|
449
|
+
// see `rewriteStagedSkillBodies` in runtime-artifact-conversion.cts, not
|
|
450
|
+
// here. This stage() closure runs BEFORE the staged directory's generic
|
|
451
|
+
// path-prefix rewrite pass (`applyRuntimeContentRewritesInPlace`'s
|
|
452
|
+
// `case 'claude'`), which unconditionally rewrites any bare (non-`@`)
|
|
453
|
+
// `~/.claude/` substring to the undocumented `$HOME/.claude/` form and
|
|
454
|
+
// only restores the `@`-prefixed form. Emitting the imperative
|
|
455
|
+
// tilde-path prose here would get silently mangled by that later pass;
|
|
456
|
+
// it must run AFTER it instead, once the `@`-include is in its final
|
|
457
|
+
// rewritten shape.
|
|
253
458
|
const wrappedConverter = (content, skillName) => realConverter(content, skillName, runtime, cmdNames, isGlobal);
|
|
254
459
|
return stageSkillsForRuntimeAsSkills(findInstallSourceRoot(configDir), resolved, wrappedConverter, prefix, nested, capabilityRegistry);
|
|
255
460
|
},
|
|
@@ -277,7 +482,7 @@ function convertedCommandsKind(destSubpath, prefix, converterName, configDir) {
|
|
|
277
482
|
destSubpath,
|
|
278
483
|
prefix,
|
|
279
484
|
stage: (resolved) => {
|
|
280
|
-
const converter =
|
|
485
|
+
const converter = _resolveNamedConverter(converterName, 'commands');
|
|
281
486
|
return stageCommandsForRuntimeFlat(findInstallSourceRoot(configDir), resolved, converter, prefix);
|
|
282
487
|
},
|
|
283
488
|
};
|
|
@@ -316,7 +521,11 @@ function dispatchKindEntry(entry, runtime, configDir, scope, capabilityRegistry)
|
|
|
316
521
|
default:
|
|
317
522
|
throw new TypeError(`resolveRuntimeArtifactLayout: unknown kind '${kind}' in descriptor for runtime '${runtime}'`);
|
|
318
523
|
}
|
|
319
|
-
|
|
524
|
+
// scope is guaranteed 'local' | 'global' here: resolveRuntimeArtifactLayoutFromRegistry
|
|
525
|
+
// (the only caller of dispatchKindEntry) throws TypeError before this point if scope is
|
|
526
|
+
// anything else (see the `scope !== 'local' && scope !== 'global'` guard above its
|
|
527
|
+
// dispatchKindEntry call), so isGlobalScope's throw-on-invalid-input never fires here.
|
|
528
|
+
if ((0, install_scope_cjs_1.isGlobalScope)(scope) && typeof entry.home === 'string' && entry.home !== '') {
|
|
320
529
|
result.home = node_path_1.default.join(node_os_1.default.homedir(), entry.home);
|
|
321
530
|
}
|
|
322
531
|
return result;
|
|
@@ -355,4 +564,178 @@ function resolveRuntimeArtifactLayoutFromRegistry(registry, runtime, configDir,
|
|
|
355
564
|
const kinds = entries.map((entry) => dispatchKindEntry(entry, runtime, configDir, scope, capabilityRegistry));
|
|
356
565
|
return { runtime, configDir, scope, kinds };
|
|
357
566
|
}
|
|
358
|
-
|
|
567
|
+
function getTriggerRegistry() {
|
|
568
|
+
return _require('./capability-registry.cjs');
|
|
569
|
+
}
|
|
570
|
+
/**
|
|
571
|
+
* capability-validator.cjs is a COMMITTED plain .cjs (not built from a .cts
|
|
572
|
+
* source — see its own header comment), so it is required the same way
|
|
573
|
+
* capability-registry.cjs is above: a lazy `_require` rather than a static
|
|
574
|
+
* ES import. DEFAULT_TRIGGER_PRECEDENCE is the single source of truth for
|
|
575
|
+
* "what applies when a descriptor omits triggerPrecedence"; this module
|
|
576
|
+
* reads it rather than re-declaring `['skills', 'commands']` as a second
|
|
577
|
+
* literal that could silently drift from the validator's own default.
|
|
578
|
+
*/
|
|
579
|
+
function getDefaultTriggerPrecedence() {
|
|
580
|
+
const capValidator = _require('./capability-validator.cjs');
|
|
581
|
+
return capValidator.DEFAULT_TRIGGER_PRECEDENCE;
|
|
582
|
+
}
|
|
583
|
+
/**
|
|
584
|
+
* True when a `commands` kind entry is namespaced by its destination
|
|
585
|
+
* directory rather than by a filename prefix — i.e. `destSubpath`'s basename
|
|
586
|
+
* equals `prefix` with its trailing hyphen stripped (e.g. `commands/gsd` +
|
|
587
|
+
* `gsd-`). When true, `_copyStaged` (`install-engine.cts`) and `surface.cts`
|
|
588
|
+
* both write the bare stem filename (no prefix) because the directory itself
|
|
589
|
+
* already carries the namespace; `resolveTriggerSurface` mirrors that in its
|
|
590
|
+
* own `destPath` computation. Single source of truth for the three sites
|
|
591
|
+
* that used to compute this independently (#2871 Phase 2 review finding) —
|
|
592
|
+
* a new caller MUST reuse this rather than re-deriving the rule.
|
|
593
|
+
*/
|
|
594
|
+
function isNamespacedByDir(kind, destSubpath, prefix) {
|
|
595
|
+
const destLast = node_path_1.default.posix.basename((0, shell_command_projection_cjs_1.posixNormalize)(destSubpath));
|
|
596
|
+
const prefixStem = prefix ? prefix.replace(/-$/, '') : '';
|
|
597
|
+
return kind === 'commands' && destLast === prefixStem;
|
|
598
|
+
}
|
|
599
|
+
/**
|
|
600
|
+
* Compose the destination filename `_copyStaged` (install-engine.cts) writes
|
|
601
|
+
* for a `commands` kind entry, given `isNamespacedByDir`'s result, the
|
|
602
|
+
* kind's prefix, and the file's `.md`-stripped stem. Single source of truth
|
|
603
|
+
* alongside `isNamespacedByDir` for the FILENAME COMPOSITION itself (#2871
|
|
604
|
+
* Phase 2 review finding — the boolean was single-sourced first, but the
|
|
605
|
+
* `${stem}.md` / `${prefix}${stem}.md` string-building around it stayed
|
|
606
|
+
* duplicated between `_copyStaged` and `resolveTriggerSurface`'s `destPath`
|
|
607
|
+
* prediction below, so a divergence in the write convention would not have
|
|
608
|
+
* failed anything).
|
|
609
|
+
*
|
|
610
|
+
* Byte-identical to `_copyStaged`'s prior separate branches: when
|
|
611
|
+
* `namespacedByDir` is true this returns `${stem}.md`. `_copyStaged` always
|
|
612
|
+
* derives `stem` as `entry.name.slice(0, -3)` for an `entry.name` that has
|
|
613
|
+
* already been filtered to end in `.md`, so `${stem}.md` is always exactly
|
|
614
|
+
* `entry.name` again — `_copyStaged` can pass this helper's result in place
|
|
615
|
+
* of the `entry.name` it used to write directly, with no behavior change.
|
|
616
|
+
*/
|
|
617
|
+
function composeCommandFilename(namespacedByDir, prefix, stem) {
|
|
618
|
+
return namespacedByDir ? `${stem}.md` : `${prefix}${stem}.md`;
|
|
619
|
+
}
|
|
620
|
+
/**
|
|
621
|
+
* True when candidate `a` should win over the current best `b` for the same
|
|
622
|
+
* trigger. Scope rank first (Phase 1's `install-scope.cts#scopeRank` —
|
|
623
|
+
* global outranks local; NOT re-derived here), then the runtime's
|
|
624
|
+
* `triggerPrecedence` kind ordering (lower index = higher priority). A kind
|
|
625
|
+
* absent from `precedenceRank` (should not happen — every entry's kind is
|
|
626
|
+
* validated against the same closed vocabulary the precedence list draws
|
|
627
|
+
* from) sorts last rather than throwing, so a malformed precedence value
|
|
628
|
+
* degrades to "leaves the incumbent standing" instead of corrupting the
|
|
629
|
+
* whole resolution.
|
|
630
|
+
*/
|
|
631
|
+
function isHigherPriority(a, b, precedenceRank) {
|
|
632
|
+
const rankA = (0, install_scope_cjs_1.scopeRank)(a.scope);
|
|
633
|
+
const rankB = (0, install_scope_cjs_1.scopeRank)(b.scope);
|
|
634
|
+
if (rankA !== rankB)
|
|
635
|
+
return rankA > rankB;
|
|
636
|
+
const pa = precedenceRank.get(a.kind) ?? Number.POSITIVE_INFINITY;
|
|
637
|
+
const pb = precedenceRank.get(b.kind) ?? Number.POSITIVE_INFINITY;
|
|
638
|
+
return pa < pb;
|
|
639
|
+
}
|
|
640
|
+
/**
|
|
641
|
+
* Resolve the `/gsd-<name>`-style trigger surface for a runtime: what the
|
|
642
|
+
* user types, at which scope, whether it wins or is shadowed, and (for
|
|
643
|
+
* nested-router runtimes) whether the host registers it directly or only
|
|
644
|
+
* reaches it through a router. Pure — no filesystem, no mutation of `scopes`
|
|
645
|
+
* or `opts`, and safe against a caller mutating the returned array/objects
|
|
646
|
+
* (a fresh array/objects are built on every call; nothing is cached or
|
|
647
|
+
* shared across calls beyond the read-only registry module).
|
|
648
|
+
*
|
|
649
|
+
* Only `commands` and `skills` kind entries are considered — see the
|
|
650
|
+
* module-level comment above. `resolveRuntimeArtifactLayout` is untouched by
|
|
651
|
+
* this function; they are independent readers of the same descriptor.
|
|
652
|
+
*
|
|
653
|
+
* @throws {TypeError} for an unknown runtime — same contract (and message
|
|
654
|
+
* shape) as `resolveRuntimeArtifactLayoutFromRegistry`.
|
|
655
|
+
* @throws {TypeError} for an unrecognized entry in `scopes` — reuses
|
|
656
|
+
* `install-scope.cts`'s shared `validateScopeId`, the same validator
|
|
657
|
+
* `scopeRank`/`resolveScope`/`isGlobalScope` already throw through, so this
|
|
658
|
+
* sibling of theirs cannot silently fail open on a bad scope (#2871 Phase 2
|
|
659
|
+
* review finding). `scopes: []` is untouched — an empty array has no
|
|
660
|
+
* entries to validate and still resolves to `[]`.
|
|
661
|
+
*/
|
|
662
|
+
function resolveTriggerSurface(runtime, scopes, opts) {
|
|
663
|
+
const registry = opts.registry ?? getTriggerRegistry();
|
|
664
|
+
const runtimeDescriptor = registry.runtimes[runtime]?.runtime;
|
|
665
|
+
const layout = runtimeDescriptor?.artifactLayout;
|
|
666
|
+
if (!layout) {
|
|
667
|
+
throw new TypeError(`Unknown runtime: '${runtime}' — add to runtime-artifact-layout.cjs table`);
|
|
668
|
+
}
|
|
669
|
+
for (const scope of scopes) {
|
|
670
|
+
(0, install_scope_cjs_1.validateScopeId)(scope, 'resolveTriggerSurface');
|
|
671
|
+
}
|
|
672
|
+
const scopeSet = new Set(scopes);
|
|
673
|
+
const stems = opts.stems ?? [];
|
|
674
|
+
const routerStemSet = new Set(opts.routerStems ?? []);
|
|
675
|
+
const childToRouters = opts.childToRouters ?? {};
|
|
676
|
+
const precedence = runtimeDescriptor?.triggerPrecedence ?? getDefaultTriggerPrecedence();
|
|
677
|
+
const precedenceRank = new Map(precedence.map((kind, index) => [kind, index]));
|
|
678
|
+
const surfaces = [];
|
|
679
|
+
for (const scope of install_scope_cjs_1.SCOPE_ORDER) {
|
|
680
|
+
if (!scopeSet.has(scope))
|
|
681
|
+
continue;
|
|
682
|
+
const entries = layout[scope] ?? [];
|
|
683
|
+
for (const entry of entries) {
|
|
684
|
+
if (entry.kind !== 'commands' && entry.kind !== 'skills')
|
|
685
|
+
continue; // excludes agents/kimi-agents
|
|
686
|
+
const kind = entry.kind;
|
|
687
|
+
const destSubpath = (0, shell_command_projection_cjs_1.posixNormalize)(entry.destSubpath);
|
|
688
|
+
const namespacedByDir = isNamespacedByDir(kind, entry.destSubpath, entry.prefix);
|
|
689
|
+
const nested = entry.nesting === 'nested';
|
|
690
|
+
for (const stem of stems) {
|
|
691
|
+
const trigger = `${entry.prefix}${stem}`;
|
|
692
|
+
let destPath;
|
|
693
|
+
if (kind === 'skills') {
|
|
694
|
+
destPath = `${destSubpath}/${entry.prefix}${stem}`;
|
|
695
|
+
}
|
|
696
|
+
else {
|
|
697
|
+
destPath = `${destSubpath}/${composeCommandFilename(namespacedByDir, entry.prefix, stem)}`;
|
|
698
|
+
}
|
|
699
|
+
let registration = 'direct';
|
|
700
|
+
let routerTrigger = null;
|
|
701
|
+
if (nested && routerStemSet.size > 0 && !routerStemSet.has(stem)) {
|
|
702
|
+
const owningRouters = childToRouters[stem];
|
|
703
|
+
const routerStem = owningRouters && owningRouters.length > 0 ? owningRouters[0] : undefined;
|
|
704
|
+
if (routerStem !== undefined && routerStemSet.has(routerStem)) {
|
|
705
|
+
registration = 'via-router';
|
|
706
|
+
routerTrigger = `${entry.prefix}${routerStem}`;
|
|
707
|
+
}
|
|
708
|
+
}
|
|
709
|
+
surfaces.push({ trigger, kind, scope, destPath, registration, routerTrigger, shadowedBy: null });
|
|
710
|
+
}
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
// Winner computation, per trigger string, across every scope/kind candidate.
|
|
714
|
+
const groups = new Map();
|
|
715
|
+
for (const surface of surfaces) {
|
|
716
|
+
const group = groups.get(surface.trigger);
|
|
717
|
+
if (group) {
|
|
718
|
+
group.push(surface);
|
|
719
|
+
}
|
|
720
|
+
else {
|
|
721
|
+
groups.set(surface.trigger, [surface]);
|
|
722
|
+
}
|
|
723
|
+
}
|
|
724
|
+
for (const group of groups.values()) {
|
|
725
|
+
if (group.length <= 1)
|
|
726
|
+
continue; // sole candidate: unshadowed by construction
|
|
727
|
+
let winner = group[0];
|
|
728
|
+
for (let i = 1; i < group.length; i++) {
|
|
729
|
+
const candidate = group[i];
|
|
730
|
+
if (isHigherPriority(candidate, winner, precedenceRank))
|
|
731
|
+
winner = candidate;
|
|
732
|
+
}
|
|
733
|
+
for (const surface of group) {
|
|
734
|
+
if (surface !== winner) {
|
|
735
|
+
surface.shadowedBy = { kind: winner.kind, scope: winner.scope };
|
|
736
|
+
}
|
|
737
|
+
}
|
|
738
|
+
}
|
|
739
|
+
return surfaces;
|
|
740
|
+
}
|
|
741
|
+
module.exports = { resolveRuntimeArtifactLayout, resolveRuntimeArtifactLayoutFromRegistry, findInstallSourceRoot, resolveTriggerSurface, isNamespacedByDir, composeCommandFilename };
|
|
@@ -40,8 +40,9 @@ const VALID_SANDBOX_TIERS = new Set(['none', 'codex-agent-sandbox']);
|
|
|
40
40
|
* (Marketplace/VSIX-distributed, never dispatched through
|
|
41
41
|
* install()/finishInstall()), so it is not a "config-adapter runtime" by
|
|
42
42
|
* definition. This keeps this set in lockstep with bin/install.js's
|
|
43
|
-
* `allRuntimes` (see
|
|
44
|
-
*
|
|
43
|
+
* `allRuntimes` (see the folded:issue-57-runtime-install-no-drift describe
|
|
44
|
+
* block in tests/runtime-config-adapter-registry.test.cjs) without needing a
|
|
45
|
+
* separate hand-kept exclusion list.
|
|
45
46
|
*/
|
|
46
47
|
const ALLOWED_CONFIG_RUNTIMES = new Set(Object.entries(runtimes)
|
|
47
48
|
.filter(([, cap]) => cap && cap.runtime && typeof cap.runtime['installSurface'] === 'string' && cap.runtime['installSurface'] !== 'none')
|