@opengsd/gsd-core 1.10.0 → 1.12.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/agents/gsd-code-fixer.md +1 -1
- package/agents/gsd-debug-session-manager.md +12 -1
- package/agents/gsd-debugger.md +1 -1
- package/agents/gsd-doc-synthesizer.md +2 -4
- package/agents/gsd-dom-verifier.md +169 -0
- package/agents/gsd-eval-auditor.md +1 -1
- package/agents/gsd-executor.md +22 -14
- package/agents/gsd-framework-selector.md +1 -3
- package/agents/gsd-intel-updater.md +1 -1
- package/agents/gsd-mempalace-curator.md +5 -3
- package/agents/gsd-pattern-mapper.md +11 -0
- package/agents/gsd-phase-researcher.md +23 -2
- package/agents/gsd-plan-checker.md +50 -53
- package/agents/gsd-planner.md +50 -50
- package/agents/gsd-project-researcher.md +1 -1
- package/agents/gsd-research-synthesizer.md +2 -2
- package/agents/gsd-roadmapper.md +15 -11
- package/agents/gsd-ui-checker.md +63 -4
- package/agents/gsd-ui-researcher.md +41 -3
- package/agents/gsd-user-profiler.md +3 -0
- package/agents/gsd-verifier.md +13 -4
- package/bin/install.js +1448 -1103
- package/commands/gsd/code-review.md +1 -1
- package/commands/gsd/discuss-phase.md +1 -1
- package/commands/gsd/execute-phase.md +1 -1
- package/commands/gsd/import.md +1 -1
- package/commands/gsd/map-codebase.md +1 -1
- package/commands/gsd/mempalace-capture.md +1 -1
- package/commands/gsd/mempalace-recall.md +1 -1
- package/commands/gsd/new-milestone.md +1 -1
- package/commands/gsd/quick.md +9 -5
- package/commands/gsd/review-backlog.md +2 -1
- package/commands/gsd/verify-work.md +1 -1
- package/gsd-core/bin/gsd-tools.cjs +1035 -138
- package/gsd-core/bin/lib/active-workstream-store.cjs +146 -22
- package/gsd-core/bin/lib/adr-parser.cjs +13 -7
- package/gsd-core/bin/lib/agent-install-check.cjs +392 -32
- package/gsd-core/bin/lib/api-coverage.cjs +33 -14
- package/gsd-core/bin/lib/artifacts.cjs +5 -0
- package/gsd-core/bin/lib/assumption-delta.cjs +32 -15
- package/gsd-core/bin/lib/audit-command-router.cjs +9 -2
- package/gsd-core/bin/lib/audit.cjs +1026 -268
- package/gsd-core/bin/lib/broken-windows.cjs +306 -28
- 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-lock.cjs +10 -4
- package/gsd-core/bin/lib/capability-registry.cjs +845 -130
- package/gsd-core/bin/lib/capability-source.cjs +92 -0
- package/gsd-core/bin/lib/capability-state.cjs +18 -3
- package/gsd-core/bin/lib/capability-trust.cjs +444 -25
- package/gsd-core/bin/lib/capability-validator.cjs +700 -40
- package/gsd-core/bin/lib/capability-writer.cjs +3 -2
- package/gsd-core/bin/lib/check-command-router.cjs +216 -42
- package/gsd-core/bin/lib/claude-orchestration.cjs +56 -3
- package/gsd-core/bin/lib/cli-exit.cjs +496 -10
- package/gsd-core/bin/lib/code-review-depth.cjs +288 -0
- package/gsd-core/bin/lib/codex-agent-toml.cjs +735 -0
- package/gsd-core/bin/lib/command-aliases.cjs +22 -0
- package/gsd-core/bin/lib/command-arg-projection.cjs +144 -14
- package/gsd-core/bin/lib/command-roster.cjs +44 -1
- package/gsd-core/bin/lib/command-routing-hub.cjs +31 -2
- package/gsd-core/bin/lib/commands.cjs +1172 -108
- package/gsd-core/bin/lib/commonjs-marker.cjs +12 -6
- package/gsd-core/bin/lib/complexity-trigger.cjs +1192 -0
- package/gsd-core/bin/lib/config-loader.cjs +187 -23
- package/gsd-core/bin/lib/config.cjs +102 -3
- package/gsd-core/bin/lib/configuration.cjs +129 -37
- package/gsd-core/bin/lib/core-utils.cjs +208 -33
- package/gsd-core/bin/lib/decisions.cjs +23 -0
- package/gsd-core/bin/lib/edge-probe.cjs +9 -1
- package/gsd-core/bin/lib/estimate-cli.cjs +55 -11
- package/gsd-core/bin/lib/exit-code-registry.cjs +98 -0
- package/gsd-core/bin/lib/fallow-runner.cjs +20 -44
- package/gsd-core/bin/lib/frontmatter.cjs +899 -229
- package/gsd-core/bin/lib/gap-checker.cjs +95 -10
- package/gsd-core/bin/lib/git-base-branch.cjs +276 -39
- package/gsd-core/bin/lib/gsd2-import.cjs +10 -1
- 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 +149 -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 +268 -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 +187 -0
- package/gsd-core/bin/lib/health-diagnostic-types.cjs +68 -0
- package/gsd-core/bin/lib/health-diagnostic.cjs +451 -0
- package/gsd-core/bin/lib/host-integration.cjs +39 -6
- package/gsd-core/bin/lib/host-runtime-detection.cjs +134 -0
- package/gsd-core/bin/lib/init-command-router.cjs +118 -21
- package/gsd-core/bin/lib/init.cjs +439 -168
- package/gsd-core/bin/lib/install-effort-resolver.cjs +73 -30
- package/gsd-core/bin/lib/install-engine.cjs +811 -259
- package/gsd-core/bin/lib/install-fs-adapter.cjs +262 -0
- package/gsd-core/bin/lib/install-model-override-resolver.cjs +235 -0
- package/gsd-core/bin/lib/install-profiles.cjs +212 -61
- 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-report.cjs +3 -0
- package/gsd-core/bin/lib/installer-migrations/010-antigravity-retire-confighome-artifacts.cjs +169 -0
- package/gsd-core/bin/lib/installer-migrations.cjs +148 -38
- package/gsd-core/bin/lib/intel.cjs +101 -26
- package/gsd-core/bin/lib/io.cjs +170 -15
- package/gsd-core/bin/lib/learnings.cjs +85 -14
- package/gsd-core/bin/lib/legacy-cleanup.cjs +8 -2
- package/gsd-core/bin/lib/markdown-sectionizer.cjs +2 -1
- package/gsd-core/bin/lib/markdown-table.cjs +183 -22
- package/gsd-core/bin/lib/milestone-lock.cjs +248 -0
- package/gsd-core/bin/lib/milestone.cjs +842 -73
- package/gsd-core/bin/lib/model-catalog.cjs +232 -16
- package/gsd-core/bin/lib/model-resolver.cjs +193 -68
- package/gsd-core/bin/lib/normalize-test-command.cjs +1 -1
- package/gsd-core/bin/lib/onboard-projection.cjs +5 -1
- package/gsd-core/bin/lib/pattern.cjs +122 -0
- package/gsd-core/bin/lib/phase-estimation.cjs +18 -9
- package/gsd-core/bin/lib/phase-id.cjs +514 -40
- package/gsd-core/bin/lib/phase-lifecycle.cjs +52 -19
- package/gsd-core/bin/lib/phase-locator.cjs +262 -34
- package/gsd-core/bin/lib/phase.cjs +1038 -214
- package/gsd-core/bin/lib/plan-dependency-graph.cjs +72 -1
- package/gsd-core/bin/lib/plan-document.cjs +263 -0
- package/gsd-core/bin/lib/plan-drift-guard.cjs +120 -0
- package/gsd-core/bin/lib/plan-scan.cjs +98 -3
- package/gsd-core/bin/lib/planning-command-router.cjs +61 -0
- package/gsd-core/bin/lib/planning-inspect.cjs +1168 -0
- package/gsd-core/bin/lib/planning-scope.cjs +31 -0
- package/gsd-core/bin/lib/planning-snapshot.cjs +894 -0
- package/gsd-core/bin/lib/planning-workspace.cjs +112 -6
- package/gsd-core/bin/lib/probe-core.cjs +5 -2
- package/gsd-core/bin/lib/profile-output.cjs +1 -1
- package/gsd-core/bin/lib/profile-pipeline-command-router.cjs +50 -7
- package/gsd-core/bin/lib/profile-pipeline.cjs +6 -3
- package/gsd-core/bin/lib/real-home-guard.cjs +419 -0
- package/gsd-core/bin/lib/refactor-trigger-command-router.cjs +766 -0
- package/gsd-core/bin/lib/retired-artifact-cleanup.cjs +11 -6
- package/gsd-core/bin/lib/review-lane-descriptor.cjs +22 -13
- package/gsd-core/bin/lib/review-lane-invocation.cjs +30 -0
- package/gsd-core/bin/lib/review-lane-runner.cjs +421 -66
- package/gsd-core/bin/lib/review-reviewer-selection.cjs +13 -18
- package/gsd-core/bin/lib/roadmap-command-router.cjs +59 -11
- package/gsd-core/bin/lib/roadmap-parser.cjs +1006 -184
- package/gsd-core/bin/lib/roadmap-upgrade.cjs +37 -10
- package/gsd-core/bin/lib/roadmap.cjs +442 -96
- package/gsd-core/bin/lib/runtime-artifact-conversion.cjs +702 -52
- package/gsd-core/bin/lib/runtime-artifact-install-plan.cjs +14 -2
- package/gsd-core/bin/lib/runtime-artifact-layout.cjs +459 -55
- package/gsd-core/bin/lib/runtime-config-adapter-registry.cjs +3 -2
- package/gsd-core/bin/lib/runtime-homes.cjs +69 -3
- package/gsd-core/bin/lib/runtime-hooks-surface.cjs +402 -58
- package/gsd-core/bin/lib/runtime-identity.cjs +234 -0
- package/gsd-core/bin/lib/runtime-name-policy.cjs +3 -1
- package/gsd-core/bin/lib/runtime-slash.cjs +96 -8
- package/gsd-core/bin/lib/security.cjs +104 -5
- package/gsd-core/bin/lib/shell-command-projection.cjs +342 -7
- package/gsd-core/bin/lib/smart-entry.cjs +133 -23
- package/gsd-core/bin/lib/spec-section.cjs +12 -7
- package/gsd-core/bin/lib/state-command-router.cjs +52 -19
- package/gsd-core/bin/lib/state-contract.cjs +359 -0
- package/gsd-core/bin/lib/state-document.cjs +338 -8
- package/gsd-core/bin/lib/state-md-schema.cjs +221 -0
- package/gsd-core/bin/lib/state-transition.cjs +846 -176
- package/gsd-core/bin/lib/state.cjs +2589 -369
- package/gsd-core/bin/lib/surface.cjs +33 -11
- package/gsd-core/bin/lib/task-command-router.cjs +111 -1
- package/gsd-core/bin/lib/task-content-resolution.cjs +368 -0
- package/gsd-core/bin/lib/teams-status.cjs +4 -1
- 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 +67 -23
- package/gsd-core/bin/lib/uat.cjs +1761 -167
- package/gsd-core/bin/lib/ui-consideration-probe.cjs +9 -1
- package/gsd-core/bin/lib/ui-frontend-evidence.cjs +157 -0
- package/gsd-core/bin/lib/ui-safety-gate.cjs +51 -12
- package/gsd-core/bin/lib/unusable-input.cjs +37 -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-command-router.cjs +2 -2
- package/gsd-core/bin/lib/validate.cjs +20 -6
- package/gsd-core/bin/lib/vendor/README.md +75 -0
- package/gsd-core/bin/lib/vendor/js-yaml.cjs +3014 -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 +272 -9
- package/gsd-core/bin/lib/verify-command-grounding.cjs +846 -0
- package/gsd-core/bin/lib/verify.cjs +453 -918
- package/gsd-core/bin/lib/workstream-inventory-builder.cjs +53 -32
- package/gsd-core/bin/lib/workstream-inventory.cjs +63 -10
- package/gsd-core/bin/lib/workstream-name-policy.cjs +25 -4
- package/gsd-core/bin/lib/workstream.cjs +2 -2
- package/gsd-core/bin/lib/worktree-base-ref.cjs +66 -12
- package/gsd-core/bin/lib/worktree-safety.cjs +341 -18
- package/gsd-core/bin/shared/config-defaults.manifest.json +8 -1
- package/gsd-core/bin/shared/config-schema.manifest.json +12 -1
- package/gsd-core/bin/shared/exit-codes.json +8 -0
- package/gsd-core/bin/shared/exit-codes.sh +20 -0
- package/gsd-core/bin/shared/model-catalog.json +8 -1
- package/gsd-core/references/agent-contracts.md +44 -26
- package/gsd-core/references/api-coverage.md +24 -2
- package/gsd-core/references/autonomous-smart-discuss.md +3 -3
- package/gsd-core/references/checkpoints.md +39 -21
- package/gsd-core/references/context-budget.md +1 -1
- package/gsd-core/references/decimal-phase-calculation.md +5 -5
- package/gsd-core/references/dispatch-isolation-gate.md +138 -0
- package/gsd-core/references/doc-conflict-engine.md +1 -1
- package/gsd-core/references/edge-probe.md +8 -0
- package/gsd-core/references/execute-mvp-tdd.md +4 -6
- package/gsd-core/references/execute-phase-between-wave-reset.md +15 -14
- 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 +17 -11
- package/gsd-core/references/failing-direction.md +78 -0
- package/gsd-core/references/gate-prompts.md +1 -1
- package/gsd-core/references/git-integration.md +5 -5
- package/gsd-core/references/git-planning-commit.md +5 -4
- package/gsd-core/references/gsd-run-resolver.md +1 -1
- package/gsd-core/references/loop-hook-dispatch.md +61 -2
- package/gsd-core/references/model-profiles.md +12 -4
- package/gsd-core/references/mvp-concepts.md +9 -9
- package/gsd-core/references/nyquist-compliance.md +74 -0
- package/gsd-core/references/offer-next.md +3 -5
- package/gsd-core/references/phase-argument-parsing.md +3 -3
- package/gsd-core/references/planner-failing-direction.md +53 -0
- package/gsd-core/references/planner-guidance.md +3 -9
- package/gsd-core/references/planner-human-verify-mode.md +15 -1
- package/gsd-core/references/planner-preconditions.md +1 -1
- package/gsd-core/references/planner-reviews.md +1 -1
- package/gsd-core/references/planner-revision.md +1 -1
- package/gsd-core/references/planner-verify-command-grounding.md +17 -0
- package/gsd-core/references/planning-config.md +44 -13
- package/gsd-core/references/reviewer-instances.md +31 -0
- package/gsd-core/references/revision-loop.md +1 -1
- package/gsd-core/references/runtime-aware-dispatch.md +1 -1
- package/gsd-core/references/specless-probe-fallback.md +1 -1
- package/gsd-core/references/tdd.md +1 -3
- package/gsd-core/references/ui-brand.md +65 -21
- package/gsd-core/references/ui-consideration-probe.md +1 -1
- package/gsd-core/references/universal-anti-patterns.md +5 -5
- package/gsd-core/references/verifier-phase-gates.md +192 -0
- package/gsd-core/references/verify-command-path-resolvability.md +42 -0
- package/gsd-core/references/verify-mvp-mode.md +2 -2
- package/gsd-core/references/workstream-flag.md +33 -17
- package/gsd-core/templates/README.md +1 -1
- package/gsd-core/templates/SECURITY.md +3 -3
- package/gsd-core/templates/UI-SPEC.md +25 -3
- package/gsd-core/templates/VALIDATION.md +3 -3
- package/gsd-core/templates/discussion-log.md +1 -1
- package/gsd-core/templates/phase-prompt.md +5 -4
- package/gsd-core/templates/state.md +11 -4
- package/gsd-core/templates/verification-report.md +9 -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 +3 -3
- package/gsd-core/workflows/add-tests.md +3 -8
- package/gsd-core/workflows/add-todo.md +1 -1
- package/gsd-core/workflows/ai-integration-phase.md +13 -20
- package/gsd-core/workflows/audit-fix.md +12 -3
- package/gsd-core/workflows/audit-milestone.md +9 -9
- package/gsd-core/workflows/audit-uat.md +17 -2
- package/gsd-core/workflows/autonomous/steps/converge-fail-fast.md +2 -2
- package/gsd-core/workflows/autonomous.md +11 -27
- package/gsd-core/workflows/check-todos.md +1 -1
- package/gsd-core/workflows/cleanup.md +64 -5
- package/gsd-core/workflows/code-review/steps/structural-pre-pass.md +14 -4
- package/gsd-core/workflows/code-review-fix.md +38 -11
- package/gsd-core/workflows/code-review.md +159 -52
- package/gsd-core/workflows/complete-milestone.md +151 -23
- package/gsd-core/workflows/debug.md +12 -8
- package/gsd-core/workflows/diagnose-issues.md +47 -15
- package/gsd-core/workflows/discuss-phase/modes/advisor.md +1 -1
- package/gsd-core/workflows/discuss-phase/modes/chain.md +5 -8
- package/gsd-core/workflows/discuss-phase/modes/default.md +1 -1
- package/gsd-core/workflows/discuss-phase/modes/text.md +1 -1
- package/gsd-core/workflows/discuss-phase-assumptions/steps/auto-advance-dispatch.md +1 -3
- package/gsd-core/workflows/discuss-phase-assumptions.md +4 -3
- package/gsd-core/workflows/discuss-phase.md +1 -1
- package/gsd-core/workflows/do.md +3 -6
- package/gsd-core/workflows/docs-update.md +5 -4
- package/gsd-core/workflows/edit-phase.md +27 -2
- package/gsd-core/workflows/eval-review.md +7 -14
- package/gsd-core/workflows/execute-phase/steps/codebase-drift-gate.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/executor-isolation-dispatch.md +142 -15
- package/gsd-core/workflows/execute-phase/steps/gap-closure-artifacts.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/partial-wave.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/per-plan-executor-routing.md +77 -0
- package/gsd-core/workflows/execute-phase/steps/per-plan-worktree-gate.md +24 -4
- package/gsd-core/workflows/execute-phase/steps/post-merge-gate.md +2 -2
- package/gsd-core/workflows/execute-phase/steps/protected-branch.md +21 -0
- package/gsd-core/workflows/execute-phase/steps/regression-gate-run.md +2 -2
- package/gsd-core/workflows/execute-phase/steps/wave-post-gate-hooks.md +39 -0
- package/gsd-core/workflows/execute-phase.md +72 -100
- package/gsd-core/workflows/execute-plan.md +52 -15
- package/gsd-core/workflows/explore.md +131 -4
- package/gsd-core/workflows/extract-learnings.md +1 -1
- package/gsd-core/workflows/fast.md +10 -2
- package/gsd-core/workflows/forensics.md +1 -1
- package/gsd-core/workflows/graduation.md +5 -5
- package/gsd-core/workflows/health.md +76 -10
- package/gsd-core/workflows/import.md +18 -15
- package/gsd-core/workflows/inbox.md +4 -5
- package/gsd-core/workflows/ingest-docs.md +49 -16
- package/gsd-core/workflows/insert-phase.md +5 -5
- package/gsd-core/workflows/list-seeds.md +5 -3
- package/gsd-core/workflows/list-workspaces.md +1 -1
- package/gsd-core/workflows/manager.md +12 -23
- package/gsd-core/workflows/map-codebase.md +1 -1
- package/gsd-core/workflows/milestone-summary.md +1 -1
- package/gsd-core/workflows/mvp-phase.md +8 -5
- package/gsd-core/workflows/new-milestone.md +22 -29
- package/gsd-core/workflows/new-project/steps/auto-mode-config.md +1 -1
- package/gsd-core/workflows/new-project.md +26 -40
- package/gsd-core/workflows/new-workspace.md +1 -1
- package/gsd-core/workflows/next.md +14 -2
- package/gsd-core/workflows/pause-work.md +1 -1
- package/gsd-core/workflows/plan-phase/steps/adr-ingest-express-path.md +1 -1
- package/gsd-core/workflows/plan-phase/steps/chunked-planning-mode.md +1 -1
- package/gsd-core/workflows/plan-phase/steps/prd-express-path.md +2 -4
- package/gsd-core/workflows/plan-phase/steps/stall-detection-helpers.md +3 -3
- package/gsd-core/workflows/plan-phase.md +162 -59
- package/gsd-core/workflows/plan-review-convergence.md +96 -11
- package/gsd-core/workflows/plant-seed.md +2 -2
- package/gsd-core/workflows/pr-branch.md +187 -51
- package/gsd-core/workflows/profile-user.md +16 -14
- package/gsd-core/workflows/progress.md +61 -18
- package/gsd-core/workflows/quick/steps/discussion-phase.md +1 -3
- package/gsd-core/workflows/quick/steps/plan-checker-loop.md +5 -7
- package/gsd-core/workflows/quick/steps/quick-verification.md +28 -9
- package/gsd-core/workflows/quick/steps/research-phase.md +4 -6
- package/gsd-core/workflows/quick/steps/worktree-pre-dispatch-commit.md +3 -3
- package/gsd-core/workflows/quick.md +55 -44
- package/gsd-core/workflows/remove-phase.md +4 -4
- package/gsd-core/workflows/remove-workspace.md +2 -2
- package/gsd-core/workflows/resume-project.md +8 -12
- package/gsd-core/workflows/review.md +219 -20
- package/gsd-core/workflows/scan.md +1 -1
- package/gsd-core/workflows/secure-phase.md +3 -3
- package/gsd-core/workflows/session-report.md +2 -1
- package/gsd-core/workflows/settings-advanced.md +7 -9
- package/gsd-core/workflows/settings-integrations.md +64 -31
- package/gsd-core/workflows/settings.md +69 -7
- package/gsd-core/workflows/ship.md +116 -50
- package/gsd-core/workflows/sketch-wrap-up.md +11 -17
- package/gsd-core/workflows/sketch.md +12 -18
- package/gsd-core/workflows/smart-entry.md +3 -5
- package/gsd-core/workflows/spec-phase.md +53 -13
- package/gsd-core/workflows/spike-wrap-up.md +7 -11
- package/gsd-core/workflows/spike.md +20 -31
- package/gsd-core/workflows/stats.md +2 -2
- package/gsd-core/workflows/sync-skills.md +64 -9
- package/gsd-core/workflows/thread.md +11 -7
- package/gsd-core/workflows/transition.md +49 -14
- package/gsd-core/workflows/ui-phase.md +15 -21
- package/gsd-core/workflows/ui-review.md +8 -12
- package/gsd-core/workflows/ultraplan-phase.md +5 -13
- package/gsd-core/workflows/undo.md +8 -16
- package/gsd-core/workflows/update.md +7 -11
- package/gsd-core/workflows/validate-phase.md +3 -3
- package/gsd-core/workflows/verify-work/steps/automated-ui-verification.md +25 -1
- package/gsd-core/workflows/verify-work/steps/mvp-uat-framing.md +1 -1
- package/gsd-core/workflows/verify-work.md +66 -25
- package/hooks/dist/gsd-agent-isolation-guard.js +158 -30
- package/hooks/dist/gsd-check-update-worker.js +56 -13
- package/hooks/dist/gsd-check-update.js +19 -1
- package/hooks/dist/gsd-config-reload.js +18 -12
- package/hooks/dist/gsd-context-monitor.js +19 -10
- package/hooks/dist/gsd-cursor-post-tool.js +3 -1
- package/hooks/dist/gsd-cursor-pre-tool.js +2 -3
- package/hooks/dist/gsd-cursor-session-start.js +2 -1
- package/hooks/dist/gsd-cursor-stop.js +2 -1
- package/hooks/dist/gsd-cursor-subagent-start.js +83 -3
- package/hooks/dist/gsd-cursor-subagent-stop.js +6 -3
- package/hooks/dist/gsd-ensure-canonical-path.js +2 -1
- package/hooks/dist/gsd-graphify-update.sh +22 -18
- package/hooks/dist/gsd-node-runner.sh +76 -0
- package/hooks/dist/gsd-phase-boundary.sh +1 -0
- package/hooks/dist/gsd-prompt-guard.js +37 -27
- package/hooks/dist/gsd-read-guard.js +16 -7
- package/hooks/dist/gsd-read-injection-scanner.js +55 -32
- package/hooks/dist/gsd-session-state.sh +1 -0
- package/hooks/dist/gsd-statusline.js +231 -24
- package/hooks/dist/gsd-update-banner.js +22 -1
- package/hooks/dist/gsd-validate-commit.sh +80 -6
- package/hooks/dist/gsd-windsurf-pre-command.js +16 -11
- package/hooks/dist/gsd-windsurf-pre-write.js +22 -13
- package/hooks/dist/gsd-workflow-guard.js +162 -46
- package/hooks/dist/gsd-worktree-path-guard.js +36 -21
- package/hooks/dist/gsd-write-guard.js +35 -25
- package/hooks/dist/lib/cli-exit.js +560 -0
- package/hooks/dist/lib/exit-code-registry.js +98 -0
- package/hooks/dist/lib/git-cmd.js +92 -59
- package/hooks/dist/lib/git-probe.js +84 -0
- package/hooks/dist/lib/hook-exit.js +81 -0
- 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 +9 -0
- package/hooks/dist/managed-hooks-registry.cjs +3 -0
- package/hooks/gsd-agent-isolation-guard.js +158 -30
- package/hooks/gsd-check-update-worker.js +56 -13
- package/hooks/gsd-check-update.js +19 -1
- package/hooks/gsd-config-reload.js +18 -12
- package/hooks/gsd-context-monitor.js +19 -10
- package/hooks/gsd-cursor-post-tool.js +3 -1
- package/hooks/gsd-cursor-pre-tool.js +2 -3
- package/hooks/gsd-cursor-session-start.js +2 -1
- package/hooks/gsd-cursor-stop.js +2 -1
- package/hooks/gsd-cursor-subagent-start.js +83 -3
- package/hooks/gsd-cursor-subagent-stop.js +6 -3
- package/hooks/gsd-ensure-canonical-path.js +2 -1
- package/hooks/gsd-graphify-update.sh +22 -18
- package/hooks/gsd-node-runner.sh +76 -0
- package/hooks/gsd-phase-boundary.sh +1 -0
- package/hooks/gsd-prompt-guard.js +37 -27
- package/hooks/gsd-read-guard.js +16 -7
- package/hooks/gsd-read-injection-scanner.js +55 -32
- package/hooks/gsd-session-state.sh +1 -0
- package/hooks/gsd-statusline.js +231 -24
- package/hooks/gsd-update-banner.js +22 -1
- package/hooks/gsd-validate-commit.sh +80 -6
- package/hooks/gsd-windsurf-pre-command.js +16 -11
- package/hooks/gsd-windsurf-pre-write.js +22 -13
- package/hooks/gsd-workflow-guard.js +162 -46
- package/hooks/gsd-worktree-path-guard.js +36 -21
- package/hooks/gsd-write-guard.js +35 -25
- package/hooks/lib/cli-exit.js +560 -0
- package/hooks/lib/exit-code-registry.js +98 -0
- package/hooks/lib/git-cmd.js +92 -59
- package/hooks/lib/git-probe.js +84 -0
- package/hooks/lib/hook-exit.js +81 -0
- package/hooks/lib/injection-patterns.js +45 -0
- package/hooks/lib/isolation-deny-reason.js +39 -0
- package/hooks/lib/isolation-sentinel.js +9 -0
- package/hooks/managed-hooks-registry.cjs +3 -0
- package/package.json +28 -11
- package/pi/gsd.cjs +19 -5
- package/scripts/base64-scan.sh +74 -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 +5 -0
- package/scripts/changeset/lint.cjs +60 -5
- package/scripts/check-alias-drift.cjs +7 -43
- package/scripts/check-contract-drift.cjs +297 -0
- package/scripts/check-glossary-refs.cjs +77 -15
- package/scripts/check-mutation-score-ratchet.cjs +156 -0
- package/scripts/ci-check-job-near-cap.cjs +49 -0
- package/scripts/ci-pr-mergeability.cjs +262 -0
- package/scripts/ci-test-scope.cjs +64 -14
- package/scripts/ci-timeout-report.cjs +230 -0
- package/scripts/command-contract-helpers.cjs +903 -1
- package/scripts/docs-guard-registry.cjs +396 -0
- package/scripts/gen-adr-index.cjs +728 -38
- package/scripts/gen-capability-registry.cjs +11 -21
- package/scripts/gen-context-index.cjs +2 -11
- package/scripts/gen-exit-code-docs.cjs +318 -0
- package/scripts/gen-exit-code-registry.cjs +891 -0
- package/scripts/gen-features.cjs +836 -0
- package/scripts/gen-health-docs.cjs +390 -0
- package/scripts/gen-hooks-cli-exit.cjs +239 -0
- package/scripts/gen-install-tree-fixtures.cjs +2 -2
- package/scripts/gen-inventory-manifest.cjs +50 -4
- package/scripts/gen-loop-host-contract.cjs +138 -25
- package/scripts/gen-registry.cjs +3 -14
- package/scripts/gen-scripts-cli-exit.cjs +185 -0
- package/scripts/gen-state-md-docs.cjs +727 -0
- package/scripts/{test-failure-reasons.cjs → gsd-test-gate-reasons.cjs} +6 -0
- package/scripts/lib/alias-drift-families.cjs +46 -0
- package/scripts/lib/ci-job-timing.cjs +72 -0
- package/scripts/lib/cli-exit.cjs +546 -44
- package/scripts/lib/drift-scan.cjs +308 -0
- package/scripts/lib/exit-code-registry.cjs +98 -0
- package/scripts/lib/ndjson-reporter.cjs +119 -0
- package/scripts/lint-allow-test-rule-refs.allowlist.json +1 -26
- 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-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-guard-registration.cjs +495 -0
- package/scripts/lint-docs-guard-registration.exempt-baseline.cjs +193 -0
- package/scripts/lint-eslint-glob-coverage.allowlist.json +38 -0
- package/scripts/lint-eslint-glob-coverage.cjs +340 -0
- package/scripts/{lint-fix-has-regression-test.cjs → lint-fix-has-regression-tests.cjs} +12 -6
- package/scripts/lint-frontmatter-scalar-broad-grep.cjs +237 -0
- package/scripts/lint-health-diagnostic-rule-table.cjs +461 -0
- package/scripts/lint-hooks-runtime-build-seam.cjs +262 -0
- package/scripts/lint-milestone-window-drift.cjs +468 -0
- package/scripts/lint-mutation-test-derivation-drift.cjs +86 -0
- package/scripts/lint-phase-enumeration-drift.cjs +492 -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 +471 -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 +488 -0
- package/scripts/lint-seam-enforcement.cjs +182 -0
- package/scripts/lint-slug-derivation-drift.cjs +921 -0
- package/scripts/lint-source-test-name-collision.cjs +241 -0
- package/scripts/lint-state-field-drift.cjs +805 -0
- package/scripts/lint-state-write-path-drift.cjs +950 -0
- package/scripts/lint-test-file-count.allowlist.json +137 -8
- package/scripts/lint-test-file-count.cjs +25 -3
- package/scripts/lint-unreachable-guard-drift.cjs +830 -0
- package/scripts/lint-vendored-deps.cjs +297 -0
- package/scripts/mutation-matrix.cjs +599 -50
- package/scripts/pr-changed-files.cjs +63 -0
- package/scripts/pr-template-policy.cjs +14 -4
- package/scripts/prompt-injection-scan.sh +100 -14
- package/scripts/require-issue-link-policy.cjs +192 -0
- package/scripts/secret-scan.sh +75 -13
- package/scripts/select-docs-guards.cjs +56 -0
- package/scripts/sync-runtime-launcher.cjs +24 -7
- package/skills/gsd-autonomous/SKILL.md +0 -1
- package/skills/gsd-code-review/SKILL.md +1 -1
- package/skills/gsd-discuss-phase/SKILL.md +1 -1
- package/skills/gsd-execute-phase/SKILL.md +1 -2
- package/skills/gsd-import/SKILL.md +1 -1
- package/skills/gsd-map-codebase/SKILL.md +1 -1
- package/skills/gsd-mempalace-capture/SKILL.md +1 -1
- package/skills/gsd-mempalace-recall/SKILL.md +1 -1
- package/skills/gsd-new-milestone/SKILL.md +1 -1
- package/skills/gsd-next/SKILL.md +0 -1
- package/skills/gsd-plan-phase/SKILL.md +0 -1
- package/skills/gsd-progress/SKILL.md +0 -1
- package/skills/gsd-quick/SKILL.md +9 -5
- 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/bin/lib/ui-safety-gate.cjs +0 -107
- 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 -574
- package/scripts/affected-tests-lib.cjs +0 -554
- package/scripts/lint-allow-test-rule-refs.cjs +0 -162
- package/scripts/lint-emitted-drift-ack.cjs +0 -344
- package/scripts/run-affected-tests.cjs +0 -7
- package/scripts/run-tests.cjs +0 -1051
|
@@ -17,13 +17,35 @@ 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
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");
|
|
39
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports -- export= CommonJS module, same as the sibling resolver import above
|
|
40
|
+
const installEffortResolver = require("./install-effort-resolver.cjs");
|
|
41
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports -- export= CommonJS module, same as the sibling resolver import above
|
|
42
|
+
const modelCatalog = require("./model-catalog.cjs");
|
|
26
43
|
const shell_command_projection_cjs_1 = require("./shell-command-projection.cjs");
|
|
44
|
+
// #2870: `isGlobalScope` centralizes the `scope === 'global'` boolean
|
|
45
|
+
// projection both kind-builder closures below need at the converters'
|
|
46
|
+
// positional `isGlobal` boundary (see its doc comment in install-scope.cts
|
|
47
|
+
// for why the projection is centralized rather than eliminated).
|
|
48
|
+
const install_scope_cjs_1 = require("./install-scope.cjs");
|
|
27
49
|
// In .cts (CommonJS output) files, `require` is available as a global.
|
|
28
50
|
const _require = require;
|
|
29
51
|
// ---------------------------------------------------------------------------
|
|
@@ -38,24 +60,51 @@ const _require = require;
|
|
|
38
60
|
* 3. Throw a descriptive error if neither succeeds.
|
|
39
61
|
*/
|
|
40
62
|
function findInstallSourceRoot(runtimeConfigDir) {
|
|
41
|
-
// Step 1: marker check
|
|
63
|
+
// Step 1: marker check — reads `<runtimeConfigDir>/.gsd-source`, a path
|
|
64
|
+
// under the INSTALL DESTINATION, so this probe goes through the injected
|
|
65
|
+
// adapter (installFs()).
|
|
42
66
|
if (runtimeConfigDir) {
|
|
43
67
|
const markerPath = node_path_1.default.join(runtimeConfigDir, '.gsd-source');
|
|
44
|
-
if (
|
|
68
|
+
if (installFs().existsSync(markerPath)) {
|
|
45
69
|
try {
|
|
46
|
-
const src =
|
|
47
|
-
if (src &&
|
|
70
|
+
const src = installFs().readFileSync(markerPath, 'utf8').trim();
|
|
71
|
+
if (src && installFs().existsSync(src))
|
|
48
72
|
return src;
|
|
49
73
|
}
|
|
50
74
|
catch { /* fall through */ }
|
|
51
75
|
}
|
|
52
76
|
}
|
|
53
|
-
// Step 2: walk up from __dirname
|
|
77
|
+
// Step 2: walk up from __dirname to locate the GSD PACKAGE'S OWN source
|
|
78
|
+
// tree (commands/gsd/) — this resolves where the installer's own code is
|
|
79
|
+
// running FROM, not anything under the install destination, so it is
|
|
80
|
+
// deliberately NOT routed through the injected fs adapter (#2874): a fake
|
|
81
|
+
// "destination" adapter has no reason to know about the real package's own
|
|
82
|
+
// on-disk layout (an injected adapter's store starts empty and is never
|
|
83
|
+
// seeded with real repo paths), and routing it through would make this
|
|
84
|
+
// resolution unconditionally throw rather than gracefully staging nothing.
|
|
85
|
+
//
|
|
86
|
+
// Uses `fs.statSync` in a try/catch rather than `fs.existsSync` — this is
|
|
87
|
+
// LOAD-BEARING, not a style choice: tests/executed-plan.test.cjs's F2 cases
|
|
88
|
+
// poison every method on the ROUTED fs surface (including `existsSync`,
|
|
89
|
+
// since installFs()'s REAL_ADAPTER also calls it) to prove nothing on the
|
|
90
|
+
// installRuntimeArtifacts call tree reaches real fs. The F2 "nativePlugin
|
|
91
|
+
// runtime: pi" test calls this function (via findInstallSourceRoot()) AFTER
|
|
92
|
+
// installing that poison, specifically to resolve the pi nativePlugin
|
|
93
|
+
// source path against this repo's own real layout — an operation this
|
|
94
|
+
// function must still be able to perform even while `existsSync` is
|
|
95
|
+
// poisoned, because this Step 2 walk is real-fs-only by design and was
|
|
96
|
+
// never meant to be covered by that poison list. `statSync` is not on the
|
|
97
|
+
// poisoned surface, so this probe survives; switching back to `existsSync`
|
|
98
|
+
// makes that F2 test throw (verified: reverting this to `existsSync` trips
|
|
99
|
+
// the poison and breaks the pi nativePlugin case).
|
|
54
100
|
let dir = __dirname;
|
|
55
101
|
for (let i = 0; i < 6; i++) {
|
|
56
102
|
const candidate = node_path_1.default.join(dir, 'commands', 'gsd');
|
|
57
|
-
|
|
103
|
+
try {
|
|
104
|
+
node_fs_1.default.statSync(candidate);
|
|
58
105
|
return candidate;
|
|
106
|
+
}
|
|
107
|
+
catch { /* not here — keep walking up */ }
|
|
59
108
|
const parent = node_path_1.default.dirname(dir);
|
|
60
109
|
if (parent === dir)
|
|
61
110
|
break;
|
|
@@ -72,28 +121,35 @@ function findInstallSourceRoot(runtimeConfigDir) {
|
|
|
72
121
|
* 3. Throw a descriptive error if neither succeeds.
|
|
73
122
|
*/
|
|
74
123
|
function findAgentsSourceRoot(runtimeConfigDir) {
|
|
75
|
-
// Step 1: marker check
|
|
124
|
+
// Step 1: marker check (destination-relative — routed through installFs()).
|
|
76
125
|
if (runtimeConfigDir) {
|
|
77
126
|
const markerPath = node_path_1.default.join(runtimeConfigDir, '.gsd-source');
|
|
78
|
-
if (
|
|
127
|
+
if (installFs().existsSync(markerPath)) {
|
|
79
128
|
try {
|
|
80
|
-
const src =
|
|
81
|
-
if (src &&
|
|
129
|
+
const src = installFs().readFileSync(markerPath, 'utf8').trim();
|
|
130
|
+
if (src && installFs().existsSync(src)) {
|
|
82
131
|
// Marker points to commands/gsd; agents/ is a sibling of commands/
|
|
83
132
|
const agentsCandidate = node_path_1.default.resolve(node_path_1.default.dirname(src), '..', 'agents');
|
|
84
|
-
if (
|
|
133
|
+
if (installFs().existsSync(agentsCandidate))
|
|
85
134
|
return agentsCandidate;
|
|
86
135
|
}
|
|
87
136
|
}
|
|
88
137
|
catch { /* fall through */ }
|
|
89
138
|
}
|
|
90
139
|
}
|
|
91
|
-
// Step 2: walk up from __dirname
|
|
140
|
+
// Step 2: walk up from __dirname — locates THIS package's own agents/
|
|
141
|
+
// source tree, not the install destination. See findInstallSourceRoot's
|
|
142
|
+
// Step 2 comment (#2874) for why this stays unrouted, real-fs-only, and why
|
|
143
|
+
// it uses `statSync` rather than `existsSync` (load-bearing against F2's
|
|
144
|
+
// poison of the routed fs surface, not a style choice).
|
|
92
145
|
let dir = __dirname;
|
|
93
146
|
for (let i = 0; i < 6; i++) {
|
|
94
147
|
const candidate = node_path_1.default.join(dir, 'agents');
|
|
95
|
-
|
|
148
|
+
try {
|
|
149
|
+
node_fs_1.default.statSync(candidate);
|
|
96
150
|
return candidate;
|
|
151
|
+
}
|
|
152
|
+
catch { /* not here — keep walking up */ }
|
|
97
153
|
const parent = node_path_1.default.dirname(dir);
|
|
98
154
|
if (parent === dir)
|
|
99
155
|
break;
|
|
@@ -127,9 +183,53 @@ function agentsKind(destSubpath, prefix, configDir) {
|
|
|
127
183
|
// inline agent loop, and installCodexConfig's per-agent .toml writer. The
|
|
128
184
|
// exhaustive per-runtime sweep in tests/agent-fragments-emission.install.test.cjs
|
|
129
185
|
// is what keeps a fourth from appearing uncomposed.
|
|
130
|
-
|
|
186
|
+
// #2875 Part 2 (row I2): agentCtx threaded through so a runtime using this
|
|
187
|
+
// converter:null builder (claude, plus any future identity-copy runtime)
|
|
188
|
+
// ALSO gets path-rewrites/attribution/frontmatter-extensions/normalize
|
|
189
|
+
// when a caller supplies agentCtx (createRuntimeArtifactInstallPlan /
|
|
190
|
+
// applySurface's agentCtx build). Previously this closure's `(resolved) =>`
|
|
191
|
+
// signature silently dropped the second arg every caller already passed —
|
|
192
|
+
// a caller with NO agentCtx in scope is unaffected (row I2: converter-only,
|
|
193
|
+
// as today), matching stageAgentsForRuntimeWithConverter's own contract.
|
|
194
|
+
stage: (resolved, agentCtx) => stageAgentsForRuntimeWithConverter(findAgentsSourceRoot(configDir), resolved, (content) => content, false, agentCtx),
|
|
131
195
|
};
|
|
132
196
|
}
|
|
197
|
+
/**
|
|
198
|
+
* Runtime allowlist check for a descriptor-declared `converter` name, applied
|
|
199
|
+
* at DISPATCH time (security fix). `VALID_CONVERTER_NAMES` (capability-
|
|
200
|
+
* validator.cjs) is otherwise enforced ONLY at lint/build time
|
|
201
|
+
* (`check:contract-drift`) — every `conversionExports[converterName]`
|
|
202
|
+
* dynamic-property read below trusted that a `capability.json` reaching this
|
|
203
|
+
* far had already passed that check. It had not, in general: a hand-edited
|
|
204
|
+
* or malformed descriptor naming an Object-prototype member (`"constructor"`,
|
|
205
|
+
* `"toString"`, `"hasOwnProperty"`, ...) resolves to that member instead of
|
|
206
|
+
* throwing, producing garbage staged content rather than a loud failure —
|
|
207
|
+
* pre-existing, but promoted from the `/gsd-surface`-only path to the real
|
|
208
|
+
* install path for seven runtimes by #2875 Part 2's agents-bypass closure.
|
|
209
|
+
* Required lazily (call-time, not module-top) to avoid a load-time circular
|
|
210
|
+
* require, the same pattern install-engine.cts's `_hostBehaviors` already
|
|
211
|
+
* uses for `capability-registry.cjs`. Fails CLOSED: any error loading the
|
|
212
|
+
* allowlist itself (missing module, exotic bundling) is treated as "nothing
|
|
213
|
+
* is allowed", never as "skip the check".
|
|
214
|
+
*/
|
|
215
|
+
function _resolveNamedConverter(converterName, kindLabel) {
|
|
216
|
+
let validNames;
|
|
217
|
+
try {
|
|
218
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
219
|
+
validNames = require('./capability-validator.cjs').VALID_CONVERTER_NAMES;
|
|
220
|
+
}
|
|
221
|
+
catch {
|
|
222
|
+
validNames = undefined;
|
|
223
|
+
}
|
|
224
|
+
if (!validNames || !validNames.has(converterName)) {
|
|
225
|
+
throw new Error(`Unknown converter "${converterName}" declared for a ${kindLabel} kind — refusing to dispatch (not in capability-validator.cjs's VALID_CONVERTER_NAMES allowlist).`);
|
|
226
|
+
}
|
|
227
|
+
const fn = conversionExports[converterName];
|
|
228
|
+
if (typeof fn !== 'function') {
|
|
229
|
+
throw new Error(`Converter "${converterName}" is allowlisted but is not an exported function of runtime-artifact-conversion.cjs.`);
|
|
230
|
+
}
|
|
231
|
+
return fn;
|
|
232
|
+
}
|
|
133
233
|
/**
|
|
134
234
|
* Build a converted-agents kind descriptor for runtimes whose agent `.md` files
|
|
135
235
|
* need runtime-specific frontmatter/body conversion (e.g. Copilot, Cursor, Codex).
|
|
@@ -141,27 +241,80 @@ function agentsKind(destSubpath, prefix, configDir) {
|
|
|
141
241
|
* Agent filenames are preserved verbatim (the prefix is already embedded in the
|
|
142
242
|
* agent stem — e.g. `gsd-planner.md`).
|
|
143
243
|
*
|
|
144
|
-
* #1173 SCOPE
|
|
145
|
-
* the
|
|
146
|
-
*
|
|
147
|
-
*
|
|
148
|
-
*
|
|
149
|
-
*
|
|
150
|
-
*
|
|
151
|
-
*
|
|
152
|
-
* `
|
|
153
|
-
* `
|
|
154
|
-
*
|
|
155
|
-
* (`
|
|
156
|
-
*
|
|
157
|
-
*
|
|
158
|
-
*
|
|
159
|
-
*
|
|
160
|
-
*
|
|
161
|
-
* `
|
|
162
|
-
*
|
|
163
|
-
*
|
|
164
|
-
*
|
|
244
|
+
* #1173 SCOPE, updated by #2875 Part 2 (the agents-bypass closure) — measured
|
|
245
|
+
* against the tree, not the ADR-3574 framing that preceded it:
|
|
246
|
+
*
|
|
247
|
+
* Of the four blockers this comment used to name for wiring `bin/install.js`'s
|
|
248
|
+
* inline agent loop against this resolver, THREE were already stale by the
|
|
249
|
+
* time #2875 measured them and are not re-litigated here: Copilot's
|
|
250
|
+
* `.agent.md` rename (the loop's own `destName = entry.name` comment records
|
|
251
|
+
* the ternary dropped in #2099; the descriptor fold applies it via
|
|
252
|
+
* `hostBehaviors.agentFileExtension`), the cross-cutting path-prefix rewrite +
|
|
253
|
+
* attribution (`stageAgentsForRuntimeWithConverter` already applies
|
|
254
|
+
* `applyAgentPathRewrites` -> `processAttribution` when `agentCtx` is
|
|
255
|
+
* present), and stale-file cleanup (`_removeGsdEntries` prunes every
|
|
256
|
+
* `gsd-`-prefixed entry in a kind's destSubpath, broader than the loop's own
|
|
257
|
+
* extension-gated check).
|
|
258
|
+
*
|
|
259
|
+
* The fourth — config-reading steps — was the real gap, and #2875 Part 2
|
|
260
|
+
* closed it: `stageAgentsForRuntimeWithConverter` now takes a per-file
|
|
261
|
+
* `agentName` (`agentCtx.agentName`, ADR-1235 §1) and a `targetDir`
|
|
262
|
+
* (`agentCtx.targetDir`), which together let it (a) run a post-converter
|
|
263
|
+
* frontmatter-extensions step (`applyAgentFrontmatterExtensions`, driven by
|
|
264
|
+
* `hostBehaviors.agentFrontmatterExtensions` — Claude's `effort` +
|
|
265
|
+
* `disallowedTools` injection) and (b) let THIS function resolve a per-agent
|
|
266
|
+
* model override (`installModelOverrideResolver.resolveAgentModelOverride`,
|
|
267
|
+
* `model_overrides[agent]` > `model_profile_overrides.<rt>.<tier>` > omit)
|
|
268
|
+
* before invoking a converter that needs it (kilo/opencode). Both pieces —
|
|
269
|
+
* plus a data-driven Hermes branding converter
|
|
270
|
+
* (`convertClaudeAgentToHermesAgent`, reading `hostBehaviors.brandingRewrites`
|
|
271
|
+
* rather than a hardcoded string table) — are single-sourced: `bin/install.js`
|
|
272
|
+
* requires the SAME functions this module does, so its inline loop and the
|
|
273
|
+
* descriptor path can no longer independently drift (the CLAUDE.md
|
|
274
|
+
* "Generative Fix Divergence" class the prior duplication risked).
|
|
275
|
+
*
|
|
276
|
+
* `tests/agent-descriptor-parity.test.cjs` proves byte-identical output
|
|
277
|
+
* between the inline loop and a SYNTHETIC descriptor registry (the same
|
|
278
|
+
* override seam `resolveRuntimeArtifactLayoutFromRegistry` exposes) for all
|
|
279
|
+
* six runtimes the inline loop still served: claude, cline, codex, hermes,
|
|
280
|
+
* kilo, opencode.
|
|
281
|
+
*
|
|
282
|
+
* Both findings the prior revision of this comment named as STILL deferred
|
|
283
|
+
* are now CLOSED (#2875 Part 2 Task A/B/C), measured against the real
|
|
284
|
+
* `capability.json` entries and the real production entry points, not
|
|
285
|
+
* argued from this module alone:
|
|
286
|
+
*
|
|
287
|
+
* 1. **kilo/opencode reaching `layout.kinds`.** `installEngine.
|
|
288
|
+
* installAgentsKindStandalone` (install-engine.cts) is called from inside
|
|
289
|
+
* `installOpencodeFamilyArtifacts` and resolves the agents kind through
|
|
290
|
+
* THIS SAME `resolveRuntimeArtifactLayout`/`convertedAgentsKind` path —
|
|
291
|
+
* `installOpencodeFamilyArtifacts` no longer stages only `commands` +
|
|
292
|
+
* `skills`. `bin/install.js`'s legacy-flat local path (claude-local,
|
|
293
|
+
* `hostBehaviors.localInstallStyle === 'legacy-flat'`) reaches the SAME
|
|
294
|
+
* generic loop only via `installRuntimeArtifacts`'s conditional
|
|
295
|
+
* `_isSkillsRuntime` branch; a call to `installAgentsKindStandalone` was
|
|
296
|
+
* added at claude-local's own call site to cover that scope too — the
|
|
297
|
+
* install-tree golden fixture (`tests/fixtures/install-tree/claude-local.json`)
|
|
298
|
+
* is what caught the gap when it was first missed.
|
|
299
|
+
* 2. **`/gsd:surface` / `applySurface` activation.** Confirmed convergent,
|
|
300
|
+
* not merely non-broken: for all six runtimes (claude, cline, codex,
|
|
301
|
+
* hermes, kilo, opencode), staging via `applySurface` into a freshly
|
|
302
|
+
* wiped `agents/` directory produces byte-identical output (including
|
|
303
|
+
* filenames) to `installRuntimeArtifacts`'s own write — verified directly
|
|
304
|
+
* against the built registry, not inferred.
|
|
305
|
+
*
|
|
306
|
+
* The inline loop (`_DESCRIPTOR_AGENTS_RUNTIMES` and the `bin/install.js`
|
|
307
|
+
* agent-staging block it gated) is DELETED — every runtime the registry
|
|
308
|
+
* declares an `agents` kind for is descriptor-driven now, including a
|
|
309
|
+
* seventh runtime (`kimi-code`) this comment's own prior measurement missed
|
|
310
|
+
* (it fell through the inline loop's generic `else if` branch, same as
|
|
311
|
+
* claude, with no dedicated dialect arm — caught by the same golden fixture).
|
|
312
|
+
*
|
|
313
|
+
* Codex's `config.toml [agents.gsd-*]` strip (`bin/install.js`, under
|
|
314
|
+
* `isMinimalMode` + `hostBehaviors.tomlConfigInstall`) remains the one
|
|
315
|
+
* genuinely out-of-scope constraint: it mutates a host config file, not the
|
|
316
|
+
* agents directory, and no descriptor kind models host-config mutation. It
|
|
317
|
+
* stays exactly where it is.
|
|
165
318
|
*
|
|
166
319
|
* Mirrors the `convertedCommandsKind` pattern (#785).
|
|
167
320
|
*
|
|
@@ -176,15 +329,74 @@ function convertedAgentsKind(destSubpath, prefix, converterName, configDir, scop
|
|
|
176
329
|
destSubpath,
|
|
177
330
|
prefix,
|
|
178
331
|
stage: (resolved, agentCtx) => {
|
|
179
|
-
//
|
|
180
|
-
//
|
|
181
|
-
//
|
|
182
|
-
//
|
|
183
|
-
|
|
332
|
+
// #2870: `scope` is this function's own parameter (default `'global'`,
|
|
333
|
+
// so it is never undefined here), sourced upstream from the Install
|
|
334
|
+
// Scope Module's resolved id. `isGlobalScope` projects it to the
|
|
335
|
+
// boolean `stageAgentsForRuntimeWithConverter`'s positional API
|
|
336
|
+
// requires — see its doc comment in install-scope.cts.
|
|
337
|
+
const rawConverter = _resolveNamedConverter(converterName, 'agents');
|
|
338
|
+
// #2875 Part 2 (J5-J8): kilo/opencode agent converters take an options
|
|
339
|
+
// bag (`{isAgent, modelOverride}`), not the `isGlobal` boolean every
|
|
340
|
+
// other agent converter's 2nd positional arg means — mirrors the
|
|
341
|
+
// inline loop's per-runtime `frontmatterDialect === 'opencode' | 'kilo'`
|
|
342
|
+
// branches (bin/install.js), which resolve model_overrides[agent] >
|
|
343
|
+
// model_profile_overrides.<runtime>.<tier> > omit BEFORE calling the
|
|
344
|
+
// converter. Resolved ONCE per stage() call (not per file — a pure
|
|
345
|
+
// function of configDir/targetDir) via the single shared precedence
|
|
346
|
+
// resolver so kilo and opencode can never diverge (J8).
|
|
347
|
+
const needsModelOverride = converterName === 'convertClaudeToOpencodeFrontmatter' || converterName === 'convertClaudeToKiloFrontmatter';
|
|
348
|
+
let converter;
|
|
349
|
+
if (needsModelOverride) {
|
|
350
|
+
const overrideTargetDir = agentCtx?.targetDir ?? configDir;
|
|
351
|
+
const modelOverrides = installModelOverrideResolver.readGsdEffectiveModelOverrides(overrideTargetDir);
|
|
352
|
+
const runtimeResolver = installModelOverrideResolver.readGsdRuntimeProfileResolver(overrideTargetDir);
|
|
353
|
+
// #3706: the resolved reasoning effort, threaded exactly as the model is —
|
|
354
|
+
// config read ONCE per stage(), per-agent value resolved per file.
|
|
355
|
+
//
|
|
356
|
+
// Gated on the effort config being PRESENT, not on a value coming back.
|
|
357
|
+
// `resolveInstallTimeEffort` always returns something (measured: 'high'
|
|
358
|
+
// even with no project config and no effort block), so "skip when
|
|
359
|
+
// resolution yields no value" has no trigger and would stamp `variant:`
|
|
360
|
+
// into every generated agent file for every existing install. OpenCode's
|
|
361
|
+
// built-in variant sets are provider-specific upstream (Anthropic ships
|
|
362
|
+
// only `high`/`max`), so a level GSD resolved is not guaranteed to name a
|
|
363
|
+
// variant the user's provider actually has — emitting one unasked-for is
|
|
364
|
+
// the risk this gate avoids. #1156's rule for `model: inherit` is the
|
|
365
|
+
// precedent: do not emit a key the runtime may not understand.
|
|
366
|
+
//
|
|
367
|
+
// OpenCode only; the kilo converter ignores the field (no EFFORT_ARGV.kilo).
|
|
368
|
+
const effortConfig = converterName === 'convertClaudeToOpencodeFrontmatter'
|
|
369
|
+
? installEffortResolver.readGsdEffectiveEffortConfig(overrideTargetDir)
|
|
370
|
+
: null;
|
|
371
|
+
converter = (content, _isGlobal, meta) => {
|
|
372
|
+
const modelOverride = meta
|
|
373
|
+
? installModelOverrideResolver.resolveAgentModelOverride(meta.agentName, modelOverrides, runtimeResolver)
|
|
374
|
+
: null;
|
|
375
|
+
// The universal level is NOT emitted raw. `clampEffortForHost` is the
|
|
376
|
+
// declared OpenCode effort capability (EFFORT_ARGV.opencode: its own
|
|
377
|
+
// `supported` set + `clamp`), and it is what rejects a level that is
|
|
378
|
+
// not a wire value — most importantly `inherit`, which per #3533 (10d)
|
|
379
|
+
// means "omit the key and follow the host default" and must never be
|
|
380
|
+
// written literally. Anything unsupported clamps to null, which omits
|
|
381
|
+
// the key rather than inventing one.
|
|
382
|
+
const universal = effortConfig && meta
|
|
383
|
+
? installEffortResolver.resolveInstallTimeEffort(effortConfig, meta.agentName)
|
|
384
|
+
: null;
|
|
385
|
+
const variant = universal ? modelCatalog.clampEffortForHost('opencode', universal) : null;
|
|
386
|
+
return rawConverter(content, { isAgent: true, modelOverride, variant });
|
|
387
|
+
};
|
|
388
|
+
}
|
|
389
|
+
else {
|
|
390
|
+
// isGlobal is threaded so scope-aware agent converters (copilot, antigravity)
|
|
391
|
+
// choose global-home vs workspace-relative paths; converters that only take
|
|
392
|
+
// (content) ignore the extra positional arg. Mirrors skillsKind's scope
|
|
393
|
+
// threading (#1173).
|
|
394
|
+
converter = (content) => rawConverter(content, (0, install_scope_cjs_1.isGlobalScope)(scope));
|
|
395
|
+
}
|
|
184
396
|
// ADR-1235 §1: when agentCtx is provided (by createRuntimeArtifactInstallPlan
|
|
185
397
|
// for descriptor-driven runtimes), thread it through so stageAgentsForRuntimeWithConverter
|
|
186
398
|
// can apply the full pre-converter + post-converter sequence in the correct order.
|
|
187
|
-
return stageAgentsForRuntimeWithConverter(findAgentsSourceRoot(configDir), resolved, converter, scope
|
|
399
|
+
return stageAgentsForRuntimeWithConverter(findAgentsSourceRoot(configDir), resolved, converter, (0, install_scope_cjs_1.isGlobalScope)(scope), agentCtx);
|
|
188
400
|
},
|
|
189
401
|
};
|
|
190
402
|
}
|
|
@@ -199,28 +411,28 @@ function kimiAgentsKind(destSubpath, prefix, configDir) {
|
|
|
199
411
|
// sees marker-free content — same single composing stager as agentsKind.
|
|
200
412
|
const stagedAgents = stageAgentsForRuntimeWithConverter(findAgentsSourceRoot(configDir), resolved, (content) => content);
|
|
201
413
|
const subagents = [];
|
|
202
|
-
if (
|
|
203
|
-
for (const entry of
|
|
414
|
+
if (installFs().existsSync(stagedAgents)) {
|
|
415
|
+
for (const entry of installFs().readdirSync(stagedAgents, { withFileTypes: true })) {
|
|
204
416
|
if (!entry.isFile() || !entry.name.endsWith('.md'))
|
|
205
417
|
continue;
|
|
206
418
|
const agentPath = node_path_1.default.join(stagedAgents, entry.name);
|
|
207
419
|
subagents.push({
|
|
208
420
|
path: (0, shell_command_projection_cjs_1.posixNormalize)(node_path_1.default.join('agents', entry.name)),
|
|
209
|
-
content:
|
|
421
|
+
content: installFs().readFileSync(agentPath, 'utf8'),
|
|
210
422
|
});
|
|
211
423
|
}
|
|
212
424
|
}
|
|
213
425
|
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`;
|
|
214
426
|
const artifacts = buildKimiAgentArtifacts({ rootAgent, subagents });
|
|
215
|
-
const stageDir =
|
|
427
|
+
const stageDir = mkInstallTempDir('gsd-kimi-agents-');
|
|
216
428
|
installProfiles.STAGED_DIRS.add(stageDir);
|
|
217
|
-
|
|
218
|
-
|
|
429
|
+
installFs().writeFileSync(node_path_1.default.join(stageDir, 'gsd.yaml'), artifacts.root.yaml);
|
|
430
|
+
installFs().writeFileSync(node_path_1.default.join(stageDir, 'gsd.md'), artifacts.root.prompt);
|
|
219
431
|
const subagentsDir = node_path_1.default.join(stageDir, 'subagents');
|
|
220
|
-
|
|
432
|
+
installFs().mkdirSync(subagentsDir, { recursive: true });
|
|
221
433
|
for (const artifact of artifacts.subagents) {
|
|
222
|
-
|
|
223
|
-
|
|
434
|
+
installFs().writeFileSync(node_path_1.default.join(subagentsDir, `${artifact.name}.yaml`), artifact.yaml);
|
|
435
|
+
installFs().writeFileSync(node_path_1.default.join(subagentsDir, `${artifact.name}.md`), artifact.prompt);
|
|
224
436
|
}
|
|
225
437
|
return stageDir;
|
|
226
438
|
},
|
|
@@ -251,7 +463,7 @@ function skillsKind(destSubpath, prefix, converterName, runtime, configDir, nest
|
|
|
251
463
|
prefix,
|
|
252
464
|
converter: converterName,
|
|
253
465
|
stage: (resolved) => {
|
|
254
|
-
const realConverter =
|
|
466
|
+
const realConverter = _resolveNamedConverter(converterName, 'skills');
|
|
255
467
|
// Compute cmdNames once per stage call for performance (#3583).
|
|
256
468
|
// Extra trailing args are ignored by converters that don't need them. The
|
|
257
469
|
// isGlobal flag is the 5th positional (NOT the 3rd): the 3rd positional is
|
|
@@ -261,7 +473,21 @@ function skillsKind(destSubpath, prefix, converterName, runtime, configDir, nest
|
|
|
261
473
|
const cmdNames = conversionExports.readGsdCommandNames
|
|
262
474
|
? conversionExports.readGsdCommandNames()
|
|
263
475
|
: [];
|
|
264
|
-
|
|
476
|
+
// #2870: same judgment as convertedAgentsKind above — `scope` is this
|
|
477
|
+
// function's own parameter (default `'global'`, so it is never
|
|
478
|
+
// undefined here); `isGlobalScope` projects it to the boolean
|
|
479
|
+
// `realConverter`'s positional `isGlobal` arg requires.
|
|
480
|
+
const isGlobal = (0, install_scope_cjs_1.isGlobalScope)(scope);
|
|
481
|
+
// #2873 (4b): spec-root reachability is applied LATER in the pipeline —
|
|
482
|
+
// see `rewriteStagedSkillBodies` in runtime-artifact-conversion.cts, not
|
|
483
|
+
// here. This stage() closure runs BEFORE the staged directory's generic
|
|
484
|
+
// path-prefix rewrite pass (`applyRuntimeContentRewritesInPlace`'s
|
|
485
|
+
// `case 'claude'`), which unconditionally rewrites any bare (non-`@`)
|
|
486
|
+
// `~/.claude/` substring to the undocumented `$HOME/.claude/` form and
|
|
487
|
+
// only restores the `@`-prefixed form. Emitting the imperative
|
|
488
|
+
// tilde-path prose here would get silently mangled by that later pass;
|
|
489
|
+
// it must run AFTER it instead, once the `@`-include is in its final
|
|
490
|
+
// rewritten shape.
|
|
265
491
|
const wrappedConverter = (content, skillName) => realConverter(content, skillName, runtime, cmdNames, isGlobal);
|
|
266
492
|
return stageSkillsForRuntimeAsSkills(findInstallSourceRoot(configDir), resolved, wrappedConverter, prefix, nested, capabilityRegistry);
|
|
267
493
|
},
|
|
@@ -289,7 +515,7 @@ function convertedCommandsKind(destSubpath, prefix, converterName, configDir) {
|
|
|
289
515
|
destSubpath,
|
|
290
516
|
prefix,
|
|
291
517
|
stage: (resolved) => {
|
|
292
|
-
const converter =
|
|
518
|
+
const converter = _resolveNamedConverter(converterName, 'commands');
|
|
293
519
|
return stageCommandsForRuntimeFlat(findInstallSourceRoot(configDir), resolved, converter, prefix);
|
|
294
520
|
},
|
|
295
521
|
};
|
|
@@ -328,7 +554,11 @@ function dispatchKindEntry(entry, runtime, configDir, scope, capabilityRegistry)
|
|
|
328
554
|
default:
|
|
329
555
|
throw new TypeError(`resolveRuntimeArtifactLayout: unknown kind '${kind}' in descriptor for runtime '${runtime}'`);
|
|
330
556
|
}
|
|
331
|
-
|
|
557
|
+
// scope is guaranteed 'local' | 'global' here: resolveRuntimeArtifactLayoutFromRegistry
|
|
558
|
+
// (the only caller of dispatchKindEntry) throws TypeError before this point if scope is
|
|
559
|
+
// anything else (see the `scope !== 'local' && scope !== 'global'` guard above its
|
|
560
|
+
// dispatchKindEntry call), so isGlobalScope's throw-on-invalid-input never fires here.
|
|
561
|
+
if ((0, install_scope_cjs_1.isGlobalScope)(scope) && typeof entry.home === 'string' && entry.home !== '') {
|
|
332
562
|
result.home = node_path_1.default.join(node_os_1.default.homedir(), entry.home);
|
|
333
563
|
}
|
|
334
564
|
return result;
|
|
@@ -367,4 +597,178 @@ function resolveRuntimeArtifactLayoutFromRegistry(registry, runtime, configDir,
|
|
|
367
597
|
const kinds = entries.map((entry) => dispatchKindEntry(entry, runtime, configDir, scope, capabilityRegistry));
|
|
368
598
|
return { runtime, configDir, scope, kinds };
|
|
369
599
|
}
|
|
370
|
-
|
|
600
|
+
function getTriggerRegistry() {
|
|
601
|
+
return _require('./capability-registry.cjs');
|
|
602
|
+
}
|
|
603
|
+
/**
|
|
604
|
+
* capability-validator.cjs is a COMMITTED plain .cjs (not built from a .cts
|
|
605
|
+
* source — see its own header comment), so it is required the same way
|
|
606
|
+
* capability-registry.cjs is above: a lazy `_require` rather than a static
|
|
607
|
+
* ES import. DEFAULT_TRIGGER_PRECEDENCE is the single source of truth for
|
|
608
|
+
* "what applies when a descriptor omits triggerPrecedence"; this module
|
|
609
|
+
* reads it rather than re-declaring `['skills', 'commands']` as a second
|
|
610
|
+
* literal that could silently drift from the validator's own default.
|
|
611
|
+
*/
|
|
612
|
+
function getDefaultTriggerPrecedence() {
|
|
613
|
+
const capValidator = _require('./capability-validator.cjs');
|
|
614
|
+
return capValidator.DEFAULT_TRIGGER_PRECEDENCE;
|
|
615
|
+
}
|
|
616
|
+
/**
|
|
617
|
+
* True when a `commands` kind entry is namespaced by its destination
|
|
618
|
+
* directory rather than by a filename prefix — i.e. `destSubpath`'s basename
|
|
619
|
+
* equals `prefix` with its trailing hyphen stripped (e.g. `commands/gsd` +
|
|
620
|
+
* `gsd-`). When true, `_copyStaged` (`install-engine.cts`) and `surface.cts`
|
|
621
|
+
* both write the bare stem filename (no prefix) because the directory itself
|
|
622
|
+
* already carries the namespace; `resolveTriggerSurface` mirrors that in its
|
|
623
|
+
* own `destPath` computation. Single source of truth for the three sites
|
|
624
|
+
* that used to compute this independently (#2871 Phase 2 review finding) —
|
|
625
|
+
* a new caller MUST reuse this rather than re-deriving the rule.
|
|
626
|
+
*/
|
|
627
|
+
function isNamespacedByDir(kind, destSubpath, prefix) {
|
|
628
|
+
const destLast = node_path_1.default.posix.basename((0, shell_command_projection_cjs_1.posixNormalize)(destSubpath));
|
|
629
|
+
const prefixStem = prefix ? prefix.replace(/-$/, '') : '';
|
|
630
|
+
return kind === 'commands' && destLast === prefixStem;
|
|
631
|
+
}
|
|
632
|
+
/**
|
|
633
|
+
* Compose the destination filename `_copyStaged` (install-engine.cts) writes
|
|
634
|
+
* for a `commands` kind entry, given `isNamespacedByDir`'s result, the
|
|
635
|
+
* kind's prefix, and the file's `.md`-stripped stem. Single source of truth
|
|
636
|
+
* alongside `isNamespacedByDir` for the FILENAME COMPOSITION itself (#2871
|
|
637
|
+
* Phase 2 review finding — the boolean was single-sourced first, but the
|
|
638
|
+
* `${stem}.md` / `${prefix}${stem}.md` string-building around it stayed
|
|
639
|
+
* duplicated between `_copyStaged` and `resolveTriggerSurface`'s `destPath`
|
|
640
|
+
* prediction below, so a divergence in the write convention would not have
|
|
641
|
+
* failed anything).
|
|
642
|
+
*
|
|
643
|
+
* Byte-identical to `_copyStaged`'s prior separate branches: when
|
|
644
|
+
* `namespacedByDir` is true this returns `${stem}.md`. `_copyStaged` always
|
|
645
|
+
* derives `stem` as `entry.name.slice(0, -3)` for an `entry.name` that has
|
|
646
|
+
* already been filtered to end in `.md`, so `${stem}.md` is always exactly
|
|
647
|
+
* `entry.name` again — `_copyStaged` can pass this helper's result in place
|
|
648
|
+
* of the `entry.name` it used to write directly, with no behavior change.
|
|
649
|
+
*/
|
|
650
|
+
function composeCommandFilename(namespacedByDir, prefix, stem) {
|
|
651
|
+
return namespacedByDir ? `${stem}.md` : `${prefix}${stem}.md`;
|
|
652
|
+
}
|
|
653
|
+
/**
|
|
654
|
+
* True when candidate `a` should win over the current best `b` for the same
|
|
655
|
+
* trigger. Scope rank first (Phase 1's `install-scope.cts#scopeRank` —
|
|
656
|
+
* global outranks local; NOT re-derived here), then the runtime's
|
|
657
|
+
* `triggerPrecedence` kind ordering (lower index = higher priority). A kind
|
|
658
|
+
* absent from `precedenceRank` (should not happen — every entry's kind is
|
|
659
|
+
* validated against the same closed vocabulary the precedence list draws
|
|
660
|
+
* from) sorts last rather than throwing, so a malformed precedence value
|
|
661
|
+
* degrades to "leaves the incumbent standing" instead of corrupting the
|
|
662
|
+
* whole resolution.
|
|
663
|
+
*/
|
|
664
|
+
function isHigherPriority(a, b, precedenceRank) {
|
|
665
|
+
const rankA = (0, install_scope_cjs_1.scopeRank)(a.scope);
|
|
666
|
+
const rankB = (0, install_scope_cjs_1.scopeRank)(b.scope);
|
|
667
|
+
if (rankA !== rankB)
|
|
668
|
+
return rankA > rankB;
|
|
669
|
+
const pa = precedenceRank.get(a.kind) ?? Number.POSITIVE_INFINITY;
|
|
670
|
+
const pb = precedenceRank.get(b.kind) ?? Number.POSITIVE_INFINITY;
|
|
671
|
+
return pa < pb;
|
|
672
|
+
}
|
|
673
|
+
/**
|
|
674
|
+
* Resolve the `/gsd-<name>`-style trigger surface for a runtime: what the
|
|
675
|
+
* user types, at which scope, whether it wins or is shadowed, and (for
|
|
676
|
+
* nested-router runtimes) whether the host registers it directly or only
|
|
677
|
+
* reaches it through a router. Pure — no filesystem, no mutation of `scopes`
|
|
678
|
+
* or `opts`, and safe against a caller mutating the returned array/objects
|
|
679
|
+
* (a fresh array/objects are built on every call; nothing is cached or
|
|
680
|
+
* shared across calls beyond the read-only registry module).
|
|
681
|
+
*
|
|
682
|
+
* Only `commands` and `skills` kind entries are considered — see the
|
|
683
|
+
* module-level comment above. `resolveRuntimeArtifactLayout` is untouched by
|
|
684
|
+
* this function; they are independent readers of the same descriptor.
|
|
685
|
+
*
|
|
686
|
+
* @throws {TypeError} for an unknown runtime — same contract (and message
|
|
687
|
+
* shape) as `resolveRuntimeArtifactLayoutFromRegistry`.
|
|
688
|
+
* @throws {TypeError} for an unrecognized entry in `scopes` — reuses
|
|
689
|
+
* `install-scope.cts`'s shared `validateScopeId`, the same validator
|
|
690
|
+
* `scopeRank`/`resolveScope`/`isGlobalScope` already throw through, so this
|
|
691
|
+
* sibling of theirs cannot silently fail open on a bad scope (#2871 Phase 2
|
|
692
|
+
* review finding). `scopes: []` is untouched — an empty array has no
|
|
693
|
+
* entries to validate and still resolves to `[]`.
|
|
694
|
+
*/
|
|
695
|
+
function resolveTriggerSurface(runtime, scopes, opts) {
|
|
696
|
+
const registry = opts.registry ?? getTriggerRegistry();
|
|
697
|
+
const runtimeDescriptor = registry.runtimes[runtime]?.runtime;
|
|
698
|
+
const layout = runtimeDescriptor?.artifactLayout;
|
|
699
|
+
if (!layout) {
|
|
700
|
+
throw new TypeError(`Unknown runtime: '${runtime}' — add to runtime-artifact-layout.cjs table`);
|
|
701
|
+
}
|
|
702
|
+
for (const scope of scopes) {
|
|
703
|
+
(0, install_scope_cjs_1.validateScopeId)(scope, 'resolveTriggerSurface');
|
|
704
|
+
}
|
|
705
|
+
const scopeSet = new Set(scopes);
|
|
706
|
+
const stems = opts.stems ?? [];
|
|
707
|
+
const routerStemSet = new Set(opts.routerStems ?? []);
|
|
708
|
+
const childToRouters = opts.childToRouters ?? {};
|
|
709
|
+
const precedence = runtimeDescriptor?.triggerPrecedence ?? getDefaultTriggerPrecedence();
|
|
710
|
+
const precedenceRank = new Map(precedence.map((kind, index) => [kind, index]));
|
|
711
|
+
const surfaces = [];
|
|
712
|
+
for (const scope of install_scope_cjs_1.SCOPE_ORDER) {
|
|
713
|
+
if (!scopeSet.has(scope))
|
|
714
|
+
continue;
|
|
715
|
+
const entries = layout[scope] ?? [];
|
|
716
|
+
for (const entry of entries) {
|
|
717
|
+
if (entry.kind !== 'commands' && entry.kind !== 'skills')
|
|
718
|
+
continue; // excludes agents/kimi-agents
|
|
719
|
+
const kind = entry.kind;
|
|
720
|
+
const destSubpath = (0, shell_command_projection_cjs_1.posixNormalize)(entry.destSubpath);
|
|
721
|
+
const namespacedByDir = isNamespacedByDir(kind, entry.destSubpath, entry.prefix);
|
|
722
|
+
const nested = entry.nesting === 'nested';
|
|
723
|
+
for (const stem of stems) {
|
|
724
|
+
const trigger = `${entry.prefix}${stem}`;
|
|
725
|
+
let destPath;
|
|
726
|
+
if (kind === 'skills') {
|
|
727
|
+
destPath = `${destSubpath}/${entry.prefix}${stem}`;
|
|
728
|
+
}
|
|
729
|
+
else {
|
|
730
|
+
destPath = `${destSubpath}/${composeCommandFilename(namespacedByDir, entry.prefix, stem)}`;
|
|
731
|
+
}
|
|
732
|
+
let registration = 'direct';
|
|
733
|
+
let routerTrigger = null;
|
|
734
|
+
if (nested && routerStemSet.size > 0 && !routerStemSet.has(stem)) {
|
|
735
|
+
const owningRouters = childToRouters[stem];
|
|
736
|
+
const routerStem = owningRouters && owningRouters.length > 0 ? owningRouters[0] : undefined;
|
|
737
|
+
if (routerStem !== undefined && routerStemSet.has(routerStem)) {
|
|
738
|
+
registration = 'via-router';
|
|
739
|
+
routerTrigger = `${entry.prefix}${routerStem}`;
|
|
740
|
+
}
|
|
741
|
+
}
|
|
742
|
+
surfaces.push({ trigger, kind, scope, destPath, registration, routerTrigger, shadowedBy: null });
|
|
743
|
+
}
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
// Winner computation, per trigger string, across every scope/kind candidate.
|
|
747
|
+
const groups = new Map();
|
|
748
|
+
for (const surface of surfaces) {
|
|
749
|
+
const group = groups.get(surface.trigger);
|
|
750
|
+
if (group) {
|
|
751
|
+
group.push(surface);
|
|
752
|
+
}
|
|
753
|
+
else {
|
|
754
|
+
groups.set(surface.trigger, [surface]);
|
|
755
|
+
}
|
|
756
|
+
}
|
|
757
|
+
for (const group of groups.values()) {
|
|
758
|
+
if (group.length <= 1)
|
|
759
|
+
continue; // sole candidate: unshadowed by construction
|
|
760
|
+
let winner = group[0];
|
|
761
|
+
for (let i = 1; i < group.length; i++) {
|
|
762
|
+
const candidate = group[i];
|
|
763
|
+
if (isHigherPriority(candidate, winner, precedenceRank))
|
|
764
|
+
winner = candidate;
|
|
765
|
+
}
|
|
766
|
+
for (const surface of group) {
|
|
767
|
+
if (surface !== winner) {
|
|
768
|
+
surface.shadowedBy = { kind: winner.kind, scope: winner.scope };
|
|
769
|
+
}
|
|
770
|
+
}
|
|
771
|
+
}
|
|
772
|
+
return surfaces;
|
|
773
|
+
}
|
|
774
|
+
module.exports = { resolveRuntimeArtifactLayout, resolveRuntimeArtifactLayoutFromRegistry, findInstallSourceRoot, resolveTriggerSurface, isNamespacedByDir, composeCommandFilename };
|