@hasna/skills 0.9.13 → 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.13",
36871
+ version: "0.9.15",
36872
36872
  description: "Skills library for AI coding agents",
36873
36873
  type: "module",
36874
36874
  bin: {
@@ -50548,7 +50548,7 @@ function canonical2(value) {
50548
50548
  function inferencePreference(key, child) {
50549
50549
  if (key === "skipDangerousModePermissionPrompt") {
50550
50550
  need2(child.kind === "literal" && (child.value === "true" || child.value === "false"), "contains an invalid dialog acknowledgment");
50551
- return true;
50551
+ return false;
50552
50552
  }
50553
50553
  if (key === "effortLevel") {
50554
50554
  need2(child.kind === "string" && PERSISTED_EFFORT_LEVELS.has(child.value), "contains an invalid persisted effort level");
@@ -51233,6 +51233,20 @@ function planAgentIntegration(options) {
51233
51233
  recheckRootAliases(aliases);
51234
51234
  return { dataDir: dataDir3, profileId, changes, nativeSkills, observedPolicy: { path: policyPath, before: previousPolicy }, discoveryBefore: discoveries, discoveryAfter, ...aliases.length ? { rootAliases: aliases } : {} };
51235
51235
  }
51236
+ function verifyCoordinatedDiscovery(binding, home, aliases) {
51237
+ try {
51238
+ if (binding.method !== "automatic" && binding.method !== "reviewed")
51239
+ throw new Error("Invalid managed discovery method");
51240
+ verifyAgentDiscovery(binding);
51241
+ if (binding.method === "automatic") {
51242
+ const current = resolveAgentDiscovery({ home, agent: binding.agent, canonical: (path) => canonicalAgentPath(path, aliases) });
51243
+ if (JSON.stringify(current) !== JSON.stringify(binding))
51244
+ throw new Error("Configured native discovery roots changed during Claude update");
51245
+ }
51246
+ } catch (error) {
51247
+ throw new Error(`NATIVE_SKILL_DRIFT: ${error.message}`);
51248
+ }
51249
+ }
51236
51250
  function atomicWrite2(path, content) {
51237
51251
  assertSafePath(path);
51238
51252
  mkdirSync5(dirname10(path), { recursive: true, mode: 448 });
@@ -51257,8 +51271,12 @@ function applyAgentIntegration(plan) {
51257
51271
  recheckRootAliases(aliases);
51258
51272
  for (const agent of plan.managedAgentChecks?.agents ?? [])
51259
51273
  assertManagedAgentBridge(agent, { home: plan.managedAgentChecks.home, dataDir: plan.dataDir, projectDir: plan.managedAgentChecks.home });
51260
- for (const binding of plan.discoveryBefore ?? [])
51261
- verifyAgentDiscovery(binding);
51274
+ for (const binding of plan.discoveryBefore ?? []) {
51275
+ if (plan.managedAgentChecks)
51276
+ verifyCoordinatedDiscovery(binding, plan.managedAgentChecks.home, aliases);
51277
+ else
51278
+ verifyAgentDiscovery(binding);
51279
+ }
51262
51280
  if (plan.observedPolicy && currentText(plan.observedPolicy.path) !== plan.observedPolicy.before)
51263
51281
  throw new Error("Agent policy changed after planning");
51264
51282
  for (const change of plan.changes)
@@ -51290,8 +51308,12 @@ function applyAgentIntegration(plan) {
51290
51308
  written.push({ path: change.path, before: change.before, after: after2 });
51291
51309
  }
51292
51310
  recheckRootAliases(aliases);
51293
- for (const binding of plan.discoveryAfter ?? [])
51294
- verifyAgentDiscovery(binding);
51311
+ for (const binding of plan.discoveryAfter ?? []) {
51312
+ if (plan.managedAgentChecks)
51313
+ verifyCoordinatedDiscovery(binding, plan.managedAgentChecks.home, aliases);
51314
+ else
51315
+ verifyAgentDiscovery(binding);
51316
+ }
51295
51317
  for (const agent of plan.managedAgentChecks?.agents ?? [])
51296
51318
  assertManagedAgentBridge(agent, { home: plan.managedAgentChecks.home, dataDir: plan.dataDir, projectDir: plan.managedAgentChecks.home });
51297
51319
  atomicWrite2(join20(backupRoot, "receipt.json"), JSON.stringify({ version: 1, changes: written.map((change) => ({ path: change.path, beforeHash: change.before === null ? null : sha(change.before), afterHash: sha(change.after) })), backups, ...aliases.length ? { rootAliases: aliases } : {} }) + `
@@ -54674,39 +54696,132 @@ var fail2 = () => new Error('CODEX_HOOK_TRUST_UNSUPPORTED_LAYOUT: preserve and c
54674
54696
  };
54675
54697
  var init_codex_hook_trust_layout = () => {};
54676
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
+
54677
54782
  // src/lib/codex-hook-discovery-recovery.ts
54678
54783
  import { createHash as createHash15 } from "crypto";
54679
- import { isDeepStrictEqual as isDeepStrictEqual5 } from "util";
54680
- 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
+ };
54681
54792
  const raw = binding.sources.filter((source) => source.path === current.file && source.hashMode === "bytes");
54682
54793
  if (!raw.some((source) => source.sha256 !== current.sha256))
54683
54794
  return;
54684
54795
  need4(binding.agent === "codex" && binding.method === "reviewed" && raw.length === 1 && raw[0].sha256 === before2.sha256 && before2.sha256 !== current.sha256, "RECONCILE_DISCOVERY_CONFIG_WITNESS");
54685
54796
  need4(raw[0].format === undefined && raw[0].fields === undefined && raw[0].managedPlugins === undefined, "RECONCILE_DISCOVERY_CONFIG_WITNESS");
54686
54797
  const typed = binding.sources.filter((source) => source.path === current.file && source.format === "toml");
54687
- need4(typed.length === 1 && typed[0].hashMode === undefined && isDeepStrictEqual5(typed[0].fields, fields), "RECONCILE_DISCOVERY_TYPED_WITNESS");
54688
- 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);
54689
54800
  const project = (value) => Object.fromEntries(fields.map((field2) => [field2, value[field2] ?? null]));
54690
54801
  const projection = sha2(JSON.stringify(project(original)));
54691
- need4(typed[0].sha256 === projection && sha2(JSON.stringify(project(actual))) === projection && isDeepStrictEqual5(project(original), project(actual)), "RECONCILE_DISCOVERY_TYPED_WITNESS");
54692
- 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");
54693
- 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);
54694
54806
  expected.hooks ??= {};
54695
54807
  expected.hooks.state ??= {};
54696
- for (const hook of hooks)
54808
+ for (const hook of journalHooks)
54697
54809
  expected.hooks.state[hook.key] = { ...expected.hooks.state[hook.key], enabled: true, trusted_hash: hook.currentHash };
54698
- 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");
54699
54813
  unchanged2(before2);
54700
54814
  unchanged2(current);
54701
54815
  const witness = Object.freeze({ configPath: current.file, beforeSha256: before2.sha256, currentSha256: current.sha256, discoverySha256: sha2(JSON.stringify(binding)), typedProjectionSha256: projection });
54702
- proofs.set(witness, { before: before2, current });
54816
+ proofs2.set(witness, { before: before2, current, recheckAdditions });
54703
54817
  return witness;
54704
54818
  }
54705
54819
  function assertCodexHookDiscoveryRecovery(binding, witness) {
54706
- const proof = proofs.get(witness);
54820
+ const proof = proofs2.get(witness);
54707
54821
  need4(!!proof && binding.agent === "codex" && witness.discoverySha256 === sha2(JSON.stringify(binding)), "RECONCILE_DISCOVERY_RECOVERY_CHANGED");
54708
54822
  unchanged2(proof.before);
54709
54823
  unchanged2(proof.current);
54824
+ proof.recheckAdditions();
54710
54825
  }
54711
54826
  function verifiesCodexHookDiscoverySource(binding, source, currentDigest, witness) {
54712
54827
  if (!witness || source.path !== witness.configPath || source.hashMode !== "bytes")
@@ -54715,21 +54830,22 @@ function verifiesCodexHookDiscoverySource(binding, source, currentDigest, witnes
54715
54830
  need4(source.sha256 === witness.beforeSha256 && currentDigest === witness.currentSha256, "RECONCILE_DISCOVERY_RECOVERY_CHANGED");
54716
54831
  return true;
54717
54832
  }
54718
- 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;
54719
54834
  var init_codex_hook_discovery_recovery = __esm(() => {
54720
54835
  init_codex_hook_trust_files();
54721
54836
  init_codex_hook_trust_layout();
54837
+ init_codex_hook_additions_review();
54722
54838
  fields = ["plugins", "marketplaces", "skills"];
54723
- proofs = new WeakMap;
54839
+ proofs2 = new WeakMap;
54724
54840
  });
54725
54841
 
54726
54842
  // src/lib/agent-discovery.ts
54727
54843
  import { createHash as createHash16 } from "crypto";
54728
54844
  import { lstatSync as lstatSync20, readFileSync as readFileSync17, readdirSync as readdirSync10, realpathSync as realpathSync4 } from "fs";
54729
- import { basename as basename8, dirname as dirname16, isAbsolute as isAbsolute14, join as join31, resolve as resolve15, sep as sep5 } from "path";
54730
- 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) {
54731
54847
  try {
54732
- const value = toml ? Bun.TOML.parse(text2) : JSON.parse(text2);
54848
+ const value = toml ? Bun.TOML.parse(text3) : JSON.parse(text3);
54733
54849
  if (!value || typeof value !== "object" || Array.isArray(value))
54734
54850
  throw new Error;
54735
54851
  return value;
@@ -54738,7 +54854,7 @@ function parseConfig(text2, path, toml = false) {
54738
54854
  }
54739
54855
  }
54740
54856
  function safe4(path) {
54741
- if (!isAbsolute14(path) || path.includes("\x00"))
54857
+ if (!isAbsolute15(path) || path.includes("\x00"))
54742
54858
  throw new Error("Expected an absolute native discovery path");
54743
54859
  for (let cursor = path;; cursor = dirname16(cursor)) {
54744
54860
  if (lstatSync20(cursor, { throwIfNoEntry: false })?.isSymbolicLink())
@@ -54791,12 +54907,12 @@ function projected(source, changes, budget = discoveryByteBudget()) {
54791
54907
  return hashDiscoveryPathFile(source.path, budget, changes);
54792
54908
  return hashRawDiscoveryFile(source.path, budget, changes);
54793
54909
  }
54794
- const text2 = read2(source.path, changes);
54795
- if (text2 === null)
54910
+ const text3 = read2(source.path, changes);
54911
+ if (text3 === null)
54796
54912
  return null;
54797
54913
  if (!source.format)
54798
- return digest(text2);
54799
- 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");
54800
54916
  if (!object4 || typeof object4 !== "object" || Array.isArray(object4))
54801
54917
  throw new Error("Expected native discovery configuration object");
54802
54918
  return digest(JSON.stringify(Object.fromEntries((source.fields ?? []).map((field2) => [field2, object4[field2] ?? null]))));
@@ -54940,8 +55056,8 @@ function resolveAgentDiscovery(options) {
54940
55056
  if (!lstatSync20(builtinRoot, { throwIfNoEntry: false })?.isDirectory())
54941
55057
  unresolved("installed Gemini builtin root is missing");
54942
55058
  for (const name of readdirSync10(builtinRoot).sort()) {
54943
- const text2 = witness(join31(builtinRoot, name, "SKILL.md"));
54944
- 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);
54945
55061
  if (!match?.[1] || builtinNames.includes(match[1]))
54946
55062
  unresolved("installed Gemini builtin name is missing or ambiguous");
54947
55063
  builtinNames.push(match[1]);
@@ -55019,7 +55135,7 @@ function resolveAgentDiscovery(options) {
55019
55135
  unresolved("unsupported plugin enablement");
55020
55136
  const split2 = id.lastIndexOf("@"), name = id.slice(0, split2), marketplace = id.slice(split2 + 1);
55021
55137
  const market = config.marketplaces?.[marketplace] ?? (marketplace === "personal" ? { source_type: "local", source: home } : undefined);
55022
- 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))
55023
55139
  unresolved("enabled plugin marketplace is not an explicit local source");
55024
55140
  const catalogText = witness(join31(market.source, ".agents/plugins/marketplace.json"));
55025
55141
  if (catalogText === null)
@@ -55035,7 +55151,7 @@ function resolveAgentDiscovery(options) {
55035
55151
  if ((config.plugin?.length ?? 0) > 0 || config.skills?.urls?.length)
55036
55152
  unresolved("external plugin or remote skill source");
55037
55153
  for (const path of config.skills?.paths ?? []) {
55038
- if (typeof path !== "string" || !isAbsolute14(path))
55154
+ if (typeof path !== "string" || !isAbsolute15(path))
55039
55155
  unresolved("relative or malformed added skill root");
55040
55156
  roots.add(path);
55041
55157
  }
@@ -55073,7 +55189,7 @@ function resolveAgentDiscovery(options) {
55073
55189
  }
55074
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))) } : {} };
55075
55191
  }
55076
- var digest = (text2) => createHash16("sha256").update(text2).digest("hex");
55192
+ var digest = (text3) => createHash16("sha256").update(text3).digest("hex");
55077
55193
  var init_agent_discovery = __esm(() => {
55078
55194
  init_agent_policy_limits();
55079
55195
  init_agent_hermes();
@@ -55205,7 +55321,7 @@ import {
55205
55321
  statSync as statSync10,
55206
55322
  writeFileSync as writeFileSync9
55207
55323
  } from "fs";
55208
- 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";
55209
55325
  function getPortableSkillsRoot(options = {}) {
55210
55326
  return resolvePortableSkillsRoot(options, true);
55211
55327
  }
@@ -55363,7 +55479,7 @@ function assertDisjointImportPaths(source, destination) {
55363
55479
  const destinationPath = physicalImportPath(destination);
55364
55480
  const contains2 = (parent, child) => {
55365
55481
  const path = relative5(parent, child);
55366
- return path === "" || !isAbsolute15(path) && path !== ".." && !path.startsWith(`..${sep7}`);
55482
+ return path === "" || !isAbsolute16(path) && path !== ".." && !path.startsWith(`..${sep7}`);
55367
55483
  };
55368
55484
  if (contains2(sourcePath, destinationPath) || contains2(destinationPath, sourcePath)) {
55369
55485
  throw new Error("Source and destination skill directories must not overlap");
@@ -55580,7 +55696,7 @@ function safeIsDirectory(path) {
55580
55696
  }
55581
55697
  }
55582
55698
  function isSafeRelativePath2(value) {
55583
- if (!value.trim() || isAbsolute15(value))
55699
+ if (!value.trim() || isAbsolute16(value))
55584
55700
  return false;
55585
55701
  const normalized = normalize2(value).replace(/\\/g, "/");
55586
55702
  return normalized !== ".." && !normalized.startsWith("../") && !normalized.includes("/../");
@@ -57604,8 +57720,8 @@ function getPublicSkillDiscovery(skill) {
57604
57720
  function publicDiscoveryTags(tags) {
57605
57721
  return tags.filter((tag) => !VENDOR_TAGS.has(tag.toLowerCase()));
57606
57722
  }
57607
- function sanitizePublicDiscoveryText(text2) {
57608
- 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, " ");
57609
57725
  let previous;
57610
57726
  do {
57611
57727
  previous = sanitized;
@@ -66225,8 +66341,8 @@ function lt_default() {
66225
66341
  localeError: error33()
66226
66342
  };
66227
66343
  }
66228
- var capitalizeFirstCharacter = (text2) => {
66229
- return text2.charAt(0).toUpperCase() + text2.slice(1);
66344
+ var capitalizeFirstCharacter = (text3) => {
66345
+ return text3.charAt(0).toUpperCase() + text3.slice(1);
66230
66346
  }, error33 = () => {
66231
66347
  const Sizable = {
66232
66348
  string: {
@@ -74059,7 +74175,7 @@ __export(exports_schemas2, {
74059
74175
  httpUrl: () => httpUrl,
74060
74176
  hostname: () => hostname2,
74061
74177
  hex: () => hex2,
74062
- hash: () => hash2,
74178
+ hash: () => hash3,
74063
74179
  guid: () => guid2,
74064
74180
  function: () => _function,
74065
74181
  float64: () => float64,
@@ -74265,7 +74381,7 @@ function hostname2(_params) {
74265
74381
  function hex2(_params) {
74266
74382
  return _stringFormat(ZodCustomStringFormat, "hex", exports_regexes.hex, _params);
74267
74383
  }
74268
- function hash2(alg, params) {
74384
+ function hash3(alg, params) {
74269
74385
  const enc = params?.enc ?? "hex";
74270
74386
  const format = `${alg}_${enc}`;
74271
74387
  const regex2 = exports_regexes[format];
@@ -76525,7 +76641,7 @@ __export(exports_external, {
76525
76641
  httpUrl: () => httpUrl,
76526
76642
  hostname: () => hostname2,
76527
76643
  hex: () => hex2,
76528
- hash: () => hash2,
76644
+ hash: () => hash3,
76529
76645
  guid: () => guid2,
76530
76646
  gte: () => _gte,
76531
76647
  gt: () => _gt,
@@ -76760,8 +76876,8 @@ function safeAvailabilityCode(code) {
76760
76876
  return;
76761
76877
  return /^[A-Z0-9_]+$/.test(code) ? code : undefined;
76762
76878
  }
76763
- function sanitizeAvailabilityText(text2) {
76764
- 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();
76765
76881
  }
76766
76882
  function parseRemoteRegistryPayload(payload) {
76767
76883
  const parsed = parseRemoteContract(remoteRegistrySchema, payload, "Remote registry payload did not match the expected skills contract");
@@ -76966,11 +77082,11 @@ function canonicalJsonAtDepth(value, maximumBytes, maximumDepth) {
76966
77082
  throw new Error("Invalid canonical JSON depth bound");
76967
77083
  let bytes = 0;
76968
77084
  const active = new Set;
76969
- const piece = (text2) => {
76970
- bytes += Buffer.byteLength(text2);
77085
+ const piece = (text3) => {
77086
+ bytes += Buffer.byteLength(text3);
76971
77087
  if (bytes > maximumBytes)
76972
77088
  throw new Error("Canonical JSON exceeds its bound");
76973
- return text2;
77089
+ return text3;
76974
77090
  };
76975
77091
  const visit3 = (v, depth) => {
76976
77092
  if (depth > maximumDepth)
@@ -77109,9 +77225,9 @@ function requireResult(value) {
77109
77225
  if (!value)
77110
77226
  throw new RemoteRecurringReadError;
77111
77227
  }
77112
- function termsIntegrity(terms, hash3, identity4, own2) {
77228
+ function termsIntegrity(terms, hash4, identity4, own2) {
77113
77229
  requireResult(terms.organizationId === identity4.organization.id && (!own2 || terms.approvedByUserId === identity4.user.id && terms.approvedMembershipId === identity4.user.membershipId));
77114
- requireResult(canonicalJsonSha256(terms) === hash3);
77230
+ requireResult(canonicalJsonSha256(terms) === hash4);
77115
77231
  requireResult(canonicalJsonSha256({ skill: terms.skill, input: terms.input, args: terms.args, runtime: terms.runtime }) === terms.payloadSha256);
77116
77232
  requireResult(Date.parse(terms.expiresAt) > Date.parse(terms.startsAt));
77117
77233
  }
@@ -77507,7 +77623,7 @@ function invalid3() {
77507
77623
  throw new Error(invalidWorkspaceResult);
77508
77624
  }
77509
77625
  function organization(v) {
77510
- 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))
77511
77627
  return invalid3();
77512
77628
  return { id: v.id, slug: v.slug, name: v.name };
77513
77629
  }
@@ -77527,7 +77643,7 @@ function parseWorkspaceIdentity(value, expectedUserId) {
77527
77643
  if (!record4(value))
77528
77644
  return invalid3();
77529
77645
  const user = value.user;
77530
- 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))
77531
77647
  return invalid3();
77532
77648
  if (user.id !== expectedUserId)
77533
77649
  throw new WorkspaceIdentityMismatchError;
@@ -77558,7 +77674,7 @@ function workspaceSelectionFailure(value, status) {
77558
77674
  const code = value.code;
77559
77675
  return workspaceSelectionFailures[code][0] === status ? code : null;
77560
77676
  }
77561
- 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;
77562
77678
  var init_remote_workspace_selection = __esm(() => {
77563
77679
  WorkspaceContextInputError = class WorkspaceContextInputError extends Error {
77564
77680
  constructor() {
@@ -80372,17 +80488,17 @@ var init_install = __esm(() => {
80372
80488
 
80373
80489
  // src/lib/compact-output.ts
80374
80490
  function truncateText(value, maxChars = 96) {
80375
- const text3 = String(value ?? "").replace(/\s+/g, " ").trim();
80376
- if (text3.length <= maxChars)
80377
- return text3;
80378
- 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()}...`;
80379
80495
  }
80380
80496
  function previewText(value, maxChars = DEFAULT_PREVIEW_CHARS) {
80381
- const text3 = String(value ?? "");
80497
+ const text4 = String(value ?? "");
80382
80498
  return {
80383
- text: text3.length > maxChars ? `${text3.slice(0, Math.max(0, maxChars - 3))}...` : text3,
80384
- length: text3.length,
80385
- 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
80386
80502
  };
80387
80503
  }
80388
80504
  function parsePageLimit(value, fallback, options = {}) {
@@ -80501,10 +80617,10 @@ function handleBrowseError(error61) {
80501
80617
  process.exitCode = 1;
80502
80618
  }
80503
80619
  async function writeJson(value, space) {
80504
- const text3 = `${JSON.stringify(value, null, space)}
80620
+ const text4 = `${JSON.stringify(value, null, space)}
80505
80621
  `;
80506
80622
  await new Promise((resolve19, reject2) => {
80507
- process.stdout.write(text3, (error61) => {
80623
+ process.stdout.write(text4, (error61) => {
80508
80624
  if (error61)
80509
80625
  reject2(error61);
80510
80626
  else
@@ -81063,7 +81179,7 @@ function handleDiff(name, options) {
81063
81179
  const present = existsSync22(dir);
81064
81180
  const managed = existsSync22(join37(dir, SYNC_MARKER_FILE));
81065
81181
  const skillMdPath = join37(dir, "SKILL.md");
81066
- const hash3 = present && existsSync22(skillMdPath) ? hashSkillMarkdownFile(skillMdPath) : undefined;
81182
+ const hash4 = present && existsSync22(skillMdPath) ? hashSkillMarkdownFile(skillMdPath) : undefined;
81067
81183
  let stub;
81068
81184
  if (present && existsSync22(skillMdPath)) {
81069
81185
  try {
@@ -81072,13 +81188,13 @@ function handleDiff(name, options) {
81072
81188
  stub = undefined;
81073
81189
  }
81074
81190
  }
81075
- const diverged = present && canonical4.present && managed && hash3 !== canonical4.hash;
81191
+ const diverged = present && canonical4.present && managed && hash4 !== canonical4.hash;
81076
81192
  homes.push({
81077
81193
  agent,
81078
81194
  path: dir,
81079
81195
  present,
81080
81196
  managed,
81081
- ...hash3 ? { hash: hash3 } : {},
81197
+ ...hash4 ? { hash: hash4 } : {},
81082
81198
  ...stub !== undefined ? { stub } : {},
81083
81199
  ...diverged !== undefined ? { diverged } : {}
81084
81200
  });
@@ -81934,13 +82050,13 @@ function scanUnmarkedHomes(options = {}) {
81934
82050
  const skillMdPath = join39(dir, "SKILL.md");
81935
82051
  if (!existsSync24(skillMdPath))
81936
82052
  continue;
81937
- const hash3 = hashSkillMarkdownFile(skillMdPath);
82053
+ const hash4 = hashSkillMarkdownFile(skillMdPath);
81938
82054
  const mtime = statSync12(skillMdPath).mtime.toISOString();
81939
- const entry = { agent, skill, home, path: dir, hash: hash3, mtime };
82055
+ const entry = { agent, skill, home, path: dir, hash: hash4, mtime };
81940
82056
  const canonicalHash = index.get(skill);
81941
82057
  if (canonicalHash === undefined) {
81942
82058
  scan.unknown.push({ ...entry });
81943
- } else if (canonicalHash === hash3) {
82059
+ } else if (canonicalHash === hash4) {
81944
82060
  scan.adoptable.push(entry);
81945
82061
  } else {
81946
82062
  scan.conflicts.push({ ...entry, canonicalHash });
@@ -82028,10 +82144,10 @@ function pruneOwnership(dir) {
82028
82144
  const after2 = fstatSync15(descriptor), current = lstatSync22(dir), markerPathAfter = lstatSync22(markerPath);
82029
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)
82030
82146
  return;
82031
- 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);
82032
82148
  if (!isSkillsOwnershipMarker(marker))
82033
82149
  return;
82034
- 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]) };
82035
82151
  } catch {
82036
82152
  return;
82037
82153
  } finally {
@@ -82077,15 +82193,15 @@ function pruneStrayHomes(options = {}) {
82077
82193
  const marker = owned.marker;
82078
82194
  ownership.set(dir, owned.identity);
82079
82195
  const skillMdPath = join39(dir, "SKILL.md");
82080
- const hash3 = existsSync24(skillMdPath) ? hashSkillMarkdownFile(skillMdPath) : "";
82081
- 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 });
82082
82198
  }
82083
82199
  }
82084
82200
  if (!options.apply) {
82085
82201
  return { candidates, pruned: 0, dryRun: true };
82086
82202
  }
82087
82203
  const appDir = options.homeDir ? join39(options.homeDir, ".hasna", "skills") : getDataDir();
82088
- 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);
82089
82205
  let pruned = 0;
82090
82206
  for (const candidate2 of candidates) {
82091
82207
  if (pruneOwnership(candidate2.path)?.identity !== ownership.get(candidate2.path))
@@ -82316,10 +82432,10 @@ function setEnvAssignment(path, assignment) {
82316
82432
  }
82317
82433
  let prepared = initial2;
82318
82434
  if (previous) {
82319
- const original = readFileSync27(descriptor), text3 = original.toString("utf8");
82320
- if (!Buffer.from(text3, "utf8").equals(original))
82435
+ const original = readFileSync27(descriptor), text4 = original.toString("utf8");
82436
+ if (!Buffer.from(text4, "utf8").equals(original))
82321
82437
  throw new EnvAssignmentError(INVALID_LAYOUT);
82322
- prepared = prepareEnvAssignment(assignment, text3);
82438
+ prepared = prepareEnvAssignment(assignment, text4);
82323
82439
  }
82324
82440
  const bytes = Buffer.from(prepared.content, "utf8");
82325
82441
  let written = 0;
@@ -82859,7 +82975,7 @@ import { closeSync as closeSync17, fstatSync as fstatSync17, openSync as openSyn
82859
82975
  import { O_NOFOLLOW as O_NOFOLLOW3, O_NONBLOCK as O_NONBLOCK3, O_RDONLY as O_RDONLY3 } from "constants";
82860
82976
  import { createRequire as createRequire2 } from "module";
82861
82977
  import { hostname as osHostname2 } from "os";
82862
- import { isAbsolute as isAbsolute16, join as join42 } from "path";
82978
+ import { isAbsolute as isAbsolute17, join as join42 } from "path";
82863
82979
  import { createRequire as createRequire22 } from "module";
82864
82980
  function envToken2(name) {
82865
82981
  return name.toUpperCase().replace(/-/g, "_");
@@ -82883,7 +82999,7 @@ function homeDir2(env3) {
82883
82999
  }
82884
83000
  function absoluteOverride2(env3, key) {
82885
83001
  const value = env3[key]?.trim();
82886
- return value && isAbsolute16(value) ? value : null;
83002
+ return value && isAbsolute17(value) ? value : null;
82887
83003
  }
82888
83004
  function hasnaHomeDir2(env3) {
82889
83005
  const override = absoluteOverride2(env3, HASNA_HOME_ENV_KEY2);
@@ -82914,10 +83030,10 @@ function credentialDiskSources2(name, env3) {
82914
83030
  function profileDiskSources2(name, env3, profile) {
82915
83031
  return credentialDiskSourceList2(name, env3, profile).map((s) => s.path);
82916
83032
  }
82917
- function parseEnvFile2(text3) {
83033
+ function parseEnvFile2(text4) {
82918
83034
  const values2 = new Map;
82919
83035
  const unusable = new Set;
82920
- for (const rawLine of text3.split(/\r?\n/)) {
83036
+ for (const rawLine of text4.split(/\r?\n/)) {
82921
83037
  const line = rawLine.trim();
82922
83038
  if (line.length === 0 || line.startsWith("#"))
82923
83039
  continue;
@@ -83157,8 +83273,8 @@ function keychainAccount2(env3, options) {
83157
83273
  const user = env3.USER?.trim();
83158
83274
  return user || null;
83159
83275
  }
83160
- function keychainFailureHint2(text3) {
83161
- 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() ?? "";
83162
83278
  const clean = line.replace(/[\u0000-\u001f\u007f]/g, "").slice(0, 200);
83163
83279
  return clean ? `: ${clean}` : "";
83164
83280
  }
@@ -83736,12 +83852,12 @@ function createHasnaHttpTransportInternal(options, requestBindingProvider) {
83736
83852
  await response.body?.cancel();
83737
83853
  } catch {}
83738
83854
  } else {
83739
- const text3 = await response.text();
83740
- if (text3.length > 0) {
83855
+ const text4 = await response.text();
83856
+ if (text4.length > 0) {
83741
83857
  try {
83742
- parsed = JSON.parse(text3);
83858
+ parsed = JSON.parse(text4);
83743
83859
  } catch {
83744
- parsed = text3;
83860
+ parsed = text4;
83745
83861
  }
83746
83862
  }
83747
83863
  }
@@ -83844,13 +83960,13 @@ class SecretsClient {
83844
83960
  headers,
83845
83961
  redirect: "manual"
83846
83962
  });
83847
- const text3 = await response.text();
83963
+ const text4 = await response.text();
83848
83964
  let body = undefined;
83849
- if (text3) {
83965
+ if (text4) {
83850
83966
  try {
83851
- body = JSON.parse(text3);
83967
+ body = JSON.parse(text4);
83852
83968
  } catch {
83853
- body = text3;
83969
+ body = text4;
83854
83970
  }
83855
83971
  }
83856
83972
  if (!response.ok) {
@@ -84179,7 +84295,7 @@ function refuse(code, message) {
84179
84295
  function record7(value) {
84180
84296
  return !!value && typeof value === "object" && !Array.isArray(value);
84181
84297
  }
84182
- function exactKeys2(value, keys2) {
84298
+ function exactKeys3(value, keys2) {
84183
84299
  return Object.keys(value).length === keys2.length && keys2.every((key) => Object.hasOwn(value, key));
84184
84300
  }
84185
84301
  function identifier2(value) {
@@ -84219,7 +84335,7 @@ function readSelectedSecretBindings(path) {
84219
84335
  }
84220
84336
  }
84221
84337
  function validateSelectedSecretBindings(value, scope, names) {
84222
- 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)) {
84223
84339
  return refuse("INVALID_SECRET_BINDINGS", "Secret bindings do not match the hasna.skills-secret-bindings.v1 contract.");
84224
84340
  }
84225
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 })) {
@@ -84244,7 +84360,7 @@ function validateSelectedSecretBindings(value, scope, names) {
84244
84360
  } catch {
84245
84361
  return refuse("INVALID_SECRET_BINDINGS", "Secret bindings require a canonical HTTPS Secrets /v1 authority (loopback HTTP is allowed).");
84246
84362
  }
84247
- 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 === ".."))) {
84248
84364
  return refuse("INVALID_SECRET_BINDINGS", "Bind every declared environment name exactly once to a vault key; undeclared bindings and values are refused.");
84249
84365
  }
84250
84366
  return structuredClone(value);
@@ -84274,7 +84390,7 @@ async function resolveSelectedSecrets(bindings, createClient2 = createSecretsCli
84274
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.");
84275
84391
  }
84276
84392
  }
84277
- function redactExecutionSecrets(text3, env3) {
84393
+ function redactExecutionSecrets(text4, env3) {
84278
84394
  const values2 = new Set(Object.values(env3).flatMap((value) => {
84279
84395
  let encoded = "";
84280
84396
  try {
@@ -84283,8 +84399,8 @@ function redactExecutionSecrets(text3, env3) {
84283
84399
  return [value, JSON.stringify(value).slice(1, -1), Buffer.from(value).toString("base64"), encoded];
84284
84400
  }));
84285
84401
  for (const value of [...values2].filter(Boolean).sort((a, b) => b.length - a.length))
84286
- text3 = text3.split(value).join("[REDACTED]");
84287
- return text3;
84402
+ text4 = text4.split(value).join("[REDACTED]");
84403
+ return text4;
84288
84404
  }
84289
84405
  var init_execution_secrets = __esm(() => {
84290
84406
  init_sdk();
@@ -84422,7 +84538,7 @@ var init_execution_grants = __esm(() => {
84422
84538
  });
84423
84539
 
84424
84540
  // src/lib/execution-grant-client.ts
84425
- import { isDeepStrictEqual as isDeepStrictEqual6 } from "util";
84541
+ import { isDeepStrictEqual as isDeepStrictEqual7 } from "util";
84426
84542
  function id(value) {
84427
84543
  if (!grantIdentifier(value))
84428
84544
  throw new Error("Invalid execution grant profile or revision identifier.");
@@ -84474,7 +84590,7 @@ async function saveExecutionGrantPolicy(profileId, grants, revision) {
84474
84590
  headers: revision === undefined ? { "If-None-Match": "*" } : { "If-Match": `"${revision}"` },
84475
84591
  body: JSON.stringify({ grants: snapshot2 })
84476
84592
  }));
84477
- 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)) {
84478
84594
  throw new Error("The API did not preserve the reviewed execution grant policy; read it before retrying.");
84479
84595
  }
84480
84596
  return policy;
@@ -84485,7 +84601,7 @@ async function resolveExecutionGrant(input2) {
84485
84601
  if (!grantRecord(value) || Object.keys(value).length !== 3 || !grantIdentifier(value.policyRevision) || !grantIdentifier(value.grantId) || !grantRecord(value.bindings)) {
84486
84602
  throw new SkillSelectionError("INVALID_EXECUTION_GRANT", "The Skills API returned an invalid execution grant.");
84487
84603
  }
84488
- 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)) {
84489
84605
  throw new SkillSelectionError("EXECUTION_GRANT_SCOPE_MISMATCH", "The Skills API returned a grant for a different selection or consumer.");
84490
84606
  }
84491
84607
  return value;
@@ -93580,10 +93696,10 @@ var require_util = __commonJS((exports) => {
93580
93696
  var codegen_1 = require_codegen();
93581
93697
  var code_1 = require_code();
93582
93698
  function toHash(arr) {
93583
- const hash3 = {};
93699
+ const hash4 = {};
93584
93700
  for (const item of arr)
93585
- hash3[item] = true;
93586
- return hash3;
93701
+ hash4[item] = true;
93702
+ return hash4;
93587
93703
  }
93588
93704
  exports.toHash = toHash;
93589
93705
  function alwaysValidSchema(it, schema) {
@@ -97045,7 +97161,7 @@ var require_core = __commonJS((exports) => {
97045
97161
  errorsText(errors5 = this.errors, { separator = ", ", dataVar = "data" } = {}) {
97046
97162
  if (!errors5 || errors5.length === 0)
97047
97163
  return "No errors";
97048
- 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);
97049
97165
  }
97050
97166
  $dataMetaSchema(metaSchema, keywordsJsonPointers) {
97051
97167
  const rules = this.RULES.all;
@@ -101123,11 +101239,11 @@ var init_remote_invitation_recovery = __esm(() => {
101123
101239
  // src/lib/remote-private-publications.ts
101124
101240
  import { createHash as createHash23 } from "crypto";
101125
101241
  function checkedPublicationDeclaration(value) {
101126
- 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)
101127
101243
  return bad();
101128
101244
  try {
101129
101245
  const manifest = JSON.parse(value.manifestText);
101130
- 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))
101131
101247
  return bad();
101132
101248
  } catch {
101133
101249
  return bad();
@@ -101135,7 +101251,7 @@ function checkedPublicationDeclaration(value) {
101135
101251
  return Object.freeze({ ...value });
101136
101252
  }
101137
101253
  function checkedPublicationView(value, skillId, intentId, declaration) {
101138
- 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)
101139
101255
  return invalid5();
101140
101256
  if (declaration && ["version", "expectedCurrentVersionId", "archiveSha256", "archiveByteSize"].some((k) => value[k] !== declaration[k]))
101141
101257
  return invalid5();
@@ -101382,7 +101498,7 @@ var PRIVATE_PUBLICATION_MAX_BYTES, failures2, PrivatePublicationError, bad = ()
101382
101498
  throw new PrivatePublicationError("INVALID_PUBLICATION_INPUT", "Invalid publication input or recovery data.");
101383
101499
  }, invalid5 = () => {
101384
101500
  throw new PrivatePublicationError("INVALID_PUBLICATION_RESPONSE", "The server returned an invalid publication result.");
101385
- }, 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");
101386
101502
  var init_remote_private_publications = __esm(() => {
101387
101503
  init_fleet_credentials();
101388
101504
  init_remote_workspace_selection();
@@ -101443,8 +101559,8 @@ async function requestAuthApi(instance, path, options) {
101443
101559
  apiUrl: safeUrl
101444
101560
  });
101445
101561
  }
101446
- const text3 = await res.text();
101447
- const body = text3 ? parseJsonBody(text3) : {};
101562
+ const text4 = await res.text();
101563
+ const body = text4 ? parseJsonBody(text4) : {};
101448
101564
  if (!res.ok) {
101449
101565
  const record11 = isRecord5(body) ? body : {};
101450
101566
  const detail = typeof record11.detail === "string" ? record11.detail : undefined;
@@ -101460,15 +101576,15 @@ async function requestAuthApi(instance, path, options) {
101460
101576
  }
101461
101577
  return body;
101462
101578
  }
101463
- function parseJsonBody(text3) {
101579
+ function parseJsonBody(text4) {
101464
101580
  try {
101465
- return JSON.parse(text3);
101581
+ return JSON.parse(text4);
101466
101582
  } catch {
101467
- return { detail: condenseErrorBody(text3) };
101583
+ return { detail: condenseErrorBody(text4) };
101468
101584
  }
101469
101585
  }
101470
- function condenseErrorBody(text3) {
101471
- 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;
101472
101588
  const collapsed = stripped.replace(/\s+/g, " ").trim();
101473
101589
  if (collapsed.length <= MAX_ERROR_DETAIL_LENGTH)
101474
101590
  return collapsed;
@@ -101684,12 +101800,12 @@ function safeText(file2) {
101684
101800
  }
101685
101801
  }
101686
101802
  function checkIdentityMetadata(file2, identity4) {
101687
- const text3 = safeText(file2);
101688
- if (text3 === null)
101803
+ const text4 = safeText(file2);
101804
+ if (text4 === null)
101689
101805
  return;
101690
101806
  let value;
101691
101807
  try {
101692
- value = JSON.parse(text3);
101808
+ value = JSON.parse(text4);
101693
101809
  } catch {
101694
101810
  return fail3("The profile identity metadata is invalid. Sign in again before managing this workspace.");
101695
101811
  }
@@ -102028,7 +102144,7 @@ var init_recurring_customer = __esm(() => {
102028
102144
 
102029
102145
  // src/lib/recurring-recovery.ts
102030
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";
102031
- 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";
102032
102148
  import { randomUUID as randomUUID7 } from "crypto";
102033
102149
 
102034
102150
  class RecoveryOwner {
@@ -102036,7 +102152,7 @@ class RecoveryOwner {
102036
102152
  parents = [];
102037
102153
  constructor(directory) {
102038
102154
  this.directory = directory;
102039
- if (!isAbsolute17(directory) || resolve20(directory) !== directory || realpathSync9(directory) !== directory)
102155
+ if (!isAbsolute18(directory) || resolve20(directory) !== directory || realpathSync9(directory) !== directory)
102040
102156
  invalid6();
102041
102157
  for (let path = directory;; path = dirname23(path)) {
102042
102158
  const stat3 = lstatSync25(path);
@@ -102171,7 +102287,7 @@ function base2(customer, organizationId) {
102171
102287
  };
102172
102288
  }
102173
102289
  function create3(directory, intent) {
102174
- if (!isAbsolute17(directory) || resolve20(directory) !== directory || realpathSync9(dirname23(directory)) !== dirname23(directory))
102290
+ if (!isAbsolute18(directory) || resolve20(directory) !== directory || realpathSync9(dirname23(directory)) !== dirname23(directory))
102175
102291
  invalid6();
102176
102292
  mkdirSync17(directory, { mode: 448 });
102177
102293
  const owner2 = new RecoveryOwner(directory), checked = intentSchema.parse(intent), intentSha256 = canonicalJsonSha256(checked);
@@ -102334,12 +102450,12 @@ var init_recurring_recovery = __esm(() => {
102334
102450
  });
102335
102451
 
102336
102452
  // src/lib/recurring-surface.ts
102337
- import { isAbsolute as isAbsolute18 } from "path";
102453
+ import { isAbsolute as isAbsolute19 } from "path";
102338
102454
  function recurringMcpSchema(action) {
102339
102455
  return action === "activate" ? recurringSurfaceSchemas.activate.extend({ code, confirm: exports_external.literal(true) }) : recurringSurfaceSchemas[action];
102340
102456
  }
102341
- function expectedDraft(draft, hash4) {
102342
- if (!draft || draft.termsSha256 !== hash4)
102457
+ function expectedDraft(draft, hash5) {
102458
+ if (!draft || draft.termsSha256 !== hash5)
102343
102459
  throw new RemoteRecurringError("RECURRING_TERMS_UNAVAILABLE");
102344
102460
  return draft;
102345
102461
  }
@@ -102439,7 +102555,7 @@ var init_recurring_surface = __esm(() => {
102439
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}$/);
102440
102556
  context = { userId: uuid13.optional(), membershipId: uuid13.optional() };
102441
102557
  page2 = { limit: exports_external.number().int().min(1).max(100).optional(), cursor: exports_external.string().min(1).max(2048).optional() };
102442
- 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");
102443
102559
  email4 = exports_external.string().trim().toLowerCase().email().max(254);
102444
102560
  code = exports_external.string().regex(/^\d{6}$/);
102445
102561
  recurringSurfaceSchemas = {
@@ -105241,10 +105357,10 @@ var init_private_publication_customer = __esm(() => {
105241
105357
 
105242
105358
  // src/lib/private-publication-recovery.ts
105243
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";
105244
- 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";
105245
105361
  import { randomUUID as randomUUID8 } from "crypto";
105246
105362
  function safeDirectory(directory2) {
105247
- if (!isAbsolute19(directory2) || directory2 !== resolve21(directory2) || realpathSync10(directory2) !== directory2)
105363
+ if (!isAbsolute20(directory2) || directory2 !== resolve21(directory2) || realpathSync10(directory2) !== directory2)
105248
105364
  return fail4();
105249
105365
  for (let path = directory2;; path = dirname26(path)) {
105250
105366
  const stat3 = lstatSync26(path);
@@ -105382,7 +105498,7 @@ async function preparePrivatePublication(client2, sourceDirectory, recoveryDirec
105382
105498
  phase: "prepared",
105383
105499
  intent: null
105384
105500
  };
105385
- if (!isAbsolute19(recoveryDirectory) || resolve21(recoveryDirectory) !== recoveryDirectory || realpathSync10(dirname26(recoveryDirectory)) !== dirname26(recoveryDirectory))
105501
+ if (!isAbsolute20(recoveryDirectory) || resolve21(recoveryDirectory) !== recoveryDirectory || realpathSync10(dirname26(recoveryDirectory)) !== dirname26(recoveryDirectory))
105386
105502
  return fail4();
105387
105503
  mkdirSync21(recoveryDirectory, { mode: 448 });
105388
105504
  safeDirectory(recoveryDirectory);
@@ -105483,10 +105599,10 @@ var init_private_publication_recovery = __esm(() => {
105483
105599
  });
105484
105600
 
105485
105601
  // src/mcp/private-publication-tools.ts
105486
- import { isAbsolute as isAbsolute20 } from "path";
105602
+ import { isAbsolute as isAbsolute21 } from "path";
105487
105603
  function registerPrivatePublicationTools(server) {
105488
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}$/);
105489
- 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");
105490
105606
  const verification2 = { email: exports_external.string().email().max(254), code: exports_external.string().regex(/^\d{6}$/), userId: uuid9, membershipId: uuid9, recoveryDirectory: directory2 };
105491
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.";
105492
105608
  const handler = (action) => async (value) => {
@@ -106132,7 +106248,7 @@ __export(exports_runtime, {
106132
106248
  });
106133
106249
  import { createHash as createHash25, randomUUID as randomUUID9 } from "crypto";
106134
106250
  import { lstatSync as lstatSync27, mkdirSync as mkdirSync23, readFileSync as readFileSync35, realpathSync as realpathSync11, writeFileSync as writeFileSync22 } from "fs";
106135
- 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";
106136
106252
  import { createInterface } from "readline";
106137
106253
  function registerRuntime(parent) {
106138
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) => {
@@ -106259,7 +106375,7 @@ Updating ${name}...
106259
106375
  async function readUpdatedVersion(bunExecutable) {
106260
106376
  const output2 = await readUpdateCommand([bunExecutable, "pm", "bin", "-g"]);
106261
106377
  const globalBin = output2.replace(/\r?\n$/, "");
106262
- if (!globalBin || !isAbsolute21(globalBin) || /[\r\n\0]/.test(globalBin))
106378
+ if (!globalBin || !isAbsolute22(globalBin) || /[\r\n\0]/.test(globalBin))
106263
106379
  throw new Error("Update bin discovery failed");
106264
106380
  const installed = Bun.which("skills", { PATH: globalBin, cwd: globalBin });
106265
106381
  const selected = Bun.which("skills");
@@ -107225,13 +107341,13 @@ import { emitKeypressEvents } from "readline";
107225
107341
  async function readCode() {
107226
107342
  if (process.stdin.isTTY)
107227
107343
  throw new NameInputError("Pipe a fresh six-digit verification code when using --code-stdin.");
107228
- let text3 = "";
107344
+ let text4 = "";
107229
107345
  for await (const chunk2 of process.stdin) {
107230
- text3 += chunk2.toString();
107231
- if (text3.length > 32)
107346
+ text4 += chunk2.toString();
107347
+ if (text4.length > 32)
107232
107348
  throw new NameInputError("Supply only a six-digit verification code on stdin.");
107233
107349
  }
107234
- const code2 = text3.trim();
107350
+ const code2 = text4.trim();
107235
107351
  if (!/^\d{6}$/.test(code2))
107236
107352
  throw new NameInputError("Supply only a six-digit verification code on stdin.");
107237
107353
  return code2;
@@ -107259,7 +107375,7 @@ function promptCode() {
107259
107375
  resolve22(answer);
107260
107376
  };
107261
107377
  const cancel = () => finish(null);
107262
- const keypress = (text3, key) => {
107378
+ const keypress = (text4, key) => {
107263
107379
  if (key.ctrl && ["c", "d"].includes(key.name ?? "") || key.name === "escape")
107264
107380
  return cancel();
107265
107381
  if (key.name === "return" || key.name === "enter") {
@@ -107275,8 +107391,8 @@ Enter all six digits: `);
107275
107391
  value = value.slice(0, -1);
107276
107392
  output2.write("\b \b");
107277
107393
  }
107278
- } else if (/^[0-9]$/.test(text3) && value.length < 6) {
107279
- value += text3;
107394
+ } else if (/^[0-9]$/.test(text4) && value.length < 6) {
107395
+ value += text4;
107280
107396
  output2.write("*");
107281
107397
  }
107282
107398
  };
@@ -107758,7 +107874,7 @@ import {
107758
107874
  statSync as statSync19,
107759
107875
  writeFileSync as writeFileSync23
107760
107876
  } from "fs";
107761
- 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";
107762
107878
  function validateStationId(stationId) {
107763
107879
  if (!/^[a-z0-9-]+$/.test(stationId)) {
107764
107880
  throw new StationSnapshotError("INVALID_STATION", `station id must be a slug, got: ${stationId}`);
@@ -107864,7 +107980,7 @@ function writeStationSnapshot(options) {
107864
107980
  for (const plan of plans) {
107865
107981
  const destination = resolve22(repoRoot, plan.destination);
107866
107982
  const destinationRelative = relative8(repoRoot, destination);
107867
- if (destinationRelative.startsWith("..") || destinationRelative.startsWith(sep10) || isAbsolute22(destinationRelative)) {
107983
+ if (destinationRelative.startsWith("..") || destinationRelative.startsWith(sep10) || isAbsolute23(destinationRelative)) {
107868
107984
  throw new StationSnapshotError("DESTINATION_ESCAPE", `destination escapes repo root: ${plan.destination}`);
107869
107985
  }
107870
107986
  let existingDigest = null;
@@ -108339,10 +108455,10 @@ var init_create_sync_config = __esm(() => {
108339
108455
  // src/lib/codex-hook-rpc.ts
108340
108456
  import { execFile, spawn as spawn3 } from "child_process";
108341
108457
  import { realpathSync as realpathSync12, statSync as statSync20 } from "fs";
108342
- import { isAbsolute as isAbsolute23 } from "path";
108458
+ import { isAbsolute as isAbsolute24 } from "path";
108343
108459
  import { promisify } from "util";
108344
108460
  async function connectCodexHookRpc(options) {
108345
- 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 });
108346
108462
  if (!found)
108347
108463
  throw new Error("CODEX_HOOK_TRUST_NATIVE_UNAVAILABLE: install Codex or pass --codex-command");
108348
108464
  const binary = realpathSync12(found), stat3 = statSync20(binary);
@@ -108478,10 +108594,10 @@ var init_codex_hook_rpc = __esm(() => {
108478
108594
 
108479
108595
  // src/lib/codex-hook-trust-identity.ts
108480
108596
  import { realpathSync as realpathSync13 } from "fs";
108481
- import { dirname as dirname30, isAbsolute as isAbsolute24, join as join56 } from "path";
108482
- 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";
108483
108599
  function inspectRecordedSkillsCli(command, expected) {
108484
- need4(isAbsolute24(command) && !command.includes("\x00"), "RECONCILE_RECORDED_COMMAND_REQUIRED");
108600
+ need4(isAbsolute25(command) && !command.includes("\x00"), "RECONCILE_RECORDED_COMMAND_REQUIRED");
108485
108601
  const resolved = realpathSync13(command);
108486
108602
  const cli = snapshot(resolved, false, { readOnlyPackage: true });
108487
108603
  const manifest = snapshot(join56(dirname30(dirname30(resolved)), "package.json"), false, { readOnlyPackage: true });
@@ -108489,7 +108605,7 @@ function inspectRecordedSkillsCli(command, expected) {
108489
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");
108490
108606
  need4((cli.stat.mode & 0o100n) !== 0n, "SKILLS_COMMAND_NOT_EXECUTABLE");
108491
108607
  const receipt = { path: resolved, version: pkg.version, sha256: cli.sha256, manifestSha256: manifest.sha256 };
108492
- need4(isDeepStrictEqual7(receipt, expected), "RECONCILE_SKILLS_BINDING_CHANGED");
108608
+ need4(isDeepStrictEqual8(receipt, expected), "RECONCILE_SKILLS_BINDING_CHANGED");
108493
108609
  return { receipt, recheck() {
108494
108610
  need4(realpathSync13(command) === resolved, "SKILLS_COMMAND_CHANGED");
108495
108611
  unchanged2(cli);
@@ -108500,7 +108616,7 @@ function bindSkillsCli(command, reviewed) {
108500
108616
  const normal = Bun.which("skills", { PATH: process.env.PATH });
108501
108617
  need4(normal, "SKILLS_COMMAND_UNAVAILABLE");
108502
108618
  const resolved = realpathSync13(normal);
108503
- const bound = isAbsolute24(command) ? command : command === "skills" ? normal : undefined;
108619
+ const bound = isAbsolute25(command) ? command : command === "skills" ? normal : undefined;
108504
108620
  need4(bound && realpathSync13(bound) === resolved, "SKILLS_COMMAND_MISMATCH");
108505
108621
  const entrypoint = reviewed?.path ?? process.argv[1];
108506
108622
  need4(entrypoint && realpathSync13(entrypoint) === resolved, "SKILLS_ENTRYPOINT_MISMATCH");
@@ -108525,19 +108641,19 @@ var init_codex_hook_trust_identity = __esm(() => {
108525
108641
  });
108526
108642
 
108527
108643
  // src/lib/codex-hook-policy-recovery.ts
108528
- import { isDeepStrictEqual as isDeepStrictEqual8 } from "util";
108644
+ import { isDeepStrictEqual as isDeepStrictEqual9 } from "util";
108529
108645
  function reviewedClaudeDiscoveryChange(beforeText, currentText, options) {
108530
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");
108531
108647
  need4(options.reviewedPlanDigest === undefined || /^[a-f0-9]{64}$/.test(options.reviewedPlanDigest), "RECONCILE_RECOVERY_PLAN_CHANGED");
108532
108648
  const before2 = parseManagedSkillPolicy(beforeText), current = parseManagedSkillPolicy(currentText);
108533
108649
  const oldDiscovery = before2.bridge?.discovery?.claude, newDiscovery = current.bridge?.discovery?.claude;
108534
108650
  need4(oldDiscovery?.agent === "claude" && newDiscovery?.agent === "claude" && oldDiscovery.method === "reviewed" && newDiscovery.method === "reviewed", "RECONCILE_POLICY_CHANGED");
108535
- 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] }));
108536
108652
  need4(changes.length > 0, "RECONCILE_POLICY_CHANGED");
108537
108653
  const compared = structuredClone(current);
108538
108654
  compared.bridge.discovery.claude.roots = oldDiscovery.roots;
108539
108655
  compared.bridge.discovery.claude.sources = oldDiscovery.sources;
108540
- need4(isDeepStrictEqual8(before2, compared), "RECONCILE_POLICY_CHANGED");
108656
+ need4(isDeepStrictEqual9(before2, compared), "RECONCILE_POLICY_CHANGED");
108541
108657
  verifyAgentDiscovery(newDiscovery);
108542
108658
  return { reason: options.reason, changes };
108543
108659
  }
@@ -108547,69 +108663,6 @@ var init_codex_hook_policy_recovery = __esm(() => {
108547
108663
  init_agent_discovery();
108548
108664
  });
108549
108665
 
108550
- // src/lib/codex-hook-additions-review.ts
108551
- import { isAbsolute as isAbsolute25 } from "path";
108552
- import { isDeepStrictEqual as isDeepStrictEqual9 } from "util";
108553
- function exactKeys3(value, keys3) {
108554
- need4(value && typeof value === "object" && !Array.isArray(value) && isDeepStrictEqual9(Object.keys(value).sort(), [...keys3].sort()), "RECONCILE_ADDITIONS_REVIEW_SCHEMA");
108555
- }
108556
- function reviewNativeHookAdditions(options) {
108557
- need4(isAbsolute25(options.path), "RECONCILE_ADDITIONS_REVIEW_PATH");
108558
- const reviewFile = snapshot(options.path, true), review = JSON.parse(reviewFile.text);
108559
- exactKeys3(review, ["version", "kind", "reason", "producerEvidence", "journalIntentSha256", "policySha256", "configCurrentSha256", "hooksCurrentSha256", "producerBefore", "additions"]);
108560
- need4(review.version === 1 && review.kind === "native-hook-additions" && text3(review.reason) && text3(review.producerEvidence), "RECONCILE_ADDITIONS_REVIEW_SCHEMA");
108561
- for (const [name, expected] of [["journalIntentSha256", options.intent.sha256], ["policySha256", options.policy.sha256], ["configCurrentSha256", options.configCurrent.sha256], ["hooksCurrentSha256", options.hooksCurrent.sha256]])
108562
- need4(hash4(review[name]) && review[name] === expected, "RECONCILE_ADDITIONS_REVIEW_CHANGED");
108563
- exactKeys3(review.producerBefore, ["configPath", "configSha256", "hooksPath", "hooksSha256"]);
108564
- const before2 = review.producerBefore;
108565
- need4(isAbsolute25(before2.configPath) && isAbsolute25(before2.hooksPath) && hash4(before2.configSha256) && hash4(before2.hooksSha256), "RECONCILE_ADDITIONS_PRODUCER_PREIMAGE");
108566
- const producerConfig = snapshot(before2.configPath, true), producerHooks = snapshot(before2.hooksPath, true);
108567
- need4(producerConfig.sha256 === before2.configSha256 && producerHooks.sha256 === before2.hooksSha256 && producerHooks.sha256 === options.hooksBefore.sha256, "RECONCILE_ADDITIONS_PRODUCER_PREIMAGE");
108568
- const original = structure2(options.configBefore.text), producer = structure2(producerConfig.text), expectedProducer = structuredClone(original), originalKeys = options.journalHooks.map((hook) => hook.key);
108569
- expectedProducer.hooks ??= {};
108570
- expectedProducer.hooks.state ??= {};
108571
- for (const hook of options.journalHooks)
108572
- expectedProducer.hooks.state[hook.key] = { ...expectedProducer.hooks.state[hook.key], enabled: true, trusted_hash: hook.currentHash };
108573
- 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");
108574
- need4(Array.isArray(review.additions) && review.additions.length > 0 && review.additions.length <= 20, "RECONCILE_ADDITIONS_REVIEW_SCHEMA");
108575
- const expectedHooks = JSON.parse(options.hooksBefore.text), currentHooks = JSON.parse(options.hooksCurrent.text), expectedConfig = structuredClone(producer);
108576
- need4(expectedHooks.hooks && typeof expectedHooks.hooks === "object" && !Array.isArray(expectedHooks.hooks), "RECONCILE_ADDITIONS_DECLARATIONS");
108577
- const added = [], seen = new Set, commands = new Set(options.recordedNativeHooks.map((hook) => hook.command));
108578
- for (const addition of review.additions) {
108579
- exactKeys3(addition, ["event", "nativeHook"]);
108580
- need4(Object.hasOwn(events, addition.event), "RECONCILE_ADDITIONS_DECLARATIONS");
108581
- const { event, nativeHook: hook } = addition;
108582
- exactKeys3(hook, nativeKeys);
108583
- const groups = expectedHooks.hooks[event] ?? [];
108584
- need4(Array.isArray(groups), "RECONCILE_ADDITIONS_DECLARATIONS");
108585
- const key = `${options.nativeHooksPath}:${events[event][1]}:${groups.length}:0`;
108586
- need4(hook.key === key && !seen.has(key) && !options.recordedNativeHooks.some((originalHook) => originalHook.key === key) && !Object.hasOwn(expectedConfig.hooks.state, key), "RECONCILE_ADDITIONS_IDENTITY");
108587
- 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");
108588
- seen.add(key);
108589
- commands.add(hook.command);
108590
- added.push(hook);
108591
- expectedHooks.hooks[event] = [...groups, { hooks: [{ type: "command", command: hook.command, timeout: hook.timeoutSec }] }];
108592
- expectedConfig.hooks.state[key] = { enabled: true, trusted_hash: hook.currentHash };
108593
- }
108594
- need4(isDeepStrictEqual9(expectedHooks, currentHooks), "RECONCILE_ADDITIONS_DECLARATIONS");
108595
- const keys3 = added.map((hook) => hook.key);
108596
- 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");
108597
- const recheck = () => {
108598
- unchanged2(reviewFile);
108599
- unchanged2(producerConfig);
108600
- unchanged2(producerHooks);
108601
- };
108602
- recheck();
108603
- 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 } };
108604
- }
108605
- 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;
108606
- var init_codex_hook_additions_review = __esm(() => {
108607
- init_codex_hook_trust_files();
108608
- init_codex_hook_trust_layout();
108609
- events = { UserPromptSubmit: ["userPromptSubmit", "user_prompt_submit"], SessionStart: ["sessionStart", "session_start"], SubagentStart: ["subagentStart", "subagent_start"] };
108610
- nativeKeys = ["key", "eventName", "handlerType", "command", "matcher", "timeoutSec", "async", "statusMessage", "additionalContextLimit", "sourcePath", "source", "pluginId", "isManaged", "currentHash", "enabled", "trustStatus"];
108611
- });
108612
-
108613
108666
  // src/lib/agent-codex-trust.ts
108614
108667
  import { lstatSync as lstatSync29, mkdirSync as mkdirSync25, readdirSync as readdirSync20, readFileSync as readFileSync37, realpathSync as realpathSync14, statSync as statSync21 } from "fs";
108615
108668
  import { createHash as createHash27, randomUUID as randomUUID10 } from "crypto";
@@ -108696,8 +108749,11 @@ async function reconcileCodexNativeHooks(options, connect = connectCodexHookRpc)
108696
108749
  const before2 = structure3(configBefore.text), current = structure3(currentConfig.text), expectedConfig = structuredClone(before2);
108697
108750
  expectedConfig.hooks ??= {};
108698
108751
  expectedConfig.hooks.state ??= {};
108699
- for (const hook of managedHooks)
108752
+ for (const hook of intent.hooks)
108700
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 };
108701
108757
  if (supersededBinding) {
108702
108758
  for (const hook of intent.hooks) {
108703
108759
  const state = current.hooks?.state?.[hook.key];
@@ -108705,7 +108761,7 @@ async function reconcileCodexNativeHooks(options, connect = connectCodexHookRpc)
108705
108761
  }
108706
108762
  } else
108707
108763
  need4(isDeepStrictEqual10(expectedConfig, current), "RECONCILE_CONFIG_DRIFT");
108708
- 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;
108709
108765
  assertManagedAgentBridge("codex", { home, dataDir: dataDir3, projectDir: home, codexDiscoveryRecovery: configDiscoveryRecovery });
108710
108766
  const recoveryCli = recovery ? bindSkillsCli("skills", options.reviewedSkillsCli) : undefined;
108711
108767
  if (recoveryCli)