@hasna/skills 0.10.73 → 0.10.75
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 +684 -142
- package/bin/mcp.js +215 -104
- 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/cli/stray-arguments.d.ts +29 -0
- package/dist/index.js +206 -111
- package/dist/lib/portable-skills-files.d.ts +10 -0
- package/dist/lib/search.d.ts +18 -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 +172 -33
- 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.75",
|
|
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
|
|
@@ -60951,6 +60988,118 @@ var init_skillinfo = __esm(() => {
|
|
|
60951
60988
|
GENERIC_ENV_PATTERN = /\b((?:OPENAI|ANTHROPIC|GEMINI|XAI|ELEVENLABS|DEEPGRAM|REPLICATE|FAL|STABILITY|EXA|FIRECRAWL|TWILIO|SENDGRID|RESEND|SLACK|DISCORD|NOTION|LINEAR|GITHUB|AWS|GOOGLE|CLOUDFLARE|VERCEL|SUPABASE|STRIPE)_[A-Z_]+)\b/g;
|
|
60952
60989
|
});
|
|
60953
60990
|
|
|
60991
|
+
// src/lib/search.ts
|
|
60992
|
+
function editDistance(a, b) {
|
|
60993
|
+
if (a === b)
|
|
60994
|
+
return 0;
|
|
60995
|
+
if (a.length === 0)
|
|
60996
|
+
return b.length;
|
|
60997
|
+
if (b.length === 0)
|
|
60998
|
+
return a.length;
|
|
60999
|
+
const prev = Array.from({ length: b.length + 1 }, (_, i) => i);
|
|
61000
|
+
const curr = new Array(b.length + 1);
|
|
61001
|
+
for (let i = 1;i <= a.length; i++) {
|
|
61002
|
+
curr[0] = i;
|
|
61003
|
+
for (let j = 1;j <= b.length; j++) {
|
|
61004
|
+
const cost = a[i - 1] === b[j - 1] ? 0 : 1;
|
|
61005
|
+
curr[j] = Math.min(curr[j - 1] + 1, prev[j] + 1, prev[j - 1] + cost);
|
|
61006
|
+
}
|
|
61007
|
+
prev.splice(0, prev.length, ...curr);
|
|
61008
|
+
}
|
|
61009
|
+
return prev[b.length];
|
|
61010
|
+
}
|
|
61011
|
+
function fuzzyMatchScore(word, target) {
|
|
61012
|
+
if (target.includes(word))
|
|
61013
|
+
return 1;
|
|
61014
|
+
const tokens = target.split(/[\s\-_]+/).filter(Boolean);
|
|
61015
|
+
for (const token of tokens) {
|
|
61016
|
+
if (token.startsWith(word))
|
|
61017
|
+
return 0.6;
|
|
61018
|
+
}
|
|
61019
|
+
if (word.length >= 3) {
|
|
61020
|
+
const maxDist = word.length <= 3 ? 1 : 2;
|
|
61021
|
+
for (const token of tokens) {
|
|
61022
|
+
if (Math.abs(token.length - word.length) <= maxDist) {
|
|
61023
|
+
const dist = editDistance(word, token);
|
|
61024
|
+
if (dist <= maxDist)
|
|
61025
|
+
return 0.4;
|
|
61026
|
+
}
|
|
61027
|
+
}
|
|
61028
|
+
}
|
|
61029
|
+
return 0;
|
|
61030
|
+
}
|
|
61031
|
+
function searchSkills(query, registry = loadRegistry()) {
|
|
61032
|
+
const words2 = query.toLowerCase().split(/\s+/).filter(Boolean);
|
|
61033
|
+
if (words2.length === 0)
|
|
61034
|
+
return [];
|
|
61035
|
+
const scored = [];
|
|
61036
|
+
for (const skill of registry) {
|
|
61037
|
+
const nameLower = skill.name.toLowerCase();
|
|
61038
|
+
const displayNameLower = skill.displayName.toLowerCase();
|
|
61039
|
+
const descriptionLower = skill.description.toLowerCase();
|
|
61040
|
+
const tagsLower = skill.tags.map((t2) => t2.toLowerCase());
|
|
61041
|
+
const tagsCombined = tagsLower.join(" ");
|
|
61042
|
+
let score = 0;
|
|
61043
|
+
let allWordsMatch = true;
|
|
61044
|
+
for (const word of words2) {
|
|
61045
|
+
let wordScore = 0;
|
|
61046
|
+
const nameMatch = fuzzyMatchScore(word, nameLower);
|
|
61047
|
+
if (nameMatch > 0)
|
|
61048
|
+
wordScore += 10 * nameMatch;
|
|
61049
|
+
const displayMatch = fuzzyMatchScore(word, displayNameLower);
|
|
61050
|
+
if (displayMatch > 0)
|
|
61051
|
+
wordScore += 7 * displayMatch;
|
|
61052
|
+
const tagMatch = Math.max(...tagsLower.map((t2) => fuzzyMatchScore(word, t2)), fuzzyMatchScore(word, tagsCombined));
|
|
61053
|
+
if (tagMatch > 0)
|
|
61054
|
+
wordScore += 5 * tagMatch;
|
|
61055
|
+
const descMatch = fuzzyMatchScore(word, descriptionLower);
|
|
61056
|
+
if (descMatch > 0)
|
|
61057
|
+
wordScore += 2 * descMatch;
|
|
61058
|
+
if (wordScore === 0) {
|
|
61059
|
+
allWordsMatch = false;
|
|
61060
|
+
break;
|
|
61061
|
+
}
|
|
61062
|
+
score += wordScore;
|
|
61063
|
+
}
|
|
61064
|
+
if (allWordsMatch && score > 0) {
|
|
61065
|
+
scored.push({ skill, score });
|
|
61066
|
+
}
|
|
61067
|
+
}
|
|
61068
|
+
scored.sort((a, b) => b.score - a.score);
|
|
61069
|
+
return scored.map((s) => s.skill);
|
|
61070
|
+
}
|
|
61071
|
+
function findCloseSkillNames(query, names, maxResults = 3) {
|
|
61072
|
+
if (maxResults <= 0)
|
|
61073
|
+
return [];
|
|
61074
|
+
const q = query.trim().toLowerCase();
|
|
61075
|
+
if (q.length === 0)
|
|
61076
|
+
return [];
|
|
61077
|
+
const tokens = q.split("-").filter(Boolean);
|
|
61078
|
+
const ranked = [];
|
|
61079
|
+
if (q.length >= 3) {
|
|
61080
|
+
for (const name of names) {
|
|
61081
|
+
const candidate = name.toLowerCase();
|
|
61082
|
+
const rank = candidate === q ? 0 : candidate.endsWith(`-${q}`) || candidate.startsWith(`${q}-`) ? 1 : tokens.length > 1 && tokens.every((token) => candidate.split("-").includes(token)) ? 2 : undefined;
|
|
61083
|
+
if (rank !== undefined)
|
|
61084
|
+
ranked.push([name, rank]);
|
|
61085
|
+
}
|
|
61086
|
+
}
|
|
61087
|
+
ranked.sort((a, b) => a[1] - b[1] || a[0].length - b[0].length || a[0].localeCompare(b[0]));
|
|
61088
|
+
const found = ranked.slice(0, maxResults).map(([name]) => name);
|
|
61089
|
+
if (found.length === maxResults)
|
|
61090
|
+
return found;
|
|
61091
|
+
const taken = new Set(found);
|
|
61092
|
+
const threshold = Math.max(3, Math.floor(q.length / 2));
|
|
61093
|
+
const byDistance = names.filter((name) => !taken.has(name)).map((name) => ({ name, distance: editDistance(q, name.toLowerCase()) })).filter((entry) => entry.distance <= threshold).sort((a, b) => a.distance - b.distance || a.name.localeCompare(b.name));
|
|
61094
|
+
return [...found, ...byDistance.slice(0, maxResults - found.length).map((entry) => entry.name)];
|
|
61095
|
+
}
|
|
61096
|
+
function findSimilarSkills(query, maxResults = 3, registry = loadRegistry()) {
|
|
61097
|
+
return findCloseSkillNames(query, registry.map((skill) => skill.name), maxResults);
|
|
61098
|
+
}
|
|
61099
|
+
var init_search = __esm(() => {
|
|
61100
|
+
init_registry();
|
|
61101
|
+
});
|
|
61102
|
+
|
|
60954
61103
|
// src/lib/selected-document.ts
|
|
60955
61104
|
function readSelectedDocument(entries, file) {
|
|
60956
61105
|
const entry = file !== undefined ? entries.find((candidate) => candidate.path === file) : DOCUMENT_PATHS.map((path) => entries.find((candidate) => candidate.path === path && candidate.bytes.length > 0)).find(Boolean);
|
|
@@ -61071,11 +61220,30 @@ function exactProfileSelection(spec, profile) {
|
|
|
61071
61220
|
const at2 = spec.lastIndexOf("@");
|
|
61072
61221
|
const slug = at2 > 0 ? spec.slice(0, at2) : spec;
|
|
61073
61222
|
const version = at2 > 0 ? spec.slice(at2 + 1) : undefined;
|
|
61074
|
-
const
|
|
61075
|
-
if (
|
|
61076
|
-
throw new SkillSelectionError("SKILL_NOT_SELECTED",
|
|
61223
|
+
const named = profile.selections.filter((entry) => entry.slug === slug || entry.aliases?.includes(slug));
|
|
61224
|
+
if (version === "")
|
|
61225
|
+
throw new SkillSelectionError("SKILL_NOT_SELECTED", emptyVersionRefusal(spec));
|
|
61226
|
+
if (named.length === 0)
|
|
61227
|
+
throw new SkillSelectionError("SKILL_NOT_SELECTED", unknownNameRefusal(slug, profile));
|
|
61228
|
+
const selection = version === undefined ? named[0] : named.find((entry) => entry.version === version);
|
|
61229
|
+
if (!selection)
|
|
61230
|
+
throw new SkillSelectionError("SKILL_NOT_SELECTED", wrongVersionRefusal(slug, version, named));
|
|
61077
61231
|
return selection;
|
|
61078
61232
|
}
|
|
61233
|
+
function emptyVersionRefusal(spec) {
|
|
61234
|
+
return `The requested name '${spec}' has an empty version. ${ACCEPTED_FORM}`;
|
|
61235
|
+
}
|
|
61236
|
+
function wrongVersionRefusal(slug, version, named) {
|
|
61237
|
+
const versions = [...new Set(named.map((entry) => entry.version))].sort();
|
|
61238
|
+
const canonical9 = named[0].slug;
|
|
61239
|
+
return `Skill '${slug}' is selected at version '${versions.join("', '")}', but '${version}' was requested. ` + `Accepted form: '${canonical9}@${versions[0]}'.`;
|
|
61240
|
+
}
|
|
61241
|
+
function unknownNameRefusal(slug, profile) {
|
|
61242
|
+
const names = profile.selections.flatMap((entry) => [entry.slug, ...entry.aliases ?? []]);
|
|
61243
|
+
const close = findCloseSkillNames(slug, names);
|
|
61244
|
+
const hint = close.length > 0 ? ` Did you mean: ${close.join(", ")}?` : "";
|
|
61245
|
+
return `Skill '${slug}' is not selected by this Skills profile or project lock.${hint} ` + `Read the accepted names with 'skills search <term>' or 'skills list --all --json'; accept one with 'skills pin <name>'. ${ACCEPTED_FORM}`;
|
|
61246
|
+
}
|
|
61079
61247
|
async function loadSelectedSkill(spec, profileId, options = {}) {
|
|
61080
61248
|
const context = await resolveSelectionContext(profileId, options);
|
|
61081
61249
|
const selection = exactProfileSelection(spec, context.receipt.profile);
|
|
@@ -61120,9 +61288,11 @@ async function selectedSkillRequirements(spec, profileId, options = {}) {
|
|
|
61120
61288
|
}
|
|
61121
61289
|
return { ...getSkillRequirementsFromContent(selection.slug, texts, dependencies), selection };
|
|
61122
61290
|
}
|
|
61291
|
+
var ACCEPTED_FORM = "Accepted form: '<slug>' or '<slug>@<version>'.";
|
|
61123
61292
|
var init_selection_resolver = __esm(() => {
|
|
61124
61293
|
init_profile_client();
|
|
61125
61294
|
init_skillinfo();
|
|
61295
|
+
init_search();
|
|
61126
61296
|
init_selected_document();
|
|
61127
61297
|
init_selection_cache();
|
|
61128
61298
|
});
|
|
@@ -62715,6 +62885,9 @@ function verifyAgentDiscovery(binding, codexRecovery, reviewedRootAliases, witne
|
|
|
62715
62885
|
function claudeControlSource(source) {
|
|
62716
62886
|
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
62887
|
}
|
|
62888
|
+
function retainedAbsentClaudeRoot(absentRoots, source) {
|
|
62889
|
+
return claudeControlSource(source) ? undefined : retainedAbsentRoot(absentRoots, source);
|
|
62890
|
+
}
|
|
62718
62891
|
function classifyClaudeDiscoverySources(binding) {
|
|
62719
62892
|
if (!binding || binding.agent !== "claude" || !Array.isArray(binding.sources))
|
|
62720
62893
|
throw new Error("Invalid Claude discovery binding");
|
|
@@ -62735,7 +62908,7 @@ function classifyClaudeDiscoverySources(binding) {
|
|
|
62735
62908
|
};
|
|
62736
62909
|
const budget2 = discoveryByteBudget();
|
|
62737
62910
|
return binding.sources.map((source) => {
|
|
62738
|
-
const root2 =
|
|
62911
|
+
const root2 = retainedAbsentClaudeRoot(absentRoots, source);
|
|
62739
62912
|
if (root2 !== undefined)
|
|
62740
62913
|
return { status: "retained-absent", root: root2, witness: retainableAbsentWitness(source) };
|
|
62741
62914
|
let current;
|
|
@@ -63150,7 +63323,10 @@ function resolveAgentDiscovery(options) {
|
|
|
63150
63323
|
if (!review.sources.some((source) => source.path === canonical9(configPath)))
|
|
63151
63324
|
throw new Error("Discovery review must include the agent configuration source");
|
|
63152
63325
|
const reviewedSources = supersedesSettingsProjection(agent, review.sources, canonical9(configPath)) ? sources.filter((source) => !isSupersededSettingsProjection(agent, canonical9(configPath), source)) : sources;
|
|
63326
|
+
const absentRoots = absentRetiredClaudeRoots(supplied);
|
|
63153
63327
|
const reviewedSourcesWithManifestProjection = review.sources.map((source) => {
|
|
63328
|
+
if (retainedAbsentClaudeRoot(absentRoots, source) !== undefined)
|
|
63329
|
+
return source;
|
|
63154
63330
|
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
63331
|
return { path: source.path, hashMode: CLAUDE_ORPHAN_MARKER_MODE, sha256: hashClaudePluginCacheOrphanMarker(source.path) };
|
|
63156
63332
|
}
|
|
@@ -63183,6 +63359,11 @@ function resolveAgentDiscovery(options) {
|
|
|
63183
63359
|
});
|
|
63184
63360
|
if (agent === "claude")
|
|
63185
63361
|
assertReviewedClaudeCacheClosures(home, config, review, canonical9);
|
|
63362
|
+
for (const root2 of absentRoots) {
|
|
63363
|
+
safe6(root2);
|
|
63364
|
+
if (lstatSync32(root2, { throwIfNoEntry: false }))
|
|
63365
|
+
throw new Error("Retired native materialization changed during discovery review");
|
|
63366
|
+
}
|
|
63186
63367
|
const combined = [...reviewedSources, ...reviewedSourcesWithManifestProjection];
|
|
63187
63368
|
const unique = combined.filter((source, index) => combined.findIndex((candidate2) => isDeepStrictEqual13(candidate2, source)) === index);
|
|
63188
63369
|
return { ...supplied, roots: [...new Set([...roots, ...supplied.roots])].sort(), sources: unique, ...agent === "gemini" ? { builtinNames } : {} };
|
|
@@ -63933,95 +64114,6 @@ var init_registry_types = __esm(() => {
|
|
|
63933
64114
|
BASIC_SKILL_NAMES = [];
|
|
63934
64115
|
});
|
|
63935
64116
|
|
|
63936
|
-
// src/lib/search.ts
|
|
63937
|
-
function editDistance(a, b) {
|
|
63938
|
-
if (a === b)
|
|
63939
|
-
return 0;
|
|
63940
|
-
if (a.length === 0)
|
|
63941
|
-
return b.length;
|
|
63942
|
-
if (b.length === 0)
|
|
63943
|
-
return a.length;
|
|
63944
|
-
const prev = Array.from({ length: b.length + 1 }, (_, i) => i);
|
|
63945
|
-
const curr = new Array(b.length + 1);
|
|
63946
|
-
for (let i = 1;i <= a.length; i++) {
|
|
63947
|
-
curr[0] = i;
|
|
63948
|
-
for (let j = 1;j <= b.length; j++) {
|
|
63949
|
-
const cost = a[i - 1] === b[j - 1] ? 0 : 1;
|
|
63950
|
-
curr[j] = Math.min(curr[j - 1] + 1, prev[j] + 1, prev[j - 1] + cost);
|
|
63951
|
-
}
|
|
63952
|
-
prev.splice(0, prev.length, ...curr);
|
|
63953
|
-
}
|
|
63954
|
-
return prev[b.length];
|
|
63955
|
-
}
|
|
63956
|
-
function fuzzyMatchScore(word, target) {
|
|
63957
|
-
if (target.includes(word))
|
|
63958
|
-
return 1;
|
|
63959
|
-
const tokens = target.split(/[\s\-_]+/).filter(Boolean);
|
|
63960
|
-
for (const token of tokens) {
|
|
63961
|
-
if (token.startsWith(word))
|
|
63962
|
-
return 0.6;
|
|
63963
|
-
}
|
|
63964
|
-
if (word.length >= 3) {
|
|
63965
|
-
const maxDist = word.length <= 3 ? 1 : 2;
|
|
63966
|
-
for (const token of tokens) {
|
|
63967
|
-
if (Math.abs(token.length - word.length) <= maxDist) {
|
|
63968
|
-
const dist = editDistance(word, token);
|
|
63969
|
-
if (dist <= maxDist)
|
|
63970
|
-
return 0.4;
|
|
63971
|
-
}
|
|
63972
|
-
}
|
|
63973
|
-
}
|
|
63974
|
-
return 0;
|
|
63975
|
-
}
|
|
63976
|
-
function searchSkills(query, registry = loadRegistry()) {
|
|
63977
|
-
const words2 = query.toLowerCase().split(/\s+/).filter(Boolean);
|
|
63978
|
-
if (words2.length === 0)
|
|
63979
|
-
return [];
|
|
63980
|
-
const scored = [];
|
|
63981
|
-
for (const skill of registry) {
|
|
63982
|
-
const nameLower = skill.name.toLowerCase();
|
|
63983
|
-
const displayNameLower = skill.displayName.toLowerCase();
|
|
63984
|
-
const descriptionLower = skill.description.toLowerCase();
|
|
63985
|
-
const tagsLower = skill.tags.map((t2) => t2.toLowerCase());
|
|
63986
|
-
const tagsCombined = tagsLower.join(" ");
|
|
63987
|
-
let score = 0;
|
|
63988
|
-
let allWordsMatch = true;
|
|
63989
|
-
for (const word of words2) {
|
|
63990
|
-
let wordScore = 0;
|
|
63991
|
-
const nameMatch = fuzzyMatchScore(word, nameLower);
|
|
63992
|
-
if (nameMatch > 0)
|
|
63993
|
-
wordScore += 10 * nameMatch;
|
|
63994
|
-
const displayMatch = fuzzyMatchScore(word, displayNameLower);
|
|
63995
|
-
if (displayMatch > 0)
|
|
63996
|
-
wordScore += 7 * displayMatch;
|
|
63997
|
-
const tagMatch = Math.max(...tagsLower.map((t2) => fuzzyMatchScore(word, t2)), fuzzyMatchScore(word, tagsCombined));
|
|
63998
|
-
if (tagMatch > 0)
|
|
63999
|
-
wordScore += 5 * tagMatch;
|
|
64000
|
-
const descMatch = fuzzyMatchScore(word, descriptionLower);
|
|
64001
|
-
if (descMatch > 0)
|
|
64002
|
-
wordScore += 2 * descMatch;
|
|
64003
|
-
if (wordScore === 0) {
|
|
64004
|
-
allWordsMatch = false;
|
|
64005
|
-
break;
|
|
64006
|
-
}
|
|
64007
|
-
score += wordScore;
|
|
64008
|
-
}
|
|
64009
|
-
if (allWordsMatch && score > 0) {
|
|
64010
|
-
scored.push({ skill, score });
|
|
64011
|
-
}
|
|
64012
|
-
}
|
|
64013
|
-
scored.sort((a, b) => b.score - a.score);
|
|
64014
|
-
return scored.map((s) => s.skill);
|
|
64015
|
-
}
|
|
64016
|
-
function findSimilarSkills(query, maxResults = 3, registry = loadRegistry()) {
|
|
64017
|
-
const q = query.toLowerCase();
|
|
64018
|
-
const scored = registry.map((s) => ({ name: s.name, dist: editDistance(q, s.name.toLowerCase()) })).filter((s) => s.dist <= Math.max(3, Math.floor(q.length / 2))).sort((a, b) => a.dist - b.dist);
|
|
64019
|
-
return scored.slice(0, maxResults).map((s) => s.name);
|
|
64020
|
-
}
|
|
64021
|
-
var init_search = __esm(() => {
|
|
64022
|
-
init_registry();
|
|
64023
|
-
});
|
|
64024
|
-
|
|
64025
64117
|
// src/lib/registry.ts
|
|
64026
64118
|
var exports_registry = {};
|
|
64027
64119
|
__export(exports_registry, {
|
|
@@ -88723,6 +88815,24 @@ function optionPrefix(program2, args) {
|
|
|
88723
88815
|
return { indices, separator: -1 };
|
|
88724
88816
|
}
|
|
88725
88817
|
|
|
88818
|
+
// src/cli/stray-arguments.ts
|
|
88819
|
+
function permitStrayArguments(command) {
|
|
88820
|
+
selfRefusing.add(command);
|
|
88821
|
+
return command.allowExcessArguments(true);
|
|
88822
|
+
}
|
|
88823
|
+
function rejectStrayArguments(command) {
|
|
88824
|
+
for (const child2 of command.commands) {
|
|
88825
|
+
if (child2.registeredArguments.length === 0 && !selfRefusing.has(child2)) {
|
|
88826
|
+
child2.allowExcessArguments(false);
|
|
88827
|
+
}
|
|
88828
|
+
rejectStrayArguments(child2);
|
|
88829
|
+
}
|
|
88830
|
+
}
|
|
88831
|
+
var selfRefusing;
|
|
88832
|
+
var init_stray_arguments = __esm(() => {
|
|
88833
|
+
selfRefusing = new WeakSet;
|
|
88834
|
+
});
|
|
88835
|
+
|
|
88726
88836
|
// src/lib/revision.ts
|
|
88727
88837
|
import { createHash as createHash33 } from "crypto";
|
|
88728
88838
|
function revisionIdOf(content) {
|
|
@@ -90772,7 +90882,13 @@ function handleReadRefusal(error61) {
|
|
|
90772
90882
|
async function handleInfoError(name, options, error61) {
|
|
90773
90883
|
if (isSkillsFleetCredentialError(error61))
|
|
90774
90884
|
return handleReadRefusal(error61);
|
|
90775
|
-
|
|
90885
|
+
let remote = options.remote === true;
|
|
90886
|
+
if (!remote) {
|
|
90887
|
+
try {
|
|
90888
|
+
remote = (await requireSkillsReadAccess()).mode === "hosted";
|
|
90889
|
+
} catch {}
|
|
90890
|
+
}
|
|
90891
|
+
const notFound = await resolveRemoteNotFound(name, remote, error61.message);
|
|
90776
90892
|
if (options.json)
|
|
90777
90893
|
console.log(JSON.stringify(notFound));
|
|
90778
90894
|
else
|
|
@@ -94457,7 +94573,11 @@ var exports_selected_run = {};
|
|
|
94457
94573
|
__export(exports_selected_run, {
|
|
94458
94574
|
resolveSelectedRun: () => resolveSelectedRun,
|
|
94459
94575
|
prepareSelectedSecretBindings: () => prepareSelectedSecretBindings,
|
|
94460
|
-
|
|
94576
|
+
instructionRunRefusal: () => instructionRunRefusal,
|
|
94577
|
+
instructionEntrypointMismatch: () => instructionEntrypointMismatch,
|
|
94578
|
+
instructionCommandEntry: () => instructionCommandEntry,
|
|
94579
|
+
executeSelectedLocal: () => executeSelectedLocal,
|
|
94580
|
+
declaredOperation: () => declaredOperation
|
|
94461
94581
|
});
|
|
94462
94582
|
import { createHash as createHash36 } from "crypto";
|
|
94463
94583
|
import { spawn as spawn3 } from "child_process";
|
|
@@ -94470,12 +94590,51 @@ async function resolveSelectedRun(spec, profileId, options = {}) {
|
|
|
94470
94590
|
const entries = await readSelectedEntries(selection2, context, options);
|
|
94471
94591
|
return { selection: selection2, profileId: context.receipt.profile.profileId, entries, ...describeEntries(entries), cacheDir: selectionCacheRoot(options) };
|
|
94472
94592
|
}
|
|
94593
|
+
function declaredOperation(manifest) {
|
|
94594
|
+
const entry = instructionCommandEntry(manifest);
|
|
94595
|
+
if (!entry)
|
|
94596
|
+
return null;
|
|
94597
|
+
const runtime = manifest.runtime;
|
|
94598
|
+
if (!runtime || typeof runtime !== "object" || Array.isArray(runtime))
|
|
94599
|
+
return null;
|
|
94600
|
+
if (runtime.runtime !== "bun" && runtime.runtime !== "node" && runtime.runtime !== "python3")
|
|
94601
|
+
return null;
|
|
94602
|
+
if (instructionEntrypointMismatch(manifest))
|
|
94603
|
+
return null;
|
|
94604
|
+
return { entry };
|
|
94605
|
+
}
|
|
94606
|
+
function instructionCommandEntry(manifest) {
|
|
94607
|
+
const commands = Array.isArray(manifest.commands) ? manifest.commands : [];
|
|
94608
|
+
const command = commands[0];
|
|
94609
|
+
if (!command || typeof command !== "object" || typeof command.entry !== "string" || command.entry.length === 0)
|
|
94610
|
+
return null;
|
|
94611
|
+
return command.entry;
|
|
94612
|
+
}
|
|
94613
|
+
function instructionEntrypointMismatch(manifest) {
|
|
94614
|
+
const entry = instructionCommandEntry(manifest);
|
|
94615
|
+
const declared = manifest.runtime;
|
|
94616
|
+
if (!entry || !declared || typeof declared !== "object" || Array.isArray(declared))
|
|
94617
|
+
return null;
|
|
94618
|
+
const runtimeEntrypoint = declared.entrypoint;
|
|
94619
|
+
return typeof runtimeEntrypoint === "string" && runtimeEntrypoint !== entry ? runtimeEntrypoint : null;
|
|
94620
|
+
}
|
|
94621
|
+
function instructionRunRefusal(manifest, isBundledFile) {
|
|
94622
|
+
const declaredEntry = instructionCommandEntry(manifest);
|
|
94623
|
+
if (declaredEntry && !isBundledFile(declaredEntry))
|
|
94624
|
+
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.` };
|
|
94625
|
+
const mismatch = instructionEntrypointMismatch(manifest);
|
|
94626
|
+
if (mismatch)
|
|
94627
|
+
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.` };
|
|
94628
|
+
if (!declaredOperation(manifest))
|
|
94629
|
+
return { code: "INSTRUCTION_SKILL", message: "This selected skill contains instructions. Use skills load instead of skills run." };
|
|
94630
|
+
return null;
|
|
94631
|
+
}
|
|
94473
94632
|
async function prepareSelectedSecretBindings(selected, cwd2 = process.cwd()) {
|
|
94474
94633
|
const entries = await readCachedSelection(selected.selection, { cacheDir: selected.cacheDir });
|
|
94475
94634
|
if (!entries)
|
|
94476
94635
|
throw new SkillSelectionError("CACHED_BUNDLE_MISSING", "The selected execution bundle is not cached.");
|
|
94477
94636
|
const { kind, manifest } = describeEntries(entries);
|
|
94478
|
-
if (kind !== "executable")
|
|
94637
|
+
if (kind !== "executable" && !declaredOperation(manifest))
|
|
94479
94638
|
throw new SkillSelectionError("INSTRUCTION_SKILL", "Instruction skills do not accept execution secret bindings.");
|
|
94480
94639
|
const names = declaredSecretNames(manifest.runtime?.env);
|
|
94481
94640
|
if (!names.length)
|
|
@@ -94488,8 +94647,12 @@ async function executeSelectedLocal(selected, options = {}) {
|
|
|
94488
94647
|
if (!entries)
|
|
94489
94648
|
throw new SkillSelectionError("CACHED_BUNDLE_MISSING", "The selected local execution bundle is not cached.");
|
|
94490
94649
|
const { kind, manifest, packageJson } = describeEntries(entries);
|
|
94491
|
-
|
|
94492
|
-
|
|
94650
|
+
const operation = declaredOperation(manifest);
|
|
94651
|
+
if (kind === "instruction") {
|
|
94652
|
+
const refusal3 = instructionRunRefusal(manifest, (path) => entries.some((entry) => entry.path === path));
|
|
94653
|
+
if (refusal3)
|
|
94654
|
+
throw new SkillSelectionError(refusal3.code, refusal3.message);
|
|
94655
|
+
}
|
|
94493
94656
|
const runtime = manifest.runtime ?? {};
|
|
94494
94657
|
if (!runtime || typeof runtime !== "object" || Array.isArray(runtime))
|
|
94495
94658
|
throw new SkillSelectionError("INVALID_SKILL_MANIFEST", "The selected runtime declaration is invalid.");
|
|
@@ -94508,9 +94671,9 @@ async function executeSelectedLocal(selected, options = {}) {
|
|
|
94508
94671
|
const executable2 = runtimeName === "bun" ? process.execPath : Bun.which(runtimeName);
|
|
94509
94672
|
if (!executable2)
|
|
94510
94673
|
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);
|
|
94674
|
+
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
94675
|
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.");
|
|
94676
|
+
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
94677
|
const args = options.args ?? [];
|
|
94515
94678
|
if (args.length > 128 || args.some((arg) => typeof arg !== "string" || arg.length > 16384 || arg.includes("\x00")))
|
|
94516
94679
|
throw new SkillSelectionError("INVALID_RUN_INPUT", "Local skill arguments exceed their limits.");
|
|
@@ -94585,6 +94748,7 @@ async function executeSelectedLocal(selected, options = {}) {
|
|
|
94585
94748
|
selection: selection2,
|
|
94586
94749
|
target: "local",
|
|
94587
94750
|
runtime: runtimeName,
|
|
94751
|
+
entrypoint: declaredEntry,
|
|
94588
94752
|
inputDigest: `sha256:${createHash36("sha256").update(input2).digest("hex")}`,
|
|
94589
94753
|
runDirectory,
|
|
94590
94754
|
...executionGrant ? { executionGrant } : {},
|
|
@@ -113378,13 +113542,18 @@ function registerOperationTools(server) {
|
|
|
113378
113542
|
return mcpError("CONFLICTING_EXECUTION_MODES", "Use remote for the configured server catalog and quote, or target for selected execution, not both.");
|
|
113379
113543
|
if (managed && !remote) {
|
|
113380
113544
|
try {
|
|
113381
|
-
const { resolveSelectedRun: resolveSelectedRun2, executeSelectedLocal: executeSelectedLocal2 } = await Promise.resolve().then(() => (init_selected_run(), exports_selected_run));
|
|
113545
|
+
const { resolveSelectedRun: resolveSelectedRun2, executeSelectedLocal: executeSelectedLocal2, instructionRunRefusal: instructionRunRefusal2 } = await Promise.resolve().then(() => (init_selected_run(), exports_selected_run));
|
|
113382
113546
|
const resolved = await resolveSelectedRun2(name, selectedProfileId(), { projectDir: process.cwd() });
|
|
113383
|
-
if (resolved.kind === "instruction")
|
|
113384
|
-
|
|
113547
|
+
if (resolved.kind === "instruction") {
|
|
113548
|
+
const refusal3 = instructionRunRefusal2(resolved.manifest, (path) => resolved.entries.some((entry) => entry.path === path));
|
|
113549
|
+
if (refusal3)
|
|
113550
|
+
return mcpError(refusal3.code, refusal3.message);
|
|
113551
|
+
}
|
|
113385
113552
|
if (files?.length)
|
|
113386
113553
|
return mcpError("SELECTED_INPUT_REQUIRED", "Selected executions require their declared JSON input; use the CLI cloud execution input contract for files.");
|
|
113387
113554
|
if (target === "cloud") {
|
|
113555
|
+
if (resolved.kind === "instruction")
|
|
113556
|
+
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
113557
|
if (args?.length || quoteReceipt || maxCredits !== undefined || maxCostCents !== undefined)
|
|
113389
113558
|
return mcpError("SELECTED_INPUT_REQUIRED", "The selected cloud execution contract accepts declared JSON input, not legacy run arguments or quote receipts.");
|
|
113390
113559
|
const { CloudExecutionClient: CloudExecutionClient2 } = await Promise.resolve().then(() => (init_cloud_executions(), exports_cloud_executions));
|
|
@@ -117170,14 +117339,14 @@ function registerRuntime(parent) {
|
|
|
117170
117339
|
const exportsCommand = parent.command("exports").description("Inspect or open skill run exports");
|
|
117171
117340
|
exportsCommand.command("open").argument("<run-id>", "Run id").option("--json", "Output as JSON", false).description("Open the export directory for a run").action((runId2, options) => handleExportsOpen(runId2, options));
|
|
117172
117341
|
exportsCommand.command("download").argument("<run-id>", "Remote run id").option("--json", "Output as JSON", false).description("Download remote run artifacts into .skills/exports").action((runId2, options) => handleExportsDownload(runId2, options));
|
|
117173
|
-
parent.command("mcp").option("--register <agent>", "Register MCP server with agent").option("--json", "Output registration result as JSON", false).
|
|
117342
|
+
permitStrayArguments(parent.command("mcp").option("--register <agent>", "Register MCP server with agent").option("--json", "Output registration result as JSON", false).description("Start MCP server (stdio) or register with an agent").action(async (options, command) => {
|
|
117174
117343
|
const stray = command.args[0];
|
|
117175
117344
|
if (stray !== undefined) {
|
|
117176
117345
|
console.error(source_default.red(`error: unknown argument '${stray}'. 'skills mcp' takes no positional arguments. ` + `Valid forms: 'skills mcp' (start the MCP stdio server), ` + `'skills mcp --register <agent>', 'skills mcp --register all'`));
|
|
117177
117346
|
process.exit(1);
|
|
117178
117347
|
}
|
|
117179
117348
|
await handleMcp(options);
|
|
117180
|
-
});
|
|
117349
|
+
}));
|
|
117181
117350
|
const setup = parent.command("setup").description("Point this CLI at a Skills API server, or register agent integrations").option("--api-url <url>", "Skills API origin to send remote work to").option("--global", "Accepted for compatibility; the API origin is always per-user", false).option("--json", "Output setup result as JSON", false).action(async (options) => handleSetup(options));
|
|
117182
117351
|
setup.command("agents").option("--json", "Output registration result as JSON", false).description("Register the Skills MCP server with all supported agents").action(async (options) => handleMcp({ register: "all", json: options.json }));
|
|
117183
117352
|
parent.command("self-update").description("Update @hasna/skills to the latest version").option("--json", "Output result as JSON", false).option("--version <version>", "Install this exact @hasna/skills version as a staged copyfile runtime").option("--min-release-age <days>", "Require a positive integer dependency release age in days for an exact-version update").option("--min-release-age-exclude <pattern>", "Exclude matching package identities from the release-age policy (repeatable)", (pattern, prior) => [...prior, pattern], []).option("--reviewed-lock <path>", "Install from this private absolute package-lock.json path without resolving dependency ranges").option("--reviewed-lock-sha256 <sha256>", "Exact reviewed SHA-256 of the supplied package-lock.json").option("--rollback <receipt-id>", "Restore launcher links from an exact copyfile rollout receipt").option("--adopt-aliases", "Switch verified legacy @hasna/skills aliases to the active copyfile runtime").option("--rollback-aliases <receipt-id>", "Restore aliases from an exact adoption receipt").action(async (options) => {
|
|
@@ -117550,8 +117719,11 @@ async function handleRun(name, args2, options, separatorBeforeSkill) {
|
|
|
117550
117719
|
projectDir: process.cwd(),
|
|
117551
117720
|
sessionId: options.session
|
|
117552
117721
|
}) : undefined;
|
|
117553
|
-
if (selected?.kind === "instruction")
|
|
117554
|
-
|
|
117722
|
+
if (selected?.kind === "instruction") {
|
|
117723
|
+
const refusal3 = instructionRunRefusal(selected.manifest, (path) => selected.entries.some((entry) => entry.path === path));
|
|
117724
|
+
if (refusal3)
|
|
117725
|
+
throw new Error(refusal3.message);
|
|
117726
|
+
}
|
|
117555
117727
|
if (selected) {
|
|
117556
117728
|
slug2 = selected.selection.slug;
|
|
117557
117729
|
version2 = selected.selection.version;
|
|
@@ -117576,6 +117748,8 @@ async function handleRun(name, args2, options, separatorBeforeSkill) {
|
|
|
117576
117748
|
process.exitCode = result4.exitCode;
|
|
117577
117749
|
return;
|
|
117578
117750
|
}
|
|
117751
|
+
if (selected?.kind === "instruction")
|
|
117752
|
+
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
117753
|
if (args2.length || options.remote || options.file?.length)
|
|
117580
117754
|
throw new Error("Cloud execution accepts structured --input only");
|
|
117581
117755
|
if (!version2 || options.input === undefined)
|
|
@@ -118267,6 +118441,7 @@ var init_runtime = __esm(() => {
|
|
|
118267
118441
|
init_execution_secrets();
|
|
118268
118442
|
init_context();
|
|
118269
118443
|
init_registry();
|
|
118444
|
+
init_stray_arguments();
|
|
118270
118445
|
init_skillinfo();
|
|
118271
118446
|
init_skill_contract();
|
|
118272
118447
|
init_blog_article();
|
|
@@ -121866,6 +122041,369 @@ var init_profiles = __esm(() => {
|
|
|
121866
122041
|
init_remote_permissions();
|
|
121867
122042
|
});
|
|
121868
122043
|
|
|
122044
|
+
// src/lib/selection-provenance.ts
|
|
122045
|
+
function label(value) {
|
|
122046
|
+
return value !== undefined && SAFE_LABEL2.test(value) ? value : "an unnamed value";
|
|
122047
|
+
}
|
|
122048
|
+
async function attempt2(read3) {
|
|
122049
|
+
try {
|
|
122050
|
+
return { ok: true, value: await read3() };
|
|
122051
|
+
} catch {
|
|
122052
|
+
return { ok: false, code: "READ_REFUSED" };
|
|
122053
|
+
}
|
|
122054
|
+
}
|
|
122055
|
+
function sameRevision(observed, reference) {
|
|
122056
|
+
return observed !== undefined && reference !== undefined && observed === reference;
|
|
122057
|
+
}
|
|
122058
|
+
function sameIdentity2(observed, reference) {
|
|
122059
|
+
if (observed.profileId !== undefined && reference.profileId !== undefined && observed.profileId !== reference.profileId)
|
|
122060
|
+
return false;
|
|
122061
|
+
if (observed.authority !== undefined && reference.authority !== undefined && observed.authority !== reference.authority)
|
|
122062
|
+
return false;
|
|
122063
|
+
if (observed.workspaceId !== undefined && reference.workspaceId !== undefined && observed.workspaceId !== reference.workspaceId)
|
|
122064
|
+
return false;
|
|
122065
|
+
return true;
|
|
122066
|
+
}
|
|
122067
|
+
function supportedIdentityValue(value) {
|
|
122068
|
+
return typeof value === "string" && value.trim() !== "";
|
|
122069
|
+
}
|
|
122070
|
+
function uncomparableFields(observed, reference, required2) {
|
|
122071
|
+
return required2.filter((field3) => !supportedIdentityValue(observed[field3]) || !supportedIdentityValue(reference[field3]));
|
|
122072
|
+
}
|
|
122073
|
+
function supportedIdentityFields(source) {
|
|
122074
|
+
const out = {};
|
|
122075
|
+
for (const field3 of ["profileId", "profileRevision", "authority", "workspaceId"]) {
|
|
122076
|
+
const value = source[field3];
|
|
122077
|
+
if (supportedIdentityValue(value))
|
|
122078
|
+
out[field3] = value;
|
|
122079
|
+
}
|
|
122080
|
+
return out;
|
|
122081
|
+
}
|
|
122082
|
+
function revisionReason(labelText, observed, reference, status) {
|
|
122083
|
+
const seen = label(observed);
|
|
122084
|
+
if (status === "current")
|
|
122085
|
+
return `${labelText} revision ${seen} is the selected revision`;
|
|
122086
|
+
return `${labelText} revision ${seen} is not the selected revision ${label(reference)}`;
|
|
122087
|
+
}
|
|
122088
|
+
async function resolveReference(input3, options) {
|
|
122089
|
+
const fromSnapshot = (reasonCode, because) => {
|
|
122090
|
+
let receipt;
|
|
122091
|
+
try {
|
|
122092
|
+
receipt = readSelectionProfile(input3.profileId, options);
|
|
122093
|
+
} catch {
|
|
122094
|
+
return { profileId: input3.profileId, source: "unavailable", reasonCode: "REFERENCE_UNAVAILABLE", reason: `${because} The locally synced snapshot is unreadable too.`, selections: noSelections };
|
|
122095
|
+
}
|
|
122096
|
+
if (!receipt)
|
|
122097
|
+
return { profileId: input3.profileId, source: "unavailable", reasonCode: "REFERENCE_UNAVAILABLE", reason: `${because} Nothing is synced locally either, so no consumer can be compared.`, selections: noSelections };
|
|
122098
|
+
return {
|
|
122099
|
+
profileId: receipt.profile.profileId,
|
|
122100
|
+
...supportedIdentityFields({ profileRevision: receipt.profile.profileRevision, authority: receipt.profile.authority, workspaceId: receipt.profile.workspaceId }),
|
|
122101
|
+
selectionCount: receipt.profile.selections.length,
|
|
122102
|
+
observedAt: receipt.verifiedAt,
|
|
122103
|
+
source: "synced-snapshot",
|
|
122104
|
+
reasonCode,
|
|
122105
|
+
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.`,
|
|
122106
|
+
selections: receipt.profile.selections
|
|
122107
|
+
};
|
|
122108
|
+
};
|
|
122109
|
+
if (input3.cached)
|
|
122110
|
+
return fromSnapshot("REFERENCE_NOT_AUTHORITY", "--cached was requested, so the authority was not read.");
|
|
122111
|
+
const read3 = options.readSelected ?? (async (profileId) => {
|
|
122112
|
+
const client2 = await createProfileClient();
|
|
122113
|
+
const profile2 = await client2.resolveProfile(profileId);
|
|
122114
|
+
return { profileId: profile2.profileId, profileRevision: profile2.profileRevision, authority: profile2.authority, workspaceId: profile2.workspaceId, selections: profile2.selections };
|
|
122115
|
+
});
|
|
122116
|
+
const attempted = await attempt2(() => read3(input3.profileId));
|
|
122117
|
+
if (!attempted.ok)
|
|
122118
|
+
return fromSnapshot("READ_REFUSED", "The authority did not answer for the selected profile.");
|
|
122119
|
+
const profile = attempted.value;
|
|
122120
|
+
if (!profile?.profileId || !profile.profileRevision || !Array.isArray(profile.selections)) {
|
|
122121
|
+
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 };
|
|
122122
|
+
}
|
|
122123
|
+
return {
|
|
122124
|
+
profileId: profile.profileId,
|
|
122125
|
+
profileRevision: profile.profileRevision,
|
|
122126
|
+
selectionCount: profile.selections.length,
|
|
122127
|
+
...profile.authority === undefined ? {} : { authority: profile.authority },
|
|
122128
|
+
...profile.workspaceId === undefined ? {} : { workspaceId: profile.workspaceId },
|
|
122129
|
+
source: "authority",
|
|
122130
|
+
reasonCode: "REFERENCE_FROM_AUTHORITY",
|
|
122131
|
+
reason: `Read from the authority for profile ${label(profile.profileId)}.`,
|
|
122132
|
+
selections: profile.selections
|
|
122133
|
+
};
|
|
122134
|
+
}
|
|
122135
|
+
function activationConsumer(input3, reference, options) {
|
|
122136
|
+
const base3 = {
|
|
122137
|
+
kind: "station",
|
|
122138
|
+
source: "local-receipt",
|
|
122139
|
+
id: input3.localStationId,
|
|
122140
|
+
idKind: "local-host",
|
|
122141
|
+
status: "unverified",
|
|
122142
|
+
reasonCode: "NO_LOCAL_RECEIPT",
|
|
122143
|
+
reason: ""
|
|
122144
|
+
};
|
|
122145
|
+
const refuse10 = (reasonCode, reason2) => ({ consumer: { ...base3, reasonCode, reason: reason2 }, compared: noSelections });
|
|
122146
|
+
let receipt;
|
|
122147
|
+
try {
|
|
122148
|
+
receipt = readSelectionProfile(input3.profileId, options);
|
|
122149
|
+
} catch {
|
|
122150
|
+
return refuse10("READ_REFUSED", `This machine's activated snapshot for profile ${label(input3.profileId)} could not be read.`);
|
|
122151
|
+
}
|
|
122152
|
+
if (!receipt)
|
|
122153
|
+
return refuse10("NO_LOCAL_RECEIPT", `This machine holds no activated snapshot for profile ${label(input3.profileId)}.`);
|
|
122154
|
+
const profile = receipt.profile;
|
|
122155
|
+
const observed = {
|
|
122156
|
+
...base3,
|
|
122157
|
+
...supportedIdentityFields({ profileId: profile.profileId, profileRevision: profile.profileRevision, authority: profile.authority, workspaceId: profile.workspaceId }),
|
|
122158
|
+
observedAt: receipt.verifiedAt,
|
|
122159
|
+
selectionCount: profile.selections.length
|
|
122160
|
+
};
|
|
122161
|
+
if (!sameIdentity2(observed, reference)) {
|
|
122162
|
+
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 };
|
|
122163
|
+
}
|
|
122164
|
+
if (reference.source !== "authority") {
|
|
122165
|
+
return { consumer: { ...observed, status: "unverified", reasonCode: reference.reasonCode, reason: `${reference.reason} This snapshot alone cannot say whether the machine is current.` }, compared: noSelections };
|
|
122166
|
+
}
|
|
122167
|
+
const missingActivation = uncomparableFields(observed, reference, REQUIRED_IDENTITY["local-receipt"]);
|
|
122168
|
+
if (missingActivation.length > 0) {
|
|
122169
|
+
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 };
|
|
122170
|
+
}
|
|
122171
|
+
const status = sameRevision(profile.profileRevision, reference.profileRevision) ? "current" : "behind";
|
|
122172
|
+
return {
|
|
122173
|
+
consumer: {
|
|
122174
|
+
...observed,
|
|
122175
|
+
status,
|
|
122176
|
+
reasonCode: status === "current" ? "CURRENT_SCHEMA_MATCH" : "REVISION_BEHIND",
|
|
122177
|
+
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.`
|
|
122178
|
+
},
|
|
122179
|
+
compared: profile.selections
|
|
122180
|
+
};
|
|
122181
|
+
}
|
|
122182
|
+
async function stationConsumer(input3, reference, options) {
|
|
122183
|
+
const base3 = {
|
|
122184
|
+
kind: "station",
|
|
122185
|
+
source: "authority-receipt",
|
|
122186
|
+
id: input3.stationId,
|
|
122187
|
+
idKind: "requested-station",
|
|
122188
|
+
status: "unverified",
|
|
122189
|
+
reasonCode: "NO_STATION_REPORTED",
|
|
122190
|
+
reason: ""
|
|
122191
|
+
};
|
|
122192
|
+
const refuse10 = (reasonCode, reason2) => ({ consumer: { ...base3, reasonCode, reason: reason2 }, compared: noSelections });
|
|
122193
|
+
if (reference.source !== "authority") {
|
|
122194
|
+
return refuse10("REFERENCE_NOT_AUTHORITY", "The station receipt was not compared: this receipt has no authenticated selection to compare it with.");
|
|
122195
|
+
}
|
|
122196
|
+
const read3 = options.readStation ?? (async (stationId) => {
|
|
122197
|
+
const state = await readStationSkillState(stationId);
|
|
122198
|
+
return { profileId: state.profileId, profileRevision: state.profileRevision, appliedAt: state.appliedAt, workspaceId: state.workspaceId, selections: state.selections };
|
|
122199
|
+
});
|
|
122200
|
+
const attempted = await attempt2(() => read3(input3.stationId));
|
|
122201
|
+
if (!attempted.ok)
|
|
122202
|
+
return refuse10("READ_REFUSED", `The authority did not answer for station ${label(input3.stationId)}.`);
|
|
122203
|
+
const station = attempted.value;
|
|
122204
|
+
const observed = {
|
|
122205
|
+
...base3,
|
|
122206
|
+
...supportedIdentityFields({ profileId: station.profileId, profileRevision: station.profileRevision, workspaceId: station.workspaceId }),
|
|
122207
|
+
observedAt: station.appliedAt,
|
|
122208
|
+
selectionCount: station.selections.length
|
|
122209
|
+
};
|
|
122210
|
+
if (!sameIdentity2(observed, reference)) {
|
|
122211
|
+
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 };
|
|
122212
|
+
}
|
|
122213
|
+
const missing2 = uncomparableFields(observed, reference, REQUIRED_IDENTITY["authority-receipt"]);
|
|
122214
|
+
if (missing2.length > 0) {
|
|
122215
|
+
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 };
|
|
122216
|
+
}
|
|
122217
|
+
if (sameRevision(station.profileRevision, reference.profileRevision)) {
|
|
122218
|
+
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 };
|
|
122219
|
+
}
|
|
122220
|
+
return {
|
|
122221
|
+
consumer: {
|
|
122222
|
+
...observed,
|
|
122223
|
+
status: "behind",
|
|
122224
|
+
reasonCode: "REVISION_BEHIND",
|
|
122225
|
+
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.`
|
|
122226
|
+
},
|
|
122227
|
+
compared: station.selections
|
|
122228
|
+
};
|
|
122229
|
+
}
|
|
122230
|
+
function sessionConsumer(input3, reference, options) {
|
|
122231
|
+
const unnamed = {
|
|
122232
|
+
kind: "session",
|
|
122233
|
+
source: "session-receipt",
|
|
122234
|
+
id: "unnamed",
|
|
122235
|
+
idKind: "local-host",
|
|
122236
|
+
status: "unverified",
|
|
122237
|
+
reasonCode: "NO_SESSION_NAMED",
|
|
122238
|
+
reason: "No session was named, so its pin and load receipts were not read; pass --session <id>."
|
|
122239
|
+
};
|
|
122240
|
+
if (!input3.sessionId)
|
|
122241
|
+
return { consumer: unnamed, compared: noSelections };
|
|
122242
|
+
const base3 = {
|
|
122243
|
+
kind: "session",
|
|
122244
|
+
source: "session-receipt",
|
|
122245
|
+
id: input3.sessionId,
|
|
122246
|
+
idKind: "local-host",
|
|
122247
|
+
status: "unverified",
|
|
122248
|
+
reasonCode: "NO_SESSION_RECEIPT",
|
|
122249
|
+
reason: ""
|
|
122250
|
+
};
|
|
122251
|
+
const refuse10 = (reasonCode, reason2) => ({ consumer: { ...base3, reasonCode, reason: reason2 }, compared: noSelections });
|
|
122252
|
+
let session;
|
|
122253
|
+
try {
|
|
122254
|
+
session = inspectSkillSession(input3.sessionId, options);
|
|
122255
|
+
} catch {
|
|
122256
|
+
return refuse10("READ_REFUSED", `The session receipt for the named session could not be read.`);
|
|
122257
|
+
}
|
|
122258
|
+
const consumed = session.selections.filter((selection2) => selection2.loaded).map((selection2) => ({ slug: selection2.slug, version: selection2.version, bundleDigest: selection2.bundleDigest }));
|
|
122259
|
+
const observed = {
|
|
122260
|
+
...base3,
|
|
122261
|
+
...supportedIdentityFields({ profileId: session.profileId, profileRevision: session.profileRevision, authority: session.authority, workspaceId: session.workspaceId }),
|
|
122262
|
+
observedAt: session.verifiedAt,
|
|
122263
|
+
selectionCount: session.selectionCount,
|
|
122264
|
+
loadedCount: session.loadedCount,
|
|
122265
|
+
consumed
|
|
122266
|
+
};
|
|
122267
|
+
if (!sameIdentity2(observed, reference)) {
|
|
122268
|
+
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 };
|
|
122269
|
+
}
|
|
122270
|
+
if (reference.source !== "authority") {
|
|
122271
|
+
return { consumer: { ...observed, status: "unverified", reasonCode: reference.reasonCode, reason: `${reference.reason} This pin alone cannot say whether the session is current.` }, compared: noSelections };
|
|
122272
|
+
}
|
|
122273
|
+
const missingPin = uncomparableFields(observed, reference, REQUIRED_IDENTITY["session-receipt"]);
|
|
122274
|
+
if (missingPin.length > 0) {
|
|
122275
|
+
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 };
|
|
122276
|
+
}
|
|
122277
|
+
if (sameRevision(session.profileRevision, reference.profileRevision)) {
|
|
122278
|
+
return {
|
|
122279
|
+
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.` },
|
|
122280
|
+
compared: consumed
|
|
122281
|
+
};
|
|
122282
|
+
}
|
|
122283
|
+
return {
|
|
122284
|
+
consumer: {
|
|
122285
|
+
...observed,
|
|
122286
|
+
status: "pinned",
|
|
122287
|
+
reasonCode: "PINNED_BY_DESIGN",
|
|
122288
|
+
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.`
|
|
122289
|
+
},
|
|
122290
|
+
compared: consumed
|
|
122291
|
+
};
|
|
122292
|
+
}
|
|
122293
|
+
function driftFor(result2, reference) {
|
|
122294
|
+
if (reference.source !== "authority" || result2.compared.length === 0)
|
|
122295
|
+
return [];
|
|
122296
|
+
if (result2.consumer.status === "unverified" && result2.consumer.reasonCode === "IDENTITY_MISMATCH")
|
|
122297
|
+
return [];
|
|
122298
|
+
const selected = new Map(reference.selections.map((selection2) => [selection2.slug, selection2.version]));
|
|
122299
|
+
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));
|
|
122300
|
+
}
|
|
122301
|
+
async function readSelectionProvenance(input3, options = {}) {
|
|
122302
|
+
if (!input3.profileId?.trim())
|
|
122303
|
+
throw new Error("A selection profile id is required to read selection provenance.");
|
|
122304
|
+
if (!input3.stationId?.trim() || input3.stationId.length > LABEL_MAX_CHARS)
|
|
122305
|
+
throw new Error("A station id is required to read selection provenance.");
|
|
122306
|
+
if (!input3.localStationId?.trim() || input3.localStationId.length > LABEL_MAX_CHARS)
|
|
122307
|
+
throw new Error("The local host id is required to read selection provenance.");
|
|
122308
|
+
const reference = await resolveReference(input3, options);
|
|
122309
|
+
const results2 = [activationConsumer(input3, reference, options), await stationConsumer(input3, reference, options), sessionConsumer(input3, reference, options)];
|
|
122310
|
+
const drift = results2.flatMap((result2) => driftFor(result2, reference));
|
|
122311
|
+
return {
|
|
122312
|
+
schemaVersion: 1,
|
|
122313
|
+
readOnly: true,
|
|
122314
|
+
selectionProfile: input3.profileId,
|
|
122315
|
+
selected: {
|
|
122316
|
+
profileId: reference.profileId,
|
|
122317
|
+
...supportedIdentityValue(reference.profileRevision) ? { profileRevision: reference.profileRevision, selectionCount: reference.selectionCount } : {},
|
|
122318
|
+
...supportedIdentityValue(reference.authority) ? { authority: reference.authority } : {},
|
|
122319
|
+
...supportedIdentityValue(reference.workspaceId) ? { workspaceId: reference.workspaceId } : {},
|
|
122320
|
+
...reference.observedAt === undefined ? {} : { observedAt: reference.observedAt },
|
|
122321
|
+
source: reference.source,
|
|
122322
|
+
reasonCode: reference.reasonCode,
|
|
122323
|
+
reason: reference.reason
|
|
122324
|
+
},
|
|
122325
|
+
consumers: results2.map((result2) => result2.consumer),
|
|
122326
|
+
drift: drift.slice(0, PROVENANCE_DRIFT_LIMIT),
|
|
122327
|
+
driftTruncated: drift.length > PROVENANCE_DRIFT_LIMIT,
|
|
122328
|
+
notAttested: [
|
|
122329
|
+
"Published version and digest evidence for skill payloads: read it with skills versions and skills review-export.",
|
|
122330
|
+
"Native discovery, native locks and project locks: read them with skills hook check and skills sessions recover-lock.",
|
|
122331
|
+
"Live consumer adoption: a receipt shows what a session loaded, never that an agent honoured it."
|
|
122332
|
+
]
|
|
122333
|
+
};
|
|
122334
|
+
}
|
|
122335
|
+
var PROVENANCE_DRIFT_LIMIT = 200, SAFE_LABEL2, LABEL_MAX_CHARS = 200, noSelections, REQUIRED_IDENTITY;
|
|
122336
|
+
var init_selection_provenance = __esm(() => {
|
|
122337
|
+
init_session_reconciliation();
|
|
122338
|
+
init_profile_admin();
|
|
122339
|
+
init_profile_client();
|
|
122340
|
+
init_selection_cache();
|
|
122341
|
+
SAFE_LABEL2 = /^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/;
|
|
122342
|
+
noSelections = [];
|
|
122343
|
+
REQUIRED_IDENTITY = {
|
|
122344
|
+
"local-receipt": ["profileId", "profileRevision", "authority", "workspaceId"],
|
|
122345
|
+
"session-receipt": ["profileId", "profileRevision", "authority", "workspaceId"],
|
|
122346
|
+
"authority-receipt": ["profileId", "profileRevision", "workspaceId"]
|
|
122347
|
+
};
|
|
122348
|
+
});
|
|
122349
|
+
|
|
122350
|
+
// src/cli/commands/provenance.ts
|
|
122351
|
+
var exports_provenance = {};
|
|
122352
|
+
__export(exports_provenance, {
|
|
122353
|
+
registerProvenance: () => registerProvenance,
|
|
122354
|
+
provenanceLines: () => provenanceLines
|
|
122355
|
+
});
|
|
122356
|
+
import { hostname as hostname5 } from "os";
|
|
122357
|
+
function provenanceLines(receipt) {
|
|
122358
|
+
const selected = receipt.selected;
|
|
122359
|
+
const lines = [
|
|
122360
|
+
`Selection profile ${receipt.selectionProfile}`,
|
|
122361
|
+
`Selected: ${selected.profileRevision ?? "unavailable"} (${selected.selectionCount ?? 0} selections, ${selected.source})`
|
|
122362
|
+
];
|
|
122363
|
+
for (const consumer of receipt.consumers)
|
|
122364
|
+
lines.push(...consumerLines(consumer));
|
|
122365
|
+
if (receipt.drift.length > 0) {
|
|
122366
|
+
lines.push(`Drift (${receipt.drift.length}${receipt.driftTruncated ? ", truncated" : ""}):`);
|
|
122367
|
+
for (const row2 of receipt.drift)
|
|
122368
|
+
lines.push(`- ${row2.source} ${row2.id}: ${row2.slug} ${row2.selectedVersion} -> ${row2.observedVersion}`);
|
|
122369
|
+
}
|
|
122370
|
+
return lines;
|
|
122371
|
+
}
|
|
122372
|
+
function consumerLines(consumer) {
|
|
122373
|
+
const label2 = consumer.kind === "session" ? "Pinned" : consumer.source === "local-receipt" ? "Activated" : "Applied";
|
|
122374
|
+
const identity6 = consumer.kind === "session" ? `session ${consumer.id}` : consumer.idKind === "local-host" ? `this machine (${consumer.id})` : `station ${consumer.id}`;
|
|
122375
|
+
const lines = [`${label2}: ${identity6} ${consumer.profileRevision ?? "no receipt"} [${consumer.status}] ${consumer.reasonCode}`, ` ${consumer.reason}`];
|
|
122376
|
+
if (consumer.kind === "session" && consumer.consumed) {
|
|
122377
|
+
lines.push(`Consumed: ${consumer.loadedCount ?? 0} of ${consumer.selectionCount ?? 0} selections loaded`);
|
|
122378
|
+
for (const selection2 of consumer.consumed)
|
|
122379
|
+
lines.push(`- ${selection2.slug}@${selection2.version} ${selection2.bundleDigest}`);
|
|
122380
|
+
}
|
|
122381
|
+
return lines;
|
|
122382
|
+
}
|
|
122383
|
+
function registerProvenance(parent) {
|
|
122384
|
+
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) => {
|
|
122385
|
+
try {
|
|
122386
|
+
const localStationId = process.env.HASNA_STATION ?? hostname5();
|
|
122387
|
+
const receipt = await readSelectionProvenance({
|
|
122388
|
+
profileId: selectedProfileId(options.selectionProfile),
|
|
122389
|
+
localStationId,
|
|
122390
|
+
stationId: options.station ?? localStationId,
|
|
122391
|
+
...options.session === undefined ? {} : { sessionId: options.session },
|
|
122392
|
+
...options.cached ? { cached: true } : {}
|
|
122393
|
+
});
|
|
122394
|
+
await writeCliOutput(options.json ? JSON.stringify(receipt) : provenanceLines(receipt).join(`
|
|
122395
|
+
`));
|
|
122396
|
+
} catch (error61) {
|
|
122397
|
+
console.error(error61.message);
|
|
122398
|
+
process.exitCode = 1;
|
|
122399
|
+
}
|
|
122400
|
+
});
|
|
122401
|
+
}
|
|
122402
|
+
var init_provenance = __esm(() => {
|
|
122403
|
+
init_selection_provenance();
|
|
122404
|
+
init_context();
|
|
122405
|
+
});
|
|
122406
|
+
|
|
121869
122407
|
// src/cli/commands/grants.ts
|
|
121870
122408
|
var exports_grants = {};
|
|
121871
122409
|
__export(exports_grants, {
|
|
@@ -123312,7 +123850,7 @@ __export(exports_publish, {
|
|
|
123312
123850
|
});
|
|
123313
123851
|
import { execFileSync as execFileSync3 } from "child_process";
|
|
123314
123852
|
import { existsSync as existsSync39, readFileSync as readFileSync52 } from "fs";
|
|
123315
|
-
import { hostname as
|
|
123853
|
+
import { hostname as hostname6 } from "os";
|
|
123316
123854
|
import { join as join79 } from "path";
|
|
123317
123855
|
function registerPublish(parent) {
|
|
123318
123856
|
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 +124034,7 @@ function buildVersionManifest(skillDir, packed) {
|
|
|
123496
124034
|
unpackedByteSize: packed.unpackedByteSize,
|
|
123497
124035
|
bundleSha256: packed.sha256,
|
|
123498
124036
|
provenance: {
|
|
123499
|
-
machine:
|
|
124037
|
+
machine: hostname6(),
|
|
123500
124038
|
agent: process.env.SKILLS_AGENT_ID ?? process.env.HASNA_AGENT_ID ?? process.env.AGENT_ID ?? null,
|
|
123501
124039
|
cliVersion: package_default.version,
|
|
123502
124040
|
gitRemote: sanitizeGitRemote(gitValue(skillDir, ["remote", "get-url", "origin"])),
|
|
@@ -123875,9 +124413,9 @@ function printWhoami(payload) {
|
|
|
123875
124413
|
console.log(source_default.dim(`Auth: ${payload.authSource}`));
|
|
123876
124414
|
const permissions = recordField(payload.permissions);
|
|
123877
124415
|
if (permissions) {
|
|
123878
|
-
const
|
|
123879
|
-
console.log(`Publish: ${
|
|
123880
|
-
console.log(`Profiles write: ${
|
|
124416
|
+
const label2 = (value) => value === true ? "allowed" : value === false ? "denied" : "unknown";
|
|
124417
|
+
console.log(`Publish: ${label2(permissions.publish)}`);
|
|
124418
|
+
console.log(`Profiles write: ${label2(permissions.profilesWrite)}`);
|
|
123881
124419
|
}
|
|
123882
124420
|
if (payload.offline)
|
|
123883
124421
|
console.log(source_default.dim("(offline \u2014 showing cached info)"));
|
|
@@ -124503,7 +125041,7 @@ function promptInvitationRecoveryCode() {
|
|
|
124503
125041
|
}
|
|
124504
125042
|
function promptInvitationProof(kind) {
|
|
124505
125043
|
const length = kind === "token" ? 43 : 6;
|
|
124506
|
-
const
|
|
125044
|
+
const label2 = kind === "token" ? "invitation token" : "recovery code";
|
|
124507
125045
|
const character = kind === "token" ? /^[A-Za-z0-9_-]$/ : /^\d$/;
|
|
124508
125046
|
const { stdin, stderr: output2 } = process, wasRaw = stdin.isRaw, wasFlowing = stdin.readableFlowing;
|
|
124509
125047
|
return new Promise((resolve49) => {
|
|
@@ -124534,13 +125072,13 @@ function promptInvitationProof(kind) {
|
|
|
124534
125072
|
value = "";
|
|
124535
125073
|
overflow = false;
|
|
124536
125074
|
output2.write(`
|
|
124537
|
-
Enter exactly ${length} ${
|
|
125075
|
+
Enter exactly ${length} ${label2} characters: `);
|
|
124538
125076
|
return;
|
|
124539
125077
|
}
|
|
124540
125078
|
if (value.length === length)
|
|
124541
125079
|
return finish(value);
|
|
124542
125080
|
output2.write(`
|
|
124543
|
-
Enter the complete ${
|
|
125081
|
+
Enter the complete ${label2}: `);
|
|
124544
125082
|
value = "";
|
|
124545
125083
|
return;
|
|
124546
125084
|
}
|
|
@@ -124555,7 +125093,7 @@ Enter the complete ${label}: `);
|
|
|
124555
125093
|
if (value.length === length) {
|
|
124556
125094
|
overflow = true;
|
|
124557
125095
|
output2.write(`
|
|
124558
|
-
The ${
|
|
125096
|
+
The ${label2} is too long. Press Enter to start again.`);
|
|
124559
125097
|
} else {
|
|
124560
125098
|
value += text4;
|
|
124561
125099
|
output2.write("*");
|
|
@@ -124563,7 +125101,7 @@ The ${label} is too long. Press Enter to start again.`);
|
|
|
124563
125101
|
} else if (text4 && !key2.ctrl && !key2.meta) {
|
|
124564
125102
|
overflow = true;
|
|
124565
125103
|
output2.write(`
|
|
124566
|
-
The ${
|
|
125104
|
+
The ${label2} contains invalid characters. Press Enter to start again.`);
|
|
124567
125105
|
}
|
|
124568
125106
|
};
|
|
124569
125107
|
const timer = setTimeout(cancel, 5 * 60 * 1000);
|
|
@@ -133645,6 +134183,7 @@ init_registry();
|
|
|
133645
134183
|
init_discovery();
|
|
133646
134184
|
init_fleet_credentials();
|
|
133647
134185
|
init_read_access();
|
|
134186
|
+
init_stray_arguments();
|
|
133648
134187
|
var jsx_dev_runtime8 = __toESM(require_jsx_dev_runtime(), 1);
|
|
133649
134188
|
var isTTY2 = (process.stdout.isTTY ?? false) && (process.stdin.isTTY ?? false);
|
|
133650
134189
|
var program2 = new Command;
|
|
@@ -133654,7 +134193,7 @@ program2.hook("preAction", () => {
|
|
|
133654
134193
|
recordEnvironmentProfile(process.env.HASNA_PROFILE);
|
|
133655
134194
|
selectCliSkillsCredentialProfile(profile);
|
|
133656
134195
|
});
|
|
133657
|
-
program2.command("interactive", { isDefault: true }).alias("i").
|
|
134196
|
+
permitStrayArguments(program2.command("interactive", { isDefault: true }).alias("i").description("Interactive skill browser (TUI)").action(async (_options, command) => {
|
|
133658
134197
|
const stray = command.args[0];
|
|
133659
134198
|
if (stray !== undefined) {
|
|
133660
134199
|
const verbs = program2.commands.map((c) => c.name()).filter((n2) => n2 !== "interactive").sort();
|
|
@@ -133681,7 +134220,7 @@ program2.command("interactive", { isDefault: true }).alias("i").allowExcessArgum
|
|
|
133681
134220
|
render_default(/* @__PURE__ */ jsx_dev_runtime8.jsxDEV(App2, {
|
|
133682
134221
|
initialAccess: access
|
|
133683
134222
|
}, undefined, false, undefined, this));
|
|
133684
|
-
});
|
|
134223
|
+
}));
|
|
133685
134224
|
var { registerInstall: registerInstall2 } = await Promise.resolve().then(() => (init_install(), exports_install));
|
|
133686
134225
|
registerInstall2(program2);
|
|
133687
134226
|
var { registerBrowse: registerBrowse2 } = await Promise.resolve().then(() => (init_list(), exports_list));
|
|
@@ -133712,6 +134251,8 @@ var { registerPluginAdmission: registerPluginAdmission2 } = await Promise.resolv
|
|
|
133712
134251
|
registerPluginAdmission2(program2);
|
|
133713
134252
|
var { registerProfiles: registerProfiles2 } = await Promise.resolve().then(() => (init_profiles(), exports_profiles));
|
|
133714
134253
|
registerProfiles2(program2);
|
|
134254
|
+
var { registerProvenance: registerProvenance2 } = await Promise.resolve().then(() => (init_provenance(), exports_provenance));
|
|
134255
|
+
registerProvenance2(program2);
|
|
133715
134256
|
var { registerGrants: registerGrants2 } = await Promise.resolve().then(() => (init_grants(), exports_grants));
|
|
133716
134257
|
registerGrants2(program2);
|
|
133717
134258
|
var { registerHydrate: registerHydrate2 } = await Promise.resolve().then(() => (init_hydrate(), exports_hydrate));
|
|
@@ -133741,6 +134282,7 @@ registerStorage2(program2);
|
|
|
133741
134282
|
var { registerRegistryReconcile: registerRegistryReconcile2 } = await Promise.resolve().then(() => (init_registry_reconcile2(), exports_registry_reconcile));
|
|
133742
134283
|
registerRegistryReconcile2(program2);
|
|
133743
134284
|
registerEventsCommands(program2, { source: "skills" });
|
|
134285
|
+
rejectStrayArguments(program2);
|
|
133744
134286
|
var cliArgs = process.argv.slice(2);
|
|
133745
134287
|
var colorFlag = optionPrefix(program2, cliArgs).indices.find((index) => cliArgs[index] === "--no-color");
|
|
133746
134288
|
if (colorFlag !== undefined) {
|