@opengsd/gsd-core 1.12.0 → 1.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/.opencode/plugins/gsd-core.js +12 -0
- package/agents/gsd-executor.md +63 -35
- package/agents/gsd-plan-checker.md +76 -57
- package/agents/gsd-planner.md +14 -0
- package/agents/gsd-ui-checker.md +19 -3
- package/agents/gsd-ui-researcher.md +29 -0
- package/agents/gsd-verifier.md +23 -1
- package/bin/install.js +239 -67
- package/commands/gsd/execute-phase.md +1 -1
- package/commands/gsd/ns-workflow.md +2 -1
- package/commands/gsd/phase.md +1 -1
- package/commands/gsd/quick-batch.md +105 -0
- package/commands/gsd/surface.md +18 -8
- package/gsd-core/bin/gsd-tools.cjs +195 -50
- package/gsd-core/bin/lib/capability-activation.cjs +27 -0
- package/gsd-core/bin/lib/capability-registry.cjs +514 -114
- package/gsd-core/bin/lib/capability-state.cjs +7 -1
- package/gsd-core/bin/lib/capability-validator.cjs +120 -4
- package/gsd-core/bin/lib/capability-writer.cjs +14 -4
- package/gsd-core/bin/lib/check-command-router.cjs +85 -2
- package/gsd-core/bin/lib/claude-orchestration.cjs +10 -25
- package/gsd-core/bin/lib/clusters.cjs +1 -0
- package/gsd-core/bin/lib/command-aliases.cjs +16 -0
- package/gsd-core/bin/lib/commands.cjs +337 -13
- package/gsd-core/bin/lib/config-loader.cjs +3 -0
- package/gsd-core/bin/lib/core-utils.cjs +34 -7
- package/gsd-core/bin/lib/decisions.cjs +213 -1
- package/gsd-core/bin/lib/edge-probe.cjs +14 -1
- package/gsd-core/bin/lib/file-overlap-partitioner.cjs +74 -0
- package/gsd-core/bin/lib/frontmatter.cjs +137 -23
- package/gsd-core/bin/lib/gap-checker.cjs +22 -13
- package/gsd-core/bin/lib/git-base-branch.cjs +10 -2
- package/gsd-core/bin/lib/health-diagnostic-rules/phase-structure.cjs +8 -2
- package/gsd-core/bin/lib/health-diagnostic-rules/roadmap-disk-consistency.cjs +54 -11
- package/gsd-core/bin/lib/health-diagnostic-rules/state-consistency.cjs +75 -22
- package/gsd-core/bin/lib/host-integration.cjs +57 -5
- package/gsd-core/bin/lib/init-command-router.cjs +14 -0
- package/gsd-core/bin/lib/init.cjs +132 -15
- package/gsd-core/bin/lib/install-engine.cjs +184 -12
- package/gsd-core/bin/lib/install-model-override-resolver.cjs +45 -0
- package/gsd-core/bin/lib/install-profiles.cjs +22 -14
- package/gsd-core/bin/lib/installer-migration-report.cjs +1 -0
- package/gsd-core/bin/lib/io.cjs +35 -0
- package/gsd-core/bin/lib/loop-resolver.cjs +14 -8
- package/gsd-core/bin/lib/markdown-table.cjs +123 -0
- package/gsd-core/bin/lib/milestone.cjs +22 -2
- package/gsd-core/bin/lib/phase-command-router.cjs +13 -6
- package/gsd-core/bin/lib/phase-id.cjs +251 -9
- package/gsd-core/bin/lib/phase.cjs +774 -35
- package/gsd-core/bin/lib/plan-document.cjs +10 -0
- package/gsd-core/bin/lib/planning-snapshot.cjs +147 -20
- package/gsd-core/bin/lib/planning-workspace.cjs +103 -28
- package/gsd-core/bin/lib/quick-batch-command-router.cjs +285 -0
- package/gsd-core/bin/lib/quick-batch-dispatch.cjs +250 -0
- package/gsd-core/bin/lib/quick-batch.cjs +840 -0
- package/gsd-core/bin/lib/review-lane-descriptor.cjs +53 -5
- package/gsd-core/bin/lib/review-lane-invocation.cjs +73 -1
- package/gsd-core/bin/lib/review-lane-runner.cjs +136 -10
- package/gsd-core/bin/lib/roadmap-parser.cjs +499 -26
- package/gsd-core/bin/lib/roadmap.cjs +187 -58
- package/gsd-core/bin/lib/runtime-artifact-conversion.cjs +233 -33
- package/gsd-core/bin/lib/runtime-artifact-install-plan.cjs +16 -17
- package/gsd-core/bin/lib/runtime-artifact-layout.cjs +286 -108
- package/gsd-core/bin/lib/runtime-hooks-surface.cjs +215 -43
- package/gsd-core/bin/lib/shell-command-projection.cjs +4 -0
- package/gsd-core/bin/lib/smart-entry.cjs +7 -9
- package/gsd-core/bin/lib/state-document.cjs +30 -5
- package/gsd-core/bin/lib/state-md-schema.cjs +23 -13
- package/gsd-core/bin/lib/state-transition.cjs +333 -44
- package/gsd-core/bin/lib/state.cjs +684 -125
- package/gsd-core/bin/lib/surface.cjs +23 -8
- package/gsd-core/bin/lib/tdd-red-evidence.cjs +133 -0
- package/gsd-core/bin/lib/uat.cjs +1419 -515
- package/gsd-core/bin/lib/update-context.cjs +6 -2
- package/gsd-core/bin/lib/validate.cjs +230 -12
- package/gsd-core/bin/lib/verification-command-router.cjs +2 -1
- package/gsd-core/bin/lib/verification.cjs +273 -12
- package/gsd-core/bin/lib/verify-command-router.cjs +1 -0
- package/gsd-core/bin/lib/verify.cjs +346 -16
- package/gsd-core/bin/lib/workstream-inventory.cjs +20 -2
- package/gsd-core/bin/lib/worktree-safety.cjs +8 -0
- package/gsd-core/bin/shared/config-schema.manifest.json +8 -0
- package/gsd-core/bin/verify-reapply-patches.cjs +70 -3
- package/gsd-core/references/agent-contracts.md +3 -3
- package/gsd-core/references/edge-probe.md +17 -13
- package/gsd-core/references/execute-mvp-tdd.md +18 -16
- package/gsd-core/references/execute-phase-response-language.md +6 -0
- package/gsd-core/references/executor-examples.md +42 -0
- package/gsd-core/references/few-shot-examples/plan-checker.md +15 -15
- package/gsd-core/references/mvp-concepts.md +2 -2
- package/gsd-core/references/plan-checker-examples.md +41 -0
- package/gsd-core/references/planner-antipatterns.md +25 -0
- package/gsd-core/references/planner-chunked.md +5 -1
- package/gsd-core/references/planner-coupling.md +42 -0
- package/gsd-core/references/planner-quick-batch.md +71 -0
- package/gsd-core/references/planner-reviews.md +47 -0
- package/gsd-core/references/planner-revision.md +75 -2
- package/gsd-core/references/planning-config.md +2 -1
- package/gsd-core/references/response-language-directive.md +9 -0
- package/gsd-core/references/revision-loop.md +118 -11
- package/gsd-core/references/tdd.md +14 -9
- package/gsd-core/references/verifier-evidence-gate.md +160 -0
- package/gsd-core/templates/phase-prompt.md +4 -0
- package/gsd-core/templates/verification-report.md +5 -0
- package/gsd-core/workflows/add-backlog.md +2 -0
- package/gsd-core/workflows/add-phase.md +2 -0
- package/gsd-core/workflows/add-tests.md +1 -1
- package/gsd-core/workflows/add-todo.md +1 -1
- package/gsd-core/workflows/ai-integration-phase.md +1 -1
- package/gsd-core/workflows/analyze-dependencies.md +2 -0
- package/gsd-core/workflows/audit-fix.md +2 -0
- package/gsd-core/workflows/audit-milestone.md +2 -0
- package/gsd-core/workflows/audit-uat.md +2 -0
- package/gsd-core/workflows/autonomous.md +2 -0
- package/gsd-core/workflows/check-todos.md +1 -1
- package/gsd-core/workflows/cleanup.md +1 -1
- package/gsd-core/workflows/code-review/steps/structural-pre-pass.md +15 -13
- package/gsd-core/workflows/code-review-fix.md +2 -0
- package/gsd-core/workflows/code-review.md +73 -31
- package/gsd-core/workflows/complete-milestone.md +13 -4
- package/gsd-core/workflows/debug.md +1 -1
- package/gsd-core/workflows/diagnose-issues.md +5 -1
- package/gsd-core/workflows/discuss-phase/modes/advisor.md +2 -0
- package/gsd-core/workflows/discuss-phase/modes/all.md +2 -0
- package/gsd-core/workflows/discuss-phase/modes/analyze.md +2 -0
- package/gsd-core/workflows/discuss-phase/modes/auto.md +2 -0
- package/gsd-core/workflows/discuss-phase/modes/batch.md +2 -0
- package/gsd-core/workflows/discuss-phase/modes/chain.md +2 -0
- package/gsd-core/workflows/discuss-phase/modes/default.md +2 -0
- package/gsd-core/workflows/discuss-phase/modes/power.md +2 -0
- package/gsd-core/workflows/discuss-phase/modes/text.md +2 -0
- package/gsd-core/workflows/discuss-phase/templates/context.md +2 -0
- package/gsd-core/workflows/discuss-phase/templates/discussion-log.md +2 -0
- package/gsd-core/workflows/discuss-phase-assumptions.md +1 -1
- package/gsd-core/workflows/discuss-phase-power.md +2 -0
- package/gsd-core/workflows/discuss-phase.md +1 -1
- package/gsd-core/workflows/do.md +43 -13
- package/gsd-core/workflows/docs-update.md +1 -1
- package/gsd-core/workflows/edit-phase.md +2 -0
- package/gsd-core/workflows/eval-review.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/codebase-drift-gate.md +2 -0
- package/gsd-core/workflows/execute-phase/steps/executor-isolation-dispatch.md +17 -1
- package/gsd-core/workflows/execute-phase/steps/per-plan-worktree-gate.md +8 -2
- package/gsd-core/workflows/execute-phase/steps/regression-gate-run.md +2 -0
- package/gsd-core/workflows/execute-phase/steps/tdd-applicability-resolution.md +25 -0
- package/gsd-core/workflows/execute-phase/steps/worktree-recovery-policy.md +2 -0
- package/gsd-core/workflows/execute-phase.md +32 -14
- package/gsd-core/workflows/execute-plan.md +8 -8
- package/gsd-core/workflows/explore.md +2 -0
- package/gsd-core/workflows/extract-learnings.md +2 -0
- package/gsd-core/workflows/fast.md +6 -0
- package/gsd-core/workflows/forensics.md +2 -0
- package/gsd-core/workflows/graduation.md +1 -1
- package/gsd-core/workflows/health.md +1 -1
- package/gsd-core/workflows/help/modes/brief.md +2 -0
- package/gsd-core/workflows/help/modes/default.md +2 -0
- package/gsd-core/workflows/help/modes/full.md +12 -0
- package/gsd-core/workflows/help/modes/topic.md +2 -0
- package/gsd-core/workflows/help.md +2 -0
- package/gsd-core/workflows/import.md +3 -3
- package/gsd-core/workflows/inbox.md +1 -1
- package/gsd-core/workflows/ingest-docs.md +1 -1
- package/gsd-core/workflows/insert-phase.md +2 -0
- package/gsd-core/workflows/list-phase-assumptions.md +2 -0
- package/gsd-core/workflows/list-seeds.md +2 -0
- package/gsd-core/workflows/list-workspaces.md +2 -0
- package/gsd-core/workflows/manager.md +3 -3
- package/gsd-core/workflows/map-codebase.md +2 -0
- package/gsd-core/workflows/milestone-summary.md +2 -0
- package/gsd-core/workflows/mvp-phase.md +1 -1
- package/gsd-core/workflows/new-milestone.md +1 -1
- package/gsd-core/workflows/new-project.md +5 -3
- package/gsd-core/workflows/new-workspace.md +1 -1
- package/gsd-core/workflows/next.md +2 -0
- package/gsd-core/workflows/node-repair.md +2 -0
- package/gsd-core/workflows/note.md +2 -0
- package/gsd-core/workflows/onboard.md +1 -1
- package/gsd-core/workflows/pause-work.md +19 -4
- package/gsd-core/workflows/plan-phase/steps/chunked-planning-mode.md +100 -18
- package/gsd-core/workflows/plan-phase/steps/prd-express-path.md +2 -0
- package/gsd-core/workflows/plan-phase/steps/stall-detection-helpers.md +9 -0
- package/gsd-core/workflows/plan-phase.md +130 -12
- package/gsd-core/workflows/plan-review-convergence.md +102 -10
- package/gsd-core/workflows/plant-seed.md +1 -1
- package/gsd-core/workflows/pr-branch.md +11 -3
- package/gsd-core/workflows/profile-user.md +1 -1
- package/gsd-core/workflows/progress/steps/forensic-audit.md +1 -1
- package/gsd-core/workflows/progress.md +25 -3
- package/gsd-core/workflows/quick/steps/plan-checker-loop.md +37 -2
- package/gsd-core/workflows/quick/steps/research-phase.md +3 -3
- package/gsd-core/workflows/quick-batch/steps/batch-init.md +55 -0
- package/gsd-core/workflows/quick-batch/steps/completion.md +65 -0
- package/gsd-core/workflows/quick-batch/steps/merge-wave.md +100 -0
- package/gsd-core/workflows/quick-batch/steps/plan-checker-loop.md +147 -0
- package/gsd-core/workflows/quick-batch/steps/planner-wave.md +158 -0
- package/gsd-core/workflows/quick-batch/steps/research-phase.md +95 -0
- package/gsd-core/workflows/quick-batch/steps/resume-mode.md +49 -0
- package/gsd-core/workflows/quick-batch/steps/verification-wave.md +73 -0
- package/gsd-core/workflows/quick-batch/steps/worktree-dispatch.md +169 -0
- package/gsd-core/workflows/quick-batch.md +203 -0
- package/gsd-core/workflows/quick.md +13 -3
- package/gsd-core/workflows/reapply-patches.md +2 -0
- package/gsd-core/workflows/remove-phase.md +2 -0
- package/gsd-core/workflows/remove-workspace.md +1 -1
- package/gsd-core/workflows/resume-project.md +6 -2
- package/gsd-core/workflows/review.md +215 -10
- package/gsd-core/workflows/scan.md +2 -0
- package/gsd-core/workflows/section-manifest.json +12 -0
- package/gsd-core/workflows/secure-phase.md +1 -1
- package/gsd-core/workflows/session-report.md +2 -0
- package/gsd-core/workflows/settings-advanced.md +2 -0
- package/gsd-core/workflows/settings-integrations.md +9 -8
- package/gsd-core/workflows/settings.md +1 -1
- package/gsd-core/workflows/ship.md +10 -10
- package/gsd-core/workflows/sketch-wrap-up.md +2 -0
- package/gsd-core/workflows/sketch.md +1 -1
- package/gsd-core/workflows/smart-entry.md +1 -1
- package/gsd-core/workflows/spec-phase.md +24 -19
- package/gsd-core/workflows/spike-wrap-up.md +2 -0
- package/gsd-core/workflows/spike.md +1 -1
- package/gsd-core/workflows/stats.md +2 -0
- package/gsd-core/workflows/sync-skills.md +12 -4
- package/gsd-core/workflows/thread.md +2 -0
- package/gsd-core/workflows/transition.md +2 -0
- package/gsd-core/workflows/ui-phase.md +26 -5
- package/gsd-core/workflows/ui-review.md +1 -1
- package/gsd-core/workflows/ultraplan-phase.md +2 -0
- package/gsd-core/workflows/undo.md +1 -1
- package/gsd-core/workflows/update.md +41 -38
- package/gsd-core/workflows/validate-phase.md +1 -1
- package/gsd-core/workflows/verify-work.md +49 -3
- package/hooks/dist/gsd-check-update-worker.js +19 -2
- package/hooks/dist/gsd-context-monitor.js +283 -12
- package/hooks/dist/gsd-node-runner.sh +1 -0
- package/hooks/dist/gsd-prompt-guard.js +30 -5
- package/hooks/dist/gsd-read-guard.js +2 -0
- package/hooks/dist/gsd-read-injection-scanner.js +5 -5
- package/hooks/dist/gsd-secret-read-guard.js +1079 -0
- package/hooks/dist/gsd-statusline.js +7 -3
- package/hooks/dist/gsd-validate-commit.sh +444 -7
- package/hooks/dist/gsd-workflow-guard.js +2 -1
- package/hooks/dist/lib/git-cmd.js +210 -1
- package/hooks/dist/lib/injection-patterns.js +36 -6
- package/hooks/dist/managed-hooks-registry.cjs +1 -0
- package/hooks/gsd-check-update-worker.js +19 -2
- package/hooks/gsd-context-monitor.js +283 -12
- package/hooks/gsd-node-runner.sh +1 -0
- package/hooks/gsd-prompt-guard.js +30 -5
- package/hooks/gsd-read-guard.js +2 -0
- package/hooks/gsd-read-injection-scanner.js +5 -5
- package/hooks/gsd-secret-read-guard.js +1079 -0
- package/hooks/gsd-statusline.js +7 -3
- package/hooks/gsd-validate-commit.sh +444 -7
- package/hooks/gsd-workflow-guard.js +2 -1
- package/hooks/hooks.json +6 -0
- package/hooks/lib/git-cmd.js +210 -1
- package/hooks/lib/injection-patterns.js +36 -6
- package/hooks/managed-hooks-registry.cjs +1 -0
- package/package.json +5 -5
- package/scripts/build-hooks.js +11 -4
- package/scripts/ci-test-scope.cjs +7 -0
- package/scripts/docs-guard-registry.cjs +10 -0
- package/scripts/gen-loop-host-contract.cjs +67 -15
- package/scripts/lib/shellcheck-fetch.cjs +247 -0
- package/scripts/lint-allow-test-rule-refs.allowlist.json +0 -6
- package/scripts/lint-allow-test-rule-refs.effective-ceiling.json +1 -1
- package/scripts/lint-allow-test-rule-refs.unverified-ceiling.json +1 -1
- package/scripts/lint-docs-guard-registration.exempt-baseline.cjs +5 -0
- package/scripts/lint-phase-enumeration-drift.cjs +24 -6
- package/scripts/lint-phase-id-drift.cjs +133 -8
- package/scripts/lint-portable-grep.cjs +176 -0
- package/scripts/lint-response-language-coverage.cjs +524 -0
- package/scripts/lint-test-file-count.allowlist.json +3 -1
- package/scripts/lint-workflow-shellcheck-baseline.json +1027 -0
- package/scripts/lint-workflow-shellcheck.cjs +614 -0
- package/scripts/npm-audit-baseline.cjs +376 -0
- package/scripts/prompt-injection-scan.sh +8 -0
- package/scripts/require-issue-link-policy.cjs +16 -1
- package/skills/gsd-execute-phase/SKILL.md +1 -1
- package/skills/gsd-ns-workflow/SKILL.md +1 -0
- package/skills/gsd-phase/SKILL.md +1 -1
- package/skills/gsd-quick-batch/SKILL.md +105 -0
- package/skills/gsd-surface/SKILL.md +18 -8
- package/vscode/package.json +1 -1
|
@@ -25,6 +25,10 @@ const node_os_1 = __importDefault(require("node:os"));
|
|
|
25
25
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
26
26
|
const installFsAdapter = require("./install-fs-adapter.cjs");
|
|
27
27
|
const { installFs, mkInstallTempDir } = installFsAdapter;
|
|
28
|
+
// Reuse the install manifest's existing parser and streamed SHA-256
|
|
29
|
+
// classification instead of deriving a second integrity implementation here.
|
|
30
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
31
|
+
const installerMigrations = require("./installer-migrations.cjs");
|
|
28
32
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
29
33
|
const installProfiles = require("./install-profiles.cjs");
|
|
30
34
|
const { stageSkillsForProfile, stageAgentsForRuntimeWithConverter, stageSkillsForRuntimeAsSkills, stageCommandsForRuntimeFlat, } = installProfiles;
|
|
@@ -48,127 +52,288 @@ const shell_command_projection_cjs_1 = require("./shell-command-projection.cjs")
|
|
|
48
52
|
const install_scope_cjs_1 = require("./install-scope.cjs");
|
|
49
53
|
// In .cts (CommonJS output) files, `require` is available as a global.
|
|
50
54
|
const _require = require;
|
|
55
|
+
function requiredRuntimeSurfaceSourceClasses(kinds) {
|
|
56
|
+
const required = new Set();
|
|
57
|
+
for (const kind of kinds) {
|
|
58
|
+
if (kind.kind === 'commands' || kind.kind === 'skills')
|
|
59
|
+
required.add('commands');
|
|
60
|
+
if (kind.kind === 'agents' || kind.kind === 'kimi-agents')
|
|
61
|
+
required.add('agents');
|
|
62
|
+
}
|
|
63
|
+
return required;
|
|
64
|
+
}
|
|
51
65
|
// ---------------------------------------------------------------------------
|
|
52
66
|
// Source root finders
|
|
53
67
|
// ---------------------------------------------------------------------------
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
68
|
+
function isReadableDirectory(candidate, routed) {
|
|
69
|
+
try {
|
|
70
|
+
const io = routed ? installFs() : node_fs_1.default;
|
|
71
|
+
const stat = io.lstatSync(candidate);
|
|
72
|
+
if (!stat.isDirectory() || stat.isSymbolicLink())
|
|
73
|
+
return false;
|
|
74
|
+
const entries = io.readdirSync(candidate);
|
|
75
|
+
let readableFiles = 0;
|
|
76
|
+
for (const name of entries) {
|
|
77
|
+
const child = node_path_1.default.join(candidate, name);
|
|
78
|
+
const childStat = io.lstatSync(child);
|
|
79
|
+
if (childStat.isSymbolicLink())
|
|
80
|
+
return false;
|
|
81
|
+
if (childStat.isDirectory()) {
|
|
82
|
+
if (!isReadableDirectory(child, routed))
|
|
83
|
+
return false;
|
|
84
|
+
readableFiles += 1;
|
|
85
|
+
}
|
|
86
|
+
else if (childStat.isFile()) {
|
|
87
|
+
if (routed)
|
|
88
|
+
io.readFileSync(child);
|
|
89
|
+
else
|
|
90
|
+
node_fs_1.default.accessSync(child, node_fs_1.default.constants.R_OK);
|
|
91
|
+
readableFiles += 1;
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
return false;
|
|
73
95
|
}
|
|
74
|
-
catch { /* fall through */ }
|
|
75
96
|
}
|
|
97
|
+
return readableFiles > 0;
|
|
76
98
|
}
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
//
|
|
93
|
-
//
|
|
94
|
-
//
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
const
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
99
|
+
catch {
|
|
100
|
+
return false;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
function isPhysicallyConfinedTo(root, candidate) {
|
|
104
|
+
try {
|
|
105
|
+
const physicalRoot = installFs().realpathSync(root);
|
|
106
|
+
const physicalCandidate = installFs().realpathSync(candidate);
|
|
107
|
+
return physicalCandidate === physicalRoot || physicalCandidate.startsWith(physicalRoot + node_path_1.default.sep);
|
|
108
|
+
}
|
|
109
|
+
catch {
|
|
110
|
+
return false;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
function installedManifestIsComplete(runtimeConfigDir, required) {
|
|
114
|
+
// This synchronous admission check binds provider selection to the corpus
|
|
115
|
+
// observed here. Same-user mutation after resolution is outside #4132's
|
|
116
|
+
// threat model and would require a broader snapshot/transaction design.
|
|
117
|
+
const io = installFs();
|
|
118
|
+
const manifestPath = node_path_1.default.join(runtimeConfigDir, 'gsd-file-manifest.json');
|
|
119
|
+
if (!io.existsSync(manifestPath))
|
|
120
|
+
return false;
|
|
121
|
+
if (!isPhysicallyConfinedTo(runtimeConfigDir, manifestPath))
|
|
122
|
+
return false;
|
|
123
|
+
try {
|
|
124
|
+
const manifest = installerMigrations.readInstallManifest(runtimeConfigDir);
|
|
125
|
+
if (manifest.manifestVersion === null)
|
|
126
|
+
return false;
|
|
127
|
+
const keys = Object.keys(manifest.files);
|
|
128
|
+
const prefixes = [];
|
|
129
|
+
if (required.has('commands'))
|
|
130
|
+
prefixes.push('gsd-core/commands/gsd/');
|
|
131
|
+
if (required.has('agents'))
|
|
132
|
+
prefixes.push('gsd-core/agents/');
|
|
133
|
+
for (const prefix of prefixes) {
|
|
134
|
+
const expected = keys.filter((key) => key.startsWith(prefix));
|
|
135
|
+
if (expected.length === 0)
|
|
136
|
+
return false;
|
|
137
|
+
const expectedSet = new Set(expected);
|
|
138
|
+
const corpusRoot = node_path_1.default.resolve(runtimeConfigDir, ...prefix.slice(0, -1).split('/'));
|
|
139
|
+
if (!isPhysicallyConfinedTo(runtimeConfigDir, corpusRoot))
|
|
140
|
+
return false;
|
|
141
|
+
let actualFiles = 0;
|
|
142
|
+
const visit = (dir) => {
|
|
143
|
+
for (const name of io.readdirSync(dir)) {
|
|
144
|
+
const candidate = node_path_1.default.join(dir, name);
|
|
145
|
+
const stat = io.lstatSync(candidate);
|
|
146
|
+
if (stat.isSymbolicLink())
|
|
147
|
+
return false;
|
|
148
|
+
if (stat.isDirectory()) {
|
|
149
|
+
if (!visit(candidate))
|
|
150
|
+
return false;
|
|
151
|
+
}
|
|
152
|
+
else if (stat.isFile()) {
|
|
153
|
+
const relative = node_path_1.default.relative(corpusRoot, candidate).split(node_path_1.default.sep).join('/');
|
|
154
|
+
if (!expectedSet.has(prefix + relative))
|
|
155
|
+
return false;
|
|
156
|
+
actualFiles += 1;
|
|
157
|
+
}
|
|
158
|
+
else {
|
|
159
|
+
return false;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
return true;
|
|
163
|
+
};
|
|
164
|
+
if (!visit(corpusRoot) || actualFiles !== expected.length)
|
|
165
|
+
return false;
|
|
166
|
+
for (const key of expected) {
|
|
167
|
+
const parts = key.split('/');
|
|
168
|
+
if (parts.some((part) => part === '' || part === '.' || part === '..'))
|
|
169
|
+
return false;
|
|
170
|
+
const candidate = node_path_1.default.resolve(runtimeConfigDir, ...parts);
|
|
171
|
+
const root = node_path_1.default.resolve(runtimeConfigDir);
|
|
172
|
+
if (!candidate.startsWith(root + node_path_1.default.sep))
|
|
173
|
+
return false;
|
|
174
|
+
const stat = io.lstatSync(candidate);
|
|
175
|
+
if (!stat.isFile() || stat.isSymbolicLink())
|
|
176
|
+
return false;
|
|
177
|
+
if (installerMigrations.classifyArtifact(runtimeConfigDir, key, manifest).classification !== 'managed-pristine') {
|
|
178
|
+
return false;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
106
181
|
}
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
dir = parent;
|
|
182
|
+
return true;
|
|
183
|
+
}
|
|
184
|
+
catch {
|
|
185
|
+
return false;
|
|
112
186
|
}
|
|
113
|
-
throw new Error(`findInstallSourceRoot: could not locate commands/gsd from ${__dirname}`);
|
|
114
187
|
}
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
const
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
188
|
+
function providerHasRequiredClasses(provider, required, routed, runtimeConfigDir) {
|
|
189
|
+
if (provider.kind === 'installed' && runtimeConfigDir) {
|
|
190
|
+
return installedManifestIsComplete(runtimeConfigDir, required);
|
|
191
|
+
}
|
|
192
|
+
return (!required.has('commands') || isReadableDirectory(provider.commandsRoot, routed)) &&
|
|
193
|
+
(!required.has('agents') || isReadableDirectory(provider.agentsRoot, routed));
|
|
194
|
+
}
|
|
195
|
+
function providersShareRequiredRoots(left, right, required) {
|
|
196
|
+
const leftFs = left.kind === 'package' ? node_fs_1.default : installFs();
|
|
197
|
+
const rightFs = right.kind === 'package' ? node_fs_1.default : installFs();
|
|
198
|
+
const physicalRootsOverlap = (leftRoot, rightRoot) => {
|
|
199
|
+
const canonicalize = (io, root) => {
|
|
200
|
+
let existing = node_path_1.default.resolve(root);
|
|
201
|
+
const missingSegments = [];
|
|
202
|
+
while (true) {
|
|
203
|
+
try {
|
|
204
|
+
return node_path_1.default.resolve(io.realpathSync(existing), ...missingSegments);
|
|
205
|
+
}
|
|
206
|
+
catch (error) {
|
|
207
|
+
if (error.code !== 'ENOENT')
|
|
208
|
+
return null;
|
|
209
|
+
const parent = node_path_1.default.dirname(existing);
|
|
210
|
+
if (parent === existing)
|
|
211
|
+
return null;
|
|
212
|
+
missingSegments.unshift(node_path_1.default.basename(existing));
|
|
213
|
+
existing = parent;
|
|
135
214
|
}
|
|
136
215
|
}
|
|
137
|
-
|
|
216
|
+
};
|
|
217
|
+
const overlap = (leftPath, rightPath) => {
|
|
218
|
+
const relative = node_path_1.default.relative(leftPath, rightPath);
|
|
219
|
+
return relative === '' ||
|
|
220
|
+
(relative !== '..' && !relative.startsWith(`..${node_path_1.default.sep}`) && !node_path_1.default.isAbsolute(relative));
|
|
221
|
+
};
|
|
222
|
+
const physicalLeft = canonicalize(leftFs, leftRoot);
|
|
223
|
+
const physicalRight = canonicalize(rightFs, rightRoot);
|
|
224
|
+
if (!physicalLeft || !physicalRight)
|
|
225
|
+
return true;
|
|
226
|
+
return overlap(physicalLeft, physicalRight) || overlap(physicalRight, physicalLeft);
|
|
227
|
+
};
|
|
228
|
+
return (required.has('commands') && physicalRootsOverlap(left.commandsRoot, right.commandsRoot)) ||
|
|
229
|
+
(required.has('agents') && physicalRootsOverlap(left.agentsRoot, right.agentsRoot));
|
|
230
|
+
}
|
|
231
|
+
function markerProvider(runtimeConfigDir) {
|
|
232
|
+
const markerPath = node_path_1.default.join(runtimeConfigDir, '.gsd-source');
|
|
233
|
+
try {
|
|
234
|
+
if (!installFs().existsSync(markerPath))
|
|
235
|
+
return null;
|
|
236
|
+
const markerStat = installFs().lstatSync(markerPath);
|
|
237
|
+
if (!markerStat.isFile() || markerStat.isSymbolicLink())
|
|
238
|
+
return null;
|
|
239
|
+
const commandsRoot = installFs().readFileSync(markerPath, 'utf8').trim();
|
|
240
|
+
if (!commandsRoot)
|
|
241
|
+
return null;
|
|
242
|
+
// A marker written by the installer may point at this process's executing
|
|
243
|
+
// package. Preserve package-source IO on real fs so the existing injected
|
|
244
|
+
// destination adapter remains destination-only (#2874).
|
|
245
|
+
const packaged = packageProvider(new Set(['commands']));
|
|
246
|
+
if (packaged && node_path_1.default.resolve(commandsRoot) === node_path_1.default.resolve(packaged.commandsRoot)) {
|
|
247
|
+
return packaged;
|
|
138
248
|
}
|
|
249
|
+
return {
|
|
250
|
+
kind: 'marker',
|
|
251
|
+
commandsRoot,
|
|
252
|
+
agentsRoot: node_path_1.default.resolve(node_path_1.default.dirname(commandsRoot), '..', 'agents'),
|
|
253
|
+
};
|
|
139
254
|
}
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
255
|
+
catch {
|
|
256
|
+
return null;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
function packageProvider(required) {
|
|
260
|
+
// Package-source IO deliberately stays on real fs; injected install adapters
|
|
261
|
+
// model destinations, not the executing package tree (#2874).
|
|
145
262
|
let dir = __dirname;
|
|
146
263
|
for (let i = 0; i < 6; i++) {
|
|
147
|
-
const candidate =
|
|
148
|
-
|
|
149
|
-
|
|
264
|
+
const candidate = {
|
|
265
|
+
kind: 'package',
|
|
266
|
+
commandsRoot: node_path_1.default.join(dir, 'commands', 'gsd'),
|
|
267
|
+
agentsRoot: node_path_1.default.join(dir, 'agents'),
|
|
268
|
+
};
|
|
269
|
+
if (providerHasRequiredClasses(candidate, required, false))
|
|
150
270
|
return candidate;
|
|
151
|
-
}
|
|
152
|
-
catch { /* not here — keep walking up */ }
|
|
153
271
|
const parent = node_path_1.default.dirname(dir);
|
|
154
272
|
if (parent === dir)
|
|
155
273
|
break;
|
|
156
274
|
dir = parent;
|
|
157
275
|
}
|
|
158
|
-
|
|
276
|
+
return null;
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
279
|
+
* Select one complete source provider for an entire resolved layout.
|
|
280
|
+
* Provider mixing is forbidden: a skills+agents layout cannot take commands
|
|
281
|
+
* from one package version and agents from another.
|
|
282
|
+
*/
|
|
283
|
+
function resolveSourceProvider(runtimeConfigDir, requiredClasses, scope = 'global', authority = 'compatible') {
|
|
284
|
+
const required = new Set(requiredClasses);
|
|
285
|
+
let rejectedInstalled = null;
|
|
286
|
+
if (required.size === 0) {
|
|
287
|
+
return { kind: 'package', commandsRoot: '', agentsRoot: '' };
|
|
288
|
+
}
|
|
289
|
+
if (runtimeConfigDir && scope === 'global') {
|
|
290
|
+
const installed = {
|
|
291
|
+
kind: 'installed',
|
|
292
|
+
commandsRoot: node_path_1.default.join(runtimeConfigDir, 'gsd-core', 'commands', 'gsd'),
|
|
293
|
+
agentsRoot: node_path_1.default.join(runtimeConfigDir, 'gsd-core', 'agents'),
|
|
294
|
+
};
|
|
295
|
+
if (providerHasRequiredClasses(installed, required, true, runtimeConfigDir))
|
|
296
|
+
return installed;
|
|
297
|
+
rejectedInstalled = installed;
|
|
298
|
+
const marker = markerProvider(runtimeConfigDir);
|
|
299
|
+
if (marker && !providersShareRequiredRoots(marker, installed, required) && providerHasRequiredClasses(marker, required, marker.kind !== 'package')) {
|
|
300
|
+
return marker;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
else if (runtimeConfigDir) {
|
|
304
|
+
const marker = markerProvider(runtimeConfigDir);
|
|
305
|
+
if (marker && providerHasRequiredClasses(marker, required, marker.kind !== 'package'))
|
|
306
|
+
return marker;
|
|
307
|
+
}
|
|
308
|
+
if (authority === 'compatible') {
|
|
309
|
+
const packaged = packageProvider(required);
|
|
310
|
+
if (packaged &&
|
|
311
|
+
(!rejectedInstalled || !providersShareRequiredRoots(packaged, rejectedInstalled, required))) {
|
|
312
|
+
return packaged;
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
throw new Error(`Runtime Surface source is unavailable or incomplete for ${[...required].sort().join('+')}; ` +
|
|
316
|
+
'install or upgrade gsd-core before materializing this surface.');
|
|
317
|
+
}
|
|
318
|
+
function sourceRootFor(context, sourceClass) {
|
|
319
|
+
context.provider ??= resolveSourceProvider(context.runtimeConfigDir, context.required, context.scope, context.authority);
|
|
320
|
+
return sourceClass === 'commands' ? context.provider.commandsRoot : context.provider.agentsRoot;
|
|
321
|
+
}
|
|
322
|
+
function findInstallSourceRoot(runtimeConfigDir) {
|
|
323
|
+
return resolveSourceProvider(runtimeConfigDir, ['commands']).commandsRoot;
|
|
159
324
|
}
|
|
160
325
|
// ---------------------------------------------------------------------------
|
|
161
326
|
// Layout table builders
|
|
162
327
|
// ---------------------------------------------------------------------------
|
|
163
|
-
function commandsKind(destSubpath, prefix,
|
|
328
|
+
function commandsKind(destSubpath, prefix, sourceContext) {
|
|
164
329
|
return {
|
|
165
330
|
kind: 'commands',
|
|
166
331
|
destSubpath,
|
|
167
332
|
prefix,
|
|
168
|
-
stage: (resolved) => stageSkillsForProfile(
|
|
333
|
+
stage: (resolved) => stageSkillsForProfile(sourceRootFor(sourceContext, 'commands'), resolved),
|
|
169
334
|
};
|
|
170
335
|
}
|
|
171
|
-
function agentsKind(destSubpath, prefix, configDir) {
|
|
336
|
+
function agentsKind(destSubpath, prefix, configDir, sourceContext) {
|
|
172
337
|
return {
|
|
173
338
|
kind: 'agents',
|
|
174
339
|
destSubpath,
|
|
@@ -191,7 +356,7 @@ function agentsKind(destSubpath, prefix, configDir) {
|
|
|
191
356
|
// signature silently dropped the second arg every caller already passed —
|
|
192
357
|
// a caller with NO agentCtx in scope is unaffected (row I2: converter-only,
|
|
193
358
|
// as today), matching stageAgentsForRuntimeWithConverter's own contract.
|
|
194
|
-
stage: (resolved, agentCtx) => stageAgentsForRuntimeWithConverter(
|
|
359
|
+
stage: (resolved, agentCtx) => stageAgentsForRuntimeWithConverter(sourceRootFor(sourceContext, 'agents'), resolved, (content) => content, false, agentCtx?.runtime ? agentCtx : undefined),
|
|
195
360
|
};
|
|
196
361
|
}
|
|
197
362
|
/**
|
|
@@ -323,7 +488,7 @@ function _resolveNamedConverter(converterName, kindLabel) {
|
|
|
323
488
|
* @param converterName name of converter function in Runtime Artifact Conversion exports
|
|
324
489
|
* @param configDir runtime config dir (for .gsd-source marker resolution)
|
|
325
490
|
*/
|
|
326
|
-
function convertedAgentsKind(destSubpath, prefix, converterName, configDir, scope
|
|
491
|
+
function convertedAgentsKind(destSubpath, prefix, converterName, configDir, sourceContext, scope) {
|
|
327
492
|
return {
|
|
328
493
|
kind: 'agents',
|
|
329
494
|
destSubpath,
|
|
@@ -396,20 +561,20 @@ function convertedAgentsKind(destSubpath, prefix, converterName, configDir, scop
|
|
|
396
561
|
// ADR-1235 §1: when agentCtx is provided (by createRuntimeArtifactInstallPlan
|
|
397
562
|
// for descriptor-driven runtimes), thread it through so stageAgentsForRuntimeWithConverter
|
|
398
563
|
// can apply the full pre-converter + post-converter sequence in the correct order.
|
|
399
|
-
return stageAgentsForRuntimeWithConverter(
|
|
564
|
+
return stageAgentsForRuntimeWithConverter(sourceRootFor(sourceContext, 'agents'), resolved, converter, (0, install_scope_cjs_1.isGlobalScope)(scope), agentCtx?.runtime ? agentCtx : undefined);
|
|
400
565
|
},
|
|
401
566
|
};
|
|
402
567
|
}
|
|
403
|
-
function kimiAgentsKind(destSubpath, prefix, configDir) {
|
|
568
|
+
function kimiAgentsKind(destSubpath, prefix, configDir, sourceContext) {
|
|
404
569
|
return {
|
|
405
570
|
kind: 'kimi-agents',
|
|
406
571
|
destSubpath,
|
|
407
572
|
prefix,
|
|
408
|
-
stage: (resolved) => {
|
|
573
|
+
stage: (resolved, agentCtx) => {
|
|
409
574
|
const buildKimiAgentArtifacts = conversionExports['buildKimiAgentArtifacts'];
|
|
410
575
|
// #2995: compose at staging (identity converter) so the readFileSync below
|
|
411
576
|
// sees marker-free content — same single composing stager as agentsKind.
|
|
412
|
-
const stagedAgents = stageAgentsForRuntimeWithConverter(
|
|
577
|
+
const stagedAgents = stageAgentsForRuntimeWithConverter(sourceRootFor(sourceContext, 'agents'), resolved, (content) => content, false, agentCtx);
|
|
413
578
|
const subagents = [];
|
|
414
579
|
if (installFs().existsSync(stagedAgents)) {
|
|
415
580
|
for (const entry of installFs().readdirSync(stagedAgents, { withFileTypes: true })) {
|
|
@@ -456,7 +621,7 @@ function kimiAgentsKind(destSubpath, prefix, configDir) {
|
|
|
456
621
|
* their declaring capId at staging time. Absent -> stage() stages
|
|
457
622
|
* nothing third-party (fail closed).
|
|
458
623
|
*/
|
|
459
|
-
function skillsKind(destSubpath, prefix, converterName, runtime, configDir, nested
|
|
624
|
+
function skillsKind(destSubpath, prefix, converterName, runtime, configDir, nested, scope, sourceContext, capabilityRegistry) {
|
|
460
625
|
return {
|
|
461
626
|
kind: 'skills',
|
|
462
627
|
destSubpath,
|
|
@@ -489,7 +654,7 @@ function skillsKind(destSubpath, prefix, converterName, runtime, configDir, nest
|
|
|
489
654
|
// it must run AFTER it instead, once the `@`-include is in its final
|
|
490
655
|
// rewritten shape.
|
|
491
656
|
const wrappedConverter = (content, skillName) => realConverter(content, skillName, runtime, cmdNames, isGlobal);
|
|
492
|
-
return stageSkillsForRuntimeAsSkills(
|
|
657
|
+
return stageSkillsForRuntimeAsSkills(sourceRootFor(sourceContext, 'commands'), resolved, wrappedConverter, prefix, nested, capabilityRegistry);
|
|
493
658
|
},
|
|
494
659
|
};
|
|
495
660
|
}
|
|
@@ -509,14 +674,14 @@ function skillsKind(destSubpath, prefix, converterName, runtime, configDir, nest
|
|
|
509
674
|
* @param converterName name of converter function in Runtime Artifact Conversion exports
|
|
510
675
|
* @param configDir runtime config dir (for .gsd-source marker resolution)
|
|
511
676
|
*/
|
|
512
|
-
function convertedCommandsKind(destSubpath, prefix, converterName,
|
|
677
|
+
function convertedCommandsKind(destSubpath, prefix, converterName, sourceContext) {
|
|
513
678
|
return {
|
|
514
679
|
kind: 'commands',
|
|
515
680
|
destSubpath,
|
|
516
681
|
prefix,
|
|
517
682
|
stage: (resolved) => {
|
|
518
683
|
const converter = _resolveNamedConverter(converterName, 'commands');
|
|
519
|
-
return stageCommandsForRuntimeFlat(
|
|
684
|
+
return stageCommandsForRuntimeFlat(sourceRootFor(sourceContext, 'commands'), resolved, converter, prefix);
|
|
520
685
|
},
|
|
521
686
|
};
|
|
522
687
|
}
|
|
@@ -527,29 +692,29 @@ function getRegistry() {
|
|
|
527
692
|
* Map a single ArtifactKindDescriptor entry to an ArtifactKind using the
|
|
528
693
|
* matching builder function. Mirrors the hand-built calls in the old switch.
|
|
529
694
|
*/
|
|
530
|
-
function dispatchKindEntry(entry, runtime, configDir, scope, capabilityRegistry) {
|
|
695
|
+
function dispatchKindEntry(entry, runtime, configDir, scope, capabilityRegistry, sourceContext) {
|
|
531
696
|
const { kind, destSubpath, prefix, nesting, converter } = entry;
|
|
532
697
|
const nested = nesting === 'nested';
|
|
533
698
|
let result;
|
|
534
699
|
switch (kind) {
|
|
535
700
|
case 'commands':
|
|
536
701
|
result = converter == null
|
|
537
|
-
? commandsKind(destSubpath, prefix,
|
|
538
|
-
: convertedCommandsKind(destSubpath, prefix, converter,
|
|
702
|
+
? commandsKind(destSubpath, prefix, sourceContext)
|
|
703
|
+
: convertedCommandsKind(destSubpath, prefix, converter, sourceContext);
|
|
539
704
|
break;
|
|
540
705
|
case 'agents':
|
|
541
706
|
result = converter == null
|
|
542
|
-
? agentsKind(destSubpath, prefix, configDir)
|
|
543
|
-
: convertedAgentsKind(destSubpath, prefix, converter, configDir, scope);
|
|
707
|
+
? agentsKind(destSubpath, prefix, configDir, sourceContext)
|
|
708
|
+
: convertedAgentsKind(destSubpath, prefix, converter, configDir, sourceContext, scope);
|
|
544
709
|
break;
|
|
545
710
|
case 'skills':
|
|
546
711
|
if (converter == null) {
|
|
547
712
|
throw new TypeError(`resolveRuntimeArtifactLayout: skills entry for '${runtime}' has converter=null (converter is required for skills)`);
|
|
548
713
|
}
|
|
549
|
-
result = skillsKind(destSubpath, prefix, converter, runtime, configDir, nested, scope, capabilityRegistry);
|
|
714
|
+
result = skillsKind(destSubpath, prefix, converter, runtime, configDir, nested, scope, sourceContext, capabilityRegistry);
|
|
550
715
|
break;
|
|
551
716
|
case 'kimi-agents':
|
|
552
|
-
result = kimiAgentsKind(destSubpath, prefix, configDir);
|
|
717
|
+
result = kimiAgentsKind(destSubpath, prefix, configDir, sourceContext);
|
|
553
718
|
break;
|
|
554
719
|
default:
|
|
555
720
|
throw new TypeError(`resolveRuntimeArtifactLayout: unknown kind '${kind}' in descriptor for runtime '${runtime}'`);
|
|
@@ -594,7 +759,20 @@ function resolveRuntimeArtifactLayoutFromRegistry(registry, runtime, configDir,
|
|
|
594
759
|
throw new TypeError(`Unknown runtime: '${runtime}' — add to runtime-artifact-layout.cjs table`);
|
|
595
760
|
}
|
|
596
761
|
const entries = desc[scope] ?? [];
|
|
597
|
-
const
|
|
762
|
+
const required = requiredRuntimeSurfaceSourceClasses(entries);
|
|
763
|
+
// Stage closures share one lazy source-resolution context, so the first kind
|
|
764
|
+
// to stage selects and caches one complete provider for every required source
|
|
765
|
+
// class. Global layouts accept only installed or marker providers; the
|
|
766
|
+
// installer owns its private package fallback by retrying through a transient
|
|
767
|
+
// compatibility marker after source resolution fails. Local layouts retain
|
|
768
|
+
// compatible marker/package resolution and never provision the global corpus.
|
|
769
|
+
const sourceContext = {
|
|
770
|
+
runtimeConfigDir: configDir,
|
|
771
|
+
scope,
|
|
772
|
+
required,
|
|
773
|
+
authority: scope === 'local' ? 'compatible' : 'runtime',
|
|
774
|
+
};
|
|
775
|
+
const kinds = entries.map((entry) => dispatchKindEntry(entry, runtime, configDir, scope, capabilityRegistry, sourceContext));
|
|
598
776
|
return { runtime, configDir, scope, kinds };
|
|
599
777
|
}
|
|
600
778
|
function getTriggerRegistry() {
|