@hasna/skills 0.10.73 → 0.10.74
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/README.md +77 -0
- package/bin/index.js +516 -45
- package/bin/mcp.js +79 -12
- package/bin/migrate.js +1 -1
- package/bin/server.js +1 -1
- package/bin/worker.js +1 -1
- package/dist/cli/commands/provenance.d.ts +18 -0
- package/dist/index.js +74 -22
- package/dist/lib/portable-skills-files.d.ts +10 -0
- package/dist/lib/selected-run.d.ts +45 -0
- package/dist/lib/selection-provenance.d.ts +108 -0
- package/dist/runtime-prerequisites.js +1 -1
- package/dist/sdk/index.js +123 -27
- package/docs/plugin-admission.md +13 -9
- package/docs/skill-standard.md +18 -4
- package/package.json +1 -1
package/bin/index.js
CHANGED
|
@@ -36888,7 +36888,7 @@ var package_default;
|
|
|
36888
36888
|
var init_package = __esm(() => {
|
|
36889
36889
|
package_default = {
|
|
36890
36890
|
name: "@hasna/skills",
|
|
36891
|
-
version: "0.10.
|
|
36891
|
+
version: "0.10.74",
|
|
36892
36892
|
description: "Skills library for AI coding agents",
|
|
36893
36893
|
type: "module",
|
|
36894
36894
|
bin: {
|
|
@@ -39496,8 +39496,8 @@ function ensureInstructionSkillFiles(skillPath, manifest) {
|
|
|
39496
39496
|
displayName: manifest.displayName ?? displayName(manifest.name),
|
|
39497
39497
|
category: manifest.category ?? "Development Tools",
|
|
39498
39498
|
tags: manifest.tags?.length ? manifest.tags : ["custom", manifest.name],
|
|
39499
|
-
inputs: [],
|
|
39500
|
-
commands: []
|
|
39499
|
+
inputs: Array.isArray(manifest.inputs) ? manifest.inputs : [],
|
|
39500
|
+
commands: Array.isArray(manifest.commands) ? manifest.commands : []
|
|
39501
39501
|
};
|
|
39502
39502
|
if (!existsSync10(join10(skillPath, "SKILL.md"))) {
|
|
39503
39503
|
writeFileSync2(join10(skillPath, "SKILL.md"), renderSkillMd(next));
|
|
@@ -58192,11 +58192,19 @@ function planAgentIntegration(options) {
|
|
|
58192
58192
|
const executable2 = discoveryExecutable(agent) ?? (prior ? recordedDiscoveryExecutable(agent, prior) : null);
|
|
58193
58193
|
executables.set(agent, executable2);
|
|
58194
58194
|
const retainedReview = options.discoveryInputs === undefined && policy.bridge?.discovery?.[agent]?.method === "reviewed" ? { ...policy.bridge.discovery[agent], ...agent === "codex" ? { codexDisabledPluginSkills: policy.bridge.codexPluginSkills ?? [] } : {} } : undefined;
|
|
58195
|
-
|
|
58196
|
-
|
|
58197
|
-
|
|
58195
|
+
try {
|
|
58196
|
+
if (retainedReview) {
|
|
58197
|
+
assertRetainedReviewState(agent, { home, dataDir: dataDir3, projectDir: options.projectDir ?? home });
|
|
58198
|
+
retainedAgents.push(agent);
|
|
58199
|
+
}
|
|
58200
|
+
return resolveAgentDiscovery({ home, agent, reviewed: options.discoveryInputs, retainedReview, canonical: (path) => canonicalAgentPath(path, aliases), executable: executable2 });
|
|
58201
|
+
} catch (error) {
|
|
58202
|
+
if (isDiscoveryRootUnresolved(error) || error instanceof SumiPathResolverError || error instanceof NativeSkillCopiesDriftError)
|
|
58203
|
+
throw error;
|
|
58204
|
+
if (!retainedReview)
|
|
58205
|
+
throw error;
|
|
58206
|
+
throw new Error(`NATIVE_SKILL_DRIFT: ${error.message.replace(/^NATIVE_SKILL_DRIFT: /, "")}. This agent reuses a saved discovery review and that review no longer verifies, so a fresh explicit review is required: skills hook install --agent ${agent} --discovery-inputs <review> --apply.`);
|
|
58198
58207
|
}
|
|
58199
|
-
return resolveAgentDiscovery({ home, agent, reviewed: options.discoveryInputs, retainedReview, canonical: (path) => canonicalAgentPath(path, aliases), executable: executable2 });
|
|
58200
58208
|
});
|
|
58201
58209
|
const codexConfigBefore = options.agents.includes("codex") ? readOptional(canonicalAgentPath(join34(home, ".codex", "config.toml"), aliases)) : null;
|
|
58202
58210
|
const codexConfig = Bun.TOML.parse(codexConfigBefore ?? "");
|
|
@@ -58867,7 +58875,7 @@ function applyAgentIntegrationUnlocked(plan, options = {}, assertCurrent) {
|
|
|
58867
58875
|
assertCurrent();
|
|
58868
58876
|
recheckRootAliases(aliases);
|
|
58869
58877
|
for (const agent of plan.retainedReviewChecks?.agents ?? [])
|
|
58870
|
-
|
|
58878
|
+
assertRetainedReviewState(agent, { ...plan.retainedReviewChecks, dataDir: plan.dataDir });
|
|
58871
58879
|
if (plan.reviewArtifactMigration) {
|
|
58872
58880
|
const verified = planReviewedArtifactMigration(plan.reviewArtifactMigration);
|
|
58873
58881
|
if (JSON.stringify(verified.changes) !== JSON.stringify(plan.changes) || JSON.stringify(verified.discoveryAfter) !== JSON.stringify(plan.discoveryAfter))
|
|
@@ -58910,6 +58918,8 @@ function applyAgentIntegrationUnlocked(plan, options = {}, assertCurrent) {
|
|
|
58910
58918
|
if (!plan.changes.length) {
|
|
58911
58919
|
assertCurrent();
|
|
58912
58920
|
recheckRootAliases(aliases);
|
|
58921
|
+
for (const agent of plan.retainedReviewChecks?.agents ?? [])
|
|
58922
|
+
assertManagedAgentBridge(agent, { ...plan.retainedReviewChecks, dataDir: plan.dataDir });
|
|
58913
58923
|
return { changed: [], backups, ...aliases.length ? { rootAliases: aliases } : {} };
|
|
58914
58924
|
}
|
|
58915
58925
|
assertSafePath(backupRoot);
|
|
@@ -58959,6 +58969,8 @@ function applyAgentIntegrationUnlocked(plan, options = {}, assertCurrent) {
|
|
|
58959
58969
|
}
|
|
58960
58970
|
for (const agent of plan.managedAgentChecks?.agents ?? [])
|
|
58961
58971
|
assertManagedAgentBridge(agent, { home: plan.managedAgentChecks.home, dataDir: plan.dataDir, projectDir: plan.managedAgentChecks.projectDir ?? plan.managedAgentChecks.home });
|
|
58972
|
+
for (const agent of plan.retainedReviewChecks?.agents ?? [])
|
|
58973
|
+
assertManagedAgentBridge(agent, { ...plan.retainedReviewChecks, dataDir: plan.dataDir });
|
|
58962
58974
|
atomicWrite2(join34(backupRoot, "receipt.json"), JSON.stringify({ version: 1, changes: written.map((change) => ({ path: change.path, beforeHash: change.before === null ? null : sha4(change.before), afterHash: sha4(change.after) })), backups, ...plan.cacheWitnessUpgrade ? { cacheWitnessUpgrade: plan.cacheWitnessUpgrade } : {}, ...plan.retainedReviewArtifacts?.length ? { retainedReviewArtifacts: plan.retainedReviewArtifacts.map((item) => ({ path: item.path, ...item.artifact })) } : {}, ...aliases.length ? { rootAliases: aliases } : {} }) + `
|
|
58963
58975
|
`);
|
|
58964
58976
|
} catch (error) {
|
|
@@ -59299,7 +59311,7 @@ function codexPromptDriftWarning(report) {
|
|
|
59299
59311
|
function assertManagedAgentBridge(agent, options = {}) {
|
|
59300
59312
|
return assertManagedAgentBridgeWithDiscovery(agent, options);
|
|
59301
59313
|
}
|
|
59302
|
-
function
|
|
59314
|
+
function assertManagedBridgeCustody(agent, options = {}, provenDiscovery) {
|
|
59303
59315
|
const home = resolve24(options.home ?? homedir3()), dataDir3 = options.dataDir ?? getDataDirReadOnly();
|
|
59304
59316
|
assertSafePath(join34(dataDir3, "agent-policy.json"));
|
|
59305
59317
|
const snapshot2 = readManagedSkillPolicySnapshot(dataDir3);
|
|
@@ -59316,7 +59328,6 @@ function assertManagedAgentBridgeWithDiscovery(agent, options = {}, provenDiscov
|
|
|
59316
59328
|
if (!isOwnedCliBridge(expected, [expected]))
|
|
59317
59329
|
throw new Error("NATIVE_SKILL_DRIFT: the native Skills bridge is missing or modified; repair it before continuing");
|
|
59318
59330
|
const roots = projectAncestorDirectories([options.projectDir ?? process.cwd(), ...options.projectDirs ?? [], ...agent === "hermes" && process.env.TERMINAL_CWD ? [process.cwd()] : []]);
|
|
59319
|
-
const visible = (entry) => entry.agent === agent || ["codex", "gemini", "opencode", "hermes", "sumi"].includes(agent) && entry.path.includes(`${sep13}.agents${sep13}skills${sep13}`) || ["opencode", "sumi"].includes(agent) && entry.agent === "claude";
|
|
59320
59331
|
const discovery = provenDiscovery ?? binding.discovery?.[agent];
|
|
59321
59332
|
assertProjectDiscovery(agent, [...roots], home, (path) => canonicalAgentPath(path, aliases), discovery);
|
|
59322
59333
|
for (const source of discovery?.sources ?? [])
|
|
@@ -59331,11 +59342,27 @@ function assertManagedAgentBridgeWithDiscovery(agent, options = {}, provenDiscov
|
|
|
59331
59342
|
throw new Error("NATIVE_SKILL_DRIFT: the native hook command/profile binding is missing");
|
|
59332
59343
|
if (options.profileId !== undefined && options.profileId !== profile)
|
|
59333
59344
|
throw new Error("NATIVE_SKILL_DRIFT: the hook selection profile differs from its managed binding; restart the native client after reviewing skills hook install");
|
|
59345
|
+
return { home, dataDir: dataDir3, binding, aliases, expected, roots, discovery, configPath, config, command, profile };
|
|
59346
|
+
}
|
|
59347
|
+
function assertUnrepairableBridgeProtection(custody, agent) {
|
|
59348
|
+
if (agent !== "hermes")
|
|
59349
|
+
return;
|
|
59350
|
+
const { home, dataDir: dataDir3, binding, config, command, profile } = custody;
|
|
59351
|
+
const supervisor = binding.supervisors?.hermes;
|
|
59352
|
+
if (supervisor?.path !== join34(dataDir3, "agent-hooks", "hermes.js") || supervisor?.sha256 !== sha4(renderHermesSupervisor(command, profile)))
|
|
59353
|
+
throw new Error("NATIVE_SKILL_DRIFT: Hermes supervisor binding changed; run skills hook install");
|
|
59354
|
+
assertHermesProtection(home, config, command, profile, supervisor);
|
|
59355
|
+
}
|
|
59356
|
+
function assertRetainedReviewState(agent, options) {
|
|
59357
|
+
const custody = assertManagedBridgeCustody(agent, options);
|
|
59358
|
+
assertUnrepairableBridgeProtection(custody, agent);
|
|
59359
|
+
assertManagedNativeDiscovery(custody, agent, options);
|
|
59360
|
+
}
|
|
59361
|
+
function assertManagedAgentBridgeWithDiscovery(agent, options = {}, provenDiscovery) {
|
|
59362
|
+
const custody = assertManagedBridgeCustody(agent, options, provenDiscovery);
|
|
59363
|
+
const { home, aliases, expected, discovery, config, command, profile } = custody;
|
|
59334
59364
|
if (agent === "hermes") {
|
|
59335
|
-
|
|
59336
|
-
if (supervisor?.path !== join34(dataDir3, "agent-hooks", "hermes.js") || supervisor?.sha256 !== sha4(renderHermesSupervisor(command, profile)))
|
|
59337
|
-
throw new Error("NATIVE_SKILL_DRIFT: Hermes supervisor binding changed; run skills hook install");
|
|
59338
|
-
assertHermesProtection(home, config, command, profile, supervisor);
|
|
59365
|
+
assertUnrepairableBridgeProtection(custody, agent);
|
|
59339
59366
|
} else if (agent === "sumi") {
|
|
59340
59367
|
if (JSON.stringify(config.permissions?.filter((rule) => rule.action === "skill")) !== JSON.stringify(SUMI_SKILL_PERMISSIONS) || !isManagedSumiPlugin(readOptional(join34(sumiConfigDirectory(home, process.env, options.projectDir ?? process.cwd()), "plugins", "skills-cli.js")), command, profile))
|
|
59341
59368
|
throw new Error("NATIVE_SKILL_DRIFT: Sumi bridge protection changed; run skills hook install");
|
|
@@ -59357,6 +59384,21 @@ function assertManagedAgentBridgeWithDiscovery(agent, options = {}, provenDiscov
|
|
|
59357
59384
|
if (agent === "gemini" && (config.hooksConfig?.enabled === false || config.skills?.enabled !== true || !["antigravity-support", "skill-creator"].every((name) => config.skills?.disabled?.includes(name)) || config.skills?.disabled?.includes(CLI_BRIDGE_NAME)))
|
|
59358
59385
|
throw new Error("NATIVE_SKILL_DRIFT: Gemini bridge or bundled-skill protection changed; run skills hook install");
|
|
59359
59386
|
}
|
|
59387
|
+
if (agent === "codex") {
|
|
59388
|
+
const codexConfig = Bun.TOML.parse(readOptional(canonicalAgentPath(join34(home, ".codex", "config.toml"), aliases)) ?? "");
|
|
59389
|
+
if (codexConfig.skills?.bundled?.enabled !== false)
|
|
59390
|
+
throw new Error("NATIVE_SKILL_DRIFT: Codex bundled skill reseeding is not disabled (skills.bundled.enabled); run skills hook install");
|
|
59391
|
+
const setting = (path) => (codexConfig.skills?.config ?? []).filter((entry) => typeof entry.path === "string" && [path, join34(path, "SKILL.md")].includes(canonicalAgentPath(entry.path, aliases)));
|
|
59392
|
+
if ([...setting(expected), ...(codexConfig.skills?.config ?? []).filter((entry) => typeof entry.name === "string" && entry.name.trim() === CLI_BRIDGE_NAME)].some((entry) => entry.enabled === false))
|
|
59393
|
+
throw new Error("NATIVE_SKILL_DRIFT: the Codex CLI bridge is disabled; run skills hook install");
|
|
59394
|
+
}
|
|
59395
|
+
if (agent === "gemini" && discovery && !discovery.builtinNames?.every((name) => config.skills.disabled.includes(name)))
|
|
59396
|
+
throw new Error("NATIVE_SKILL_DRIFT: an installed Gemini builtin is not disabled");
|
|
59397
|
+
return assertManagedNativeDiscovery(custody, agent, options);
|
|
59398
|
+
}
|
|
59399
|
+
function assertManagedNativeDiscovery(custody, agent, options) {
|
|
59400
|
+
const { home, dataDir: dataDir3, binding, aliases, expected, roots, discovery } = custody;
|
|
59401
|
+
const visible = (entry) => entry.agent === agent || ["codex", "gemini", "opencode", "hermes", "sumi"].includes(agent) && entry.path.includes(`${sep13}.agents${sep13}skills${sep13}`) || ["opencode", "sumi"].includes(agent) && entry.agent === "claude";
|
|
59360
59402
|
const codexPath = canonicalAgentPath(join34(home, ".codex", "config.toml"), aliases);
|
|
59361
59403
|
const vendorCache = canonicalAgentPath(join34(home, ".codex", "plugins", "cache"), aliases);
|
|
59362
59404
|
const witnessTolerance = agent === "codex" && options.codexPromptHook === true ? {
|
|
@@ -59367,11 +59409,6 @@ function assertManagedAgentBridgeWithDiscovery(agent, options = {}, provenDiscov
|
|
|
59367
59409
|
if (options.codexDiscoveryRecovery && (agent !== "codex" || options.codexDiscoveryRecovery.configPath !== codexPath))
|
|
59368
59410
|
throw new Error("NATIVE_SKILL_DRIFT: Codex trust recovery names a different configuration root");
|
|
59369
59411
|
const codexConfig = agent === "codex" ? Bun.TOML.parse(readOptional(codexPath) ?? "") : {};
|
|
59370
|
-
if (agent === "codex" && codexConfig.skills?.bundled?.enabled !== false)
|
|
59371
|
-
throw new Error("NATIVE_SKILL_DRIFT: Codex bundled skill reseeding is not disabled (skills.bundled.enabled); run skills hook install");
|
|
59372
|
-
const setting = (path) => (codexConfig.skills?.config ?? []).filter((entry) => typeof entry.path === "string" && [path, join34(path, "SKILL.md")].includes(canonicalAgentPath(entry.path, aliases)));
|
|
59373
|
-
if (agent === "codex" && [...setting(expected), ...(codexConfig.skills?.config ?? []).filter((entry) => typeof entry.name === "string" && entry.name.trim() === CLI_BRIDGE_NAME)].some((entry) => entry.enabled === false))
|
|
59374
|
-
throw new Error("NATIVE_SKILL_DRIFT: the Codex CLI bridge is disabled; run skills hook install");
|
|
59375
59412
|
if (agent === "codex" && !reviewedCodexPluginCapabilitiesUnchanged(canonicalAgentPath(join34(home, ".codex/plugins/cache"), aliases), binding.codexPluginSkills ?? [], (path) => new TextDecoder("utf-8", { fatal: true }).decode(readNativeBytes(path, 1024 * 1024)), codexConfig.skills?.config ?? []))
|
|
59376
59413
|
throw new Error("NATIVE_SKILL_DRIFT: reviewed native plugin capability controls changed; run skills hook install with a fresh discovery review");
|
|
59377
59414
|
const disabledPlugin = (entry) => {
|
|
@@ -59408,8 +59445,6 @@ function assertManagedAgentBridgeWithDiscovery(agent, options = {}, provenDiscov
|
|
|
59408
59445
|
};
|
|
59409
59446
|
if (!discovery || discovery.agent !== agent)
|
|
59410
59447
|
throw new Error("NATIVE_SKILL_DRIFT: native discovery coverage is missing; run skills hook install");
|
|
59411
|
-
if (agent === "gemini" && !discovery.builtinNames?.every((name) => config.skills.disabled.includes(name)))
|
|
59412
|
-
throw new Error("NATIVE_SKILL_DRIFT: an installed Gemini builtin is not disabled");
|
|
59413
59448
|
try {
|
|
59414
59449
|
verifyAgentDiscovery(agent === "codex" ? { ...discovery, codexDisabledPluginSkills: binding.codexPluginSkills ?? [] } : discovery, options.codexDiscoveryRecovery, aliases, witnessTolerance);
|
|
59415
59450
|
if (agent === "sumi" && discovery.method === "reviewed")
|
|
@@ -59464,7 +59499,7 @@ function assertManagedAgentBridgeWithDiscovery(agent, options = {}, provenDiscov
|
|
|
59464
59499
|
return false;
|
|
59465
59500
|
}
|
|
59466
59501
|
}, read: (path) => new TextDecoder("utf-8", { fatal: true }).decode(readNativeBytes(path, 1024 * 1024)) });
|
|
59467
|
-
throw new
|
|
59502
|
+
throw new NativeSkillCopiesDriftError(`NATIVE_SKILL_DRIFT: ${blocking.length} unexpected native skill copies were found: ${nativeSkillPathList(blocking.map((entry) => entry.path))}. ${remediation}${adapterRefusal ? ` Native policy adapter refused: ${adapterRefusal}` : ""}`);
|
|
59468
59503
|
}
|
|
59469
59504
|
recheckRootAliases(aliases);
|
|
59470
59505
|
const discoveryChanges = (witnessTolerance?.changes ?? []).filter((change, index, all) => all.findIndex((other) => other.kind === change.kind && other.path === change.path) === index);
|
|
@@ -59505,7 +59540,7 @@ function assertNativeExportAllowed(dataDir3 = getDataDirReadOnly()) {
|
|
|
59505
59540
|
if (requiresCliSkillLoading(dataDir3))
|
|
59506
59541
|
throw new Error("NATIVE_SKILL_EXPORT_DISABLED: this station loads skills through the Skills CLI; use skills sync --selection-profile <id>");
|
|
59507
59542
|
}
|
|
59508
|
-
var sha4 = (data) => createHash26("sha256").update(data).digest("hex"), HOOK_EVENTS, ROOTS, SKILLS_LOADING_POLICY = "Skills loading policy: discover skills with `skills list` or `skills search`, and read selected instructions with `skills load <slug>`. Use `skills sync` to refresh the shared profile. The only native skill is the owned skills-cli bridge. Create and edit payload skills in the Skills authoring workspace; do not copy payload instructions into native discovery folders. Context loading does not authorize execution; use `skills run` only when the task calls for running a skill.";
|
|
59543
|
+
var sha4 = (data) => createHash26("sha256").update(data).digest("hex"), HOOK_EVENTS, ROOTS, NativeSkillCopiesDriftError, SKILLS_LOADING_POLICY = "Skills loading policy: discover skills with `skills list` or `skills search`, and read selected instructions with `skills load <slug>`. Use `skills sync` to refresh the shared profile. The only native skill is the owned skills-cli bridge. Create and edit payload skills in the Skills authoring workspace; do not copy payload instructions into native discovery folders. Context loading does not authorize execution; use `skills run` only when the task calls for running a skill.";
|
|
59509
59544
|
var init_agent_integration = __esm(() => {
|
|
59510
59545
|
init_sumi_settings_witness();
|
|
59511
59546
|
init_codex_corpus_write();
|
|
@@ -59534,6 +59569,8 @@ var init_agent_integration = __esm(() => {
|
|
|
59534
59569
|
init_retained_review_artifacts();
|
|
59535
59570
|
HOOK_EVENTS = ["UserPromptSubmit", "SessionStart", "SubagentStart"];
|
|
59536
59571
|
ROOTS = NATIVE_SKILL_ROOTS;
|
|
59572
|
+
NativeSkillCopiesDriftError = class NativeSkillCopiesDriftError extends Error {
|
|
59573
|
+
};
|
|
59537
59574
|
});
|
|
59538
59575
|
|
|
59539
59576
|
// src/lib/home-migration.ts
|
|
@@ -62715,6 +62752,9 @@ function verifyAgentDiscovery(binding, codexRecovery, reviewedRootAliases, witne
|
|
|
62715
62752
|
function claudeControlSource(source) {
|
|
62716
62753
|
return CLAUDE_CONTROL_WITNESS_MODES.has(source.hashMode ?? "") || CLAUDE_CONTROL_FILES.has(basename16(source.path)) && !source.path.includes(`${sep14}.claude${sep14}plugins${sep14}cache${sep14}`);
|
|
62717
62754
|
}
|
|
62755
|
+
function retainedAbsentClaudeRoot(absentRoots, source) {
|
|
62756
|
+
return claudeControlSource(source) ? undefined : retainedAbsentRoot(absentRoots, source);
|
|
62757
|
+
}
|
|
62718
62758
|
function classifyClaudeDiscoverySources(binding) {
|
|
62719
62759
|
if (!binding || binding.agent !== "claude" || !Array.isArray(binding.sources))
|
|
62720
62760
|
throw new Error("Invalid Claude discovery binding");
|
|
@@ -62735,7 +62775,7 @@ function classifyClaudeDiscoverySources(binding) {
|
|
|
62735
62775
|
};
|
|
62736
62776
|
const budget2 = discoveryByteBudget();
|
|
62737
62777
|
return binding.sources.map((source) => {
|
|
62738
|
-
const root2 =
|
|
62778
|
+
const root2 = retainedAbsentClaudeRoot(absentRoots, source);
|
|
62739
62779
|
if (root2 !== undefined)
|
|
62740
62780
|
return { status: "retained-absent", root: root2, witness: retainableAbsentWitness(source) };
|
|
62741
62781
|
let current;
|
|
@@ -63150,7 +63190,10 @@ function resolveAgentDiscovery(options) {
|
|
|
63150
63190
|
if (!review.sources.some((source) => source.path === canonical9(configPath)))
|
|
63151
63191
|
throw new Error("Discovery review must include the agent configuration source");
|
|
63152
63192
|
const reviewedSources = supersedesSettingsProjection(agent, review.sources, canonical9(configPath)) ? sources.filter((source) => !isSupersededSettingsProjection(agent, canonical9(configPath), source)) : sources;
|
|
63193
|
+
const absentRoots = absentRetiredClaudeRoots(supplied);
|
|
63153
63194
|
const reviewedSourcesWithManifestProjection = review.sources.map((source) => {
|
|
63195
|
+
if (retainedAbsentClaudeRoot(absentRoots, source) !== undefined)
|
|
63196
|
+
return source;
|
|
63154
63197
|
if (agent === "claude" && source.format === undefined && source.fields === undefined && source.managedPlugins === undefined && source.reviewArtifact === undefined && [undefined, "bytes", "path-bytes"].includes(source.hashMode) && isClaudePluginCacheOrphanMarker(source.path)) {
|
|
63155
63198
|
return { path: source.path, hashMode: CLAUDE_ORPHAN_MARKER_MODE, sha256: hashClaudePluginCacheOrphanMarker(source.path) };
|
|
63156
63199
|
}
|
|
@@ -63183,6 +63226,11 @@ function resolveAgentDiscovery(options) {
|
|
|
63183
63226
|
});
|
|
63184
63227
|
if (agent === "claude")
|
|
63185
63228
|
assertReviewedClaudeCacheClosures(home, config, review, canonical9);
|
|
63229
|
+
for (const root2 of absentRoots) {
|
|
63230
|
+
safe6(root2);
|
|
63231
|
+
if (lstatSync32(root2, { throwIfNoEntry: false }))
|
|
63232
|
+
throw new Error("Retired native materialization changed during discovery review");
|
|
63233
|
+
}
|
|
63186
63234
|
const combined = [...reviewedSources, ...reviewedSourcesWithManifestProjection];
|
|
63187
63235
|
const unique = combined.filter((source, index) => combined.findIndex((candidate2) => isDeepStrictEqual13(candidate2, source)) === index);
|
|
63188
63236
|
return { ...supplied, roots: [...new Set([...roots, ...supplied.roots])].sort(), sources: unique, ...agent === "gemini" ? { builtinNames } : {} };
|
|
@@ -94457,7 +94505,11 @@ var exports_selected_run = {};
|
|
|
94457
94505
|
__export(exports_selected_run, {
|
|
94458
94506
|
resolveSelectedRun: () => resolveSelectedRun,
|
|
94459
94507
|
prepareSelectedSecretBindings: () => prepareSelectedSecretBindings,
|
|
94460
|
-
|
|
94508
|
+
instructionRunRefusal: () => instructionRunRefusal,
|
|
94509
|
+
instructionEntrypointMismatch: () => instructionEntrypointMismatch,
|
|
94510
|
+
instructionCommandEntry: () => instructionCommandEntry,
|
|
94511
|
+
executeSelectedLocal: () => executeSelectedLocal,
|
|
94512
|
+
declaredOperation: () => declaredOperation
|
|
94461
94513
|
});
|
|
94462
94514
|
import { createHash as createHash36 } from "crypto";
|
|
94463
94515
|
import { spawn as spawn3 } from "child_process";
|
|
@@ -94470,12 +94522,51 @@ async function resolveSelectedRun(spec, profileId, options = {}) {
|
|
|
94470
94522
|
const entries = await readSelectedEntries(selection2, context, options);
|
|
94471
94523
|
return { selection: selection2, profileId: context.receipt.profile.profileId, entries, ...describeEntries(entries), cacheDir: selectionCacheRoot(options) };
|
|
94472
94524
|
}
|
|
94525
|
+
function declaredOperation(manifest) {
|
|
94526
|
+
const entry = instructionCommandEntry(manifest);
|
|
94527
|
+
if (!entry)
|
|
94528
|
+
return null;
|
|
94529
|
+
const runtime = manifest.runtime;
|
|
94530
|
+
if (!runtime || typeof runtime !== "object" || Array.isArray(runtime))
|
|
94531
|
+
return null;
|
|
94532
|
+
if (runtime.runtime !== "bun" && runtime.runtime !== "node" && runtime.runtime !== "python3")
|
|
94533
|
+
return null;
|
|
94534
|
+
if (instructionEntrypointMismatch(manifest))
|
|
94535
|
+
return null;
|
|
94536
|
+
return { entry };
|
|
94537
|
+
}
|
|
94538
|
+
function instructionCommandEntry(manifest) {
|
|
94539
|
+
const commands = Array.isArray(manifest.commands) ? manifest.commands : [];
|
|
94540
|
+
const command = commands[0];
|
|
94541
|
+
if (!command || typeof command !== "object" || typeof command.entry !== "string" || command.entry.length === 0)
|
|
94542
|
+
return null;
|
|
94543
|
+
return command.entry;
|
|
94544
|
+
}
|
|
94545
|
+
function instructionEntrypointMismatch(manifest) {
|
|
94546
|
+
const entry = instructionCommandEntry(manifest);
|
|
94547
|
+
const declared = manifest.runtime;
|
|
94548
|
+
if (!entry || !declared || typeof declared !== "object" || Array.isArray(declared))
|
|
94549
|
+
return null;
|
|
94550
|
+
const runtimeEntrypoint = declared.entrypoint;
|
|
94551
|
+
return typeof runtimeEntrypoint === "string" && runtimeEntrypoint !== entry ? runtimeEntrypoint : null;
|
|
94552
|
+
}
|
|
94553
|
+
function instructionRunRefusal(manifest, isBundledFile) {
|
|
94554
|
+
const declaredEntry = instructionCommandEntry(manifest);
|
|
94555
|
+
if (declaredEntry && !isBundledFile(declaredEntry))
|
|
94556
|
+
return { code: "LOCAL_ENTRYPOINT_MISSING", message: `This selected instruction skill declares its operation entry as ${declaredEntry}, which is not a regular file in the selected bundle; a different runtime.entrypoint never substitutes for it.` };
|
|
94557
|
+
const mismatch = instructionEntrypointMismatch(manifest);
|
|
94558
|
+
if (mismatch)
|
|
94559
|
+
return { code: "LOCAL_ENTRYPOINT_MISMATCH", message: `This selected instruction skill declares its operation entry as ${declaredEntry}, but its runtime.entrypoint is ${mismatch}; the two must agree.` };
|
|
94560
|
+
if (!declaredOperation(manifest))
|
|
94561
|
+
return { code: "INSTRUCTION_SKILL", message: "This selected skill contains instructions. Use skills load instead of skills run." };
|
|
94562
|
+
return null;
|
|
94563
|
+
}
|
|
94473
94564
|
async function prepareSelectedSecretBindings(selected, cwd2 = process.cwd()) {
|
|
94474
94565
|
const entries = await readCachedSelection(selected.selection, { cacheDir: selected.cacheDir });
|
|
94475
94566
|
if (!entries)
|
|
94476
94567
|
throw new SkillSelectionError("CACHED_BUNDLE_MISSING", "The selected execution bundle is not cached.");
|
|
94477
94568
|
const { kind, manifest } = describeEntries(entries);
|
|
94478
|
-
if (kind !== "executable")
|
|
94569
|
+
if (kind !== "executable" && !declaredOperation(manifest))
|
|
94479
94570
|
throw new SkillSelectionError("INSTRUCTION_SKILL", "Instruction skills do not accept execution secret bindings.");
|
|
94480
94571
|
const names = declaredSecretNames(manifest.runtime?.env);
|
|
94481
94572
|
if (!names.length)
|
|
@@ -94488,8 +94579,12 @@ async function executeSelectedLocal(selected, options = {}) {
|
|
|
94488
94579
|
if (!entries)
|
|
94489
94580
|
throw new SkillSelectionError("CACHED_BUNDLE_MISSING", "The selected local execution bundle is not cached.");
|
|
94490
94581
|
const { kind, manifest, packageJson } = describeEntries(entries);
|
|
94491
|
-
|
|
94492
|
-
|
|
94582
|
+
const operation = declaredOperation(manifest);
|
|
94583
|
+
if (kind === "instruction") {
|
|
94584
|
+
const refusal3 = instructionRunRefusal(manifest, (path) => entries.some((entry) => entry.path === path));
|
|
94585
|
+
if (refusal3)
|
|
94586
|
+
throw new SkillSelectionError(refusal3.code, refusal3.message);
|
|
94587
|
+
}
|
|
94493
94588
|
const runtime = manifest.runtime ?? {};
|
|
94494
94589
|
if (!runtime || typeof runtime !== "object" || Array.isArray(runtime))
|
|
94495
94590
|
throw new SkillSelectionError("INVALID_SKILL_MANIFEST", "The selected runtime declaration is invalid.");
|
|
@@ -94508,9 +94603,9 @@ async function executeSelectedLocal(selected, options = {}) {
|
|
|
94508
94603
|
const executable2 = runtimeName === "bun" ? process.execPath : Bun.which(runtimeName);
|
|
94509
94604
|
if (!executable2)
|
|
94510
94605
|
throw new SkillSelectionError("LOCAL_RUNTIME_UNAVAILABLE", "The selected runtime is not installed on this station.");
|
|
94511
|
-
const declaredEntry = runtime.entrypoint ?? (typeof packageJson.bin === "string" ? packageJson.bin : packageJson.bin && typeof packageJson.bin === "object" ? Object.values(packageJson.bin)[0] : undefined);
|
|
94606
|
+
const declaredEntry = (kind === "instruction" ? operation?.entry : undefined) ?? runtime.entrypoint ?? (typeof packageJson.bin === "string" ? packageJson.bin : packageJson.bin && typeof packageJson.bin === "object" ? Object.values(packageJson.bin)[0] : undefined);
|
|
94512
94607
|
if (typeof declaredEntry !== "string" || !entries.some((entry) => entry.path === declaredEntry))
|
|
94513
|
-
throw new SkillSelectionError("LOCAL_ENTRYPOINT_MISSING", "The selected bundle must declare a regular-file entrypoint in its runtime manifest or package bin.");
|
|
94608
|
+
throw new SkillSelectionError("LOCAL_ENTRYPOINT_MISSING", kind === "instruction" ? "The selected instruction skill must declare the operation entrypoint it ships in its manifest, and that declared entry must be a regular file in the selected bundle; a different runtime.entrypoint never substitutes for it." : "The selected bundle must declare a regular-file entrypoint in its runtime manifest or package bin.");
|
|
94514
94609
|
const args = options.args ?? [];
|
|
94515
94610
|
if (args.length > 128 || args.some((arg) => typeof arg !== "string" || arg.length > 16384 || arg.includes("\x00")))
|
|
94516
94611
|
throw new SkillSelectionError("INVALID_RUN_INPUT", "Local skill arguments exceed their limits.");
|
|
@@ -94585,6 +94680,7 @@ async function executeSelectedLocal(selected, options = {}) {
|
|
|
94585
94680
|
selection: selection2,
|
|
94586
94681
|
target: "local",
|
|
94587
94682
|
runtime: runtimeName,
|
|
94683
|
+
entrypoint: declaredEntry,
|
|
94588
94684
|
inputDigest: `sha256:${createHash36("sha256").update(input2).digest("hex")}`,
|
|
94589
94685
|
runDirectory,
|
|
94590
94686
|
...executionGrant ? { executionGrant } : {},
|
|
@@ -113378,13 +113474,18 @@ function registerOperationTools(server) {
|
|
|
113378
113474
|
return mcpError("CONFLICTING_EXECUTION_MODES", "Use remote for the configured server catalog and quote, or target for selected execution, not both.");
|
|
113379
113475
|
if (managed && !remote) {
|
|
113380
113476
|
try {
|
|
113381
|
-
const { resolveSelectedRun: resolveSelectedRun2, executeSelectedLocal: executeSelectedLocal2 } = await Promise.resolve().then(() => (init_selected_run(), exports_selected_run));
|
|
113477
|
+
const { resolveSelectedRun: resolveSelectedRun2, executeSelectedLocal: executeSelectedLocal2, instructionRunRefusal: instructionRunRefusal2 } = await Promise.resolve().then(() => (init_selected_run(), exports_selected_run));
|
|
113382
113478
|
const resolved = await resolveSelectedRun2(name, selectedProfileId(), { projectDir: process.cwd() });
|
|
113383
|
-
if (resolved.kind === "instruction")
|
|
113384
|
-
|
|
113479
|
+
if (resolved.kind === "instruction") {
|
|
113480
|
+
const refusal3 = instructionRunRefusal2(resolved.manifest, (path) => resolved.entries.some((entry) => entry.path === path));
|
|
113481
|
+
if (refusal3)
|
|
113482
|
+
return mcpError(refusal3.code, refusal3.message);
|
|
113483
|
+
}
|
|
113385
113484
|
if (files?.length)
|
|
113386
113485
|
return mcpError("SELECTED_INPUT_REQUIRED", "Selected executions require their declared JSON input; use the CLI cloud execution input contract for files.");
|
|
113387
113486
|
if (target === "cloud") {
|
|
113487
|
+
if (resolved.kind === "instruction")
|
|
113488
|
+
return mcpError("INSTRUCTION_SKILL", "Cloud execution requires an executable skill version; run the declared operation locally on a managed station, or load the instructions with skills load.");
|
|
113388
113489
|
if (args?.length || quoteReceipt || maxCredits !== undefined || maxCostCents !== undefined)
|
|
113389
113490
|
return mcpError("SELECTED_INPUT_REQUIRED", "The selected cloud execution contract accepts declared JSON input, not legacy run arguments or quote receipts.");
|
|
113390
113491
|
const { CloudExecutionClient: CloudExecutionClient2 } = await Promise.resolve().then(() => (init_cloud_executions(), exports_cloud_executions));
|
|
@@ -117550,8 +117651,11 @@ async function handleRun(name, args2, options, separatorBeforeSkill) {
|
|
|
117550
117651
|
projectDir: process.cwd(),
|
|
117551
117652
|
sessionId: options.session
|
|
117552
117653
|
}) : undefined;
|
|
117553
|
-
if (selected?.kind === "instruction")
|
|
117554
|
-
|
|
117654
|
+
if (selected?.kind === "instruction") {
|
|
117655
|
+
const refusal3 = instructionRunRefusal(selected.manifest, (path) => selected.entries.some((entry) => entry.path === path));
|
|
117656
|
+
if (refusal3)
|
|
117657
|
+
throw new Error(refusal3.message);
|
|
117658
|
+
}
|
|
117555
117659
|
if (selected) {
|
|
117556
117660
|
slug2 = selected.selection.slug;
|
|
117557
117661
|
version2 = selected.selection.version;
|
|
@@ -117576,6 +117680,8 @@ async function handleRun(name, args2, options, separatorBeforeSkill) {
|
|
|
117576
117680
|
process.exitCode = result4.exitCode;
|
|
117577
117681
|
return;
|
|
117578
117682
|
}
|
|
117683
|
+
if (selected?.kind === "instruction")
|
|
117684
|
+
throw new Error("Cloud execution requires an executable skill version; run the declared operation locally on a managed station, or use skills load for the instructions.");
|
|
117579
117685
|
if (args2.length || options.remote || options.file?.length)
|
|
117580
117686
|
throw new Error("Cloud execution accepts structured --input only");
|
|
117581
117687
|
if (!version2 || options.input === undefined)
|
|
@@ -121866,6 +121972,369 @@ var init_profiles = __esm(() => {
|
|
|
121866
121972
|
init_remote_permissions();
|
|
121867
121973
|
});
|
|
121868
121974
|
|
|
121975
|
+
// src/lib/selection-provenance.ts
|
|
121976
|
+
function label(value) {
|
|
121977
|
+
return value !== undefined && SAFE_LABEL2.test(value) ? value : "an unnamed value";
|
|
121978
|
+
}
|
|
121979
|
+
async function attempt2(read3) {
|
|
121980
|
+
try {
|
|
121981
|
+
return { ok: true, value: await read3() };
|
|
121982
|
+
} catch {
|
|
121983
|
+
return { ok: false, code: "READ_REFUSED" };
|
|
121984
|
+
}
|
|
121985
|
+
}
|
|
121986
|
+
function sameRevision(observed, reference) {
|
|
121987
|
+
return observed !== undefined && reference !== undefined && observed === reference;
|
|
121988
|
+
}
|
|
121989
|
+
function sameIdentity2(observed, reference) {
|
|
121990
|
+
if (observed.profileId !== undefined && reference.profileId !== undefined && observed.profileId !== reference.profileId)
|
|
121991
|
+
return false;
|
|
121992
|
+
if (observed.authority !== undefined && reference.authority !== undefined && observed.authority !== reference.authority)
|
|
121993
|
+
return false;
|
|
121994
|
+
if (observed.workspaceId !== undefined && reference.workspaceId !== undefined && observed.workspaceId !== reference.workspaceId)
|
|
121995
|
+
return false;
|
|
121996
|
+
return true;
|
|
121997
|
+
}
|
|
121998
|
+
function supportedIdentityValue(value) {
|
|
121999
|
+
return typeof value === "string" && value.trim() !== "";
|
|
122000
|
+
}
|
|
122001
|
+
function uncomparableFields(observed, reference, required2) {
|
|
122002
|
+
return required2.filter((field3) => !supportedIdentityValue(observed[field3]) || !supportedIdentityValue(reference[field3]));
|
|
122003
|
+
}
|
|
122004
|
+
function supportedIdentityFields(source) {
|
|
122005
|
+
const out = {};
|
|
122006
|
+
for (const field3 of ["profileId", "profileRevision", "authority", "workspaceId"]) {
|
|
122007
|
+
const value = source[field3];
|
|
122008
|
+
if (supportedIdentityValue(value))
|
|
122009
|
+
out[field3] = value;
|
|
122010
|
+
}
|
|
122011
|
+
return out;
|
|
122012
|
+
}
|
|
122013
|
+
function revisionReason(labelText, observed, reference, status) {
|
|
122014
|
+
const seen = label(observed);
|
|
122015
|
+
if (status === "current")
|
|
122016
|
+
return `${labelText} revision ${seen} is the selected revision`;
|
|
122017
|
+
return `${labelText} revision ${seen} is not the selected revision ${label(reference)}`;
|
|
122018
|
+
}
|
|
122019
|
+
async function resolveReference(input3, options) {
|
|
122020
|
+
const fromSnapshot = (reasonCode, because) => {
|
|
122021
|
+
let receipt;
|
|
122022
|
+
try {
|
|
122023
|
+
receipt = readSelectionProfile(input3.profileId, options);
|
|
122024
|
+
} catch {
|
|
122025
|
+
return { profileId: input3.profileId, source: "unavailable", reasonCode: "REFERENCE_UNAVAILABLE", reason: `${because} The locally synced snapshot is unreadable too.`, selections: noSelections };
|
|
122026
|
+
}
|
|
122027
|
+
if (!receipt)
|
|
122028
|
+
return { profileId: input3.profileId, source: "unavailable", reasonCode: "REFERENCE_UNAVAILABLE", reason: `${because} Nothing is synced locally either, so no consumer can be compared.`, selections: noSelections };
|
|
122029
|
+
return {
|
|
122030
|
+
profileId: receipt.profile.profileId,
|
|
122031
|
+
...supportedIdentityFields({ profileRevision: receipt.profile.profileRevision, authority: receipt.profile.authority, workspaceId: receipt.profile.workspaceId }),
|
|
122032
|
+
selectionCount: receipt.profile.selections.length,
|
|
122033
|
+
observedAt: receipt.verifiedAt,
|
|
122034
|
+
source: "synced-snapshot",
|
|
122035
|
+
reasonCode,
|
|
122036
|
+
reason: `${because} Comparisons use the locally synced snapshot (posted work is not proof of adoption), so every consumer below is reported unverified rather than current.`,
|
|
122037
|
+
selections: receipt.profile.selections
|
|
122038
|
+
};
|
|
122039
|
+
};
|
|
122040
|
+
if (input3.cached)
|
|
122041
|
+
return fromSnapshot("REFERENCE_NOT_AUTHORITY", "--cached was requested, so the authority was not read.");
|
|
122042
|
+
const read3 = options.readSelected ?? (async (profileId) => {
|
|
122043
|
+
const client2 = await createProfileClient();
|
|
122044
|
+
const profile2 = await client2.resolveProfile(profileId);
|
|
122045
|
+
return { profileId: profile2.profileId, profileRevision: profile2.profileRevision, authority: profile2.authority, workspaceId: profile2.workspaceId, selections: profile2.selections };
|
|
122046
|
+
});
|
|
122047
|
+
const attempted = await attempt2(() => read3(input3.profileId));
|
|
122048
|
+
if (!attempted.ok)
|
|
122049
|
+
return fromSnapshot("READ_REFUSED", "The authority did not answer for the selected profile.");
|
|
122050
|
+
const profile = attempted.value;
|
|
122051
|
+
if (!profile?.profileId || !profile.profileRevision || !Array.isArray(profile.selections)) {
|
|
122052
|
+
return { profileId: input3.profileId, source: "unavailable", reasonCode: "REFERENCE_UNAVAILABLE", reason: "The authority returned a selection profile this client does not recognise, so no consumer can be compared.", selections: noSelections };
|
|
122053
|
+
}
|
|
122054
|
+
return {
|
|
122055
|
+
profileId: profile.profileId,
|
|
122056
|
+
profileRevision: profile.profileRevision,
|
|
122057
|
+
selectionCount: profile.selections.length,
|
|
122058
|
+
...profile.authority === undefined ? {} : { authority: profile.authority },
|
|
122059
|
+
...profile.workspaceId === undefined ? {} : { workspaceId: profile.workspaceId },
|
|
122060
|
+
source: "authority",
|
|
122061
|
+
reasonCode: "REFERENCE_FROM_AUTHORITY",
|
|
122062
|
+
reason: `Read from the authority for profile ${label(profile.profileId)}.`,
|
|
122063
|
+
selections: profile.selections
|
|
122064
|
+
};
|
|
122065
|
+
}
|
|
122066
|
+
function activationConsumer(input3, reference, options) {
|
|
122067
|
+
const base3 = {
|
|
122068
|
+
kind: "station",
|
|
122069
|
+
source: "local-receipt",
|
|
122070
|
+
id: input3.localStationId,
|
|
122071
|
+
idKind: "local-host",
|
|
122072
|
+
status: "unverified",
|
|
122073
|
+
reasonCode: "NO_LOCAL_RECEIPT",
|
|
122074
|
+
reason: ""
|
|
122075
|
+
};
|
|
122076
|
+
const refuse10 = (reasonCode, reason2) => ({ consumer: { ...base3, reasonCode, reason: reason2 }, compared: noSelections });
|
|
122077
|
+
let receipt;
|
|
122078
|
+
try {
|
|
122079
|
+
receipt = readSelectionProfile(input3.profileId, options);
|
|
122080
|
+
} catch {
|
|
122081
|
+
return refuse10("READ_REFUSED", `This machine's activated snapshot for profile ${label(input3.profileId)} could not be read.`);
|
|
122082
|
+
}
|
|
122083
|
+
if (!receipt)
|
|
122084
|
+
return refuse10("NO_LOCAL_RECEIPT", `This machine holds no activated snapshot for profile ${label(input3.profileId)}.`);
|
|
122085
|
+
const profile = receipt.profile;
|
|
122086
|
+
const observed = {
|
|
122087
|
+
...base3,
|
|
122088
|
+
...supportedIdentityFields({ profileId: profile.profileId, profileRevision: profile.profileRevision, authority: profile.authority, workspaceId: profile.workspaceId }),
|
|
122089
|
+
observedAt: receipt.verifiedAt,
|
|
122090
|
+
selectionCount: profile.selections.length
|
|
122091
|
+
};
|
|
122092
|
+
if (!sameIdentity2(observed, reference)) {
|
|
122093
|
+
return { consumer: { ...observed, status: "unverified", reasonCode: "IDENTITY_MISMATCH", reason: `This machine's activated snapshot is not the selected selection's identity: it differs in profile, authority or workspace, so it is not current whatever its revision.` }, compared: noSelections };
|
|
122094
|
+
}
|
|
122095
|
+
if (reference.source !== "authority") {
|
|
122096
|
+
return { consumer: { ...observed, status: "unverified", reasonCode: reference.reasonCode, reason: `${reference.reason} This snapshot alone cannot say whether the machine is current.` }, compared: noSelections };
|
|
122097
|
+
}
|
|
122098
|
+
const missingActivation = uncomparableFields(observed, reference, REQUIRED_IDENTITY["local-receipt"]);
|
|
122099
|
+
if (missingActivation.length > 0) {
|
|
122100
|
+
return { consumer: { ...observed, status: "unverified", reasonCode: "INCOMPLETE_RECEIPT", reason: `This machine's activated snapshot does not record ${missingActivation.join(", ")}, so its identity and revision cannot be compared; it is reported unverified rather than current or behind.` }, compared: noSelections };
|
|
122101
|
+
}
|
|
122102
|
+
const status = sameRevision(profile.profileRevision, reference.profileRevision) ? "current" : "behind";
|
|
122103
|
+
return {
|
|
122104
|
+
consumer: {
|
|
122105
|
+
...observed,
|
|
122106
|
+
status,
|
|
122107
|
+
reasonCode: status === "current" ? "CURRENT_SCHEMA_MATCH" : "REVISION_BEHIND",
|
|
122108
|
+
reason: status === "current" ? revisionReason("This machine's activated snapshot", profile.profileRevision, reference.profileRevision, "current") : `${revisionReason("This machine's activated snapshot", profile.profileRevision, reference.profileRevision, "behind")}. Run skills sync to activate the selected revision here.`
|
|
122109
|
+
},
|
|
122110
|
+
compared: profile.selections
|
|
122111
|
+
};
|
|
122112
|
+
}
|
|
122113
|
+
async function stationConsumer(input3, reference, options) {
|
|
122114
|
+
const base3 = {
|
|
122115
|
+
kind: "station",
|
|
122116
|
+
source: "authority-receipt",
|
|
122117
|
+
id: input3.stationId,
|
|
122118
|
+
idKind: "requested-station",
|
|
122119
|
+
status: "unverified",
|
|
122120
|
+
reasonCode: "NO_STATION_REPORTED",
|
|
122121
|
+
reason: ""
|
|
122122
|
+
};
|
|
122123
|
+
const refuse10 = (reasonCode, reason2) => ({ consumer: { ...base3, reasonCode, reason: reason2 }, compared: noSelections });
|
|
122124
|
+
if (reference.source !== "authority") {
|
|
122125
|
+
return refuse10("REFERENCE_NOT_AUTHORITY", "The station receipt was not compared: this receipt has no authenticated selection to compare it with.");
|
|
122126
|
+
}
|
|
122127
|
+
const read3 = options.readStation ?? (async (stationId) => {
|
|
122128
|
+
const state = await readStationSkillState(stationId);
|
|
122129
|
+
return { profileId: state.profileId, profileRevision: state.profileRevision, appliedAt: state.appliedAt, workspaceId: state.workspaceId, selections: state.selections };
|
|
122130
|
+
});
|
|
122131
|
+
const attempted = await attempt2(() => read3(input3.stationId));
|
|
122132
|
+
if (!attempted.ok)
|
|
122133
|
+
return refuse10("READ_REFUSED", `The authority did not answer for station ${label(input3.stationId)}.`);
|
|
122134
|
+
const station = attempted.value;
|
|
122135
|
+
const observed = {
|
|
122136
|
+
...base3,
|
|
122137
|
+
...supportedIdentityFields({ profileId: station.profileId, profileRevision: station.profileRevision, workspaceId: station.workspaceId }),
|
|
122138
|
+
observedAt: station.appliedAt,
|
|
122139
|
+
selectionCount: station.selections.length
|
|
122140
|
+
};
|
|
122141
|
+
if (!sameIdentity2(observed, reference)) {
|
|
122142
|
+
return { consumer: { ...observed, status: "unverified", reasonCode: "IDENTITY_MISMATCH", reason: `Station ${label(input3.stationId)} last applied a different selection identity: it differs in profile or workspace from the selected profile.` }, compared: noSelections };
|
|
122143
|
+
}
|
|
122144
|
+
const missing2 = uncomparableFields(observed, reference, REQUIRED_IDENTITY["authority-receipt"]);
|
|
122145
|
+
if (missing2.length > 0) {
|
|
122146
|
+
return { consumer: { ...observed, status: "unverified", reasonCode: "INCOMPLETE_RECEIPT", reason: `The receipt the authority holds for station ${label(input3.stationId)} does not record ${missing2.join(", ")}, so its identity and revision cannot be compared; it is reported unverified rather than current or behind.` }, compared: noSelections };
|
|
122147
|
+
}
|
|
122148
|
+
if (sameRevision(station.profileRevision, reference.profileRevision)) {
|
|
122149
|
+
return { consumer: { ...observed, status: "current", reasonCode: "CURRENT_SCHEMA_MATCH", reason: revisionReason(`The receipt the authority holds for station ${label(input3.stationId)}`, station.profileRevision, reference.profileRevision, "current") }, compared: station.selections };
|
|
122150
|
+
}
|
|
122151
|
+
return {
|
|
122152
|
+
consumer: {
|
|
122153
|
+
...observed,
|
|
122154
|
+
status: "behind",
|
|
122155
|
+
reasonCode: "REVISION_BEHIND",
|
|
122156
|
+
reason: `${revisionReason(`The receipt the authority holds for station ${label(input3.stationId)}`, station.profileRevision, reference.profileRevision, "behind")}. Only an explicit skills sync writes this record, so report it before treating the machine as adrift.`
|
|
122157
|
+
},
|
|
122158
|
+
compared: station.selections
|
|
122159
|
+
};
|
|
122160
|
+
}
|
|
122161
|
+
function sessionConsumer(input3, reference, options) {
|
|
122162
|
+
const unnamed = {
|
|
122163
|
+
kind: "session",
|
|
122164
|
+
source: "session-receipt",
|
|
122165
|
+
id: "unnamed",
|
|
122166
|
+
idKind: "local-host",
|
|
122167
|
+
status: "unverified",
|
|
122168
|
+
reasonCode: "NO_SESSION_NAMED",
|
|
122169
|
+
reason: "No session was named, so its pin and load receipts were not read; pass --session <id>."
|
|
122170
|
+
};
|
|
122171
|
+
if (!input3.sessionId)
|
|
122172
|
+
return { consumer: unnamed, compared: noSelections };
|
|
122173
|
+
const base3 = {
|
|
122174
|
+
kind: "session",
|
|
122175
|
+
source: "session-receipt",
|
|
122176
|
+
id: input3.sessionId,
|
|
122177
|
+
idKind: "local-host",
|
|
122178
|
+
status: "unverified",
|
|
122179
|
+
reasonCode: "NO_SESSION_RECEIPT",
|
|
122180
|
+
reason: ""
|
|
122181
|
+
};
|
|
122182
|
+
const refuse10 = (reasonCode, reason2) => ({ consumer: { ...base3, reasonCode, reason: reason2 }, compared: noSelections });
|
|
122183
|
+
let session;
|
|
122184
|
+
try {
|
|
122185
|
+
session = inspectSkillSession(input3.sessionId, options);
|
|
122186
|
+
} catch {
|
|
122187
|
+
return refuse10("READ_REFUSED", `The session receipt for the named session could not be read.`);
|
|
122188
|
+
}
|
|
122189
|
+
const consumed = session.selections.filter((selection2) => selection2.loaded).map((selection2) => ({ slug: selection2.slug, version: selection2.version, bundleDigest: selection2.bundleDigest }));
|
|
122190
|
+
const observed = {
|
|
122191
|
+
...base3,
|
|
122192
|
+
...supportedIdentityFields({ profileId: session.profileId, profileRevision: session.profileRevision, authority: session.authority, workspaceId: session.workspaceId }),
|
|
122193
|
+
observedAt: session.verifiedAt,
|
|
122194
|
+
selectionCount: session.selectionCount,
|
|
122195
|
+
loadedCount: session.loadedCount,
|
|
122196
|
+
consumed
|
|
122197
|
+
};
|
|
122198
|
+
if (!sameIdentity2(observed, reference)) {
|
|
122199
|
+
return { consumer: { ...observed, status: "unverified", reasonCode: "IDENTITY_MISMATCH", reason: "The session pin is not the selected selection's identity: it differs in profile, authority or workspace, so it is not current whatever its revision." }, compared: noSelections };
|
|
122200
|
+
}
|
|
122201
|
+
if (reference.source !== "authority") {
|
|
122202
|
+
return { consumer: { ...observed, status: "unverified", reasonCode: reference.reasonCode, reason: `${reference.reason} This pin alone cannot say whether the session is current.` }, compared: noSelections };
|
|
122203
|
+
}
|
|
122204
|
+
const missingPin = uncomparableFields(observed, reference, REQUIRED_IDENTITY["session-receipt"]);
|
|
122205
|
+
if (missingPin.length > 0) {
|
|
122206
|
+
return { consumer: { ...observed, status: "unverified", reasonCode: "INCOMPLETE_RECEIPT", reason: `The session receipt does not record ${missingPin.join(", ")}, so its identity and revision cannot be compared; it is reported unverified rather than current, pinned or behind.` }, compared: noSelections };
|
|
122207
|
+
}
|
|
122208
|
+
if (sameRevision(session.profileRevision, reference.profileRevision)) {
|
|
122209
|
+
return {
|
|
122210
|
+
consumer: { ...observed, status: "current", reasonCode: "CURRENT_SCHEMA_MATCH", reason: `${revisionReason("The session pin", session.profileRevision, reference.profileRevision, "current")}; it loaded ${session.loadedCount} of ${session.selectionCount} selections.` },
|
|
122211
|
+
compared: consumed
|
|
122212
|
+
};
|
|
122213
|
+
}
|
|
122214
|
+
return {
|
|
122215
|
+
consumer: {
|
|
122216
|
+
...observed,
|
|
122217
|
+
status: "pinned",
|
|
122218
|
+
reasonCode: "PINNED_BY_DESIGN",
|
|
122219
|
+
reason: `${revisionReason("The session pin", session.profileRevision, reference.profileRevision, "pinned")}. A session keeps its revision when the profile moves on, so this is custody by design; skills sessions reconcile moves it intentionally.`
|
|
122220
|
+
},
|
|
122221
|
+
compared: consumed
|
|
122222
|
+
};
|
|
122223
|
+
}
|
|
122224
|
+
function driftFor(result2, reference) {
|
|
122225
|
+
if (reference.source !== "authority" || result2.compared.length === 0)
|
|
122226
|
+
return [];
|
|
122227
|
+
if (result2.consumer.status === "unverified" && result2.consumer.reasonCode === "IDENTITY_MISMATCH")
|
|
122228
|
+
return [];
|
|
122229
|
+
const selected = new Map(reference.selections.map((selection2) => [selection2.slug, selection2.version]));
|
|
122230
|
+
return result2.compared.filter((selection2) => selected.has(selection2.slug) && selected.get(selection2.slug) !== selection2.version).map((selection2) => ({ source: result2.consumer.source, id: result2.consumer.id, slug: selection2.slug, selectedVersion: selected.get(selection2.slug), observedVersion: selection2.version })).sort((left, right) => left.slug.localeCompare(right.slug) || left.source.localeCompare(right.source));
|
|
122231
|
+
}
|
|
122232
|
+
async function readSelectionProvenance(input3, options = {}) {
|
|
122233
|
+
if (!input3.profileId?.trim())
|
|
122234
|
+
throw new Error("A selection profile id is required to read selection provenance.");
|
|
122235
|
+
if (!input3.stationId?.trim() || input3.stationId.length > LABEL_MAX_CHARS)
|
|
122236
|
+
throw new Error("A station id is required to read selection provenance.");
|
|
122237
|
+
if (!input3.localStationId?.trim() || input3.localStationId.length > LABEL_MAX_CHARS)
|
|
122238
|
+
throw new Error("The local host id is required to read selection provenance.");
|
|
122239
|
+
const reference = await resolveReference(input3, options);
|
|
122240
|
+
const results2 = [activationConsumer(input3, reference, options), await stationConsumer(input3, reference, options), sessionConsumer(input3, reference, options)];
|
|
122241
|
+
const drift = results2.flatMap((result2) => driftFor(result2, reference));
|
|
122242
|
+
return {
|
|
122243
|
+
schemaVersion: 1,
|
|
122244
|
+
readOnly: true,
|
|
122245
|
+
selectionProfile: input3.profileId,
|
|
122246
|
+
selected: {
|
|
122247
|
+
profileId: reference.profileId,
|
|
122248
|
+
...supportedIdentityValue(reference.profileRevision) ? { profileRevision: reference.profileRevision, selectionCount: reference.selectionCount } : {},
|
|
122249
|
+
...supportedIdentityValue(reference.authority) ? { authority: reference.authority } : {},
|
|
122250
|
+
...supportedIdentityValue(reference.workspaceId) ? { workspaceId: reference.workspaceId } : {},
|
|
122251
|
+
...reference.observedAt === undefined ? {} : { observedAt: reference.observedAt },
|
|
122252
|
+
source: reference.source,
|
|
122253
|
+
reasonCode: reference.reasonCode,
|
|
122254
|
+
reason: reference.reason
|
|
122255
|
+
},
|
|
122256
|
+
consumers: results2.map((result2) => result2.consumer),
|
|
122257
|
+
drift: drift.slice(0, PROVENANCE_DRIFT_LIMIT),
|
|
122258
|
+
driftTruncated: drift.length > PROVENANCE_DRIFT_LIMIT,
|
|
122259
|
+
notAttested: [
|
|
122260
|
+
"Published version and digest evidence for skill payloads: read it with skills versions and skills review-export.",
|
|
122261
|
+
"Native discovery, native locks and project locks: read them with skills hook check and skills sessions recover-lock.",
|
|
122262
|
+
"Live consumer adoption: a receipt shows what a session loaded, never that an agent honoured it."
|
|
122263
|
+
]
|
|
122264
|
+
};
|
|
122265
|
+
}
|
|
122266
|
+
var PROVENANCE_DRIFT_LIMIT = 200, SAFE_LABEL2, LABEL_MAX_CHARS = 200, noSelections, REQUIRED_IDENTITY;
|
|
122267
|
+
var init_selection_provenance = __esm(() => {
|
|
122268
|
+
init_session_reconciliation();
|
|
122269
|
+
init_profile_admin();
|
|
122270
|
+
init_profile_client();
|
|
122271
|
+
init_selection_cache();
|
|
122272
|
+
SAFE_LABEL2 = /^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/;
|
|
122273
|
+
noSelections = [];
|
|
122274
|
+
REQUIRED_IDENTITY = {
|
|
122275
|
+
"local-receipt": ["profileId", "profileRevision", "authority", "workspaceId"],
|
|
122276
|
+
"session-receipt": ["profileId", "profileRevision", "authority", "workspaceId"],
|
|
122277
|
+
"authority-receipt": ["profileId", "profileRevision", "workspaceId"]
|
|
122278
|
+
};
|
|
122279
|
+
});
|
|
122280
|
+
|
|
122281
|
+
// src/cli/commands/provenance.ts
|
|
122282
|
+
var exports_provenance = {};
|
|
122283
|
+
__export(exports_provenance, {
|
|
122284
|
+
registerProvenance: () => registerProvenance,
|
|
122285
|
+
provenanceLines: () => provenanceLines
|
|
122286
|
+
});
|
|
122287
|
+
import { hostname as hostname5 } from "os";
|
|
122288
|
+
function provenanceLines(receipt) {
|
|
122289
|
+
const selected = receipt.selected;
|
|
122290
|
+
const lines = [
|
|
122291
|
+
`Selection profile ${receipt.selectionProfile}`,
|
|
122292
|
+
`Selected: ${selected.profileRevision ?? "unavailable"} (${selected.selectionCount ?? 0} selections, ${selected.source})`
|
|
122293
|
+
];
|
|
122294
|
+
for (const consumer of receipt.consumers)
|
|
122295
|
+
lines.push(...consumerLines(consumer));
|
|
122296
|
+
if (receipt.drift.length > 0) {
|
|
122297
|
+
lines.push(`Drift (${receipt.drift.length}${receipt.driftTruncated ? ", truncated" : ""}):`);
|
|
122298
|
+
for (const row2 of receipt.drift)
|
|
122299
|
+
lines.push(`- ${row2.source} ${row2.id}: ${row2.slug} ${row2.selectedVersion} -> ${row2.observedVersion}`);
|
|
122300
|
+
}
|
|
122301
|
+
return lines;
|
|
122302
|
+
}
|
|
122303
|
+
function consumerLines(consumer) {
|
|
122304
|
+
const label2 = consumer.kind === "session" ? "Pinned" : consumer.source === "local-receipt" ? "Activated" : "Applied";
|
|
122305
|
+
const identity6 = consumer.kind === "session" ? `session ${consumer.id}` : consumer.idKind === "local-host" ? `this machine (${consumer.id})` : `station ${consumer.id}`;
|
|
122306
|
+
const lines = [`${label2}: ${identity6} ${consumer.profileRevision ?? "no receipt"} [${consumer.status}] ${consumer.reasonCode}`, ` ${consumer.reason}`];
|
|
122307
|
+
if (consumer.kind === "session" && consumer.consumed) {
|
|
122308
|
+
lines.push(`Consumed: ${consumer.loadedCount ?? 0} of ${consumer.selectionCount ?? 0} selections loaded`);
|
|
122309
|
+
for (const selection2 of consumer.consumed)
|
|
122310
|
+
lines.push(`- ${selection2.slug}@${selection2.version} ${selection2.bundleDigest}`);
|
|
122311
|
+
}
|
|
122312
|
+
return lines;
|
|
122313
|
+
}
|
|
122314
|
+
function registerProvenance(parent) {
|
|
122315
|
+
parent.command("provenance").description("Read-only receipt of the selected, activated, applied, pinned and actually loaded skill versions").option("--selection-profile <id>", "Selection profile to read (default: the managed profile)").option("--station <id>", "Station whose sync receipt to read (default: HASNA_STATION, then this host)").option("--session <id>", "Also report one session's pin and the versions it actually loaded").option("--cached", "Read the reference from the locally synced snapshot and never ask the authority", false).option("--json", "Return the receipt as JSON", false).action(async (options) => {
|
|
122316
|
+
try {
|
|
122317
|
+
const localStationId = process.env.HASNA_STATION ?? hostname5();
|
|
122318
|
+
const receipt = await readSelectionProvenance({
|
|
122319
|
+
profileId: selectedProfileId(options.selectionProfile),
|
|
122320
|
+
localStationId,
|
|
122321
|
+
stationId: options.station ?? localStationId,
|
|
122322
|
+
...options.session === undefined ? {} : { sessionId: options.session },
|
|
122323
|
+
...options.cached ? { cached: true } : {}
|
|
122324
|
+
});
|
|
122325
|
+
await writeCliOutput(options.json ? JSON.stringify(receipt) : provenanceLines(receipt).join(`
|
|
122326
|
+
`));
|
|
122327
|
+
} catch (error61) {
|
|
122328
|
+
console.error(error61.message);
|
|
122329
|
+
process.exitCode = 1;
|
|
122330
|
+
}
|
|
122331
|
+
});
|
|
122332
|
+
}
|
|
122333
|
+
var init_provenance = __esm(() => {
|
|
122334
|
+
init_selection_provenance();
|
|
122335
|
+
init_context();
|
|
122336
|
+
});
|
|
122337
|
+
|
|
121869
122338
|
// src/cli/commands/grants.ts
|
|
121870
122339
|
var exports_grants = {};
|
|
121871
122340
|
__export(exports_grants, {
|
|
@@ -123312,7 +123781,7 @@ __export(exports_publish, {
|
|
|
123312
123781
|
});
|
|
123313
123782
|
import { execFileSync as execFileSync3 } from "child_process";
|
|
123314
123783
|
import { existsSync as existsSync39, readFileSync as readFileSync52 } from "fs";
|
|
123315
|
-
import { hostname as
|
|
123784
|
+
import { hostname as hostname6 } from "os";
|
|
123316
123785
|
import { join as join79 } from "path";
|
|
123317
123786
|
function registerPublish(parent) {
|
|
123318
123787
|
parent.command("push").argument("<name>", "Name of a skill in the local corpus (~/.hasna/skills/installed or the migrated ~/.hasna/skills/skills)").option("--version <version>", "Override the version recorded on the instance").option("--force-new-version", "If name@version already exists with different content, publish as the next patch version", false).option("--dry-run", "Pack and validate without uploading", false).option("--json", "Output result as JSON", false).description("Publish a local skill to the configured skills instance").action(async (name, options) => {
|
|
@@ -123496,7 +123965,7 @@ function buildVersionManifest(skillDir, packed) {
|
|
|
123496
123965
|
unpackedByteSize: packed.unpackedByteSize,
|
|
123497
123966
|
bundleSha256: packed.sha256,
|
|
123498
123967
|
provenance: {
|
|
123499
|
-
machine:
|
|
123968
|
+
machine: hostname6(),
|
|
123500
123969
|
agent: process.env.SKILLS_AGENT_ID ?? process.env.HASNA_AGENT_ID ?? process.env.AGENT_ID ?? null,
|
|
123501
123970
|
cliVersion: package_default.version,
|
|
123502
123971
|
gitRemote: sanitizeGitRemote(gitValue(skillDir, ["remote", "get-url", "origin"])),
|
|
@@ -123875,9 +124344,9 @@ function printWhoami(payload) {
|
|
|
123875
124344
|
console.log(source_default.dim(`Auth: ${payload.authSource}`));
|
|
123876
124345
|
const permissions = recordField(payload.permissions);
|
|
123877
124346
|
if (permissions) {
|
|
123878
|
-
const
|
|
123879
|
-
console.log(`Publish: ${
|
|
123880
|
-
console.log(`Profiles write: ${
|
|
124347
|
+
const label2 = (value) => value === true ? "allowed" : value === false ? "denied" : "unknown";
|
|
124348
|
+
console.log(`Publish: ${label2(permissions.publish)}`);
|
|
124349
|
+
console.log(`Profiles write: ${label2(permissions.profilesWrite)}`);
|
|
123881
124350
|
}
|
|
123882
124351
|
if (payload.offline)
|
|
123883
124352
|
console.log(source_default.dim("(offline \u2014 showing cached info)"));
|
|
@@ -124503,7 +124972,7 @@ function promptInvitationRecoveryCode() {
|
|
|
124503
124972
|
}
|
|
124504
124973
|
function promptInvitationProof(kind) {
|
|
124505
124974
|
const length = kind === "token" ? 43 : 6;
|
|
124506
|
-
const
|
|
124975
|
+
const label2 = kind === "token" ? "invitation token" : "recovery code";
|
|
124507
124976
|
const character = kind === "token" ? /^[A-Za-z0-9_-]$/ : /^\d$/;
|
|
124508
124977
|
const { stdin, stderr: output2 } = process, wasRaw = stdin.isRaw, wasFlowing = stdin.readableFlowing;
|
|
124509
124978
|
return new Promise((resolve49) => {
|
|
@@ -124534,13 +125003,13 @@ function promptInvitationProof(kind) {
|
|
|
124534
125003
|
value = "";
|
|
124535
125004
|
overflow = false;
|
|
124536
125005
|
output2.write(`
|
|
124537
|
-
Enter exactly ${length} ${
|
|
125006
|
+
Enter exactly ${length} ${label2} characters: `);
|
|
124538
125007
|
return;
|
|
124539
125008
|
}
|
|
124540
125009
|
if (value.length === length)
|
|
124541
125010
|
return finish(value);
|
|
124542
125011
|
output2.write(`
|
|
124543
|
-
Enter the complete ${
|
|
125012
|
+
Enter the complete ${label2}: `);
|
|
124544
125013
|
value = "";
|
|
124545
125014
|
return;
|
|
124546
125015
|
}
|
|
@@ -124555,7 +125024,7 @@ Enter the complete ${label}: `);
|
|
|
124555
125024
|
if (value.length === length) {
|
|
124556
125025
|
overflow = true;
|
|
124557
125026
|
output2.write(`
|
|
124558
|
-
The ${
|
|
125027
|
+
The ${label2} is too long. Press Enter to start again.`);
|
|
124559
125028
|
} else {
|
|
124560
125029
|
value += text4;
|
|
124561
125030
|
output2.write("*");
|
|
@@ -124563,7 +125032,7 @@ The ${label} is too long. Press Enter to start again.`);
|
|
|
124563
125032
|
} else if (text4 && !key2.ctrl && !key2.meta) {
|
|
124564
125033
|
overflow = true;
|
|
124565
125034
|
output2.write(`
|
|
124566
|
-
The ${
|
|
125035
|
+
The ${label2} contains invalid characters. Press Enter to start again.`);
|
|
124567
125036
|
}
|
|
124568
125037
|
};
|
|
124569
125038
|
const timer = setTimeout(cancel, 5 * 60 * 1000);
|
|
@@ -133712,6 +134181,8 @@ var { registerPluginAdmission: registerPluginAdmission2 } = await Promise.resolv
|
|
|
133712
134181
|
registerPluginAdmission2(program2);
|
|
133713
134182
|
var { registerProfiles: registerProfiles2 } = await Promise.resolve().then(() => (init_profiles(), exports_profiles));
|
|
133714
134183
|
registerProfiles2(program2);
|
|
134184
|
+
var { registerProvenance: registerProvenance2 } = await Promise.resolve().then(() => (init_provenance(), exports_provenance));
|
|
134185
|
+
registerProvenance2(program2);
|
|
133715
134186
|
var { registerGrants: registerGrants2 } = await Promise.resolve().then(() => (init_grants(), exports_grants));
|
|
133716
134187
|
registerGrants2(program2);
|
|
133717
134188
|
var { registerHydrate: registerHydrate2 } = await Promise.resolve().then(() => (init_hydrate(), exports_hydrate));
|