@hasna/skills 0.9.14 → 0.9.15

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/bin/index.js CHANGED
@@ -36868,7 +36868,7 @@ var package_default;
36868
36868
  var init_package = __esm(() => {
36869
36869
  package_default = {
36870
36870
  name: "@hasna/skills",
36871
- version: "0.9.14",
36871
+ version: "0.9.15",
36872
36872
  description: "Skills library for AI coding agents",
36873
36873
  type: "module",
36874
36874
  bin: {
@@ -54696,39 +54696,132 @@ var fail2 = () => new Error('CODEX_HOOK_TRUST_UNSUPPORTED_LAYOUT: preserve and c
54696
54696
  };
54697
54697
  var init_codex_hook_trust_layout = () => {};
54698
54698
 
54699
+ // src/lib/codex-hook-additions-review.ts
54700
+ import { isAbsolute as isAbsolute14 } from "path";
54701
+ import { isDeepStrictEqual as isDeepStrictEqual5 } from "util";
54702
+ function exactKeys2(value, keys2) {
54703
+ need4(value && typeof value === "object" && !Array.isArray(value) && isDeepStrictEqual5(Object.keys(value).sort(), [...keys2].sort()), "RECONCILE_ADDITIONS_REVIEW_SCHEMA");
54704
+ }
54705
+ function readReviewedAdditionTrustStates(proof, before2, current, journalHooks) {
54706
+ const captured = proofs.get(proof);
54707
+ need4(!!captured && captured.before.file === before2.file && captured.before.sha256 === before2.sha256 && captured.current.file === current.file && captured.current.sha256 === current.sha256 && isDeepStrictEqual5(captured.journalHooks, journalHooks.map(({ key, currentHash }) => ({ key, currentHash }))), "RECONCILE_ADDITIONS_PROOF_CHANGED");
54708
+ captured.recheck();
54709
+ unchanged2(before2);
54710
+ unchanged2(current);
54711
+ return captured.states;
54712
+ }
54713
+ function reviewNativeHookAdditions(options) {
54714
+ need4(isAbsolute14(options.path), "RECONCILE_ADDITIONS_REVIEW_PATH");
54715
+ const reviewFile = snapshot(options.path, true), review = JSON.parse(reviewFile.text);
54716
+ exactKeys2(review, ["version", "kind", "reason", "producerEvidence", "journalIntentSha256", "policySha256", "configCurrentSha256", "hooksCurrentSha256", "producerBefore", "additions"]);
54717
+ need4((review.version === 1 || review.version === 2) && review.kind === "native-hook-additions" && text2(review.reason) && text2(review.producerEvidence), "RECONCILE_ADDITIONS_REVIEW_SCHEMA");
54718
+ for (const [name, expected] of [["journalIntentSha256", options.intent.sha256], ["policySha256", options.policy.sha256], ["configCurrentSha256", options.configCurrent.sha256], ["hooksCurrentSha256", options.hooksCurrent.sha256]])
54719
+ need4(hash2(review[name]) && review[name] === expected, "RECONCILE_ADDITIONS_REVIEW_CHANGED");
54720
+ exactKeys2(review.producerBefore, ["configPath", "configSha256", "hooksPath", "hooksSha256"]);
54721
+ const before2 = review.producerBefore;
54722
+ need4(isAbsolute14(before2.configPath) && isAbsolute14(before2.hooksPath) && hash2(before2.configSha256) && hash2(before2.hooksSha256), "RECONCILE_ADDITIONS_PRODUCER_PREIMAGE");
54723
+ const producerConfig = snapshot(before2.configPath, true), producerHooks = snapshot(before2.hooksPath, true);
54724
+ need4(producerConfig.sha256 === before2.configSha256 && producerHooks.sha256 === before2.hooksSha256 && producerHooks.sha256 === options.hooksBefore.sha256, "RECONCILE_ADDITIONS_PRODUCER_PREIMAGE");
54725
+ const original = structure(options.configBefore.text), producer = structure(producerConfig.text), expectedProducer = structuredClone(original), originalKeys = options.journalHooks.map((hook) => hook.key);
54726
+ expectedProducer.hooks ??= {};
54727
+ expectedProducer.hooks.state ??= {};
54728
+ for (const hook of options.journalHooks)
54729
+ expectedProducer.hooks.state[hook.key] = { ...expectedProducer.hooks.state[hook.key], enabled: true, trusted_hash: hook.currentHash };
54730
+ need4(isDeepStrictEqual5(expectedProducer, producer) && codexTrustReconcileWitness(options.configBefore.text, originalKeys) === codexTrustReconcileWitness(producerConfig.text, originalKeys) && codexTrustUnmanagedSemantic(options.configBefore.text, originalKeys) === codexTrustUnmanagedSemantic(producerConfig.text, originalKeys), "RECONCILE_ADDITIONS_PRODUCER_PREIMAGE");
54731
+ need4(Array.isArray(review.additions) && review.additions.length > 0 && review.additions.length <= 20, "RECONCILE_ADDITIONS_REVIEW_SCHEMA");
54732
+ const expectedHooks = JSON.parse(options.hooksBefore.text), currentHooks = JSON.parse(options.hooksCurrent.text), expectedConfig = structuredClone(producer);
54733
+ need4(expectedHooks.hooks && typeof expectedHooks.hooks === "object" && !Array.isArray(expectedHooks.hooks), "RECONCILE_ADDITIONS_DECLARATIONS");
54734
+ const added = [], states = [], seen = new Set, commands = new Set(options.recordedNativeHooks.map((hook) => hook.command));
54735
+ for (const addition of review.additions) {
54736
+ exactKeys2(addition, review.version === 1 ? ["event", "nativeHook"] : ["event", "nativeHook", "trustState"]);
54737
+ need4(Object.hasOwn(review.version === 1 ? events : matchedEvents, addition.event), "RECONCILE_ADDITIONS_DECLARATIONS");
54738
+ const { event, nativeHook: hook } = addition;
54739
+ exactKeys2(hook, nativeKeys);
54740
+ const groups = expectedHooks.hooks[event] ?? [];
54741
+ need4(Array.isArray(groups), "RECONCILE_ADDITIONS_DECLARATIONS");
54742
+ const key = `${options.nativeHooksPath}:${matchedEvents[event][1]}:${groups.length}:0`;
54743
+ need4(hook.key === key && !seen.has(key) && !options.recordedNativeHooks.some((originalHook) => originalHook.key === key) && !Object.hasOwn(expectedConfig.hooks.state, key), "RECONCILE_ADDITIONS_IDENTITY");
54744
+ need4(hook.eventName === matchedEvents[event][0] && hook.handlerType === "command" && text2(hook.command, 16384) && !commands.has(hook.command) && Number.isInteger(hook.timeoutSec) && hook.timeoutSec > 0 && hook.timeoutSec <= 60 && (event === "PreToolUse" ? text2(hook.matcher) : hook.matcher === null) && hook.async === false && hook.statusMessage === null && hook.additionalContextLimit === null && hook.sourcePath === options.nativeHooksPath && hook.source === "user" && hook.pluginId === null && hook.isManaged === false && /^sha256:[a-f0-9]{64}$/.test(hook.currentHash) && hook.enabled === true && hook.trustStatus === "trusted", "RECONCILE_ADDITIONS_IDENTITY");
54745
+ let trustState = { enabled: true, trusted_hash: hook.currentHash };
54746
+ if (review.version === 2) {
54747
+ const state = addition.trustState;
54748
+ exactKeys2(state, state && Object.hasOwn(state, "enabled") ? ["enabled", "trusted_hash"] : ["trusted_hash"]);
54749
+ need4(state.trusted_hash === hook.currentHash && (!Object.hasOwn(state, "enabled") || state.enabled === true), "RECONCILE_ADDITIONS_TRUST_STATE");
54750
+ trustState = { ...state };
54751
+ }
54752
+ seen.add(key);
54753
+ commands.add(hook.command);
54754
+ added.push(hook);
54755
+ states.push(Object.freeze({ key, state: Object.freeze(trustState) }));
54756
+ expectedHooks.hooks[event] = [...groups, { ...event === "PreToolUse" ? { matcher: hook.matcher } : {}, hooks: [{ type: "command", command: hook.command, timeout: hook.timeoutSec }] }];
54757
+ expectedConfig.hooks.state[key] = trustState;
54758
+ }
54759
+ need4(isDeepStrictEqual5(expectedHooks, currentHooks), "RECONCILE_ADDITIONS_DECLARATIONS");
54760
+ const keys2 = added.map((hook) => hook.key);
54761
+ need4(isDeepStrictEqual5(expectedConfig, structure(options.configCurrent.text)) && codexTrustReconcileWitness(producerConfig.text, keys2) === codexTrustReconcileWitness(options.configCurrent.text, keys2) && codexTrustUnmanagedSemantic(producerConfig.text, keys2) === codexTrustUnmanagedSemantic(options.configCurrent.text, keys2), "RECONCILE_ADDITIONS_CONFIG");
54762
+ const inputs = [reviewFile, producerConfig, producerHooks, options.intent, options.policy, options.configBefore, options.configCurrent, options.hooksBefore, options.hooksCurrent];
54763
+ const recheck = () => {
54764
+ for (const input of inputs)
54765
+ unchanged2(input);
54766
+ };
54767
+ recheck();
54768
+ const trustProof = Object.freeze({ reviewSha256: reviewFile.sha256 });
54769
+ proofs.set(trustProof, { before: options.configBefore, current: options.configCurrent, journalHooks: options.journalHooks.map(({ key, currentHash }) => ({ key, currentHash })), states: Object.freeze(states), recheck });
54770
+ return { hooks: added, recheck, trustProof, receipt: { ...review.version === 2 ? { version: 2 } : {}, reviewPath: reviewFile.file, reviewSha256: reviewFile.sha256, reason: review.reason, producerEvidence: review.producerEvidence, producerBefore: { configPath: producerConfig.file, configSha256: producerConfig.sha256, hooksPath: producerHooks.file, hooksSha256: producerHooks.sha256 }, additions: review.version === 1 ? added : review.additions } };
54771
+ }
54772
+ var events, matchedEvents, hash2 = (value) => typeof value === "string" && /^[a-f0-9]{64}$/.test(value), text2 = (value, max2 = 2048) => typeof value === "string" && value.trim().length > 0 && value.length <= max2 && !/[\0\r\n]/.test(value), structure = (value) => JSON.parse(JSON.stringify(Bun.TOML.parse(value))), nativeKeys, proofs;
54773
+ var init_codex_hook_additions_review = __esm(() => {
54774
+ init_codex_hook_trust_files();
54775
+ init_codex_hook_trust_layout();
54776
+ events = { UserPromptSubmit: ["userPromptSubmit", "user_prompt_submit"], SessionStart: ["sessionStart", "session_start"], SubagentStart: ["subagentStart", "subagent_start"] };
54777
+ matchedEvents = { ...events, PreToolUse: ["preToolUse", "pre_tool_use"] };
54778
+ nativeKeys = ["key", "eventName", "handlerType", "command", "matcher", "timeoutSec", "async", "statusMessage", "additionalContextLimit", "sourcePath", "source", "pluginId", "isManaged", "currentHash", "enabled", "trustStatus"];
54779
+ proofs = new WeakMap;
54780
+ });
54781
+
54699
54782
  // src/lib/codex-hook-discovery-recovery.ts
54700
54783
  import { createHash as createHash15 } from "crypto";
54701
- import { isDeepStrictEqual as isDeepStrictEqual5 } from "util";
54702
- function createCodexHookDiscoveryRecovery(binding, before2, current, hooks) {
54784
+ import { isDeepStrictEqual as isDeepStrictEqual6 } from "util";
54785
+ function createCodexHookDiscoveryRecovery(binding, before2, current, hooks, additions) {
54786
+ const journalHooks = hooks.map(({ key, currentHash }) => ({ key, currentHash }));
54787
+ const additionStates = additions ? readReviewedAdditionTrustStates(additions, before2, current, journalHooks) : [];
54788
+ const recheckAdditions = () => {
54789
+ if (additions)
54790
+ readReviewedAdditionTrustStates(additions, before2, current, journalHooks);
54791
+ };
54703
54792
  const raw = binding.sources.filter((source) => source.path === current.file && source.hashMode === "bytes");
54704
54793
  if (!raw.some((source) => source.sha256 !== current.sha256))
54705
54794
  return;
54706
54795
  need4(binding.agent === "codex" && binding.method === "reviewed" && raw.length === 1 && raw[0].sha256 === before2.sha256 && before2.sha256 !== current.sha256, "RECONCILE_DISCOVERY_CONFIG_WITNESS");
54707
54796
  need4(raw[0].format === undefined && raw[0].fields === undefined && raw[0].managedPlugins === undefined, "RECONCILE_DISCOVERY_CONFIG_WITNESS");
54708
54797
  const typed = binding.sources.filter((source) => source.path === current.file && source.format === "toml");
54709
- need4(typed.length === 1 && typed[0].hashMode === undefined && isDeepStrictEqual5(typed[0].fields, fields), "RECONCILE_DISCOVERY_TYPED_WITNESS");
54710
- const original = structure(before2.text), actual = structure(current.text);
54798
+ need4(typed.length === 1 && typed[0].hashMode === undefined && isDeepStrictEqual6(typed[0].fields, fields), "RECONCILE_DISCOVERY_TYPED_WITNESS");
54799
+ const original = structure2(before2.text), actual = structure2(current.text);
54711
54800
  const project = (value) => Object.fromEntries(fields.map((field2) => [field2, value[field2] ?? null]));
54712
54801
  const projection = sha2(JSON.stringify(project(original)));
54713
- need4(typed[0].sha256 === projection && sha2(JSON.stringify(project(actual))) === projection && isDeepStrictEqual5(project(original), project(actual)), "RECONCILE_DISCOVERY_TYPED_WITNESS");
54714
- need4(hooks.length > 0 && hooks.length <= 100 && new Set(hooks.map((hook) => hook.key)).size === hooks.length && hooks.every((hook) => typeof hook.key === "string" && /^sha256:[a-f0-9]{64}$/.test(hook.currentHash)), "RECONCILE_DISCOVERY_TRUST_WITNESS");
54715
- const keys2 = hooks.map((hook) => hook.key), expected = structuredClone(original);
54802
+ need4(typed[0].sha256 === projection && sha2(JSON.stringify(project(actual))) === projection && isDeepStrictEqual6(project(original), project(actual)), "RECONCILE_DISCOVERY_TYPED_WITNESS");
54803
+ const keys2 = [...journalHooks.map((hook) => hook.key), ...additionStates.map((hook) => hook.key)];
54804
+ need4(journalHooks.length > 0 && keys2.length <= 100 && new Set(keys2).size === keys2.length && journalHooks.every((hook) => typeof hook.key === "string" && /^sha256:[a-f0-9]{64}$/.test(hook.currentHash)), "RECONCILE_DISCOVERY_TRUST_WITNESS");
54805
+ const expected = structuredClone(original);
54716
54806
  expected.hooks ??= {};
54717
54807
  expected.hooks.state ??= {};
54718
- for (const hook of hooks)
54808
+ for (const hook of journalHooks)
54719
54809
  expected.hooks.state[hook.key] = { ...expected.hooks.state[hook.key], enabled: true, trusted_hash: hook.currentHash };
54720
- need4(isDeepStrictEqual5(expected, actual) && codexTrustReconcileWitness(before2.text, keys2) === codexTrustReconcileWitness(current.text, keys2) && codexTrustUnmanagedSemantic(before2.text, keys2) === codexTrustUnmanagedSemantic(current.text, keys2), "RECONCILE_DISCOVERY_TRUST_WITNESS");
54810
+ for (const { key, state } of additionStates)
54811
+ expected.hooks.state[key] = { ...state };
54812
+ need4(isDeepStrictEqual6(expected, actual) && codexTrustReconcileWitness(before2.text, keys2) === codexTrustReconcileWitness(current.text, keys2) && codexTrustUnmanagedSemantic(before2.text, keys2) === codexTrustUnmanagedSemantic(current.text, keys2), "RECONCILE_DISCOVERY_TRUST_WITNESS");
54721
54813
  unchanged2(before2);
54722
54814
  unchanged2(current);
54723
54815
  const witness = Object.freeze({ configPath: current.file, beforeSha256: before2.sha256, currentSha256: current.sha256, discoverySha256: sha2(JSON.stringify(binding)), typedProjectionSha256: projection });
54724
- proofs.set(witness, { before: before2, current });
54816
+ proofs2.set(witness, { before: before2, current, recheckAdditions });
54725
54817
  return witness;
54726
54818
  }
54727
54819
  function assertCodexHookDiscoveryRecovery(binding, witness) {
54728
- const proof = proofs.get(witness);
54820
+ const proof = proofs2.get(witness);
54729
54821
  need4(!!proof && binding.agent === "codex" && witness.discoverySha256 === sha2(JSON.stringify(binding)), "RECONCILE_DISCOVERY_RECOVERY_CHANGED");
54730
54822
  unchanged2(proof.before);
54731
54823
  unchanged2(proof.current);
54824
+ proof.recheckAdditions();
54732
54825
  }
54733
54826
  function verifiesCodexHookDiscoverySource(binding, source, currentDigest, witness) {
54734
54827
  if (!witness || source.path !== witness.configPath || source.hashMode !== "bytes")
@@ -54737,21 +54830,22 @@ function verifiesCodexHookDiscoverySource(binding, source, currentDigest, witnes
54737
54830
  need4(source.sha256 === witness.beforeSha256 && currentDigest === witness.currentSha256, "RECONCILE_DISCOVERY_RECOVERY_CHANGED");
54738
54831
  return true;
54739
54832
  }
54740
- var sha2 = (text2) => createHash15("sha256").update(text2).digest("hex"), fields, structure = (text2) => JSON.parse(JSON.stringify(Bun.TOML.parse(text2))), proofs;
54833
+ var sha2 = (text3) => createHash15("sha256").update(text3).digest("hex"), fields, structure2 = (text3) => JSON.parse(JSON.stringify(Bun.TOML.parse(text3))), proofs2;
54741
54834
  var init_codex_hook_discovery_recovery = __esm(() => {
54742
54835
  init_codex_hook_trust_files();
54743
54836
  init_codex_hook_trust_layout();
54837
+ init_codex_hook_additions_review();
54744
54838
  fields = ["plugins", "marketplaces", "skills"];
54745
- proofs = new WeakMap;
54839
+ proofs2 = new WeakMap;
54746
54840
  });
54747
54841
 
54748
54842
  // src/lib/agent-discovery.ts
54749
54843
  import { createHash as createHash16 } from "crypto";
54750
54844
  import { lstatSync as lstatSync20, readFileSync as readFileSync17, readdirSync as readdirSync10, realpathSync as realpathSync4 } from "fs";
54751
- import { basename as basename8, dirname as dirname16, isAbsolute as isAbsolute14, join as join31, resolve as resolve15, sep as sep5 } from "path";
54752
- function parseConfig(text2, path, toml = false) {
54845
+ import { basename as basename8, dirname as dirname16, isAbsolute as isAbsolute15, join as join31, resolve as resolve15, sep as sep5 } from "path";
54846
+ function parseConfig(text3, path, toml = false) {
54753
54847
  try {
54754
- const value = toml ? Bun.TOML.parse(text2) : JSON.parse(text2);
54848
+ const value = toml ? Bun.TOML.parse(text3) : JSON.parse(text3);
54755
54849
  if (!value || typeof value !== "object" || Array.isArray(value))
54756
54850
  throw new Error;
54757
54851
  return value;
@@ -54760,7 +54854,7 @@ function parseConfig(text2, path, toml = false) {
54760
54854
  }
54761
54855
  }
54762
54856
  function safe4(path) {
54763
- if (!isAbsolute14(path) || path.includes("\x00"))
54857
+ if (!isAbsolute15(path) || path.includes("\x00"))
54764
54858
  throw new Error("Expected an absolute native discovery path");
54765
54859
  for (let cursor = path;; cursor = dirname16(cursor)) {
54766
54860
  if (lstatSync20(cursor, { throwIfNoEntry: false })?.isSymbolicLink())
@@ -54813,12 +54907,12 @@ function projected(source, changes, budget = discoveryByteBudget()) {
54813
54907
  return hashDiscoveryPathFile(source.path, budget, changes);
54814
54908
  return hashRawDiscoveryFile(source.path, budget, changes);
54815
54909
  }
54816
- const text2 = read2(source.path, changes);
54817
- if (text2 === null)
54910
+ const text3 = read2(source.path, changes);
54911
+ if (text3 === null)
54818
54912
  return null;
54819
54913
  if (!source.format)
54820
- return digest(text2);
54821
- const object4 = source.format === "yaml" ? parseHermesConfig(text2) : parseConfig(text2, source.path, source.format === "toml");
54914
+ return digest(text3);
54915
+ const object4 = source.format === "yaml" ? parseHermesConfig(text3) : parseConfig(text3, source.path, source.format === "toml");
54822
54916
  if (!object4 || typeof object4 !== "object" || Array.isArray(object4))
54823
54917
  throw new Error("Expected native discovery configuration object");
54824
54918
  return digest(JSON.stringify(Object.fromEntries((source.fields ?? []).map((field2) => [field2, object4[field2] ?? null]))));
@@ -54962,8 +55056,8 @@ function resolveAgentDiscovery(options) {
54962
55056
  if (!lstatSync20(builtinRoot, { throwIfNoEntry: false })?.isDirectory())
54963
55057
  unresolved("installed Gemini builtin root is missing");
54964
55058
  for (const name of readdirSync10(builtinRoot).sort()) {
54965
- const text2 = witness(join31(builtinRoot, name, "SKILL.md"));
54966
- const match = text2?.match(/^---\r?\n[\s\S]*?^name:\s*([a-z0-9][a-z0-9-]*)\s*$/m);
55059
+ const text3 = witness(join31(builtinRoot, name, "SKILL.md"));
55060
+ const match = text3?.match(/^---\r?\n[\s\S]*?^name:\s*([a-z0-9][a-z0-9-]*)\s*$/m);
54967
55061
  if (!match?.[1] || builtinNames.includes(match[1]))
54968
55062
  unresolved("installed Gemini builtin name is missing or ambiguous");
54969
55063
  builtinNames.push(match[1]);
@@ -55041,7 +55135,7 @@ function resolveAgentDiscovery(options) {
55041
55135
  unresolved("unsupported plugin enablement");
55042
55136
  const split2 = id.lastIndexOf("@"), name = id.slice(0, split2), marketplace = id.slice(split2 + 1);
55043
55137
  const market = config.marketplaces?.[marketplace] ?? (marketplace === "personal" ? { source_type: "local", source: home } : undefined);
55044
- if (split2 < 1 || market?.source_type !== "local" || typeof market.source !== "string" || !isAbsolute14(market.source))
55138
+ if (split2 < 1 || market?.source_type !== "local" || typeof market.source !== "string" || !isAbsolute15(market.source))
55045
55139
  unresolved("enabled plugin marketplace is not an explicit local source");
55046
55140
  const catalogText = witness(join31(market.source, ".agents/plugins/marketplace.json"));
55047
55141
  if (catalogText === null)
@@ -55057,7 +55151,7 @@ function resolveAgentDiscovery(options) {
55057
55151
  if ((config.plugin?.length ?? 0) > 0 || config.skills?.urls?.length)
55058
55152
  unresolved("external plugin or remote skill source");
55059
55153
  for (const path of config.skills?.paths ?? []) {
55060
- if (typeof path !== "string" || !isAbsolute14(path))
55154
+ if (typeof path !== "string" || !isAbsolute15(path))
55061
55155
  unresolved("relative or malformed added skill root");
55062
55156
  roots.add(path);
55063
55157
  }
@@ -55095,7 +55189,7 @@ function resolveAgentDiscovery(options) {
55095
55189
  }
55096
55190
  return { agent, roots: [...roots].sort(), sources, method: "automatic", ...agent === "gemini" ? { builtinNames } : {}, ...agent === "hermes" ? { directories: captureDiscoveryDirectories([join31(home, ".hermes/plugins"), join31(home, ".hermes/hermes-agent")].map((path) => canonical4(path))) } : {} };
55097
55191
  }
55098
- var digest = (text2) => createHash16("sha256").update(text2).digest("hex");
55192
+ var digest = (text3) => createHash16("sha256").update(text3).digest("hex");
55099
55193
  var init_agent_discovery = __esm(() => {
55100
55194
  init_agent_policy_limits();
55101
55195
  init_agent_hermes();
@@ -55227,7 +55321,7 @@ import {
55227
55321
  statSync as statSync10,
55228
55322
  writeFileSync as writeFileSync9
55229
55323
  } from "fs";
55230
- import { basename as basename10, dirname as dirname18, isAbsolute as isAbsolute15, join as join33, normalize as normalize2, relative as relative5, resolve as resolve17, sep as sep7 } from "path";
55324
+ import { basename as basename10, dirname as dirname18, isAbsolute as isAbsolute16, join as join33, normalize as normalize2, relative as relative5, resolve as resolve17, sep as sep7 } from "path";
55231
55325
  function getPortableSkillsRoot(options = {}) {
55232
55326
  return resolvePortableSkillsRoot(options, true);
55233
55327
  }
@@ -55385,7 +55479,7 @@ function assertDisjointImportPaths(source, destination) {
55385
55479
  const destinationPath = physicalImportPath(destination);
55386
55480
  const contains2 = (parent, child) => {
55387
55481
  const path = relative5(parent, child);
55388
- return path === "" || !isAbsolute15(path) && path !== ".." && !path.startsWith(`..${sep7}`);
55482
+ return path === "" || !isAbsolute16(path) && path !== ".." && !path.startsWith(`..${sep7}`);
55389
55483
  };
55390
55484
  if (contains2(sourcePath, destinationPath) || contains2(destinationPath, sourcePath)) {
55391
55485
  throw new Error("Source and destination skill directories must not overlap");
@@ -55602,7 +55696,7 @@ function safeIsDirectory(path) {
55602
55696
  }
55603
55697
  }
55604
55698
  function isSafeRelativePath2(value) {
55605
- if (!value.trim() || isAbsolute15(value))
55699
+ if (!value.trim() || isAbsolute16(value))
55606
55700
  return false;
55607
55701
  const normalized = normalize2(value).replace(/\\/g, "/");
55608
55702
  return normalized !== ".." && !normalized.startsWith("../") && !normalized.includes("/../");
@@ -57626,8 +57720,8 @@ function getPublicSkillDiscovery(skill) {
57626
57720
  function publicDiscoveryTags(tags) {
57627
57721
  return tags.filter((tag) => !VENDOR_TAGS.has(tag.toLowerCase()));
57628
57722
  }
57629
- function sanitizePublicDiscoveryText(text2) {
57630
- let sanitized = text2.replace(vendorPattern, "hosted AI").replace(/\bLLM\b/g, "AI").replace(/\s{2,}/g, " ");
57723
+ function sanitizePublicDiscoveryText(text3) {
57724
+ let sanitized = text3.replace(vendorPattern, "hosted AI").replace(/\bLLM\b/g, "AI").replace(/\s{2,}/g, " ");
57631
57725
  let previous;
57632
57726
  do {
57633
57727
  previous = sanitized;
@@ -66247,8 +66341,8 @@ function lt_default() {
66247
66341
  localeError: error33()
66248
66342
  };
66249
66343
  }
66250
- var capitalizeFirstCharacter = (text2) => {
66251
- return text2.charAt(0).toUpperCase() + text2.slice(1);
66344
+ var capitalizeFirstCharacter = (text3) => {
66345
+ return text3.charAt(0).toUpperCase() + text3.slice(1);
66252
66346
  }, error33 = () => {
66253
66347
  const Sizable = {
66254
66348
  string: {
@@ -74081,7 +74175,7 @@ __export(exports_schemas2, {
74081
74175
  httpUrl: () => httpUrl,
74082
74176
  hostname: () => hostname2,
74083
74177
  hex: () => hex2,
74084
- hash: () => hash2,
74178
+ hash: () => hash3,
74085
74179
  guid: () => guid2,
74086
74180
  function: () => _function,
74087
74181
  float64: () => float64,
@@ -74287,7 +74381,7 @@ function hostname2(_params) {
74287
74381
  function hex2(_params) {
74288
74382
  return _stringFormat(ZodCustomStringFormat, "hex", exports_regexes.hex, _params);
74289
74383
  }
74290
- function hash2(alg, params) {
74384
+ function hash3(alg, params) {
74291
74385
  const enc = params?.enc ?? "hex";
74292
74386
  const format = `${alg}_${enc}`;
74293
74387
  const regex2 = exports_regexes[format];
@@ -76547,7 +76641,7 @@ __export(exports_external, {
76547
76641
  httpUrl: () => httpUrl,
76548
76642
  hostname: () => hostname2,
76549
76643
  hex: () => hex2,
76550
- hash: () => hash2,
76644
+ hash: () => hash3,
76551
76645
  guid: () => guid2,
76552
76646
  gte: () => _gte,
76553
76647
  gt: () => _gt,
@@ -76782,8 +76876,8 @@ function safeAvailabilityCode(code) {
76782
76876
  return;
76783
76877
  return /^[A-Z0-9_]+$/.test(code) ? code : undefined;
76784
76878
  }
76785
- function sanitizeAvailabilityText(text2) {
76786
- return secretValuePatterns.reduce((value, pattern) => value.replace(pattern, "credential"), sanitizePublicDiscoveryText(text2).replace(/\b[A-Z0-9_]*(?:API_KEY|SECRET|TOKEN|CREDENTIAL)[A-Z0-9_]*\b/g, "credential")).replace(/\s{2,}/g, " ").trim();
76879
+ function sanitizeAvailabilityText(text3) {
76880
+ return secretValuePatterns.reduce((value, pattern) => value.replace(pattern, "credential"), sanitizePublicDiscoveryText(text3).replace(/\b[A-Z0-9_]*(?:API_KEY|SECRET|TOKEN|CREDENTIAL)[A-Z0-9_]*\b/g, "credential")).replace(/\s{2,}/g, " ").trim();
76787
76881
  }
76788
76882
  function parseRemoteRegistryPayload(payload) {
76789
76883
  const parsed = parseRemoteContract(remoteRegistrySchema, payload, "Remote registry payload did not match the expected skills contract");
@@ -76988,11 +77082,11 @@ function canonicalJsonAtDepth(value, maximumBytes, maximumDepth) {
76988
77082
  throw new Error("Invalid canonical JSON depth bound");
76989
77083
  let bytes = 0;
76990
77084
  const active = new Set;
76991
- const piece = (text2) => {
76992
- bytes += Buffer.byteLength(text2);
77085
+ const piece = (text3) => {
77086
+ bytes += Buffer.byteLength(text3);
76993
77087
  if (bytes > maximumBytes)
76994
77088
  throw new Error("Canonical JSON exceeds its bound");
76995
- return text2;
77089
+ return text3;
76996
77090
  };
76997
77091
  const visit3 = (v, depth) => {
76998
77092
  if (depth > maximumDepth)
@@ -77131,9 +77225,9 @@ function requireResult(value) {
77131
77225
  if (!value)
77132
77226
  throw new RemoteRecurringReadError;
77133
77227
  }
77134
- function termsIntegrity(terms, hash3, identity4, own2) {
77228
+ function termsIntegrity(terms, hash4, identity4, own2) {
77135
77229
  requireResult(terms.organizationId === identity4.organization.id && (!own2 || terms.approvedByUserId === identity4.user.id && terms.approvedMembershipId === identity4.user.membershipId));
77136
- requireResult(canonicalJsonSha256(terms) === hash3);
77230
+ requireResult(canonicalJsonSha256(terms) === hash4);
77137
77231
  requireResult(canonicalJsonSha256({ skill: terms.skill, input: terms.input, args: terms.args, runtime: terms.runtime }) === terms.payloadSha256);
77138
77232
  requireResult(Date.parse(terms.expiresAt) > Date.parse(terms.startsAt));
77139
77233
  }
@@ -77529,7 +77623,7 @@ function invalid3() {
77529
77623
  throw new Error(invalidWorkspaceResult);
77530
77624
  }
77531
77625
  function organization(v) {
77532
- if (!record4(v) || !uuid8(v.id) || !text2(v.slug) || !text2(v.name))
77626
+ if (!record4(v) || !uuid8(v.id) || !text3(v.slug) || !text3(v.name))
77533
77627
  return invalid3();
77534
77628
  return { id: v.id, slug: v.slug, name: v.name };
77535
77629
  }
@@ -77549,7 +77643,7 @@ function parseWorkspaceIdentity(value, expectedUserId) {
77549
77643
  if (!record4(value))
77550
77644
  return invalid3();
77551
77645
  const user = value.user;
77552
- if (!record4(user) || !uuid8(user.id) || !uuid8(user.membershipId) || !text2(user.email, 320) || !(user.displayName === null || text2(user.displayName)) || !role2(user.role))
77646
+ if (!record4(user) || !uuid8(user.id) || !uuid8(user.membershipId) || !text3(user.email, 320) || !(user.displayName === null || text3(user.displayName)) || !role2(user.role))
77553
77647
  return invalid3();
77554
77648
  if (user.id !== expectedUserId)
77555
77649
  throw new WorkspaceIdentityMismatchError;
@@ -77580,7 +77674,7 @@ function workspaceSelectionFailure(value, status) {
77580
77674
  const code = value.code;
77581
77675
  return workspaceSelectionFailures[code][0] === status ? code : null;
77582
77676
  }
77583
- var record4 = (v) => !!v && typeof v === "object" && !Array.isArray(v), uuid8 = (v) => typeof v === "string" && /^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/.test(v), text2 = (v, max2 = 1024) => typeof v === "string" && !!v.trim() && v.length <= max2 && !/[\p{Cc}\p{Cs}\u2028\u2029]/u.test(v), role2 = (v) => typeof v === "string" && ["owner", "admin", "member", "viewer"].includes(v), invalidWorkspaceResult = "The server returned an invalid workspace selection result.", WorkspaceContextInputError, WorkspaceIdentityMismatchError, workspaceSelectionFailures;
77677
+ var record4 = (v) => !!v && typeof v === "object" && !Array.isArray(v), uuid8 = (v) => typeof v === "string" && /^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/.test(v), text3 = (v, max2 = 1024) => typeof v === "string" && !!v.trim() && v.length <= max2 && !/[\p{Cc}\p{Cs}\u2028\u2029]/u.test(v), role2 = (v) => typeof v === "string" && ["owner", "admin", "member", "viewer"].includes(v), invalidWorkspaceResult = "The server returned an invalid workspace selection result.", WorkspaceContextInputError, WorkspaceIdentityMismatchError, workspaceSelectionFailures;
77584
77678
  var init_remote_workspace_selection = __esm(() => {
77585
77679
  WorkspaceContextInputError = class WorkspaceContextInputError extends Error {
77586
77680
  constructor() {
@@ -80394,17 +80488,17 @@ var init_install = __esm(() => {
80394
80488
 
80395
80489
  // src/lib/compact-output.ts
80396
80490
  function truncateText(value, maxChars = 96) {
80397
- const text3 = String(value ?? "").replace(/\s+/g, " ").trim();
80398
- if (text3.length <= maxChars)
80399
- return text3;
80400
- return `${text3.slice(0, Math.max(0, maxChars - 3)).trimEnd()}...`;
80491
+ const text4 = String(value ?? "").replace(/\s+/g, " ").trim();
80492
+ if (text4.length <= maxChars)
80493
+ return text4;
80494
+ return `${text4.slice(0, Math.max(0, maxChars - 3)).trimEnd()}...`;
80401
80495
  }
80402
80496
  function previewText(value, maxChars = DEFAULT_PREVIEW_CHARS) {
80403
- const text3 = String(value ?? "");
80497
+ const text4 = String(value ?? "");
80404
80498
  return {
80405
- text: text3.length > maxChars ? `${text3.slice(0, Math.max(0, maxChars - 3))}...` : text3,
80406
- length: text3.length,
80407
- truncated: text3.length > maxChars
80499
+ text: text4.length > maxChars ? `${text4.slice(0, Math.max(0, maxChars - 3))}...` : text4,
80500
+ length: text4.length,
80501
+ truncated: text4.length > maxChars
80408
80502
  };
80409
80503
  }
80410
80504
  function parsePageLimit(value, fallback, options = {}) {
@@ -80523,10 +80617,10 @@ function handleBrowseError(error61) {
80523
80617
  process.exitCode = 1;
80524
80618
  }
80525
80619
  async function writeJson(value, space) {
80526
- const text3 = `${JSON.stringify(value, null, space)}
80620
+ const text4 = `${JSON.stringify(value, null, space)}
80527
80621
  `;
80528
80622
  await new Promise((resolve19, reject2) => {
80529
- process.stdout.write(text3, (error61) => {
80623
+ process.stdout.write(text4, (error61) => {
80530
80624
  if (error61)
80531
80625
  reject2(error61);
80532
80626
  else
@@ -81085,7 +81179,7 @@ function handleDiff(name, options) {
81085
81179
  const present = existsSync22(dir);
81086
81180
  const managed = existsSync22(join37(dir, SYNC_MARKER_FILE));
81087
81181
  const skillMdPath = join37(dir, "SKILL.md");
81088
- const hash3 = present && existsSync22(skillMdPath) ? hashSkillMarkdownFile(skillMdPath) : undefined;
81182
+ const hash4 = present && existsSync22(skillMdPath) ? hashSkillMarkdownFile(skillMdPath) : undefined;
81089
81183
  let stub;
81090
81184
  if (present && existsSync22(skillMdPath)) {
81091
81185
  try {
@@ -81094,13 +81188,13 @@ function handleDiff(name, options) {
81094
81188
  stub = undefined;
81095
81189
  }
81096
81190
  }
81097
- const diverged = present && canonical4.present && managed && hash3 !== canonical4.hash;
81191
+ const diverged = present && canonical4.present && managed && hash4 !== canonical4.hash;
81098
81192
  homes.push({
81099
81193
  agent,
81100
81194
  path: dir,
81101
81195
  present,
81102
81196
  managed,
81103
- ...hash3 ? { hash: hash3 } : {},
81197
+ ...hash4 ? { hash: hash4 } : {},
81104
81198
  ...stub !== undefined ? { stub } : {},
81105
81199
  ...diverged !== undefined ? { diverged } : {}
81106
81200
  });
@@ -81956,13 +82050,13 @@ function scanUnmarkedHomes(options = {}) {
81956
82050
  const skillMdPath = join39(dir, "SKILL.md");
81957
82051
  if (!existsSync24(skillMdPath))
81958
82052
  continue;
81959
- const hash3 = hashSkillMarkdownFile(skillMdPath);
82053
+ const hash4 = hashSkillMarkdownFile(skillMdPath);
81960
82054
  const mtime = statSync12(skillMdPath).mtime.toISOString();
81961
- const entry = { agent, skill, home, path: dir, hash: hash3, mtime };
82055
+ const entry = { agent, skill, home, path: dir, hash: hash4, mtime };
81962
82056
  const canonicalHash = index.get(skill);
81963
82057
  if (canonicalHash === undefined) {
81964
82058
  scan.unknown.push({ ...entry });
81965
- } else if (canonicalHash === hash3) {
82059
+ } else if (canonicalHash === hash4) {
81966
82060
  scan.adoptable.push(entry);
81967
82061
  } else {
81968
82062
  scan.conflicts.push({ ...entry, canonicalHash });
@@ -82050,10 +82144,10 @@ function pruneOwnership(dir) {
82050
82144
  const after2 = fstatSync15(descriptor), current = lstatSync22(dir), markerPathAfter = lstatSync22(markerPath);
82051
82145
  if (!markerPathAfter.isFile() || markerPathAfter.dev !== before2.dev || markerPathAfter.ino !== before2.ino || markerPathAfter.size !== before2.size || markerPathAfter.mtimeMs !== before2.mtimeMs || markerPathAfter.ctimeMs !== before2.ctimeMs || length !== before2.size || after2.size !== before2.size || after2.mtimeMs !== before2.mtimeMs || after2.ctimeMs !== before2.ctimeMs || !current.isDirectory() || current.dev !== directory.dev || current.ino !== directory.ino)
82052
82146
  return;
82053
- const text3 = bytes.subarray(0, length).toString("utf8"), marker = JSON.parse(text3);
82147
+ const text4 = bytes.subarray(0, length).toString("utf8"), marker = JSON.parse(text4);
82054
82148
  if (!isSkillsOwnershipMarker(marker))
82055
82149
  return;
82056
- return { marker, identity: JSON.stringify([directory.dev, directory.ino, before2.dev, before2.ino, before2.mtimeMs, before2.ctimeMs, text3]) };
82150
+ return { marker, identity: JSON.stringify([directory.dev, directory.ino, before2.dev, before2.ino, before2.mtimeMs, before2.ctimeMs, text4]) };
82057
82151
  } catch {
82058
82152
  return;
82059
82153
  } finally {
@@ -82099,15 +82193,15 @@ function pruneStrayHomes(options = {}) {
82099
82193
  const marker = owned.marker;
82100
82194
  ownership.set(dir, owned.identity);
82101
82195
  const skillMdPath = join39(dir, "SKILL.md");
82102
- const hash3 = existsSync24(skillMdPath) ? hashSkillMarkdownFile(skillMdPath) : "";
82103
- candidates.push({ agent, skill, home, path: dir, hash: hash3, marker });
82196
+ const hash4 = existsSync24(skillMdPath) ? hashSkillMarkdownFile(skillMdPath) : "";
82197
+ candidates.push({ agent, skill, home, path: dir, hash: hash4, marker });
82104
82198
  }
82105
82199
  }
82106
82200
  if (!options.apply) {
82107
82201
  return { candidates, pruned: 0, dryRun: true };
82108
82202
  }
82109
82203
  const appDir = options.homeDir ? join39(options.homeDir, ".hasna", "skills") : getDataDir();
82110
- const rollbackFile = writeRollbackRecord("prune", candidates.map(({ agent, skill, path, hash: hash3, marker }) => ({ agent, skill, path, hash: hash3, marker })), appDir);
82204
+ const rollbackFile = writeRollbackRecord("prune", candidates.map(({ agent, skill, path, hash: hash4, marker }) => ({ agent, skill, path, hash: hash4, marker })), appDir);
82111
82205
  let pruned = 0;
82112
82206
  for (const candidate2 of candidates) {
82113
82207
  if (pruneOwnership(candidate2.path)?.identity !== ownership.get(candidate2.path))
@@ -82338,10 +82432,10 @@ function setEnvAssignment(path, assignment) {
82338
82432
  }
82339
82433
  let prepared = initial2;
82340
82434
  if (previous) {
82341
- const original = readFileSync27(descriptor), text3 = original.toString("utf8");
82342
- if (!Buffer.from(text3, "utf8").equals(original))
82435
+ const original = readFileSync27(descriptor), text4 = original.toString("utf8");
82436
+ if (!Buffer.from(text4, "utf8").equals(original))
82343
82437
  throw new EnvAssignmentError(INVALID_LAYOUT);
82344
- prepared = prepareEnvAssignment(assignment, text3);
82438
+ prepared = prepareEnvAssignment(assignment, text4);
82345
82439
  }
82346
82440
  const bytes = Buffer.from(prepared.content, "utf8");
82347
82441
  let written = 0;
@@ -82881,7 +82975,7 @@ import { closeSync as closeSync17, fstatSync as fstatSync17, openSync as openSyn
82881
82975
  import { O_NOFOLLOW as O_NOFOLLOW3, O_NONBLOCK as O_NONBLOCK3, O_RDONLY as O_RDONLY3 } from "constants";
82882
82976
  import { createRequire as createRequire2 } from "module";
82883
82977
  import { hostname as osHostname2 } from "os";
82884
- import { isAbsolute as isAbsolute16, join as join42 } from "path";
82978
+ import { isAbsolute as isAbsolute17, join as join42 } from "path";
82885
82979
  import { createRequire as createRequire22 } from "module";
82886
82980
  function envToken2(name) {
82887
82981
  return name.toUpperCase().replace(/-/g, "_");
@@ -82905,7 +82999,7 @@ function homeDir2(env3) {
82905
82999
  }
82906
83000
  function absoluteOverride2(env3, key) {
82907
83001
  const value = env3[key]?.trim();
82908
- return value && isAbsolute16(value) ? value : null;
83002
+ return value && isAbsolute17(value) ? value : null;
82909
83003
  }
82910
83004
  function hasnaHomeDir2(env3) {
82911
83005
  const override = absoluteOverride2(env3, HASNA_HOME_ENV_KEY2);
@@ -82936,10 +83030,10 @@ function credentialDiskSources2(name, env3) {
82936
83030
  function profileDiskSources2(name, env3, profile) {
82937
83031
  return credentialDiskSourceList2(name, env3, profile).map((s) => s.path);
82938
83032
  }
82939
- function parseEnvFile2(text3) {
83033
+ function parseEnvFile2(text4) {
82940
83034
  const values2 = new Map;
82941
83035
  const unusable = new Set;
82942
- for (const rawLine of text3.split(/\r?\n/)) {
83036
+ for (const rawLine of text4.split(/\r?\n/)) {
82943
83037
  const line = rawLine.trim();
82944
83038
  if (line.length === 0 || line.startsWith("#"))
82945
83039
  continue;
@@ -83179,8 +83273,8 @@ function keychainAccount2(env3, options) {
83179
83273
  const user = env3.USER?.trim();
83180
83274
  return user || null;
83181
83275
  }
83182
- function keychainFailureHint2(text3) {
83183
- const line = text3.split(/\r?\n/).find((entry) => entry.trim().length > 0)?.trim() ?? "";
83276
+ function keychainFailureHint2(text4) {
83277
+ const line = text4.split(/\r?\n/).find((entry) => entry.trim().length > 0)?.trim() ?? "";
83184
83278
  const clean = line.replace(/[\u0000-\u001f\u007f]/g, "").slice(0, 200);
83185
83279
  return clean ? `: ${clean}` : "";
83186
83280
  }
@@ -83758,12 +83852,12 @@ function createHasnaHttpTransportInternal(options, requestBindingProvider) {
83758
83852
  await response.body?.cancel();
83759
83853
  } catch {}
83760
83854
  } else {
83761
- const text3 = await response.text();
83762
- if (text3.length > 0) {
83855
+ const text4 = await response.text();
83856
+ if (text4.length > 0) {
83763
83857
  try {
83764
- parsed = JSON.parse(text3);
83858
+ parsed = JSON.parse(text4);
83765
83859
  } catch {
83766
- parsed = text3;
83860
+ parsed = text4;
83767
83861
  }
83768
83862
  }
83769
83863
  }
@@ -83866,13 +83960,13 @@ class SecretsClient {
83866
83960
  headers,
83867
83961
  redirect: "manual"
83868
83962
  });
83869
- const text3 = await response.text();
83963
+ const text4 = await response.text();
83870
83964
  let body = undefined;
83871
- if (text3) {
83965
+ if (text4) {
83872
83966
  try {
83873
- body = JSON.parse(text3);
83967
+ body = JSON.parse(text4);
83874
83968
  } catch {
83875
- body = text3;
83969
+ body = text4;
83876
83970
  }
83877
83971
  }
83878
83972
  if (!response.ok) {
@@ -84201,7 +84295,7 @@ function refuse(code, message) {
84201
84295
  function record7(value) {
84202
84296
  return !!value && typeof value === "object" && !Array.isArray(value);
84203
84297
  }
84204
- function exactKeys2(value, keys2) {
84298
+ function exactKeys3(value, keys2) {
84205
84299
  return Object.keys(value).length === keys2.length && keys2.every((key) => Object.hasOwn(value, key));
84206
84300
  }
84207
84301
  function identifier2(value) {
@@ -84241,7 +84335,7 @@ function readSelectedSecretBindings(path) {
84241
84335
  }
84242
84336
  }
84243
84337
  function validateSelectedSecretBindings(value, scope, names) {
84244
- if (!record7(value) || !exactKeys2(value, ["schema", "selection", "consumer", "secretsAuthority", "bindings"]) || value.schema !== "hasna.skills-secret-bindings.v1" || !record7(value.selection) || !exactKeys2(value.selection, ["authority", "workspaceId", "profileId", "profileRevision", "slug", "version", "bundleDigest"]) || !record7(value.consumer) || !exactKeys2(value.consumer, ["stationId", "workspaceDirectory"]) || !record7(value.bindings)) {
84338
+ if (!record7(value) || !exactKeys3(value, ["schema", "selection", "consumer", "secretsAuthority", "bindings"]) || value.schema !== "hasna.skills-secret-bindings.v1" || !record7(value.selection) || !exactKeys3(value.selection, ["authority", "workspaceId", "profileId", "profileRevision", "slug", "version", "bundleDigest"]) || !record7(value.consumer) || !exactKeys3(value.consumer, ["stationId", "workspaceDirectory"]) || !record7(value.bindings)) {
84245
84339
  return refuse("INVALID_SECRET_BINDINGS", "Secret bindings do not match the hasna.skills-secret-bindings.v1 contract.");
84246
84340
  }
84247
84341
  for (const [key, expected] of Object.entries({ authority: scope.selection.authority, workspaceId: scope.selection.workspaceId, profileId: scope.profileId, profileRevision: scope.selection.profileRevision, slug: scope.selection.slug, version: scope.selection.version, bundleDigest: scope.selection.bundleDigest })) {
@@ -84266,7 +84360,7 @@ function validateSelectedSecretBindings(value, scope, names) {
84266
84360
  } catch {
84267
84361
  return refuse("INVALID_SECRET_BINDINGS", "Secret bindings require a canonical HTTPS Secrets /v1 authority (loopback HTTP is allowed).");
84268
84362
  }
84269
- if (!exactKeys2(value.bindings, names) || Object.values(value.bindings).some((key) => !identifier2(key) || !/^[A-Za-z0-9][A-Za-z0-9._/-]*$/.test(key) || key.split("/").some((part) => !part || part === "." || part === ".."))) {
84363
+ if (!exactKeys3(value.bindings, names) || Object.values(value.bindings).some((key) => !identifier2(key) || !/^[A-Za-z0-9][A-Za-z0-9._/-]*$/.test(key) || key.split("/").some((part) => !part || part === "." || part === ".."))) {
84270
84364
  return refuse("INVALID_SECRET_BINDINGS", "Bind every declared environment name exactly once to a vault key; undeclared bindings and values are refused.");
84271
84365
  }
84272
84366
  return structuredClone(value);
@@ -84296,7 +84390,7 @@ async function resolveSelectedSecrets(bindings, createClient2 = createSecretsCli
84296
84390
  return refuse("LOCAL_SECRET_UNAVAILABLE", "A declared secret could not be resolved, was invalid, or has expired. The skill was not started; no fallback was attempted.");
84297
84391
  }
84298
84392
  }
84299
- function redactExecutionSecrets(text3, env3) {
84393
+ function redactExecutionSecrets(text4, env3) {
84300
84394
  const values2 = new Set(Object.values(env3).flatMap((value) => {
84301
84395
  let encoded = "";
84302
84396
  try {
@@ -84305,8 +84399,8 @@ function redactExecutionSecrets(text3, env3) {
84305
84399
  return [value, JSON.stringify(value).slice(1, -1), Buffer.from(value).toString("base64"), encoded];
84306
84400
  }));
84307
84401
  for (const value of [...values2].filter(Boolean).sort((a, b) => b.length - a.length))
84308
- text3 = text3.split(value).join("[REDACTED]");
84309
- return text3;
84402
+ text4 = text4.split(value).join("[REDACTED]");
84403
+ return text4;
84310
84404
  }
84311
84405
  var init_execution_secrets = __esm(() => {
84312
84406
  init_sdk();
@@ -84444,7 +84538,7 @@ var init_execution_grants = __esm(() => {
84444
84538
  });
84445
84539
 
84446
84540
  // src/lib/execution-grant-client.ts
84447
- import { isDeepStrictEqual as isDeepStrictEqual6 } from "util";
84541
+ import { isDeepStrictEqual as isDeepStrictEqual7 } from "util";
84448
84542
  function id(value) {
84449
84543
  if (!grantIdentifier(value))
84450
84544
  throw new Error("Invalid execution grant profile or revision identifier.");
@@ -84496,7 +84590,7 @@ async function saveExecutionGrantPolicy(profileId, grants, revision) {
84496
84590
  headers: revision === undefined ? { "If-None-Match": "*" } : { "If-Match": `"${revision}"` },
84497
84591
  body: JSON.stringify({ grants: snapshot2 })
84498
84592
  }));
84499
- if (policy.profileId !== profileId || policy.previousRevision !== (revision ?? null) || !isDeepStrictEqual6(policy.grants, snapshot2)) {
84593
+ if (policy.profileId !== profileId || policy.previousRevision !== (revision ?? null) || !isDeepStrictEqual7(policy.grants, snapshot2)) {
84500
84594
  throw new Error("The API did not preserve the reviewed execution grant policy; read it before retrying.");
84501
84595
  }
84502
84596
  return policy;
@@ -84507,7 +84601,7 @@ async function resolveExecutionGrant(input2) {
84507
84601
  if (!grantRecord(value) || Object.keys(value).length !== 3 || !grantIdentifier(value.policyRevision) || !grantIdentifier(value.grantId) || !grantRecord(value.bindings)) {
84508
84602
  throw new SkillSelectionError("INVALID_EXECUTION_GRANT", "The Skills API returned an invalid execution grant.");
84509
84603
  }
84510
- if (!isDeepStrictEqual6(value.bindings.selection, snapshot2.selection) || !isDeepStrictEqual6(value.bindings.consumer, snapshot2.consumer)) {
84604
+ if (!isDeepStrictEqual7(value.bindings.selection, snapshot2.selection) || !isDeepStrictEqual7(value.bindings.consumer, snapshot2.consumer)) {
84511
84605
  throw new SkillSelectionError("EXECUTION_GRANT_SCOPE_MISMATCH", "The Skills API returned a grant for a different selection or consumer.");
84512
84606
  }
84513
84607
  return value;
@@ -93602,10 +93696,10 @@ var require_util = __commonJS((exports) => {
93602
93696
  var codegen_1 = require_codegen();
93603
93697
  var code_1 = require_code();
93604
93698
  function toHash(arr) {
93605
- const hash3 = {};
93699
+ const hash4 = {};
93606
93700
  for (const item of arr)
93607
- hash3[item] = true;
93608
- return hash3;
93701
+ hash4[item] = true;
93702
+ return hash4;
93609
93703
  }
93610
93704
  exports.toHash = toHash;
93611
93705
  function alwaysValidSchema(it, schema) {
@@ -97067,7 +97161,7 @@ var require_core = __commonJS((exports) => {
97067
97161
  errorsText(errors5 = this.errors, { separator = ", ", dataVar = "data" } = {}) {
97068
97162
  if (!errors5 || errors5.length === 0)
97069
97163
  return "No errors";
97070
- return errors5.map((e2) => `${dataVar}${e2.instancePath} ${e2.message}`).reduce((text3, msg) => text3 + separator + msg);
97164
+ return errors5.map((e2) => `${dataVar}${e2.instancePath} ${e2.message}`).reduce((text4, msg) => text4 + separator + msg);
97071
97165
  }
97072
97166
  $dataMetaSchema(metaSchema, keywordsJsonPointers) {
97073
97167
  const rules = this.RULES.all;
@@ -101145,11 +101239,11 @@ var init_remote_invitation_recovery = __esm(() => {
101145
101239
  // src/lib/remote-private-publications.ts
101146
101240
  import { createHash as createHash23 } from "crypto";
101147
101241
  function checkedPublicationDeclaration(value) {
101148
- if (!exact(value, ["idempotencyKey", "version", "expectedCurrentVersionId", "manifestText", "archiveSha256", "archiveByteSize"]) || !publicationUuid(value.idempotencyKey) || !(value.expectedCurrentVersionId === null || publicationUuid(value.expectedCurrentVersionId)) || typeof value.version !== "string" || !value.version || value.version.length > 128 || /[\p{Cc}\p{Cs}]/u.test(value.version) || typeof value.manifestText !== "string" || Buffer.byteLength(value.manifestText) > 16384 || !hash3(value.archiveSha256) || !Number.isSafeInteger(value.archiveByteSize) || Number(value.archiveByteSize) < 1 || Number(value.archiveByteSize) > PRIVATE_PUBLICATION_MAX_BYTES)
101242
+ if (!exact(value, ["idempotencyKey", "version", "expectedCurrentVersionId", "manifestText", "archiveSha256", "archiveByteSize"]) || !publicationUuid(value.idempotencyKey) || !(value.expectedCurrentVersionId === null || publicationUuid(value.expectedCurrentVersionId)) || typeof value.version !== "string" || !value.version || value.version.length > 128 || /[\p{Cc}\p{Cs}]/u.test(value.version) || typeof value.manifestText !== "string" || Buffer.byteLength(value.manifestText) > 16384 || !hash4(value.archiveSha256) || !Number.isSafeInteger(value.archiveByteSize) || Number(value.archiveByteSize) < 1 || Number(value.archiveByteSize) > PRIVATE_PUBLICATION_MAX_BYTES)
101149
101243
  return bad();
101150
101244
  try {
101151
101245
  const manifest = JSON.parse(value.manifestText);
101152
- if (!record10(manifest) || manifest.version !== value.version || validatePortableManifestContract(manifest, { strict: true }).length || !hash3(manifest.provenance?.content_hash))
101246
+ if (!record10(manifest) || manifest.version !== value.version || validatePortableManifestContract(manifest, { strict: true }).length || !hash4(manifest.provenance?.content_hash))
101153
101247
  return bad();
101154
101248
  } catch {
101155
101249
  return bad();
@@ -101157,7 +101251,7 @@ function checkedPublicationDeclaration(value) {
101157
101251
  return Object.freeze({ ...value });
101158
101252
  }
101159
101253
  function checkedPublicationView(value, skillId, intentId, declaration) {
101160
- if (!exact(value, ["id", "skillId", "version", "expectedCurrentVersionId", "archiveSha256", "archiveByteSize", "state", "expiresAt", "createdAt", "versionId"]) || !publicationUuid(value.id) || value.skillId !== skillId || intentId !== undefined && value.id !== intentId || typeof value.version !== "string" || !value.version || value.version.length > 128 || /[\p{Cc}\p{Cs}]/u.test(value.version) || !(value.expectedCurrentVersionId === null || publicationUuid(value.expectedCurrentVersionId)) || !hash3(value.archiveSha256) || !Number.isSafeInteger(value.archiveByteSize) || Number(value.archiveByteSize) < 1 || Number(value.archiveByteSize) > PRIVATE_PUBLICATION_MAX_BYTES || typeof value.state !== "string" || !["awaiting_upload", "queued", "verifying", "needs_attention", "committed", "rejected", "cancelled", "expired"].includes(value.state) || !date6(value.expiresAt) || !date6(value.createdAt) || !(value.versionId === null || publicationUuid(value.versionId)) || value.state === "committed" && value.versionId === null)
101254
+ if (!exact(value, ["id", "skillId", "version", "expectedCurrentVersionId", "archiveSha256", "archiveByteSize", "state", "expiresAt", "createdAt", "versionId"]) || !publicationUuid(value.id) || value.skillId !== skillId || intentId !== undefined && value.id !== intentId || typeof value.version !== "string" || !value.version || value.version.length > 128 || /[\p{Cc}\p{Cs}]/u.test(value.version) || !(value.expectedCurrentVersionId === null || publicationUuid(value.expectedCurrentVersionId)) || !hash4(value.archiveSha256) || !Number.isSafeInteger(value.archiveByteSize) || Number(value.archiveByteSize) < 1 || Number(value.archiveByteSize) > PRIVATE_PUBLICATION_MAX_BYTES || typeof value.state !== "string" || !["awaiting_upload", "queued", "verifying", "needs_attention", "committed", "rejected", "cancelled", "expired"].includes(value.state) || !date6(value.expiresAt) || !date6(value.createdAt) || !(value.versionId === null || publicationUuid(value.versionId)) || value.state === "committed" && value.versionId === null)
101161
101255
  return invalid5();
101162
101256
  if (declaration && ["version", "expectedCurrentVersionId", "archiveSha256", "archiveByteSize"].some((k) => value[k] !== declaration[k]))
101163
101257
  return invalid5();
@@ -101404,7 +101498,7 @@ var PRIVATE_PUBLICATION_MAX_BYTES, failures2, PrivatePublicationError, bad = ()
101404
101498
  throw new PrivatePublicationError("INVALID_PUBLICATION_INPUT", "Invalid publication input or recovery data.");
101405
101499
  }, invalid5 = () => {
101406
101500
  throw new PrivatePublicationError("INVALID_PUBLICATION_RESPONSE", "The server returned an invalid publication result.");
101407
- }, publicationUuid = (v) => typeof v === "string" && /^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/.test(v), hash3 = (v) => typeof v === "string" && /^[a-f0-9]{64}$/.test(v), record10 = (v) => !!v && typeof v === "object" && !Array.isArray(v), exact = (v, keys3) => record10(v) && Object.keys(v).sort().join(",") === keys3.sort().join(","), date6 = (v) => typeof v === "string" && /^\d{4}-\d\d-\d\dT[0-9:.]+(?:Z|[+-](?:[01]\d|2[0-3]):[0-5]\d)$/.test(v) && Number.isFinite(Date.parse(v)), publicationSha256 = (bytes) => createHash23("sha256").update(bytes).digest("hex");
101501
+ }, publicationUuid = (v) => typeof v === "string" && /^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/.test(v), hash4 = (v) => typeof v === "string" && /^[a-f0-9]{64}$/.test(v), record10 = (v) => !!v && typeof v === "object" && !Array.isArray(v), exact = (v, keys3) => record10(v) && Object.keys(v).sort().join(",") === keys3.sort().join(","), date6 = (v) => typeof v === "string" && /^\d{4}-\d\d-\d\dT[0-9:.]+(?:Z|[+-](?:[01]\d|2[0-3]):[0-5]\d)$/.test(v) && Number.isFinite(Date.parse(v)), publicationSha256 = (bytes) => createHash23("sha256").update(bytes).digest("hex");
101408
101502
  var init_remote_private_publications = __esm(() => {
101409
101503
  init_fleet_credentials();
101410
101504
  init_remote_workspace_selection();
@@ -101465,8 +101559,8 @@ async function requestAuthApi(instance, path, options) {
101465
101559
  apiUrl: safeUrl
101466
101560
  });
101467
101561
  }
101468
- const text3 = await res.text();
101469
- const body = text3 ? parseJsonBody(text3) : {};
101562
+ const text4 = await res.text();
101563
+ const body = text4 ? parseJsonBody(text4) : {};
101470
101564
  if (!res.ok) {
101471
101565
  const record11 = isRecord5(body) ? body : {};
101472
101566
  const detail = typeof record11.detail === "string" ? record11.detail : undefined;
@@ -101482,15 +101576,15 @@ async function requestAuthApi(instance, path, options) {
101482
101576
  }
101483
101577
  return body;
101484
101578
  }
101485
- function parseJsonBody(text3) {
101579
+ function parseJsonBody(text4) {
101486
101580
  try {
101487
- return JSON.parse(text3);
101581
+ return JSON.parse(text4);
101488
101582
  } catch {
101489
- return { detail: condenseErrorBody(text3) };
101583
+ return { detail: condenseErrorBody(text4) };
101490
101584
  }
101491
101585
  }
101492
- function condenseErrorBody(text3) {
101493
- const stripped = /<[a-z!/]/i.test(text3) ? text3.replace(/<(script|style)[\s\S]*?<\/\1>/gi, " ").replace(/<[^>]*>/g, " ") : text3;
101586
+ function condenseErrorBody(text4) {
101587
+ const stripped = /<[a-z!/]/i.test(text4) ? text4.replace(/<(script|style)[\s\S]*?<\/\1>/gi, " ").replace(/<[^>]*>/g, " ") : text4;
101494
101588
  const collapsed = stripped.replace(/\s+/g, " ").trim();
101495
101589
  if (collapsed.length <= MAX_ERROR_DETAIL_LENGTH)
101496
101590
  return collapsed;
@@ -101706,12 +101800,12 @@ function safeText(file2) {
101706
101800
  }
101707
101801
  }
101708
101802
  function checkIdentityMetadata(file2, identity4) {
101709
- const text3 = safeText(file2);
101710
- if (text3 === null)
101803
+ const text4 = safeText(file2);
101804
+ if (text4 === null)
101711
101805
  return;
101712
101806
  let value;
101713
101807
  try {
101714
- value = JSON.parse(text3);
101808
+ value = JSON.parse(text4);
101715
101809
  } catch {
101716
101810
  return fail3("The profile identity metadata is invalid. Sign in again before managing this workspace.");
101717
101811
  }
@@ -102050,7 +102144,7 @@ var init_recurring_customer = __esm(() => {
102050
102144
 
102051
102145
  // src/lib/recurring-recovery.ts
102052
102146
  import { constants as constants17, closeSync as closeSync20, fsyncSync as fsyncSync5, fstatSync as fstatSync20, lstatSync as lstatSync25, mkdirSync as mkdirSync17, openSync as openSync20, readSync as readSync14, realpathSync as realpathSync9, renameSync as renameSync10, unlinkSync as unlinkSync6, writeFileSync as writeFileSync17 } from "fs";
102053
- import { dirname as dirname23, isAbsolute as isAbsolute17, join as join46, resolve as resolve20 } from "path";
102147
+ import { dirname as dirname23, isAbsolute as isAbsolute18, join as join46, resolve as resolve20 } from "path";
102054
102148
  import { randomUUID as randomUUID7 } from "crypto";
102055
102149
 
102056
102150
  class RecoveryOwner {
@@ -102058,7 +102152,7 @@ class RecoveryOwner {
102058
102152
  parents = [];
102059
102153
  constructor(directory) {
102060
102154
  this.directory = directory;
102061
- if (!isAbsolute17(directory) || resolve20(directory) !== directory || realpathSync9(directory) !== directory)
102155
+ if (!isAbsolute18(directory) || resolve20(directory) !== directory || realpathSync9(directory) !== directory)
102062
102156
  invalid6();
102063
102157
  for (let path = directory;; path = dirname23(path)) {
102064
102158
  const stat3 = lstatSync25(path);
@@ -102193,7 +102287,7 @@ function base2(customer, organizationId) {
102193
102287
  };
102194
102288
  }
102195
102289
  function create3(directory, intent) {
102196
- if (!isAbsolute17(directory) || resolve20(directory) !== directory || realpathSync9(dirname23(directory)) !== dirname23(directory))
102290
+ if (!isAbsolute18(directory) || resolve20(directory) !== directory || realpathSync9(dirname23(directory)) !== dirname23(directory))
102197
102291
  invalid6();
102198
102292
  mkdirSync17(directory, { mode: 448 });
102199
102293
  const owner2 = new RecoveryOwner(directory), checked = intentSchema.parse(intent), intentSha256 = canonicalJsonSha256(checked);
@@ -102356,12 +102450,12 @@ var init_recurring_recovery = __esm(() => {
102356
102450
  });
102357
102451
 
102358
102452
  // src/lib/recurring-surface.ts
102359
- import { isAbsolute as isAbsolute18 } from "path";
102453
+ import { isAbsolute as isAbsolute19 } from "path";
102360
102454
  function recurringMcpSchema(action) {
102361
102455
  return action === "activate" ? recurringSurfaceSchemas.activate.extend({ code, confirm: exports_external.literal(true) }) : recurringSurfaceSchemas[action];
102362
102456
  }
102363
- function expectedDraft(draft, hash4) {
102364
- if (!draft || draft.termsSha256 !== hash4)
102457
+ function expectedDraft(draft, hash5) {
102458
+ if (!draft || draft.termsSha256 !== hash5)
102365
102459
  throw new RemoteRecurringError("RECURRING_TERMS_UNAVAILABLE");
102366
102460
  return draft;
102367
102461
  }
@@ -102461,7 +102555,7 @@ var init_recurring_surface = __esm(() => {
102461
102555
  uuid13 = exports_external.string().regex(/^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/);
102462
102556
  context = { userId: uuid13.optional(), membershipId: uuid13.optional() };
102463
102557
  page2 = { limit: exports_external.number().int().min(1).max(100).optional(), cursor: exports_external.string().min(1).max(2048).optional() };
102464
- directory = exports_external.string().max(4096).refine(isAbsolute18, "Use an absolute recovery directory");
102558
+ directory = exports_external.string().max(4096).refine(isAbsolute19, "Use an absolute recovery directory");
102465
102559
  email4 = exports_external.string().trim().toLowerCase().email().max(254);
102466
102560
  code = exports_external.string().regex(/^\d{6}$/);
102467
102561
  recurringSurfaceSchemas = {
@@ -105263,10 +105357,10 @@ var init_private_publication_customer = __esm(() => {
105263
105357
 
105264
105358
  // src/lib/private-publication-recovery.ts
105265
105359
  import { constants as constants18, closeSync as closeSync21, fsyncSync as fsyncSync6, fstatSync as fstatSync21, lstatSync as lstatSync26, mkdirSync as mkdirSync21, openSync as openSync21, readSync as readSync15, realpathSync as realpathSync10, renameSync as renameSync11, unlinkSync as unlinkSync7, writeFileSync as writeFileSync20 } from "fs";
105266
- import { dirname as dirname26, isAbsolute as isAbsolute19, join as join51, resolve as resolve21 } from "path";
105360
+ import { dirname as dirname26, isAbsolute as isAbsolute20, join as join51, resolve as resolve21 } from "path";
105267
105361
  import { randomUUID as randomUUID8 } from "crypto";
105268
105362
  function safeDirectory(directory2) {
105269
- if (!isAbsolute19(directory2) || directory2 !== resolve21(directory2) || realpathSync10(directory2) !== directory2)
105363
+ if (!isAbsolute20(directory2) || directory2 !== resolve21(directory2) || realpathSync10(directory2) !== directory2)
105270
105364
  return fail4();
105271
105365
  for (let path = directory2;; path = dirname26(path)) {
105272
105366
  const stat3 = lstatSync26(path);
@@ -105404,7 +105498,7 @@ async function preparePrivatePublication(client2, sourceDirectory, recoveryDirec
105404
105498
  phase: "prepared",
105405
105499
  intent: null
105406
105500
  };
105407
- if (!isAbsolute19(recoveryDirectory) || resolve21(recoveryDirectory) !== recoveryDirectory || realpathSync10(dirname26(recoveryDirectory)) !== dirname26(recoveryDirectory))
105501
+ if (!isAbsolute20(recoveryDirectory) || resolve21(recoveryDirectory) !== recoveryDirectory || realpathSync10(dirname26(recoveryDirectory)) !== dirname26(recoveryDirectory))
105408
105502
  return fail4();
105409
105503
  mkdirSync21(recoveryDirectory, { mode: 448 });
105410
105504
  safeDirectory(recoveryDirectory);
@@ -105505,10 +105599,10 @@ var init_private_publication_recovery = __esm(() => {
105505
105599
  });
105506
105600
 
105507
105601
  // src/mcp/private-publication-tools.ts
105508
- import { isAbsolute as isAbsolute20 } from "path";
105602
+ import { isAbsolute as isAbsolute21 } from "path";
105509
105603
  function registerPrivatePublicationTools(server) {
105510
105604
  const uuid9 = exports_external.string().regex(/^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/);
105511
- const directory2 = exports_external.string().max(4096).refine(isAbsolute20, "Use an absolute local directory");
105605
+ const directory2 = exports_external.string().max(4096).refine(isAbsolute21, "Use an absolute local directory");
105512
105606
  const verification2 = { email: exports_external.string().email().max(254), code: exports_external.string().regex(/^\d{6}$/), userId: uuid9, membershipId: uuid9, recoveryDirectory: directory2 };
105513
105607
  const description = "Manage a private source publication using fresh workspace-bound verification and a host-local recovery directory. Publishing requires explicit UUID current-version comparison and upload consent. Resume reuses immutable saved bytes and intent; an uncertain PUT is finalized for server verification, never uploaded twice. Sessions and signed URLs are not returned or persisted. Private execution is unavailable. Host request history may contain the supplied verification code.";
105514
105608
  const handler = (action) => async (value) => {
@@ -106154,7 +106248,7 @@ __export(exports_runtime, {
106154
106248
  });
106155
106249
  import { createHash as createHash25, randomUUID as randomUUID9 } from "crypto";
106156
106250
  import { lstatSync as lstatSync27, mkdirSync as mkdirSync23, readFileSync as readFileSync35, realpathSync as realpathSync11, writeFileSync as writeFileSync22 } from "fs";
106157
- import { basename as basename12, isAbsolute as isAbsolute21, join as join53 } from "path";
106251
+ import { basename as basename12, isAbsolute as isAbsolute22, join as join53 } from "path";
106158
106252
  import { createInterface } from "readline";
106159
106253
  function registerRuntime(parent) {
106160
106254
  parent.command("run").argument("<skill>", "Skill name").argument("[args...]", "Arguments to pass to the skill; use -- to end Skills options").allowUnknownOption(true).passThroughOptions(true).option("--json", "Output result as JSON", false).option("--remote", "Run on the configured server, using its catalog and quote", false).option("--target <target>", "Execution target: local or cloud").option("--secret-bindings <path>", "Reviewed, exact-selection local execution vault bindings (JSON file)").option("--secret-bindings-template", "Print a scoped bindings template without resolving secrets or running the skill", false).option("--input <json>", "Structured cloud execution input").option("--skill-version <version>", "Exact selected skill version").option("--selection-profile <id>", "Selected Skills profile").option("--session <id>", "Pinned Skills session").option("--cached", "Use the explicit verified selected cache", false).option("--yes", "Approve the server's quoted credit cost for this run", false).option("--idempotency-key <key>", "Reuse this key when retrying the same remote submission").option("--file <path>", "Attach a local input file to a remote run (repeatable)", (value, prior) => [...prior, value], []).option("--wait", "Poll remote runs until a terminal status", false).option("--poll-interval-ms <ms>", "Remote polling interval in milliseconds", "1000").option("--poll-timeout-ms <ms>", "Maximum time to wait for a remote run", "300000").description("Run a skill directly").action(async (name, args2, options, command) => {
@@ -106281,7 +106375,7 @@ Updating ${name}...
106281
106375
  async function readUpdatedVersion(bunExecutable) {
106282
106376
  const output2 = await readUpdateCommand([bunExecutable, "pm", "bin", "-g"]);
106283
106377
  const globalBin = output2.replace(/\r?\n$/, "");
106284
- if (!globalBin || !isAbsolute21(globalBin) || /[\r\n\0]/.test(globalBin))
106378
+ if (!globalBin || !isAbsolute22(globalBin) || /[\r\n\0]/.test(globalBin))
106285
106379
  throw new Error("Update bin discovery failed");
106286
106380
  const installed = Bun.which("skills", { PATH: globalBin, cwd: globalBin });
106287
106381
  const selected = Bun.which("skills");
@@ -107247,13 +107341,13 @@ import { emitKeypressEvents } from "readline";
107247
107341
  async function readCode() {
107248
107342
  if (process.stdin.isTTY)
107249
107343
  throw new NameInputError("Pipe a fresh six-digit verification code when using --code-stdin.");
107250
- let text3 = "";
107344
+ let text4 = "";
107251
107345
  for await (const chunk2 of process.stdin) {
107252
- text3 += chunk2.toString();
107253
- if (text3.length > 32)
107346
+ text4 += chunk2.toString();
107347
+ if (text4.length > 32)
107254
107348
  throw new NameInputError("Supply only a six-digit verification code on stdin.");
107255
107349
  }
107256
- const code2 = text3.trim();
107350
+ const code2 = text4.trim();
107257
107351
  if (!/^\d{6}$/.test(code2))
107258
107352
  throw new NameInputError("Supply only a six-digit verification code on stdin.");
107259
107353
  return code2;
@@ -107281,7 +107375,7 @@ function promptCode() {
107281
107375
  resolve22(answer);
107282
107376
  };
107283
107377
  const cancel = () => finish(null);
107284
- const keypress = (text3, key) => {
107378
+ const keypress = (text4, key) => {
107285
107379
  if (key.ctrl && ["c", "d"].includes(key.name ?? "") || key.name === "escape")
107286
107380
  return cancel();
107287
107381
  if (key.name === "return" || key.name === "enter") {
@@ -107297,8 +107391,8 @@ Enter all six digits: `);
107297
107391
  value = value.slice(0, -1);
107298
107392
  output2.write("\b \b");
107299
107393
  }
107300
- } else if (/^[0-9]$/.test(text3) && value.length < 6) {
107301
- value += text3;
107394
+ } else if (/^[0-9]$/.test(text4) && value.length < 6) {
107395
+ value += text4;
107302
107396
  output2.write("*");
107303
107397
  }
107304
107398
  };
@@ -107780,7 +107874,7 @@ import {
107780
107874
  statSync as statSync19,
107781
107875
  writeFileSync as writeFileSync23
107782
107876
  } from "fs";
107783
- import { dirname as dirname29, isAbsolute as isAbsolute22, relative as relative8, resolve as resolve22, sep as sep10 } from "path";
107877
+ import { dirname as dirname29, isAbsolute as isAbsolute23, relative as relative8, resolve as resolve22, sep as sep10 } from "path";
107784
107878
  function validateStationId(stationId) {
107785
107879
  if (!/^[a-z0-9-]+$/.test(stationId)) {
107786
107880
  throw new StationSnapshotError("INVALID_STATION", `station id must be a slug, got: ${stationId}`);
@@ -107886,7 +107980,7 @@ function writeStationSnapshot(options) {
107886
107980
  for (const plan of plans) {
107887
107981
  const destination = resolve22(repoRoot, plan.destination);
107888
107982
  const destinationRelative = relative8(repoRoot, destination);
107889
- if (destinationRelative.startsWith("..") || destinationRelative.startsWith(sep10) || isAbsolute22(destinationRelative)) {
107983
+ if (destinationRelative.startsWith("..") || destinationRelative.startsWith(sep10) || isAbsolute23(destinationRelative)) {
107890
107984
  throw new StationSnapshotError("DESTINATION_ESCAPE", `destination escapes repo root: ${plan.destination}`);
107891
107985
  }
107892
107986
  let existingDigest = null;
@@ -108361,10 +108455,10 @@ var init_create_sync_config = __esm(() => {
108361
108455
  // src/lib/codex-hook-rpc.ts
108362
108456
  import { execFile, spawn as spawn3 } from "child_process";
108363
108457
  import { realpathSync as realpathSync12, statSync as statSync20 } from "fs";
108364
- import { isAbsolute as isAbsolute23 } from "path";
108458
+ import { isAbsolute as isAbsolute24 } from "path";
108365
108459
  import { promisify } from "util";
108366
108460
  async function connectCodexHookRpc(options) {
108367
- const found = isAbsolute23(options.command) ? options.command : Bun.which(options.command, { PATH: process.env.PATH });
108461
+ const found = isAbsolute24(options.command) ? options.command : Bun.which(options.command, { PATH: process.env.PATH });
108368
108462
  if (!found)
108369
108463
  throw new Error("CODEX_HOOK_TRUST_NATIVE_UNAVAILABLE: install Codex or pass --codex-command");
108370
108464
  const binary = realpathSync12(found), stat3 = statSync20(binary);
@@ -108500,10 +108594,10 @@ var init_codex_hook_rpc = __esm(() => {
108500
108594
 
108501
108595
  // src/lib/codex-hook-trust-identity.ts
108502
108596
  import { realpathSync as realpathSync13 } from "fs";
108503
- import { dirname as dirname30, isAbsolute as isAbsolute24, join as join56 } from "path";
108504
- import { isDeepStrictEqual as isDeepStrictEqual7 } from "util";
108597
+ import { dirname as dirname30, isAbsolute as isAbsolute25, join as join56 } from "path";
108598
+ import { isDeepStrictEqual as isDeepStrictEqual8 } from "util";
108505
108599
  function inspectRecordedSkillsCli(command, expected) {
108506
- need4(isAbsolute24(command) && !command.includes("\x00"), "RECONCILE_RECORDED_COMMAND_REQUIRED");
108600
+ need4(isAbsolute25(command) && !command.includes("\x00"), "RECONCILE_RECORDED_COMMAND_REQUIRED");
108507
108601
  const resolved = realpathSync13(command);
108508
108602
  const cli = snapshot(resolved, false, { readOnlyPackage: true });
108509
108603
  const manifest = snapshot(join56(dirname30(dirname30(resolved)), "package.json"), false, { readOnlyPackage: true });
@@ -108511,7 +108605,7 @@ function inspectRecordedSkillsCli(command, expected) {
108511
108605
  need4(pkg.name === "@hasna/skills" && /^\d+\.\d+\.\d+$/.test(pkg.version) && pkg.bin?.skills === "bin/index.js" && resolved === join56(dirname30(manifest.file), "bin/index.js"), "SKILLS_PACKAGE_MISMATCH");
108512
108606
  need4((cli.stat.mode & 0o100n) !== 0n, "SKILLS_COMMAND_NOT_EXECUTABLE");
108513
108607
  const receipt = { path: resolved, version: pkg.version, sha256: cli.sha256, manifestSha256: manifest.sha256 };
108514
- need4(isDeepStrictEqual7(receipt, expected), "RECONCILE_SKILLS_BINDING_CHANGED");
108608
+ need4(isDeepStrictEqual8(receipt, expected), "RECONCILE_SKILLS_BINDING_CHANGED");
108515
108609
  return { receipt, recheck() {
108516
108610
  need4(realpathSync13(command) === resolved, "SKILLS_COMMAND_CHANGED");
108517
108611
  unchanged2(cli);
@@ -108522,7 +108616,7 @@ function bindSkillsCli(command, reviewed) {
108522
108616
  const normal = Bun.which("skills", { PATH: process.env.PATH });
108523
108617
  need4(normal, "SKILLS_COMMAND_UNAVAILABLE");
108524
108618
  const resolved = realpathSync13(normal);
108525
- const bound = isAbsolute24(command) ? command : command === "skills" ? normal : undefined;
108619
+ const bound = isAbsolute25(command) ? command : command === "skills" ? normal : undefined;
108526
108620
  need4(bound && realpathSync13(bound) === resolved, "SKILLS_COMMAND_MISMATCH");
108527
108621
  const entrypoint = reviewed?.path ?? process.argv[1];
108528
108622
  need4(entrypoint && realpathSync13(entrypoint) === resolved, "SKILLS_ENTRYPOINT_MISMATCH");
@@ -108547,19 +108641,19 @@ var init_codex_hook_trust_identity = __esm(() => {
108547
108641
  });
108548
108642
 
108549
108643
  // src/lib/codex-hook-policy-recovery.ts
108550
- import { isDeepStrictEqual as isDeepStrictEqual8 } from "util";
108644
+ import { isDeepStrictEqual as isDeepStrictEqual9 } from "util";
108551
108645
  function reviewedClaudeDiscoveryChange(beforeText, currentText, options) {
108552
108646
  need4(typeof options.reason === "string" && options.reason.trim().length > 0 && options.reason.length <= 512 && !/[\x00-\x1f\x7f]/.test(options.reason), "RECONCILE_RECOVERY_REASON_REQUIRED");
108553
108647
  need4(options.reviewedPlanDigest === undefined || /^[a-f0-9]{64}$/.test(options.reviewedPlanDigest), "RECONCILE_RECOVERY_PLAN_CHANGED");
108554
108648
  const before2 = parseManagedSkillPolicy(beforeText), current = parseManagedSkillPolicy(currentText);
108555
108649
  const oldDiscovery = before2.bridge?.discovery?.claude, newDiscovery = current.bridge?.discovery?.claude;
108556
108650
  need4(oldDiscovery?.agent === "claude" && newDiscovery?.agent === "claude" && oldDiscovery.method === "reviewed" && newDiscovery.method === "reviewed", "RECONCILE_POLICY_CHANGED");
108557
- const changes = ["roots", "sources"].filter((key) => !isDeepStrictEqual8(oldDiscovery[key], newDiscovery[key])).map((key) => ({ path: `bridge.discovery.claude.${key}`, before: oldDiscovery[key], after: newDiscovery[key] }));
108651
+ const changes = ["roots", "sources"].filter((key) => !isDeepStrictEqual9(oldDiscovery[key], newDiscovery[key])).map((key) => ({ path: `bridge.discovery.claude.${key}`, before: oldDiscovery[key], after: newDiscovery[key] }));
108558
108652
  need4(changes.length > 0, "RECONCILE_POLICY_CHANGED");
108559
108653
  const compared = structuredClone(current);
108560
108654
  compared.bridge.discovery.claude.roots = oldDiscovery.roots;
108561
108655
  compared.bridge.discovery.claude.sources = oldDiscovery.sources;
108562
- need4(isDeepStrictEqual8(before2, compared), "RECONCILE_POLICY_CHANGED");
108656
+ need4(isDeepStrictEqual9(before2, compared), "RECONCILE_POLICY_CHANGED");
108563
108657
  verifyAgentDiscovery(newDiscovery);
108564
108658
  return { reason: options.reason, changes };
108565
108659
  }
@@ -108569,69 +108663,6 @@ var init_codex_hook_policy_recovery = __esm(() => {
108569
108663
  init_agent_discovery();
108570
108664
  });
108571
108665
 
108572
- // src/lib/codex-hook-additions-review.ts
108573
- import { isAbsolute as isAbsolute25 } from "path";
108574
- import { isDeepStrictEqual as isDeepStrictEqual9 } from "util";
108575
- function exactKeys3(value, keys3) {
108576
- need4(value && typeof value === "object" && !Array.isArray(value) && isDeepStrictEqual9(Object.keys(value).sort(), [...keys3].sort()), "RECONCILE_ADDITIONS_REVIEW_SCHEMA");
108577
- }
108578
- function reviewNativeHookAdditions(options) {
108579
- need4(isAbsolute25(options.path), "RECONCILE_ADDITIONS_REVIEW_PATH");
108580
- const reviewFile = snapshot(options.path, true), review = JSON.parse(reviewFile.text);
108581
- exactKeys3(review, ["version", "kind", "reason", "producerEvidence", "journalIntentSha256", "policySha256", "configCurrentSha256", "hooksCurrentSha256", "producerBefore", "additions"]);
108582
- need4(review.version === 1 && review.kind === "native-hook-additions" && text3(review.reason) && text3(review.producerEvidence), "RECONCILE_ADDITIONS_REVIEW_SCHEMA");
108583
- for (const [name, expected] of [["journalIntentSha256", options.intent.sha256], ["policySha256", options.policy.sha256], ["configCurrentSha256", options.configCurrent.sha256], ["hooksCurrentSha256", options.hooksCurrent.sha256]])
108584
- need4(hash4(review[name]) && review[name] === expected, "RECONCILE_ADDITIONS_REVIEW_CHANGED");
108585
- exactKeys3(review.producerBefore, ["configPath", "configSha256", "hooksPath", "hooksSha256"]);
108586
- const before2 = review.producerBefore;
108587
- need4(isAbsolute25(before2.configPath) && isAbsolute25(before2.hooksPath) && hash4(before2.configSha256) && hash4(before2.hooksSha256), "RECONCILE_ADDITIONS_PRODUCER_PREIMAGE");
108588
- const producerConfig = snapshot(before2.configPath, true), producerHooks = snapshot(before2.hooksPath, true);
108589
- need4(producerConfig.sha256 === before2.configSha256 && producerHooks.sha256 === before2.hooksSha256 && producerHooks.sha256 === options.hooksBefore.sha256, "RECONCILE_ADDITIONS_PRODUCER_PREIMAGE");
108590
- const original = structure2(options.configBefore.text), producer = structure2(producerConfig.text), expectedProducer = structuredClone(original), originalKeys = options.journalHooks.map((hook) => hook.key);
108591
- expectedProducer.hooks ??= {};
108592
- expectedProducer.hooks.state ??= {};
108593
- for (const hook of options.journalHooks)
108594
- expectedProducer.hooks.state[hook.key] = { ...expectedProducer.hooks.state[hook.key], enabled: true, trusted_hash: hook.currentHash };
108595
- need4(isDeepStrictEqual9(expectedProducer, producer) && codexTrustReconcileWitness(options.configBefore.text, originalKeys) === codexTrustReconcileWitness(producerConfig.text, originalKeys) && codexTrustUnmanagedSemantic(options.configBefore.text, originalKeys) === codexTrustUnmanagedSemantic(producerConfig.text, originalKeys), "RECONCILE_ADDITIONS_PRODUCER_PREIMAGE");
108596
- need4(Array.isArray(review.additions) && review.additions.length > 0 && review.additions.length <= 20, "RECONCILE_ADDITIONS_REVIEW_SCHEMA");
108597
- const expectedHooks = JSON.parse(options.hooksBefore.text), currentHooks = JSON.parse(options.hooksCurrent.text), expectedConfig = structuredClone(producer);
108598
- need4(expectedHooks.hooks && typeof expectedHooks.hooks === "object" && !Array.isArray(expectedHooks.hooks), "RECONCILE_ADDITIONS_DECLARATIONS");
108599
- const added = [], seen = new Set, commands = new Set(options.recordedNativeHooks.map((hook) => hook.command));
108600
- for (const addition of review.additions) {
108601
- exactKeys3(addition, ["event", "nativeHook"]);
108602
- need4(Object.hasOwn(events, addition.event), "RECONCILE_ADDITIONS_DECLARATIONS");
108603
- const { event, nativeHook: hook } = addition;
108604
- exactKeys3(hook, nativeKeys);
108605
- const groups = expectedHooks.hooks[event] ?? [];
108606
- need4(Array.isArray(groups), "RECONCILE_ADDITIONS_DECLARATIONS");
108607
- const key = `${options.nativeHooksPath}:${events[event][1]}:${groups.length}:0`;
108608
- need4(hook.key === key && !seen.has(key) && !options.recordedNativeHooks.some((originalHook) => originalHook.key === key) && !Object.hasOwn(expectedConfig.hooks.state, key), "RECONCILE_ADDITIONS_IDENTITY");
108609
- need4(hook.eventName === events[event][0] && hook.handlerType === "command" && text3(hook.command, 16384) && !commands.has(hook.command) && Number.isInteger(hook.timeoutSec) && hook.timeoutSec > 0 && hook.timeoutSec <= 60 && hook.matcher === null && hook.async === false && hook.statusMessage === null && hook.additionalContextLimit === null && hook.sourcePath === options.nativeHooksPath && hook.source === "user" && hook.pluginId === null && hook.isManaged === false && /^sha256:[a-f0-9]{64}$/.test(hook.currentHash) && hook.enabled === true && hook.trustStatus === "trusted", "RECONCILE_ADDITIONS_IDENTITY");
108610
- seen.add(key);
108611
- commands.add(hook.command);
108612
- added.push(hook);
108613
- expectedHooks.hooks[event] = [...groups, { hooks: [{ type: "command", command: hook.command, timeout: hook.timeoutSec }] }];
108614
- expectedConfig.hooks.state[key] = { enabled: true, trusted_hash: hook.currentHash };
108615
- }
108616
- need4(isDeepStrictEqual9(expectedHooks, currentHooks), "RECONCILE_ADDITIONS_DECLARATIONS");
108617
- const keys3 = added.map((hook) => hook.key);
108618
- need4(isDeepStrictEqual9(expectedConfig, structure2(options.configCurrent.text)) && codexTrustReconcileWitness(producerConfig.text, keys3) === codexTrustReconcileWitness(options.configCurrent.text, keys3) && codexTrustUnmanagedSemantic(producerConfig.text, keys3) === codexTrustUnmanagedSemantic(options.configCurrent.text, keys3), "RECONCILE_ADDITIONS_CONFIG");
108619
- const recheck = () => {
108620
- unchanged2(reviewFile);
108621
- unchanged2(producerConfig);
108622
- unchanged2(producerHooks);
108623
- };
108624
- recheck();
108625
- return { hooks: added, recheck, receipt: { reviewPath: reviewFile.file, reviewSha256: reviewFile.sha256, reason: review.reason, producerEvidence: review.producerEvidence, producerBefore: { configPath: producerConfig.file, configSha256: producerConfig.sha256, hooksPath: producerHooks.file, hooksSha256: producerHooks.sha256 }, additions: added } };
108626
- }
108627
- var events, hash4 = (value) => typeof value === "string" && /^[a-f0-9]{64}$/.test(value), text3 = (value, max2 = 2048) => typeof value === "string" && value.trim().length > 0 && value.length <= max2 && !/[\0\r\n]/.test(value), structure2 = (value) => JSON.parse(JSON.stringify(Bun.TOML.parse(value))), nativeKeys;
108628
- var init_codex_hook_additions_review = __esm(() => {
108629
- init_codex_hook_trust_files();
108630
- init_codex_hook_trust_layout();
108631
- events = { UserPromptSubmit: ["userPromptSubmit", "user_prompt_submit"], SessionStart: ["sessionStart", "session_start"], SubagentStart: ["subagentStart", "subagent_start"] };
108632
- nativeKeys = ["key", "eventName", "handlerType", "command", "matcher", "timeoutSec", "async", "statusMessage", "additionalContextLimit", "sourcePath", "source", "pluginId", "isManaged", "currentHash", "enabled", "trustStatus"];
108633
- });
108634
-
108635
108666
  // src/lib/agent-codex-trust.ts
108636
108667
  import { lstatSync as lstatSync29, mkdirSync as mkdirSync25, readdirSync as readdirSync20, readFileSync as readFileSync37, realpathSync as realpathSync14, statSync as statSync21 } from "fs";
108637
108668
  import { createHash as createHash27, randomUUID as randomUUID10 } from "crypto";
@@ -108718,8 +108749,11 @@ async function reconcileCodexNativeHooks(options, connect = connectCodexHookRpc)
108718
108749
  const before2 = structure3(configBefore.text), current = structure3(currentConfig.text), expectedConfig = structuredClone(before2);
108719
108750
  expectedConfig.hooks ??= {};
108720
108751
  expectedConfig.hooks.state ??= {};
108721
- for (const hook of managedHooks)
108752
+ for (const hook of intent.hooks)
108722
108753
  expectedConfig.hooks.state[hook.key] = { ...expectedConfig.hooks.state[hook.key], enabled: true, trusted_hash: hook.currentHash };
108754
+ if (additions)
108755
+ for (const { key, state } of readReviewedAdditionTrustStates(additions.trustProof, configBefore, currentConfig, intent.hooks))
108756
+ expectedConfig.hooks.state[key] = { ...state };
108723
108757
  if (supersededBinding) {
108724
108758
  for (const hook of intent.hooks) {
108725
108759
  const state = current.hooks?.state?.[hook.key];
@@ -108727,7 +108761,7 @@ async function reconcileCodexNativeHooks(options, connect = connectCodexHookRpc)
108727
108761
  }
108728
108762
  } else
108729
108763
  need4(isDeepStrictEqual10(expectedConfig, current), "RECONCILE_CONFIG_DRIFT");
108730
- const configDiscoveryRecovery = recovery && binding.discovery?.codex ? createCodexHookDiscoveryRecovery(binding.discovery.codex, configBefore, currentConfig, managedHooks) : undefined;
108764
+ const configDiscoveryRecovery = recovery && binding.discovery?.codex ? createCodexHookDiscoveryRecovery(binding.discovery.codex, configBefore, currentConfig, intent.hooks, additions?.trustProof) : undefined;
108731
108765
  assertManagedAgentBridge("codex", { home, dataDir: dataDir3, projectDir: home, codexDiscoveryRecovery: configDiscoveryRecovery });
108732
108766
  const recoveryCli = recovery ? bindSkillsCli("skills", options.reviewedSkillsCli) : undefined;
108733
108767
  if (recoveryCli)