@hasna/skills 0.9.10 → 0.9.11

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.10",
36871
+ version: "0.9.11",
36872
36872
  description: "Skills library for AI coding agents",
36873
36873
  type: "module",
36874
36874
  bin: {
@@ -54737,10 +54737,252 @@ var init_claude_settings_witness = __esm(() => {
54737
54737
  ]);
54738
54738
  });
54739
54739
 
54740
- // src/lib/agent-discovery.ts
54740
+ // src/lib/codex-hook-trust-files.ts
54741
+ import { closeSync as closeSync11, constants as constants11, fstatSync as fstatSync11, fsyncSync as fsyncSync3, lstatSync as lstatSync17, openSync as openSync11, readSync as readSync9, writeFileSync as writeFileSync5 } from "fs";
54741
54742
  import { createHash as createHash13 } from "crypto";
54742
- import { lstatSync as lstatSync17, readFileSync as readFileSync14, readdirSync as readdirSync9, realpathSync as realpathSync4 } from "fs";
54743
- import { basename as basename8, dirname as dirname14, isAbsolute as isAbsolute14, join as join28, resolve as resolve15, sep as sep5 } from "path";
54743
+ import { dirname as dirname14 } from "path";
54744
+ function need4(value, code) {
54745
+ if (!value)
54746
+ throw new Error(`CODEX_HOOK_TRUST_${code}`);
54747
+ }
54748
+ function safeParents(file) {
54749
+ for (let p = dirname14(file);; p = dirname14(p)) {
54750
+ const s = lstatSync17(p);
54751
+ need4(s.isDirectory() && !s.isSymbolicLink(), "UNSAFE_PARENT");
54752
+ need4((s.mode & 18) === 0 || s.uid === 0 && (s.mode & 512) !== 0, "UNSAFE_PARENT");
54753
+ if (dirname14(p) === p)
54754
+ break;
54755
+ }
54756
+ }
54757
+ function snapshot(file, privateFile = false, options = {}) {
54758
+ const readOnlyPackage = options.readOnlyPackage === true && !privateFile;
54759
+ safeParents(file);
54760
+ const initial2 = lstatSync17(file, { bigint: true });
54761
+ need4(initial2.isFile() && initial2.uid === BigInt(process.getuid()) && (initial2.nlink === 1n || readOnlyPackage && initial2.nlink > 1n) && (initial2.mode & 0o022n) === 0n && (!privateFile || (initial2.mode & 0o777n) === 0o600n), "UNSAFE_FILE");
54762
+ need4(initial2.size <= 8n * 1024n * 1024n, "FILE_BOUND");
54763
+ const fd = openSync11(file, constants11.O_RDONLY | constants11.O_NOFOLLOW | constants11.O_NONBLOCK);
54764
+ try {
54765
+ const before2 = fstatSync11(fd, { bigint: true });
54766
+ need4(sameStat(initial2, before2), "INPUT_CHANGED");
54767
+ const bytes = Buffer.alloc(Number(before2.size) + 1);
54768
+ let length = 0;
54769
+ while (length < bytes.length) {
54770
+ const n2 = readSync9(fd, bytes, length, bytes.length - length, null);
54771
+ if (!n2)
54772
+ break;
54773
+ length += n2;
54774
+ }
54775
+ need4(length === Number(before2.size) && sameStat(before2, fstatSync11(fd, { bigint: true })) && sameStat(before2, lstatSync17(file, { bigint: true })), "INPUT_CHANGED");
54776
+ const content = bytes.subarray(0, length), text2 = new TextDecoder("utf-8", { fatal: true }).decode(content);
54777
+ return { file, privateFile, readOnlyPackage, text: text2, bytes: content, stat: before2, sha256: createHash13("sha256").update(content).digest("hex") };
54778
+ } finally {
54779
+ closeSync11(fd);
54780
+ }
54781
+ }
54782
+ function unchanged2(before2) {
54783
+ const after2 = snapshot(before2.file, before2.privateFile, before2.readOnlyPackage ? { readOnlyPackage: true } : {});
54784
+ need4(sameStat(before2.stat, after2.stat) && after2.sha256 === before2.sha256, "INPUT_CHANGED");
54785
+ }
54786
+ function save(file, content) {
54787
+ safeParents(file);
54788
+ const fd = openSync11(file, constants11.O_WRONLY | constants11.O_CREAT | constants11.O_EXCL | constants11.O_NOFOLLOW, 384);
54789
+ try {
54790
+ writeFileSync5(fd, content);
54791
+ fsyncSync3(fd);
54792
+ } finally {
54793
+ closeSync11(fd);
54794
+ }
54795
+ }
54796
+ var sameStat = (a, b) => ["dev", "ino", "uid", "nlink", "mode", "size", "mtimeNs", "ctimeNs"].every((key) => a[key] === b[key]);
54797
+ var init_codex_hook_trust_files = () => {};
54798
+
54799
+ // src/lib/codex-hook-trust-layout.ts
54800
+ import { isDeepStrictEqual as isDeepStrictEqual3 } from "util";
54801
+ function codexTrustTextWitness(text2, keys2, canonicalize = true) {
54802
+ const parsed = Bun.TOML.parse(text2), wanted = new Set(keys2);
54803
+ const headers = [...text2.matchAll(/^[ \t]*(\[[^\r\n]+\])[ \t]*(#[^\r\n]*)?(?:\r?\n|$)/gm)];
54804
+ if (headers.length > 512)
54805
+ throw fail2();
54806
+ let root2 = parsed;
54807
+ for (const header of headers) {
54808
+ try {
54809
+ root2 = Bun.TOML.parse(text2.slice(0, header.index));
54810
+ break;
54811
+ } catch {}
54812
+ }
54813
+ if (root2.hooks !== undefined)
54814
+ throw fail2();
54815
+ const replacements2 = [];
54816
+ const stateSections = [];
54817
+ for (const [index, header] of headers.entries()) {
54818
+ let shape;
54819
+ try {
54820
+ shape = Bun.TOML.parse(header[1]);
54821
+ } catch {
54822
+ continue;
54823
+ }
54824
+ const state = shape.hooks?.state;
54825
+ if (!state || Object.keys(shape).length !== 1 || Object.keys(shape.hooks).length !== 1)
54826
+ continue;
54827
+ const names = Object.keys(state), start = header.index, end = headers[index + 1]?.index ?? text2.length;
54828
+ if (names.length === 0) {
54829
+ replacements2.push({ start, end: start + header[0].length, comments: header[2] ? header[2] + `
54830
+ ` : "" });
54831
+ stateSections.push({ start, end: start + header[0].length });
54832
+ } else if (names.length === 1 && !Object.keys(state[names[0]]).length) {
54833
+ stateSections.push({ start, end });
54834
+ if (!wanted.has(names[0])) {
54835
+ replacements2.push({ start, end: start + header[0].length, comments: `[hooks.state.${JSON.stringify(names[0])}]${header[2] ? " " + header[2] : ""}
54836
+ ` });
54837
+ continue;
54838
+ }
54839
+ const comments = header[2] ? [header[2]] : [];
54840
+ for (const line of text2.slice(start + header[0].length, end).split(/\r?\n/)) {
54841
+ if (!line.trim())
54842
+ continue;
54843
+ if (/^[ \t]*#/.test(line)) {
54844
+ comments.push(line);
54845
+ continue;
54846
+ }
54847
+ const field2 = /^[ \t]*(?:enabled|trusted_hash)[ \t]*=[ \t]*(?:true|false|"(?:[^"\\]|\\.)*"|'[^']*')[ \t]*(#[^\r\n]*)?$/.exec(line);
54848
+ if (!field2)
54849
+ throw fail2();
54850
+ if (field2[1])
54851
+ comments.push(field2[1]);
54852
+ }
54853
+ replacements2.push({ start, end, comments: comments.join(`
54854
+ `) + `
54855
+ ` });
54856
+ }
54857
+ }
54858
+ let noState = text2;
54859
+ for (const span of [...stateSections].reverse())
54860
+ noState = noState.slice(0, span.start) + noState.slice(span.end);
54861
+ const expected = structuredClone(parsed);
54862
+ if (expected.hooks)
54863
+ delete expected.hooks.state;
54864
+ try {
54865
+ if (!isDeepStrictEqual3(prune(Bun.TOML.parse(noState)), prune(expected)))
54866
+ throw fail2();
54867
+ } catch {
54868
+ throw fail2();
54869
+ }
54870
+ let result2 = text2;
54871
+ for (const span of replacements2.reverse())
54872
+ result2 = result2.slice(0, span.start) + span.comments + result2.slice(span.end);
54873
+ return (canonicalize ? canonicalizeTableOrder(result2) : result2).split(/\r?\n/).filter((line) => line.trim()).join(`
54874
+ `);
54875
+ }
54876
+ function codexTrustReconcileWitness(text2, keys2) {
54877
+ return codexTrustTextWitness(text2, keys2, false).replace(/[ \t]+$/gm, "");
54878
+ }
54879
+ function codexTrustUnmanagedSemantic(text2, keys2) {
54880
+ const parsed = structuredClone(Bun.TOML.parse(text2));
54881
+ for (const key of keys2)
54882
+ if (parsed.hooks?.state?.[key] !== undefined)
54883
+ delete parsed.hooks.state[key];
54884
+ return JSON.stringify(stableSemantic(prune(parsed)));
54885
+ }
54886
+ var fail2 = () => new Error('CODEX_HOOK_TRUST_UNSUPPORTED_LAYOUT: preserve and convert hook trust to ordinary [hooks.state."<key>"] tables before enrollment'), prune = (value) => {
54887
+ if (value.hooks?.state && !Object.keys(value.hooks.state).length)
54888
+ delete value.hooks.state;
54889
+ if (value.hooks && !Object.keys(value.hooks).length)
54890
+ delete value.hooks;
54891
+ return value;
54892
+ }, canonicalizeTableOrder = (text2) => {
54893
+ const headers = [...text2.matchAll(/^[ \t]*(\[\[?[^\r\n]+\]\]?)[ \t]*(#[^\r\n]*)?(?:\r?\n|$)/gm)];
54894
+ if (!headers.length)
54895
+ return text2;
54896
+ const keys2 = headers.map((header) => header[1].trim());
54897
+ const repeated = keys2.filter((key) => !key.startsWith("[[")).filter((key, index, simple2) => simple2.indexOf(key) !== index);
54898
+ const arrayKeys = keys2.filter((key) => key.startsWith("[["));
54899
+ const plain = keys2.map((key) => key.replace(/^\[\[?/, "").replace(/\]\]?$/, "").trim());
54900
+ const parentChild = plain.some((key, index) => plain.some((other, otherIndex) => index !== otherIndex && (other.startsWith(`${key}.`) || key.startsWith(`${other}.`))));
54901
+ if (repeated.length || parentChild)
54902
+ return text2;
54903
+ if (!arrayKeys.length) {
54904
+ const first2 = headers[0].index;
54905
+ const prefix2 = text2.slice(0, first2);
54906
+ const blocks2 = headers.map((header, index) => ({
54907
+ key: header[1],
54908
+ order: index,
54909
+ text: text2.slice(header.index, headers[index + 1]?.index ?? text2.length)
54910
+ }));
54911
+ blocks2.sort((a, b) => a.key.localeCompare(b.key) || a.order - b.order);
54912
+ return prefix2 + blocks2.map((block) => block.text).join("");
54913
+ }
54914
+ const first = headers[0].index;
54915
+ const prefix = text2.slice(0, first);
54916
+ const blocks = headers.map((header, index) => ({
54917
+ key: header[1],
54918
+ order: index,
54919
+ text: text2.slice(header.index, headers[index + 1]?.index ?? text2.length)
54920
+ }));
54921
+ const simple = blocks.filter((block) => !block.key.startsWith("[["));
54922
+ const arrays = blocks.filter((block) => block.key.startsWith("[["));
54923
+ return prefix + [...simple, ...arrays].map((block) => block.text).join("");
54924
+ }, stableSemantic = (value) => {
54925
+ if (Array.isArray(value))
54926
+ return value.map(stableSemantic);
54927
+ if (value && typeof value === "object")
54928
+ return Object.fromEntries(Object.keys(value).sort().map((key) => [key, stableSemantic(value[key])]));
54929
+ return value;
54930
+ };
54931
+ var init_codex_hook_trust_layout = () => {};
54932
+
54933
+ // src/lib/codex-hook-discovery-recovery.ts
54934
+ import { createHash as createHash14 } from "crypto";
54935
+ import { isDeepStrictEqual as isDeepStrictEqual4 } from "util";
54936
+ function createCodexHookDiscoveryRecovery(binding, before2, current, hooks) {
54937
+ const raw = binding.sources.filter((source) => source.path === current.file && source.hashMode === "bytes");
54938
+ if (!raw.some((source) => source.sha256 !== current.sha256))
54939
+ return;
54940
+ need4(binding.agent === "codex" && binding.method === "reviewed" && raw.length === 1 && raw[0].sha256 === before2.sha256 && before2.sha256 !== current.sha256, "RECONCILE_DISCOVERY_CONFIG_WITNESS");
54941
+ need4(raw[0].format === undefined && raw[0].fields === undefined && raw[0].managedPlugins === undefined, "RECONCILE_DISCOVERY_CONFIG_WITNESS");
54942
+ const typed = binding.sources.filter((source) => source.path === current.file && source.format === "toml");
54943
+ need4(typed.length === 1 && typed[0].hashMode === undefined && isDeepStrictEqual4(typed[0].fields, fields), "RECONCILE_DISCOVERY_TYPED_WITNESS");
54944
+ const original = structure(before2.text), actual = structure(current.text);
54945
+ const project = (value) => Object.fromEntries(fields.map((field2) => [field2, value[field2] ?? null]));
54946
+ const projection = sha(JSON.stringify(project(original)));
54947
+ need4(typed[0].sha256 === projection && sha(JSON.stringify(project(actual))) === projection && isDeepStrictEqual4(project(original), project(actual)), "RECONCILE_DISCOVERY_TYPED_WITNESS");
54948
+ 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");
54949
+ const keys2 = hooks.map((hook) => hook.key), expected = structuredClone(original);
54950
+ expected.hooks ??= {};
54951
+ expected.hooks.state ??= {};
54952
+ for (const hook of hooks)
54953
+ expected.hooks.state[hook.key] = { ...expected.hooks.state[hook.key], enabled: true, trusted_hash: hook.currentHash };
54954
+ need4(isDeepStrictEqual4(expected, actual) && codexTrustReconcileWitness(before2.text, keys2) === codexTrustReconcileWitness(current.text, keys2) && codexTrustUnmanagedSemantic(before2.text, keys2) === codexTrustUnmanagedSemantic(current.text, keys2), "RECONCILE_DISCOVERY_TRUST_WITNESS");
54955
+ unchanged2(before2);
54956
+ unchanged2(current);
54957
+ const witness = Object.freeze({ configPath: current.file, beforeSha256: before2.sha256, currentSha256: current.sha256, discoverySha256: sha(JSON.stringify(binding)), typedProjectionSha256: projection });
54958
+ proofs.set(witness, { before: before2, current });
54959
+ return witness;
54960
+ }
54961
+ function assertCodexHookDiscoveryRecovery(binding, witness) {
54962
+ const proof = proofs.get(witness);
54963
+ need4(!!proof && binding.agent === "codex" && witness.discoverySha256 === sha(JSON.stringify(binding)), "RECONCILE_DISCOVERY_RECOVERY_CHANGED");
54964
+ unchanged2(proof.before);
54965
+ unchanged2(proof.current);
54966
+ }
54967
+ function verifiesCodexHookDiscoverySource(binding, source, currentDigest, witness) {
54968
+ if (!witness || source.path !== witness.configPath || source.hashMode !== "bytes")
54969
+ return false;
54970
+ assertCodexHookDiscoveryRecovery(binding, witness);
54971
+ need4(source.sha256 === witness.beforeSha256 && currentDigest === witness.currentSha256, "RECONCILE_DISCOVERY_RECOVERY_CHANGED");
54972
+ return true;
54973
+ }
54974
+ var sha = (text2) => createHash14("sha256").update(text2).digest("hex"), fields, structure = (text2) => JSON.parse(JSON.stringify(Bun.TOML.parse(text2))), proofs;
54975
+ var init_codex_hook_discovery_recovery = __esm(() => {
54976
+ init_codex_hook_trust_files();
54977
+ init_codex_hook_trust_layout();
54978
+ fields = ["plugins", "marketplaces", "skills"];
54979
+ proofs = new WeakMap;
54980
+ });
54981
+
54982
+ // src/lib/agent-discovery.ts
54983
+ import { createHash as createHash15 } from "crypto";
54984
+ import { lstatSync as lstatSync18, readFileSync as readFileSync14, readdirSync as readdirSync9, realpathSync as realpathSync4 } from "fs";
54985
+ import { basename as basename8, dirname as dirname15, isAbsolute as isAbsolute14, join as join28, resolve as resolve15, sep as sep5 } from "path";
54744
54986
  function parseConfig(text2, path, toml = false) {
54745
54987
  try {
54746
54988
  const value = toml ? Bun.TOML.parse(text2) : JSON.parse(text2);
@@ -54754,10 +54996,10 @@ function parseConfig(text2, path, toml = false) {
54754
54996
  function safe4(path) {
54755
54997
  if (!isAbsolute14(path) || path.includes("\x00"))
54756
54998
  throw new Error("Expected an absolute native discovery path");
54757
- for (let cursor = path;; cursor = dirname14(cursor)) {
54758
- if (lstatSync17(cursor, { throwIfNoEntry: false })?.isSymbolicLink())
54999
+ for (let cursor = path;; cursor = dirname15(cursor)) {
55000
+ if (lstatSync18(cursor, { throwIfNoEntry: false })?.isSymbolicLink())
54759
55001
  throw new Error(`Refusing symlink native discovery input: ${cursor}`);
54760
- if (dirname14(cursor) === cursor)
55002
+ if (dirname15(cursor) === cursor)
54761
55003
  break;
54762
55004
  }
54763
55005
  }
@@ -54765,7 +55007,7 @@ function read2(path, changes) {
54765
55007
  safe4(path);
54766
55008
  if (changes?.has(path))
54767
55009
  return changes.get(path);
54768
- const stat2 = lstatSync17(path, { throwIfNoEntry: false });
55010
+ const stat2 = lstatSync18(path, { throwIfNoEntry: false });
54769
55011
  if (!stat2)
54770
55012
  return null;
54771
55013
  if (!stat2.isFile() || stat2.size > 16 * 1024 * 1024)
@@ -54815,7 +55057,9 @@ function projected(source, changes, budget = discoveryByteBudget()) {
54815
55057
  throw new Error("Expected native discovery configuration object");
54816
55058
  return digest(JSON.stringify(Object.fromEntries((source.fields ?? []).map((field2) => [field2, object4[field2] ?? null]))));
54817
55059
  }
54818
- function verifyAgentDiscovery(binding) {
55060
+ function verifyAgentDiscovery(binding, codexRecovery) {
55061
+ if (codexRecovery)
55062
+ assertCodexHookDiscoveryRecovery(binding, codexRecovery);
54819
55063
  if (!binding || !Array.isArray(binding.sources) || !Array.isArray(binding.roots) || binding.sources.length > AGENT_POLICY_LIMITS.discoverySources || binding.roots.length > AGENT_POLICY_LIMITS.discoveryRoots)
54820
55064
  throw new Error("Invalid native discovery binding");
54821
55065
  if (binding.agent === "hermes" && !binding.directories?.length)
@@ -54831,7 +55075,8 @@ function verifyAgentDiscovery(binding) {
54831
55075
  throw new Error("Invalid native discovery projection");
54832
55076
  if (source.sha256 !== null && !/^[a-f0-9]{64}$/.test(source.sha256))
54833
55077
  throw new Error("Invalid native discovery digest");
54834
- if (projected(source, undefined, budget) !== source.sha256)
55078
+ const current = projected(source, undefined, budget);
55079
+ if (current !== source.sha256 && !verifiesCodexHookDiscoverySource(binding, source, current, codexRecovery))
54835
55080
  throw new Error(`Native discovery input changed; run skills hook install with a fresh discovery review: ${source.path}`);
54836
55081
  }
54837
55082
  for (const root2 of binding.roots)
@@ -54883,7 +55128,7 @@ function assertProjectDiscovery(agent, directories, home, canonical4 = resolve15
54883
55128
  if (agent === "claude") {
54884
55129
  const commands = canonical4(join28(directory, ".claude/commands"));
54885
55130
  safe4(commands);
54886
- if (lstatSync17(commands, { throwIfNoEntry: false })?.isDirectory() && readdirSync9(commands).length)
55131
+ if (lstatSync18(commands, { throwIfNoEntry: false })?.isDirectory() && readdirSync9(commands).length)
54887
55132
  throw new Error("NATIVE_SKILL_DRIFT: legacy project command discovery requires a dedicated format adapter");
54888
55133
  }
54889
55134
  }
@@ -54891,8 +55136,8 @@ function assertProjectDiscovery(agent, directories, home, canonical4 = resolve15
54891
55136
  function resolveAgentDiscovery(options) {
54892
55137
  const canonical4 = options.canonical ?? resolve15, home = resolve15(options.home), agent = options.agent;
54893
55138
  const sources = [], roots = new Set, builtinNames = [];
54894
- const witness = (path, format, fields) => {
54895
- const source = { path: canonical4(path), sha256: null, ...format ? { format, fields } : {} };
55139
+ const witness = (path, format, fields2) => {
55140
+ const source = { path: canonical4(path), sha256: null, ...format ? { format, fields: fields2 } : {} };
54896
55141
  source.sha256 = projected(source);
54897
55142
  sources.push(source);
54898
55143
  return read2(source.path);
@@ -54929,21 +55174,21 @@ function resolveAgentDiscovery(options) {
54929
55174
  const executable = Bun.which("gemini");
54930
55175
  if (executable) {
54931
55176
  let packageRoot;
54932
- for (let directory = dirname14(realpathSync4(executable)), depth = 0;depth < 8; directory = dirname14(directory), depth++) {
55177
+ for (let directory = dirname15(realpathSync4(executable)), depth = 0;depth < 8; directory = dirname15(directory), depth++) {
54933
55178
  const path = join28(directory, "package.json"), raw = read2(path);
54934
55179
  if (raw !== null && parseConfig(raw, path).name === "@google/gemini-cli") {
54935
55180
  packageRoot = directory;
54936
55181
  witness(path);
54937
55182
  break;
54938
55183
  }
54939
- if (dirname14(directory) === directory)
55184
+ if (dirname15(directory) === directory)
54940
55185
  break;
54941
55186
  }
54942
55187
  if (!packageRoot)
54943
55188
  unresolved("installed Gemini package layout is not recognized");
54944
55189
  const builtinRoot = join28(packageRoot, "bundle/builtin");
54945
55190
  safe4(builtinRoot);
54946
- if (!lstatSync17(builtinRoot, { throwIfNoEntry: false })?.isDirectory())
55191
+ if (!lstatSync18(builtinRoot, { throwIfNoEntry: false })?.isDirectory())
54947
55192
  unresolved("installed Gemini builtin root is missing");
54948
55193
  for (const name of readdirSync9(builtinRoot).sort()) {
54949
55194
  const text2 = witness(join28(builtinRoot, name, "SKILL.md"));
@@ -54983,7 +55228,7 @@ function resolveAgentDiscovery(options) {
54983
55228
  unresolved("plugin hooks require a separate no-skill-injection review");
54984
55229
  const commands = join28(root2, "commands");
54985
55230
  safe4(commands);
54986
- if (agent === "claude" && (manifest.commands !== undefined || lstatSync17(commands, { throwIfNoEntry: false })?.isDirectory() && readdirSync9(commands).length))
55231
+ if (agent === "claude" && (manifest.commands !== undefined || lstatSync18(commands, { throwIfNoEntry: false })?.isDirectory() && readdirSync9(commands).length))
54987
55232
  unresolved("legacy command discovery requires retirement or a dedicated format adapter");
54988
55233
  const rootSkill = witness(join28(root2, "SKILL.md"));
54989
55234
  if (rootSkill !== null)
@@ -54997,7 +55242,7 @@ function resolveAgentDiscovery(options) {
54997
55242
  const path = resolve15(root2, value);
54998
55243
  if (path !== root2 && !path.startsWith(root2 + sep5))
54999
55244
  unresolved("plugin skill path escapes its root");
55000
- roots.add(path.endsWith(`${sep5}SKILL.md`) ? dirname14(path) : path);
55245
+ roots.add(path.endsWith(`${sep5}SKILL.md`) ? dirname15(path) : path);
55001
55246
  }
55002
55247
  }
55003
55248
  if (agent === "claude") {
@@ -55005,7 +55250,7 @@ function resolveAgentDiscovery(options) {
55005
55250
  const installed = registrations === null ? {} : parseConfig(registrations, join28(home, ".claude/plugins/installed_plugins.json")).plugins;
55006
55251
  const commands = canonical4(join28(home, ".claude/commands"));
55007
55252
  safe4(commands);
55008
- if (lstatSync17(commands, { throwIfNoEntry: false })?.isDirectory() && readdirSync9(commands).length)
55253
+ if (lstatSync18(commands, { throwIfNoEntry: false })?.isDirectory() && readdirSync9(commands).length)
55009
55254
  unresolved("legacy home command discovery requires a dedicated format adapter");
55010
55255
  for (const [id, enabled] of Object.entries(config.enabledPlugins ?? {})) {
55011
55256
  if (enabled === false)
@@ -55047,12 +55292,12 @@ function resolveAgentDiscovery(options) {
55047
55292
  }
55048
55293
  const localPlugins = join28(home, ".config/opencode/plugins");
55049
55294
  safe4(localPlugins);
55050
- if (lstatSync17(localPlugins, { throwIfNoEntry: false }) && readdirSync9(localPlugins).some((name) => name !== "skills-cli.js"))
55295
+ if (lstatSync18(localPlugins, { throwIfNoEntry: false }) && readdirSync9(localPlugins).some((name) => name !== "skills-cli.js"))
55051
55296
  unresolved("additional local plugin hooks require review");
55052
55297
  } else if (agent === "hermes") {
55053
55298
  for (const directory of [join28(home, ".hermes/plugins"), join28(home, ".hermes/hermes-agent")]) {
55054
55299
  safe4(directory);
55055
- if (lstatSync17(directory, { throwIfNoEntry: false }))
55300
+ if (lstatSync18(directory, { throwIfNoEntry: false }))
55056
55301
  unresolved("installed runtime/plugin discovery requires reviewed source bindings");
55057
55302
  }
55058
55303
  if (Bun.which("hermes") || Object.keys(config.plugins ?? {}).length)
@@ -55062,11 +55307,11 @@ function resolveAgentDiscovery(options) {
55062
55307
  unresolved("custom extension or skill paths");
55063
55308
  const directory = join28(home, ".gemini/extensions");
55064
55309
  safe4(directory);
55065
- if (lstatSync17(directory, { throwIfNoEntry: false }))
55310
+ if (lstatSync18(directory, { throwIfNoEntry: false }))
55066
55311
  for (const name of readdirSync9(directory)) {
55067
55312
  const root2 = join28(directory, name);
55068
55313
  safe4(root2);
55069
- if (!lstatSync17(root2)?.isDirectory())
55314
+ if (!lstatSync18(root2)?.isDirectory())
55070
55315
  continue;
55071
55316
  const raw = witness(join28(root2, "gemini-extension.json"));
55072
55317
  if (raw === null)
@@ -55079,7 +55324,7 @@ function resolveAgentDiscovery(options) {
55079
55324
  }
55080
55325
  return { agent, roots: [...roots].sort(), sources, method: "automatic", ...agent === "gemini" ? { builtinNames } : {}, ...agent === "hermes" ? { directories: captureDiscoveryDirectories([join28(home, ".hermes/plugins"), join28(home, ".hermes/hermes-agent")].map((path) => canonical4(path))) } : {} };
55081
55326
  }
55082
- var digest = (text2) => createHash13("sha256").update(text2).digest("hex");
55327
+ var digest = (text2) => createHash15("sha256").update(text2).digest("hex");
55083
55328
  var init_agent_discovery = __esm(() => {
55084
55329
  init_agent_policy_limits();
55085
55330
  init_agent_hermes();
@@ -55090,6 +55335,7 @@ var init_agent_discovery = __esm(() => {
55090
55335
  init_plugin_admission();
55091
55336
  init_claude_marketplace_registry();
55092
55337
  init_claude_settings_witness();
55338
+ init_codex_hook_discovery_recovery();
55093
55339
  init_agent_discovery_directories();
55094
55340
  });
55095
55341
 
@@ -55174,7 +55420,7 @@ var init_agent_adapters = __esm(() => {
55174
55420
  });
55175
55421
 
55176
55422
  // src/lib/agent-codex.ts
55177
- import { isDeepStrictEqual as isDeepStrictEqual3 } from "util";
55423
+ import { isDeepStrictEqual as isDeepStrictEqual5 } from "util";
55178
55424
  function assertCodexPathConfigEditable(text2) {
55179
55425
  const before2 = Bun.TOML.parse(text2);
55180
55426
  if (before2.skills?.config === undefined)
@@ -55183,7 +55429,7 @@ function assertCodexPathConfigEditable(text2) {
55183
55429
  delete expected.skills.config;
55184
55430
  try {
55185
55431
  const withoutSections = Bun.TOML.parse(text2.replace(CODEX_SKILL_CONFIG_SECTIONS, ""));
55186
- if (isDeepStrictEqual3(withoutSections, expected))
55432
+ if (isDeepStrictEqual5(withoutSections, expected))
55187
55433
  return;
55188
55434
  } catch {}
55189
55435
  throw new Error("Codex skill path controls require ordinary [[skills.config]] TOML tables; preserve and convert inline or dotted config arrays before running skills hook install");
@@ -55221,7 +55467,7 @@ function disableCodexBundledSkills(text2) {
55221
55467
  const candidates = new Set;
55222
55468
  const consider = (candidate2) => {
55223
55469
  try {
55224
- if (isDeepStrictEqual3(Bun.TOML.parse(candidate2), expected))
55470
+ if (isDeepStrictEqual5(Bun.TOML.parse(candidate2), expected))
55225
55471
  candidates.add(candidate2);
55226
55472
  } catch {}
55227
55473
  };
@@ -55251,16 +55497,16 @@ var init_agent_codex = __esm(() => {
55251
55497
  });
55252
55498
 
55253
55499
  // src/lib/agent-integration.ts
55254
- import { createHash as createHash14, randomUUID as randomUUID6 } from "crypto";
55255
- import { existsSync as existsSync15, lstatSync as lstatSync18, statSync as statSync8, mkdirSync as mkdirSync7, readFileSync as readFileSync15, readdirSync as readdirSync10, opendirSync as opendirSync5, readlinkSync as readlinkSync2, realpathSync as realpathSync5, renameSync as renameSync4, rmdirSync as rmdirSync3, writeFileSync as writeFileSync5, unlinkSync as unlinkSync4, chmodSync, openSync as openSync11, closeSync as closeSync11, fsyncSync as fsyncSync3, fstatSync as fstatSync11, readSync as readSync9, constants as constants11, linkSync as linkSync2 } from "fs";
55256
- import { dirname as dirname15, join as join29, resolve as resolve16, relative as relative5, isAbsolute as isAbsolute15, sep as sep6 } from "path";
55500
+ import { createHash as createHash16, randomUUID as randomUUID6 } from "crypto";
55501
+ import { existsSync as existsSync15, lstatSync as lstatSync19, statSync as statSync8, mkdirSync as mkdirSync7, readFileSync as readFileSync15, readdirSync as readdirSync10, opendirSync as opendirSync5, readlinkSync as readlinkSync2, realpathSync as realpathSync5, renameSync as renameSync4, rmdirSync as rmdirSync3, writeFileSync as writeFileSync6, unlinkSync as unlinkSync4, chmodSync, openSync as openSync12, closeSync as closeSync12, fsyncSync as fsyncSync4, fstatSync as fstatSync12, readSync as readSync10, constants as constants12, linkSync as linkSync2 } from "fs";
55502
+ import { dirname as dirname16, join as join29, resolve as resolve16, relative as relative5, isAbsolute as isAbsolute15, sep as sep6 } from "path";
55257
55503
  import { homedir as homedir4 } from "os";
55258
55504
  function assertSafePath(path) {
55259
55505
  let cursor = resolve16(path);
55260
55506
  while (true) {
55261
- if (lstatSync18(cursor, { throwIfNoEntry: false })?.isSymbolicLink())
55507
+ if (lstatSync19(cursor, { throwIfNoEntry: false })?.isSymbolicLink())
55262
55508
  throw new Error(`Refusing symlink path: ${cursor}`);
55263
- const parent = dirname15(cursor);
55509
+ const parent = dirname16(cursor);
55264
55510
  if (parent === cursor)
55265
55511
  return;
55266
55512
  cursor = parent;
@@ -55269,12 +55515,12 @@ function assertSafePath(path) {
55269
55515
  function readRootAlias(home, agent) {
55270
55516
  assertSafePath(home);
55271
55517
  const realHome = realpathSync5(home), alias = join29(realHome, `.${agent}`);
55272
- const stat2 = lstatSync18(alias, { throwIfNoEntry: false, bigint: true });
55518
+ const stat2 = lstatSync19(alias, { throwIfNoEntry: false, bigint: true });
55273
55519
  if (!stat2?.isSymbolicLink())
55274
55520
  throw new Error(`Agent root alias changed after planning: ${alias}`);
55275
- const link2 = readlinkSync2(alias), targetPath = resolve16(dirname15(alias), link2);
55521
+ const link2 = readlinkSync2(alias), targetPath = resolve16(dirname16(alias), link2);
55276
55522
  assertSafePath(targetPath);
55277
- const targetStat = lstatSync18(targetPath, { throwIfNoEntry: false });
55523
+ const targetStat = lstatSync19(targetPath, { throwIfNoEntry: false });
55278
55524
  if (!targetStat?.isDirectory())
55279
55525
  throw new Error(`Agent root alias must target an existing directory: ${alias}`);
55280
55526
  const target = realpathSync5(targetPath), inside = relative5(realHome, target);
@@ -55287,7 +55533,7 @@ function rootAliases(home, allowed = false) {
55287
55533
  return [];
55288
55534
  const result2 = [];
55289
55535
  for (const agent of ["claude", "codex"])
55290
- if (lstatSync18(join29(home, `.${agent}`), { throwIfNoEntry: false })?.isSymbolicLink())
55536
+ if (lstatSync19(join29(home, `.${agent}`), { throwIfNoEntry: false })?.isSymbolicLink())
55291
55537
  result2.push(readRootAlias(home, agent));
55292
55538
  if (result2.some((item, index) => result2.slice(index + 1).some((other) => item.target === other.target || item.target.startsWith(other.target + sep6) || other.target.startsWith(item.target + sep6))))
55293
55539
  throw new Error("Agent root alias targets must not overlap");
@@ -55308,35 +55554,35 @@ function recheckRootAliases(aliases) {
55308
55554
  }
55309
55555
  function readNativeBytes(path, maximum = 64 * 1024 * 1024) {
55310
55556
  assertSafePath(path);
55311
- const before2 = lstatSync18(path);
55557
+ const before2 = lstatSync19(path);
55312
55558
  if (!before2.isFile() || before2.size > maximum)
55313
55559
  throw new Error("Unsupported or oversized native skill file");
55314
- const descriptor = openSync11(path, constants11.O_RDONLY | constants11.O_NOFOLLOW | constants11.O_NONBLOCK);
55560
+ const descriptor = openSync12(path, constants12.O_RDONLY | constants12.O_NOFOLLOW | constants12.O_NONBLOCK);
55315
55561
  try {
55316
- const opened = fstatSync11(descriptor);
55562
+ const opened = fstatSync12(descriptor);
55317
55563
  if (!opened.isFile() || opened.dev !== before2.dev || opened.ino !== before2.ino || opened.size !== before2.size)
55318
55564
  throw new Error("Native skill file changed while reading");
55319
55565
  const bytes = Buffer.allocUnsafe(before2.size + 1);
55320
55566
  let length = 0;
55321
55567
  while (length < bytes.length) {
55322
- const count = readSync9(descriptor, bytes, length, bytes.length - length, null);
55568
+ const count = readSync10(descriptor, bytes, length, bytes.length - length, null);
55323
55569
  if (!count)
55324
55570
  break;
55325
55571
  length += count;
55326
55572
  }
55327
- const after2 = fstatSync11(descriptor);
55573
+ const after2 = fstatSync12(descriptor);
55328
55574
  if (length !== before2.size || after2.size !== before2.size || after2.mtimeMs !== opened.mtimeMs || after2.ctimeMs !== opened.ctimeMs)
55329
55575
  throw new Error("Native skill file changed while reading");
55330
55576
  return bytes.subarray(0, length);
55331
55577
  } finally {
55332
- closeSync11(descriptor);
55578
+ closeSync12(descriptor);
55333
55579
  }
55334
55580
  }
55335
55581
  function treeHash(root2) {
55336
- const hash2 = createHash14("sha256");
55582
+ const hash2 = createHash16("sha256");
55337
55583
  let bytes = 0, files = 0;
55338
55584
  function visit2(path) {
55339
- const stat2 = lstatSync18(path);
55585
+ const stat2 = lstatSync19(path);
55340
55586
  if (stat2.isSymbolicLink())
55341
55587
  throw new Error(`Refusing symlink in skill: ${path}`);
55342
55588
  const rel = relative5(root2, path);
@@ -55360,7 +55606,7 @@ function treeHash(root2) {
55360
55606
  return hash2.digest("hex");
55361
55607
  }
55362
55608
  function parseNativeMigrationTargetManifest(input) {
55363
- const digest2 = sha(input);
55609
+ const digest2 = sha2(input);
55364
55610
  let value;
55365
55611
  try {
55366
55612
  value = JSON.parse(input.toString());
@@ -55385,7 +55631,7 @@ function parseNativeMigrationTargetManifest(input) {
55385
55631
  if (!INTEGRATION_AGENTS.includes(item.agent))
55386
55632
  throw new Error(`Unsupported native migration target agent: ${item.agent}`);
55387
55633
  const projectRoot = resolve16(item.projectRoot);
55388
- if (!isAbsolute15(item.projectRoot) || projectRoot !== item.projectRoot || !existsSync15(projectRoot) || !lstatSync18(projectRoot).isDirectory())
55634
+ if (!isAbsolute15(item.projectRoot) || projectRoot !== item.projectRoot || !existsSync15(projectRoot) || !lstatSync19(projectRoot).isDirectory())
55389
55635
  throw new Error(`Native migration target project root must be an existing absolute directory: ${item.projectRoot}`);
55390
55636
  assertSafePath(projectRoot);
55391
55637
  if (isAbsolute15(item.path) || item.path.includes("\\") || item.path.length === 0 || item.path.includes("\x00"))
@@ -55413,7 +55659,7 @@ function selectNativeMigrationTargets(inventory, manifest) {
55413
55659
  const selected = [];
55414
55660
  for (const target of manifest.targets) {
55415
55661
  const projectRoot = resolve16(target.projectRoot), normalized = relative5(projectRoot, resolve16(projectRoot, target.path));
55416
- if (!isAbsolute15(target.projectRoot) || projectRoot !== target.projectRoot || !existsSync15(projectRoot) || !lstatSync18(projectRoot).isDirectory())
55662
+ if (!isAbsolute15(target.projectRoot) || projectRoot !== target.projectRoot || !existsSync15(projectRoot) || !lstatSync19(projectRoot).isDirectory())
55417
55663
  throw new Error(`Native migration target project root must be an existing absolute directory: ${target.projectRoot}`);
55418
55664
  assertSafePath(projectRoot);
55419
55665
  if (isAbsolute15(target.path) || target.path.includes("\\") || target.path.includes("\x00") || !normalized || normalized === ".." || normalized.startsWith(`..${sep6}`) || normalized !== target.path || !/^[0-9a-f]{64}$/.test(target.treeSha256))
@@ -55442,7 +55688,7 @@ function projectAncestorDirectories(projects) {
55442
55688
  if (depth >= 100)
55443
55689
  throw new Error("NATIVE_SKILL_DRIFT: project ancestor discovery limit exceeded");
55444
55690
  directories.add(path);
55445
- const parent = dirname15(path);
55691
+ const parent = dirname16(path);
55446
55692
  if (parent === path)
55447
55693
  break;
55448
55694
  path = parent;
@@ -55473,9 +55719,9 @@ function inventoryNativeSkills(home = homedir4(), options = {}) {
55473
55719
  }
55474
55720
  function emptySiblingCacheAlias(path, parent) {
55475
55721
  const link2 = readlinkSync2(path), target = resolve16(parent, link2);
55476
- if (dirname15(target) !== parent || (isAbsolute15(link2) ? link2 !== target : dirname15(link2) !== "."))
55722
+ if (dirname16(target) !== parent || (isAbsolute15(link2) ? link2 !== target : dirname16(link2) !== "."))
55477
55723
  return false;
55478
- if (!lstatSync18(target, { throwIfNoEntry: false })?.isDirectory())
55724
+ if (!lstatSync19(target, { throwIfNoEntry: false })?.isDirectory())
55479
55725
  return false;
55480
55726
  const scan = cacheScans.get(target);
55481
55727
  return Boolean(scan?.complete && !scan.hasSkills && scan.entries <= maxAliasProofEntries);
@@ -55487,7 +55733,7 @@ function inventoryNativeSkills(home = homedir4(), options = {}) {
55487
55733
  assertSafePath(path);
55488
55734
  if (!existsSync15(path))
55489
55735
  return scan;
55490
- const stat2 = lstatSync18(path);
55736
+ const stat2 = lstatSync19(path);
55491
55737
  if (stat2.isFile())
55492
55738
  return scan;
55493
55739
  if (!stat2.isDirectory())
@@ -55533,7 +55779,7 @@ function inventoryNativeSkills(home = homedir4(), options = {}) {
55533
55779
  if (isVendor && !options.includeVendor)
55534
55780
  continue;
55535
55781
  const child = join29(path, name);
55536
- if (isVendor && lstatSync18(child, { throwIfNoEntry: false })?.isSymbolicLink()) {
55782
+ if (isVendor && lstatSync19(child, { throwIfNoEntry: false })?.isSymbolicLink()) {
55537
55783
  const target = statSync8(child, { throwIfNoEntry: false });
55538
55784
  if (target?.isFile() || pluginCache && target?.isDirectory() && emptySiblingCacheAlias(child, path)) {
55539
55785
  scan.entries++;
@@ -55743,7 +55989,7 @@ function planAgentIntegration(options) {
55743
55989
  throw new Error("Refusing to overwrite an unrecognized Hermes supervisor");
55744
55990
  if (supervisorBefore !== supervisorAfter)
55745
55991
  changes.push({ path: supervisorPath, before: supervisorBefore, after: supervisorAfter });
55746
- const supervisor = { path: supervisorPath, runtime: process.execPath, sha256: sha(supervisorAfter) };
55992
+ const supervisor = { path: supervisorPath, runtime: process.execPath, sha256: sha2(supervisorAfter) };
55747
55993
  const after3 = configureHermesHooks(before2, supervisor, previous);
55748
55994
  if (before2 !== after3)
55749
55995
  changes.push({ path, before: before2, after: after3 });
@@ -55790,7 +56036,7 @@ function planAgentIntegration(options) {
55790
56036
  agents: [...new Set([...priorAgents, ...options.agents])].sort(),
55791
56037
  home: resolve16(home),
55792
56038
  includeVendor: true,
55793
- ...options.agents.includes("hermes") ? { supervisors: { ...policy.bridge?.supervisors, hermes: { path: join29(dataDir3, "agent-hooks", "hermes.js"), runtime: process.execPath, sha256: sha(renderHermesSupervisor(bindings.get("hermes").command, bindings.get("hermes").profileId)) } } } : {},
56039
+ ...options.agents.includes("hermes") ? { supervisors: { ...policy.bridge?.supervisors, hermes: { path: join29(dataDir3, "agent-hooks", "hermes.js"), runtime: process.execPath, sha256: sha2(renderHermesSupervisor(bindings.get("hermes").command, bindings.get("hermes").profileId)) } } } : {},
55794
56040
  commands: { ...policy.bridge?.commands, ...Object.fromEntries([...bindings].map(([agent, binding]) => [agent, binding.command])) },
55795
56041
  profiles: Object.fromEntries([...new Set([...priorAgents, ...options.agents])].sort().map((agent) => [agent, bindings.get(agent)?.profileId ?? policy.bridge?.profiles?.[agent] ?? policy.profileId])),
55796
56042
  disabledBuiltins: options.agents.includes("codex") ? nativeSkills.filter((entry) => entry.agent === "codex" && entry.vendor && entry.path.startsWith(canonicalAgentPath(join29(home, ".codex", "skills", ".system"), aliases) + sep6)).map((entry) => ({ path: entry.path, hash: entry.hash })) : policy.bridge?.disabledBuiltins ?? [],
@@ -55805,10 +56051,10 @@ function planAgentIntegration(options) {
55805
56051
  }
55806
56052
  function atomicWrite2(path, content) {
55807
56053
  assertSafePath(path);
55808
- mkdirSync7(dirname15(path), { recursive: true, mode: 448 });
56054
+ mkdirSync7(dirname16(path), { recursive: true, mode: 448 });
55809
56055
  const temporary = `${path}.skills-${randomUUID6()}`;
55810
56056
  try {
55811
- writeFileSync5(temporary, content, { mode: 384, flag: "wx" });
56057
+ writeFileSync6(temporary, content, { mode: 384, flag: "wx" });
55812
56058
  renameSync4(temporary, path);
55813
56059
  } finally {
55814
56060
  if (existsSync15(temporary))
@@ -55842,8 +56088,8 @@ function applyAgentIntegration(plan) {
55842
56088
  chmodSync(backupRoot, 448);
55843
56089
  for (const [index, change] of plan.changes.entries())
55844
56090
  if (change.before !== null) {
55845
- const backup = join29(backupRoot, `${index}-${sha(change.path).slice(0, 12)}.backup`);
55846
- writeFileSync5(backup, change.before, { mode: 384, flag: "wx" });
56091
+ const backup = join29(backupRoot, `${index}-${sha2(change.path).slice(0, 12)}.backup`);
56092
+ writeFileSync6(backup, change.before, { mode: 384, flag: "wx" });
55847
56093
  backups.push(backup);
55848
56094
  }
55849
56095
  try {
@@ -55851,7 +56097,7 @@ function applyAgentIntegration(plan) {
55851
56097
  recheckRootAliases(aliases);
55852
56098
  if (currentText(change.path) !== change.before)
55853
56099
  throw new Error(`Configuration changed after planning: ${change.path}`);
55854
- for (let directory = dirname15(change.path);!existsSync15(directory); directory = dirname15(directory))
56100
+ for (let directory = dirname16(change.path);!existsSync15(directory); directory = dirname16(directory))
55855
56101
  createdDirectories.add(directory);
55856
56102
  const after2 = change.after;
55857
56103
  atomicWrite2(change.path, after2);
@@ -55860,7 +56106,7 @@ function applyAgentIntegration(plan) {
55860
56106
  recheckRootAliases(aliases);
55861
56107
  for (const binding of plan.discoveryAfter ?? [])
55862
56108
  verifyAgentDiscovery(binding);
55863
- atomicWrite2(join29(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 } : {} }) + `
56109
+ atomicWrite2(join29(backupRoot, "receipt.json"), JSON.stringify({ version: 1, changes: written.map((change) => ({ path: change.path, beforeHash: change.before === null ? null : sha2(change.before), afterHash: sha2(change.after) })), backups, ...aliases.length ? { rootAliases: aliases } : {} }) + `
55864
56110
  `);
55865
56111
  } catch (error) {
55866
56112
  for (const change of written.reverse()) {
@@ -55891,11 +56137,11 @@ function applyAgentIntegration(plan) {
55891
56137
  }
55892
56138
  function syncArchiveDirectory(path) {
55893
56139
  assertSafePath(path);
55894
- const descriptor = openSync11(path, constants11.O_RDONLY | constants11.O_DIRECTORY | constants11.O_NOFOLLOW | constants11.O_NONBLOCK);
56140
+ const descriptor = openSync12(path, constants12.O_RDONLY | constants12.O_DIRECTORY | constants12.O_NOFOLLOW | constants12.O_NONBLOCK);
55895
56141
  try {
55896
- fsyncSync3(descriptor);
56142
+ fsyncSync4(descriptor);
55897
56143
  } finally {
55898
- closeSync11(descriptor);
56144
+ closeSync12(descriptor);
55899
56145
  }
55900
56146
  }
55901
56147
  function writeArchiveJournal(path, value) {
@@ -55903,18 +56149,18 @@ function writeArchiveJournal(path, value) {
55903
56149
  const temporary = `${path}.skills-${randomUUID6()}`;
55904
56150
  let descriptor;
55905
56151
  try {
55906
- descriptor = openSync11(temporary, constants11.O_WRONLY | constants11.O_CREAT | constants11.O_EXCL | constants11.O_NOFOLLOW, 384);
55907
- writeFileSync5(descriptor, `${JSON.stringify(value)}
56152
+ descriptor = openSync12(temporary, constants12.O_WRONLY | constants12.O_CREAT | constants12.O_EXCL | constants12.O_NOFOLLOW, 384);
56153
+ writeFileSync6(descriptor, `${JSON.stringify(value)}
55908
56154
  `);
55909
- fsyncSync3(descriptor);
55910
- closeSync11(descriptor);
56155
+ fsyncSync4(descriptor);
56156
+ closeSync12(descriptor);
55911
56157
  descriptor = undefined;
55912
56158
  renameSync4(temporary, path);
55913
- syncArchiveDirectory(dirname15(path));
56159
+ syncArchiveDirectory(dirname16(path));
55914
56160
  } finally {
55915
56161
  if (descriptor !== undefined)
55916
- closeSync11(descriptor);
55917
- if (lstatSync18(temporary, { throwIfNoEntry: false }))
56162
+ closeSync12(descriptor);
56163
+ if (lstatSync19(temporary, { throwIfNoEntry: false }))
55918
56164
  unlinkSync4(temporary);
55919
56165
  }
55920
56166
  }
@@ -55939,8 +56185,8 @@ function archiveNativeSkills(inventory, options) {
55939
56185
  const operationId = randomUUID6(), archiveRoot = join29(options.dataDir ?? getDataDir(), "migration", operationId, "native"), receiptPath = join29(archiveRoot, "receipt.json");
55940
56186
  const entries = selected.map((entry, index) => ({
55941
56187
  source: entry.vendor ? join29(entry.path, "SKILL.md") : entry.path,
55942
- archive: join29(archiveRoot, `${index}-${sha(entry.path).slice(0, 12)}`),
55943
- hash: entry.vendor ? sha(readNativeBytes(join29(entry.path, "SKILL.md"))) : entry.hash,
56188
+ archive: join29(archiveRoot, `${index}-${sha2(entry.path).slice(0, 12)}`),
56189
+ hash: entry.vendor ? sha2(readNativeBytes(join29(entry.path, "SKILL.md"))) : entry.hash,
55944
56190
  ...entry.vendor ? { discoveryOnly: true } : {},
55945
56191
  status: "planned"
55946
56192
  }));
@@ -55948,22 +56194,22 @@ function archiveNativeSkills(inventory, options) {
55948
56194
  const moved = [];
55949
56195
  const verifyArchive = (entry) => {
55950
56196
  assertSafePath(entry.archive);
55951
- const stat2 = lstatSync18(entry.archive);
56197
+ const stat2 = lstatSync19(entry.archive);
55952
56198
  if (entry.discoveryOnly ? !stat2.isFile() : !stat2.isDirectory())
55953
56199
  throw new Error("Archive type changed");
55954
- if ((entry.discoveryOnly ? sha(readNativeBytes(entry.archive)) : treeHash(entry.archive)) !== entry.hash)
56200
+ if ((entry.discoveryOnly ? sha2(readNativeBytes(entry.archive)) : treeHash(entry.archive)) !== entry.hash)
55955
56201
  throw new Error("Archive bytes changed");
55956
56202
  };
55957
56203
  assertSafePath(archiveRoot);
55958
56204
  const created = [];
55959
- for (let path = archiveRoot;!existsSync15(path); path = dirname15(path))
56205
+ for (let path = archiveRoot;!existsSync15(path); path = dirname16(path))
55960
56206
  created.push(path);
55961
56207
  mkdirSync7(archiveRoot, { recursive: true, mode: 448 });
55962
56208
  try {
55963
56209
  for (const directory of created)
55964
56210
  syncArchiveDirectory(directory);
55965
56211
  if (created.length)
55966
- syncArchiveDirectory(dirname15(created.at(-1)));
56212
+ syncArchiveDirectory(dirname16(created.at(-1)));
55967
56213
  writeArchiveJournal(receiptPath, journal);
55968
56214
  for (const [index, entry] of selected.entries()) {
55969
56215
  recheckRootAliases(aliases);
@@ -55975,7 +56221,7 @@ function archiveNativeSkills(inventory, options) {
55975
56221
  writeArchiveJournal(receiptPath, journal);
55976
56222
  renameSync4(move.source, move.archive);
55977
56223
  moved.push(move);
55978
- syncArchiveDirectory(dirname15(move.source));
56224
+ syncArchiveDirectory(dirname16(move.source));
55979
56225
  syncArchiveDirectory(archiveRoot);
55980
56226
  verifyArchive(move);
55981
56227
  move.status = "archived";
@@ -55996,7 +56242,7 @@ function archiveNativeSkills(inventory, options) {
55996
56242
  recheckRootAliases(aliases);
55997
56243
  assertSafePath(entry.source);
55998
56244
  assertSafePath(entry.archive);
55999
- if (lstatSync18(entry.source, { throwIfNoEntry: false })) {
56245
+ if (lstatSync19(entry.source, { throwIfNoEntry: false })) {
56000
56246
  entry.status = "recovery-required";
56001
56247
  entry.conflict = "source-occupied";
56002
56248
  continue;
@@ -56010,10 +56256,10 @@ function archiveNativeSkills(inventory, options) {
56010
56256
  }
56011
56257
  if (entry.discoveryOnly) {
56012
56258
  linkSync2(entry.archive, entry.source);
56013
- syncArchiveDirectory(dirname15(entry.source));
56259
+ syncArchiveDirectory(dirname16(entry.source));
56014
56260
  unlinkSync4(entry.archive);
56015
56261
  } else {
56016
- if (lstatSync18(entry.source, { throwIfNoEntry: false })) {
56262
+ if (lstatSync19(entry.source, { throwIfNoEntry: false })) {
56017
56263
  entry.status = "recovery-required";
56018
56264
  entry.conflict = "source-occupied";
56019
56265
  continue;
@@ -56021,7 +56267,7 @@ function archiveNativeSkills(inventory, options) {
56021
56267
  renameSync4(entry.archive, entry.source);
56022
56268
  }
56023
56269
  entry.status = "restored";
56024
- syncArchiveDirectory(dirname15(entry.source));
56270
+ syncArchiveDirectory(dirname16(entry.source));
56025
56271
  syncArchiveDirectory(archiveRoot);
56026
56272
  } catch {
56027
56273
  entry.status = "recovery-required";
@@ -56043,10 +56289,10 @@ function archiveNativeSkills(inventory, options) {
56043
56289
  function assertManagedAgentBridge(agent, options = {}) {
56044
56290
  const home = resolve16(options.home ?? homedir4()), dataDir3 = options.dataDir ?? getDataDirReadOnly();
56045
56291
  assertSafePath(join29(dataDir3, "agent-policy.json"));
56046
- const snapshot = readManagedSkillPolicySnapshot(dataDir3);
56047
- if (!snapshot)
56292
+ const snapshot2 = readManagedSkillPolicySnapshot(dataDir3);
56293
+ if (!snapshot2)
56048
56294
  throw new Error("NATIVE_SKILL_DRIFT: install the Skills bridge with skills hook install");
56049
- const binding = snapshot.value.bridge;
56295
+ const binding = snapshot2.value.bridge;
56050
56296
  if (!binding || binding.version !== CLI_BRIDGE_VERSION || binding.digest !== CLI_BRIDGE_DIGEST || binding.home !== home || !Array.isArray(binding.agents) || !binding.agents.includes(agent))
56051
56297
  throw new Error("NATIVE_SKILL_DRIFT: the managed Skills bridge binding is missing or incompatible; run skills hook install");
56052
56298
  const aliases = binding.rootAliases ?? [];
@@ -56068,7 +56314,7 @@ function assertManagedAgentBridge(agent, options = {}) {
56068
56314
  throw new Error("NATIVE_SKILL_DRIFT: the hook selection profile differs from its managed binding; restart the native client after reviewing skills hook install");
56069
56315
  if (agent === "hermes") {
56070
56316
  const supervisor = binding.supervisors?.hermes;
56071
- if (supervisor?.path !== join29(dataDir3, "agent-hooks", "hermes.js") || supervisor?.sha256 !== sha(renderHermesSupervisor(command, profile)))
56317
+ if (supervisor?.path !== join29(dataDir3, "agent-hooks", "hermes.js") || supervisor?.sha256 !== sha2(renderHermesSupervisor(command, profile)))
56072
56318
  throw new Error("NATIVE_SKILL_DRIFT: Hermes supervisor binding changed; run skills hook install");
56073
56319
  assertHermesProtection(home, config, command, profile, supervisor);
56074
56320
  } else if (agent === "opencode") {
@@ -56090,6 +56336,8 @@ function assertManagedAgentBridge(agent, options = {}) {
56090
56336
  throw new Error("NATIVE_SKILL_DRIFT: Gemini bridge or bundled-skill protection changed; run skills hook install");
56091
56337
  }
56092
56338
  const codexPath = canonicalAgentPath(join29(home, ".codex", "config.toml"), aliases);
56339
+ if (options.codexDiscoveryRecovery && (agent !== "codex" || options.codexDiscoveryRecovery.configPath !== codexPath))
56340
+ throw new Error("NATIVE_SKILL_DRIFT: Codex trust recovery names a different configuration root");
56093
56341
  const codexConfig = agent === "codex" ? Bun.TOML.parse(readOptional(codexPath) ?? "") : {};
56094
56342
  if (agent === "codex" && codexConfig.skills?.bundled?.enabled !== false)
56095
56343
  throw new Error("NATIVE_SKILL_DRIFT: Codex bundled skill reseeding is not disabled (skills.bundled.enabled); run skills hook install");
@@ -56108,7 +56356,7 @@ function assertManagedAgentBridge(agent, options = {}) {
56108
56356
  if (agent === "gemini" && !discovery.builtinNames?.every((name) => config.skills.disabled.includes(name)))
56109
56357
  throw new Error("NATIVE_SKILL_DRIFT: an installed Gemini builtin is not disabled");
56110
56358
  try {
56111
- verifyAgentDiscovery(discovery);
56359
+ verifyAgentDiscovery(discovery, options.codexDiscoveryRecovery);
56112
56360
  if (discovery.method === "automatic") {
56113
56361
  const current = resolveAgentDiscovery({ home, agent, canonical: (path) => canonicalAgentPath(path, aliases) });
56114
56362
  if (JSON.stringify(current) !== JSON.stringify(discovery))
@@ -56164,7 +56412,7 @@ function assertNativeExportAllowed(dataDir3 = getDataDirReadOnly()) {
56164
56412
  if (requiresCliSkillLoading(dataDir3))
56165
56413
  throw new Error("NATIVE_SKILL_EXPORT_DISABLED: this station loads skills through the Skills CLI; use skills sync --selection-profile <id>");
56166
56414
  }
56167
- var sha = (data) => createHash14("sha256").update(data).digest("hex"), HOOK_EVENTS, ROOTS, SKILLS_LOADING_POLICY = "Skills loading policy: discover skills with `skills list` or `skills search`, and read selected instructions with `skills load <slug>`. Use `skills sync` to refresh the shared profile. The only native skill is the owned skills-cli bridge. Create and edit payload skills in the Skills authoring workspace; do not copy payload instructions into native discovery folders. Context loading does not authorize execution; use `skills run` only when the task calls for running a skill.";
56415
+ var sha2 = (data) => createHash16("sha256").update(data).digest("hex"), HOOK_EVENTS, ROOTS, SKILLS_LOADING_POLICY = "Skills loading policy: discover skills with `skills list` or `skills search`, and read selected instructions with `skills load <slug>`. Use `skills sync` to refresh the shared profile. The only native skill is the owned skills-cli bridge. Create and edit payload skills in the Skills authoring workspace; do not copy payload instructions into native discovery folders. Context loading does not authorize execution; use `skills run` only when the task calls for running a skill.";
56168
56416
  var init_agent_integration = __esm(() => {
56169
56417
  init_config();
56170
56418
  init_managed_policy();
@@ -56194,7 +56442,7 @@ var init_agent_integration = __esm(() => {
56194
56442
  });
56195
56443
 
56196
56444
  // src/lib/home-migration.ts
56197
- import { existsSync as existsSync16, mkdirSync as mkdirSync8, readdirSync as readdirSync11, renameSync as renameSync5, rmSync as rmSync3, statSync as statSync9, writeFileSync as writeFileSync6 } from "fs";
56445
+ import { existsSync as existsSync16, mkdirSync as mkdirSync8, readdirSync as readdirSync11, renameSync as renameSync5, rmSync as rmSync3, statSync as statSync9, writeFileSync as writeFileSync7 } from "fs";
56198
56446
  import { join as join30 } from "path";
56199
56447
  function layoutMigrationRecordPath(appDir) {
56200
56448
  return join30(appDir, SKILLS_CACHE_DIRNAME, LAYOUT_MIGRATION_RECORD);
@@ -56317,7 +56565,7 @@ function migrateOwnerLayout(options = {}) {
56317
56565
  moved,
56318
56566
  note: "installed/ and legacy flat skill dirs moved into skills/; custom/ retained"
56319
56567
  };
56320
- writeFileSync6(layoutMigrationRecordPath(appDir), `${JSON.stringify(record2, null, 2)}
56568
+ writeFileSync7(layoutMigrationRecordPath(appDir), `${JSON.stringify(record2, null, 2)}
56321
56569
  `);
56322
56570
  return { status: "migrated", moved, created, record: record2 };
56323
56571
  }
@@ -56332,7 +56580,7 @@ var init_home_migration = __esm(() => {
56332
56580
  import {
56333
56581
  cpSync as cpSync2,
56334
56582
  existsSync as existsSync17,
56335
- lstatSync as lstatSync19,
56583
+ lstatSync as lstatSync20,
56336
56584
  mkdirSync as mkdirSync9,
56337
56585
  mkdtempSync as mkdtempSync2,
56338
56586
  readFileSync as readFileSync16,
@@ -56340,17 +56588,17 @@ import {
56340
56588
  renameSync as renameSync6,
56341
56589
  rmSync as rmSync4,
56342
56590
  statSync as statSync10,
56343
- writeFileSync as writeFileSync7
56591
+ writeFileSync as writeFileSync8
56344
56592
  } from "fs";
56345
56593
  import { homedir as homedir5 } from "os";
56346
- import { basename as basename9, dirname as dirname16, join as join31 } from "path";
56594
+ import { basename as basename9, dirname as dirname17, join as join31 } from "path";
56347
56595
  function isSkillsOwnershipMarker(marker) {
56348
56596
  return typeof marker === "object" && marker !== null && Object.hasOwn(marker, "managedBy") && marker.managedBy === SYNC_MARKER_MANAGED_BY;
56349
56597
  }
56350
56598
  function hasSkillsOwnershipMarker(dir) {
56351
56599
  const path = join31(dir, SYNC_MARKER_FILE);
56352
56600
  try {
56353
- if (!lstatSync19(path).isFile())
56601
+ if (!lstatSync20(path).isFile())
56354
56602
  return false;
56355
56603
  const marker = JSON.parse(readFileSync16(path, "utf8"));
56356
56604
  return isSkillsOwnershipMarker(marker);
@@ -56575,7 +56823,7 @@ function writeManagedSkillDir(dir, skillMd, options) {
56575
56823
  const action = dirExists ? "update" : "create";
56576
56824
  if (options.dryRun)
56577
56825
  return { action, path: skillMdPath };
56578
- const parentDir = dirname16(dir);
56826
+ const parentDir = dirname17(dir);
56579
56827
  mkdirSync9(parentDir, { recursive: true });
56580
56828
  const transactionDir = mkdtempSync2(join31(parentDir, `.hasna-skills-write-${basename9(dir)}-`));
56581
56829
  const candidateDir = join31(transactionDir, "candidate");
@@ -56597,10 +56845,10 @@ function writeManagedSkillDir(dir, skillMd, options) {
56597
56845
  } else {
56598
56846
  mkdirSync9(candidateDir, { recursive: true });
56599
56847
  }
56600
- writeFileSync7(candidateSkillMdPath, skillMd.endsWith(`
56848
+ writeFileSync8(candidateSkillMdPath, skillMd.endsWith(`
56601
56849
  `) ? skillMd : `${skillMd}
56602
56850
  `);
56603
- writeFileSync7(candidateMarkerPath, `${JSON.stringify(marker, null, 2)}
56851
+ writeFileSync8(candidateMarkerPath, `${JSON.stringify(marker, null, 2)}
56604
56852
  `);
56605
56853
  if (dirExists) {
56606
56854
  originalMoved = true;
@@ -56665,7 +56913,7 @@ var init_agent_sync = __esm(() => {
56665
56913
  });
56666
56914
 
56667
56915
  // src/lib/project-state.ts
56668
- import { existsSync as existsSync18, mkdirSync as mkdirSync10, readFileSync as readFileSync17, writeFileSync as writeFileSync8 } from "fs";
56916
+ import { existsSync as existsSync18, mkdirSync as mkdirSync10, readFileSync as readFileSync17, writeFileSync as writeFileSync9 } from "fs";
56669
56917
  import { join as join32 } from "path";
56670
56918
  function getProjectStateDir(targetDir = process.cwd()) {
56671
56919
  return join32(targetDir, SKILLS_PROJECT_DIR);
@@ -56701,7 +56949,7 @@ function saveProjectConfig(config, targetDir = process.cwd()) {
56701
56949
  const dir = getProjectStateDir(targetDir);
56702
56950
  mkdirSync10(dir, { recursive: true });
56703
56951
  const normalized = normalizeProjectConfig({ ...config, updatedAt: new Date().toISOString() });
56704
- writeFileSync8(getProjectConfigPath(targetDir), JSON.stringify(normalized, null, 2) + `
56952
+ writeFileSync9(getProjectConfigPath(targetDir), JSON.stringify(normalized, null, 2) + `
56705
56953
  `);
56706
56954
  }
56707
56955
  function pinProjectSkill(name, details = {}, targetDir = process.cwd()) {
@@ -76515,7 +76763,7 @@ var init_v4 = __esm(() => {
76515
76763
  });
76516
76764
 
76517
76765
  // src/lib/canonical-json.ts
76518
- import { createHash as createHash15 } from "crypto";
76766
+ import { createHash as createHash17 } from "crypto";
76519
76767
  function canonicalJson2(value, maximumBytes = 2 * 1024 * 1024) {
76520
76768
  return canonicalJsonAtDepth(value, maximumBytes, 64);
76521
76769
  }
@@ -76559,7 +76807,7 @@ function canonicalJsonAtDepth(value, maximumBytes, maximumDepth) {
76559
76807
  return visit3(value, 0);
76560
76808
  }
76561
76809
  function canonicalJsonSha256(value, maximumBytes) {
76562
- return createHash15("sha256").update(canonicalJson2(value, maximumBytes)).digest("hex");
76810
+ return createHash17("sha256").update(canonicalJson2(value, maximumBytes)).digest("hex");
76563
76811
  }
76564
76812
  var init_canonical_json = () => {};
76565
76813
 
@@ -76630,8 +76878,8 @@ function recurringFailure(value, status) {
76630
76878
  }
76631
76879
  function recurringInput(action, raw) {
76632
76880
  try {
76633
- const snapshot = JSON.parse(canonicalJson2(raw, action === "preview" ? 1048576 : 4096));
76634
- return inputs[action].parse(snapshot);
76881
+ const snapshot2 = JSON.parse(canonicalJson2(raw, action === "preview" ? 1048576 : 4096));
76882
+ return inputs[action].parse(snapshot2);
76635
76883
  } catch {
76636
76884
  throw new RecurringInputError;
76637
76885
  }
@@ -77159,9 +77407,9 @@ function timestamp2(value) {
77159
77407
  const time3 = Date.parse(value);
77160
77408
  return Number.isFinite(time3) && new Date(time3).toISOString().slice(0, 23) === value.slice(0, 23);
77161
77409
  }
77162
- function parseMember(row, fail2) {
77410
+ function parseMember(row, fail3) {
77163
77411
  if (!record5(row) || !uuid10(row.membershipId) || !uuid10(row.userId) || typeof row.email !== "string" || !row.email || !(row.displayName === null || typeof row.displayName === "string") || !isRole(row.role) || !timestamp2(row.createdAt))
77164
- return fail2();
77412
+ return fail3();
77165
77413
  return {
77166
77414
  membershipId: row.membershipId,
77167
77415
  userId: row.userId,
@@ -77188,14 +77436,14 @@ function workspaceMemberRemovalInput(membershipId, input2) {
77188
77436
  return { membershipId: value.membershipId, body: { expectedRole: value.expectedRole } };
77189
77437
  }
77190
77438
  function parseWorkspaceMemberRoleResult(value, membershipId, role3) {
77191
- const fail2 = () => {
77439
+ const fail3 = () => {
77192
77440
  throw new Error(invalidMemberResult);
77193
77441
  };
77194
77442
  if (!record5(value) || !uuid10(value.organizationId) || typeof value.changed !== "boolean")
77195
- return fail2();
77196
- const member = parseMember(value.member, fail2);
77443
+ return fail3();
77444
+ const member = parseMember(value.member, fail3);
77197
77445
  if (member.membershipId !== membershipId || member.role !== role3)
77198
- return fail2();
77446
+ return fail3();
77199
77447
  return { organizationId: value.organizationId, member, changed: value.changed };
77200
77448
  }
77201
77449
  function parseWorkspaceMemberRemovalResult(value, membershipId) {
@@ -77210,14 +77458,14 @@ function workspaceMemberFailure(value, status) {
77210
77458
  return workspaceMemberFailures[code][0] === status ? code : null;
77211
77459
  }
77212
77460
  function parseWorkspaceMembersPage(value) {
77213
- const fail2 = () => {
77461
+ const fail3 = () => {
77214
77462
  throw new Error("The server returned an invalid workspace roster.");
77215
77463
  };
77216
77464
  if (!record5(value) || !uuid10(value.organizationId) || !Array.isArray(value.members) || value.members.length > 100 || !(value.nextCursor === null || cursor(value.nextCursor)) || !value.members.length && value.nextCursor !== null)
77217
- return fail2();
77218
- const members2 = value.members.map((row) => parseMember(row, fail2));
77465
+ return fail3();
77466
+ const members2 = value.members.map((row) => parseMember(row, fail3));
77219
77467
  if (new Set(members2.map((row) => row.membershipId)).size !== members2.length)
77220
- return fail2();
77468
+ return fail3();
77221
77469
  return { organizationId: value.organizationId, members: members2, nextCursor: value.nextCursor };
77222
77470
  }
77223
77471
  var record5 = (value) => !!value && typeof value === "object" && !Array.isArray(value), cursor = (value) => typeof value === "string" && /^[A-Za-z0-9_-]{1,512}$/.test(value), uuid10 = (value) => typeof value === "string" && /^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/i.test(value), isRole = (value) => typeof value === "string" && ["owner", "admin", "member", "viewer"].includes(value), WorkspaceMemberInputError, invalidMemberResult = "The server returned an invalid workspace member result. Refresh the roster before another action.", workspaceMemberFailures;
@@ -77312,14 +77560,14 @@ var init_remote_workspace_leave = __esm(() => {
77312
77560
  });
77313
77561
 
77314
77562
  // src/lib/auth-store.ts
77315
- import { chmodSync as chmodSync2, existsSync as existsSync20, mkdirSync as mkdirSync11, readFileSync as readFileSync19, renameSync as renameSync7, statSync as statSync11, unlinkSync as unlinkSync5, writeFileSync as writeFileSync9 } from "fs";
77316
- import { basename as basename10, dirname as dirname17, join as join34 } from "path";
77563
+ import { chmodSync as chmodSync2, existsSync as existsSync20, mkdirSync as mkdirSync11, readFileSync as readFileSync19, renameSync as renameSync7, statSync as statSync11, unlinkSync as unlinkSync5, writeFileSync as writeFileSync10 } from "fs";
77564
+ import { basename as basename10, dirname as dirname18, join as join34 } from "path";
77317
77565
  function getAuthFilePath(env3 = process.env) {
77318
77566
  return skillsCredentialFilePath(env3);
77319
77567
  }
77320
77568
  function getIdentityFilePath(env3 = process.env) {
77321
77569
  const file2 = skillsCredentialFilePath(env3);
77322
- return join34(dirname17(file2), basename10(file2).replace(/^credentials/, "identity") + ".json");
77570
+ return join34(dirname18(file2), basename10(file2).replace(/^credentials/, "identity") + ".json");
77323
77571
  }
77324
77572
  function getAuthIdentity(env3 = process.env) {
77325
77573
  return readIdentity(env3);
@@ -77353,7 +77601,7 @@ function getAuthConfig(env3 = process.env, options = {}) {
77353
77601
  }
77354
77602
  function writeCredentialValues(values2, env3 = process.env) {
77355
77603
  const file2 = skillsCredentialFilePath(env3);
77356
- mkdirSync11(dirname17(file2), { recursive: true, mode: 448 });
77604
+ mkdirSync11(dirname18(file2), { recursive: true, mode: 448 });
77357
77605
  const lines = [];
77358
77606
  const written = new Set;
77359
77607
  if (existsSync20(file2)) {
@@ -77380,7 +77628,7 @@ function writeCredentialValues(values2, env3 = process.env) {
77380
77628
  `) + `
77381
77629
  `;
77382
77630
  const temp = `${file2}.tmp-${process.pid}`;
77383
- writeFileSync9(temp, body, { mode: 384 });
77631
+ writeFileSync10(temp, body, { mode: 384 });
77384
77632
  chmodSync2(temp, 384);
77385
77633
  renameSync7(temp, file2);
77386
77634
  return file2;
@@ -77428,7 +77676,7 @@ function saveAuthConfig(config2, env3 = process.env, authenticatedOrigin) {
77428
77676
  }
77429
77677
  const identityFile = getIdentityFilePath(env3);
77430
77678
  if (Object.keys(identity4).length > 0) {
77431
- writeFileSync9(identityFile, JSON.stringify({ ...identity4, apiUrl }, null, 2) + `
77679
+ writeFileSync10(identityFile, JSON.stringify({ ...identity4, apiUrl }, null, 2) + `
77432
77680
  `, { mode: 384 });
77433
77681
  chmodSync2(identityFile, 384);
77434
77682
  } else {
@@ -78818,7 +79066,7 @@ var init_remote_client = __esm(() => {
78818
79066
  });
78819
79067
 
78820
79068
  // src/lib/revision.ts
78821
- import { createHash as createHash16 } from "crypto";
79069
+ import { createHash as createHash18 } from "crypto";
78822
79070
  function revisionIdOf(content) {
78823
79071
  const canonicalContent = {
78824
79072
  slug: content.slug,
@@ -78839,7 +79087,7 @@ function revisionIdOf(content) {
78839
79087
  canonicalContent.replacementSlug = content.replacementSlug ?? null;
78840
79088
  }
78841
79089
  const canonical4 = JSON.stringify(canonicalContent);
78842
- return createHash16("sha256").update(canonical4).digest("hex");
79090
+ return createHash18("sha256").update(canonical4).digest("hex");
78843
79091
  }
78844
79092
  var REVISION_ID_PATTERN;
78845
79093
  var init_revision = __esm(() => {
@@ -78868,8 +79116,8 @@ var init_skill_bundles = __esm(() => {
78868
79116
  });
78869
79117
 
78870
79118
  // src/lib/pull.ts
78871
- import { existsSync as existsSync21, mkdirSync as mkdirSync12, mkdtempSync as mkdtempSync3, readFileSync as readFileSync20, renameSync as renameSync8, rmSync as rmSync6, writeFileSync as writeFileSync10 } from "fs";
78872
- import { dirname as dirname18, join as join35 } from "path";
79119
+ import { existsSync as existsSync21, mkdirSync as mkdirSync12, mkdtempSync as mkdtempSync3, readFileSync as readFileSync20, renameSync as renameSync8, rmSync as rmSync6, writeFileSync as writeFileSync11 } from "fs";
79120
+ import { dirname as dirname19, join as join35 } from "path";
78873
79121
  async function pullSkills(options = {}) {
78874
79122
  const client2 = options.client !== undefined ? options.client : await createRemoteSkillsClient();
78875
79123
  if (!client2) {
@@ -79173,8 +79421,8 @@ function installBundleAtomically(name, entries, options = {}, marker = {}) {
79173
79421
  try {
79174
79422
  for (const entry of entries) {
79175
79423
  const destination = join35(staging, entry.path);
79176
- mkdirSync12(dirname18(destination), { recursive: true });
79177
- writeFileSync10(destination, entry.bytes, { mode: entry.mode });
79424
+ mkdirSync12(dirname19(destination), { recursive: true });
79425
+ writeFileSync11(destination, entry.bytes, { mode: entry.mode });
79178
79426
  }
79179
79427
  writePullMarker(staging, {
79180
79428
  skill: name,
@@ -79215,7 +79463,7 @@ function writePullMarker(dir, record7) {
79215
79463
  ...record7.revisionId ? { revisionId: record7.revisionId } : {},
79216
79464
  syncedAt: new Date().toISOString()
79217
79465
  };
79218
- writeFileSync10(join35(dir, PULL_MARKER_FILE), `${JSON.stringify(marker, null, 2)}
79466
+ writeFileSync11(join35(dir, PULL_MARKER_FILE), `${JSON.stringify(marker, null, 2)}
79219
79467
  `);
79220
79468
  }
79221
79469
  async function safeMeta(client2, slug2) {
@@ -79288,7 +79536,7 @@ var init_pull = __esm(() => {
79288
79536
  });
79289
79537
 
79290
79538
  // src/lib/skill-context.ts
79291
- import { createHash as createHash17 } from "crypto";
79539
+ import { createHash as createHash19 } from "crypto";
79292
79540
  import { resolve as resolve17 } from "path";
79293
79541
  function words2(value) {
79294
79542
  return new Set(value.toLowerCase().match(/[a-z0-9]+/g) ?? []);
@@ -79377,7 +79625,7 @@ ${content}`;
79377
79625
  `);
79378
79626
  const receipt = {
79379
79627
  schemaVersion: 1,
79380
- id: createHash17("sha256").update(JSON.stringify({ profile: profile.profileRevision, sessionId, selections, omitted })).digest("hex"),
79628
+ id: createHash19("sha256").update(JSON.stringify({ profile: profile.profileRevision, sessionId, selections, omitted })).digest("hex"),
79381
79629
  profileId: profile.profileId,
79382
79630
  profileRevision: profile.profileRevision,
79383
79631
  authority: profile.authority,
@@ -79399,7 +79647,7 @@ var init_skill_context = __esm(() => {
79399
79647
  });
79400
79648
 
79401
79649
  // src/lib/session-reconciliation.ts
79402
- import { createHash as createHash18 } from "crypto";
79650
+ import { createHash as createHash20 } from "crypto";
79403
79651
  function exactTimestamp(value) {
79404
79652
  const parsed = value === undefined ? Number.NaN : Date.parse(value);
79405
79653
  if (!Number.isFinite(parsed) || new Date(parsed).toISOString() !== value) {
@@ -79417,12 +79665,12 @@ function assertPlanWindow(issuedAt, expiresAt, now3) {
79417
79665
  }
79418
79666
  }
79419
79667
  function inspectSkillSession(sessionId, options = {}) {
79420
- const snapshot = readSkillSessionSnapshot(sessionId, options), { receipt } = snapshot;
79668
+ const snapshot2 = readSkillSessionSnapshot(sessionId, options), { receipt } = snapshot2;
79421
79669
  return {
79422
79670
  sessionId,
79423
- path: snapshot.path,
79424
- receiptSha256: snapshot.sha256,
79425
- generation: snapshot.generation,
79671
+ path: snapshot2.path,
79672
+ receiptSha256: snapshot2.sha256,
79673
+ generation: snapshot2.generation,
79426
79674
  verifiedAt: receipt.verifiedAt,
79427
79675
  authority: receipt.profile.authority,
79428
79676
  workspaceId: receipt.profile.workspaceId,
@@ -79447,8 +79695,8 @@ async function reconcileSkillSession(input2, options = {}) {
79447
79695
  const expiresAt = input2.apply ? input2.planExpiresAt : new Date(now3 + SESSION_RECONCILIATION_PLAN_TTL_MS).toISOString();
79448
79696
  if (input2.apply)
79449
79697
  assertPlanWindow(issuedAt, expiresAt, now3);
79450
- const snapshot = readSkillSessionSnapshot(input2.sessionId, options), old = snapshot.receipt;
79451
- if (snapshot.sha256 !== input2.receiptSha256 || old.profile.profileId !== input2.fromProfile || old.profile.profileRevision !== input2.fromRevision) {
79698
+ const snapshot2 = readSkillSessionSnapshot(input2.sessionId, options), old = snapshot2.receipt;
79699
+ if (snapshot2.sha256 !== input2.receiptSha256 || old.profile.profileId !== input2.fromProfile || old.profile.profileRevision !== input2.fromRevision) {
79452
79700
  throw new SkillSelectionError("SESSION_RECEIPT_CHANGED", "The current session receipt does not match the reviewed old bytes, profile and revision.");
79453
79701
  }
79454
79702
  const client2 = options.client ?? await createProfileClient();
@@ -79462,14 +79710,14 @@ async function reconcileSkillSession(input2, options = {}) {
79462
79710
  }
79463
79711
  const targetKeys = new Set(target.selections.map(selectionKey));
79464
79712
  const loaded = old.loaded.filter((key) => targetKeys.has(key));
79465
- const replacementGeneration = nextSkillSessionGeneration(snapshot.generation);
79713
+ const replacementGeneration = nextSkillSessionGeneration(snapshot2.generation);
79466
79714
  const plan = {
79467
79715
  schemaVersion: 1,
79468
79716
  issuedAt,
79469
79717
  expiresAt,
79470
79718
  sessionId: input2.sessionId,
79471
- sessionPath: snapshot.path,
79472
- before: { receiptSha256: snapshot.sha256, generation: snapshot.generation, profileId: old.profile.profileId, profileRevision: old.profile.profileRevision, selectionCount: old.profile.selections.length },
79719
+ sessionPath: snapshot2.path,
79720
+ before: { receiptSha256: snapshot2.sha256, generation: snapshot2.generation, profileId: old.profile.profileId, profileRevision: old.profile.profileRevision, selectionCount: old.profile.selections.length },
79473
79721
  target: { authority: target.authority, workspaceId: target.workspaceId, profileId: target.profileId, profileRevision: target.profileRevision, profileSha256: digest3(target), selectionCount: target.selections.length },
79474
79722
  replacementGeneration,
79475
79723
  retainedLoadedCount: loaded.length,
@@ -79480,7 +79728,7 @@ async function reconcileSkillSession(input2, options = {}) {
79480
79728
  if (input2.planDigest !== undefined && input2.planDigest !== planDigest)
79481
79729
  throw new SkillSelectionError("SESSION_PLAN_CHANGED", "The session reconciliation plan differs from the reviewed plan.");
79482
79730
  if (!input2.apply)
79483
- return { applied: false, plan, planDigest, archivePath: undefined, receiptPath: undefined, beforeSha256: snapshot.sha256, afterSha256: undefined };
79731
+ return { applied: false, plan, planDigest, archivePath: undefined, receiptPath: undefined, beforeSha256: snapshot2.sha256, afterSha256: undefined };
79484
79732
  assertPlanWindow(issuedAt, expiresAt, (options.now ?? Date.now)());
79485
79733
  const replacement = {
79486
79734
  ...old,
@@ -79489,10 +79737,10 @@ async function reconcileSkillSession(input2, options = {}) {
79489
79737
  profile: target,
79490
79738
  loaded
79491
79739
  };
79492
- const result2 = replaceSkillSession(skillSessionSnapshotBinding(snapshot), replacement, { ...plan, planDigest }, options, () => assertPlanWindow(issuedAt, expiresAt, (options.now ?? Date.now)()));
79740
+ const result2 = replaceSkillSession(skillSessionSnapshotBinding(snapshot2), replacement, { ...plan, planDigest }, options, () => assertPlanWindow(issuedAt, expiresAt, (options.now ?? Date.now)()));
79493
79741
  return { applied: true, plan, planDigest, ...result2 };
79494
79742
  }
79495
- var SESSION_RECONCILIATION_PLAN_TTL_MS, digest3 = (value) => createHash18("sha256").update(JSON.stringify(value)).digest("hex");
79743
+ var SESSION_RECONCILIATION_PLAN_TTL_MS, digest3 = (value) => createHash20("sha256").update(JSON.stringify(value)).digest("hex");
79496
79744
  var init_session_reconciliation = __esm(() => {
79497
79745
  init_profile_client();
79498
79746
  init_selection_cache();
@@ -79508,7 +79756,7 @@ __export(exports_context, {
79508
79756
  parseSkillContextInput: () => parseSkillContextInput,
79509
79757
  contextResolverOptions: () => contextResolverOptions
79510
79758
  });
79511
- import { readSync as readSync10 } from "fs";
79759
+ import { readSync as readSync11 } from "fs";
79512
79760
  function selectedProfileId(explicit) {
79513
79761
  return explicit ?? process.env.HASNA_SKILLS_SELECTION_PROFILE ?? readManagedSkillPolicy()?.profileId ?? "default";
79514
79762
  }
@@ -79586,7 +79834,7 @@ async function readContextStdin() {
79586
79834
  let size2 = 0;
79587
79835
  while (true) {
79588
79836
  const chunk2 = Buffer.allocUnsafe(8192);
79589
- const count = readSync10(0, chunk2, 0, chunk2.length, null);
79837
+ const count = readSync11(0, chunk2, 0, chunk2.length, null);
79590
79838
  if (count === 0)
79591
79839
  break;
79592
79840
  size2 += count;
@@ -81165,7 +81413,7 @@ var exports_init = {};
81165
81413
  __export(exports_init, {
81166
81414
  registerSetup: () => registerSetup
81167
81415
  });
81168
- import { existsSync as existsSync23, readFileSync as readFileSync23, writeFileSync as writeFileSync11, appendFileSync } from "fs";
81416
+ import { existsSync as existsSync23, readFileSync as readFileSync23, writeFileSync as writeFileSync12, appendFileSync } from "fs";
81169
81417
  import { join as join37 } from "path";
81170
81418
  function registerSetup(parent) {
81171
81419
  parent.command("init").option("--json", "Output as JSON", false).option("--for <agent>", "Detect project type and show MCP registration guidance for agent").option("--scope <scope>", "Deprecated; agent skill-folder installs are disabled", "global").description("Initialize project for pinned skills (.env.example, .gitignore)").action((options) => handleInit(options));
@@ -81250,7 +81498,7 @@ Use: skills render`));
81250
81498
  lines.push(`# Used by: ${skills.join(", ")}`);
81251
81499
  lines.push(`${envVar}=`);
81252
81500
  }
81253
- writeFileSync11(join37(cwd2, ".env.example"), lines.join(`
81501
+ writeFileSync12(join37(cwd2, ".env.example"), lines.join(`
81254
81502
  `) + `
81255
81503
  `);
81256
81504
  envVarCount = envMap.size;
@@ -81412,7 +81660,7 @@ var init_init = __esm(() => {
81412
81660
  });
81413
81661
 
81414
81662
  // src/lib/home-adoption.ts
81415
- import { constants as constants12, closeSync as closeSync12, fstatSync as fstatSync12, lstatSync as lstatSync20, openSync as openSync12, readSync as readSync11, existsSync as existsSync24, mkdirSync as mkdirSync13, readdirSync as readdirSync13, readFileSync as readFileSync25, rmSync as rmSync7, statSync as statSync12, writeFileSync as writeFileSync12 } from "fs";
81663
+ import { constants as constants13, closeSync as closeSync13, fstatSync as fstatSync13, lstatSync as lstatSync21, openSync as openSync13, readSync as readSync12, existsSync as existsSync24, mkdirSync as mkdirSync13, readdirSync as readdirSync13, readFileSync as readFileSync25, rmSync as rmSync7, statSync as statSync12, writeFileSync as writeFileSync13 } from "fs";
81416
81664
  import { homedir as homedir7 } from "os";
81417
81665
  import { join as join38 } from "path";
81418
81666
  function indexCanonicalCorpus(corpusRoot) {
@@ -81528,7 +81776,7 @@ function appendConflictsLedger(appDir, conflicts) {
81528
81776
  for (const conflict of conflicts)
81529
81777
  byKey.set(`${conflict.agent}/${conflict.skill}`, conflict);
81530
81778
  ledger.entries = [...byKey.values()].sort((a, b) => `${a.agent}/${a.skill}`.localeCompare(`${b.agent}/${b.skill}`));
81531
- writeFileSync12(ledgerPath, `${JSON.stringify(ledger, null, 2)}
81779
+ writeFileSync13(ledgerPath, `${JSON.stringify(ledger, null, 2)}
81532
81780
  `);
81533
81781
  }
81534
81782
  function writeRollbackRecord(mode, entries, appDir = getDataDir()) {
@@ -81536,7 +81784,7 @@ function writeRollbackRecord(mode, entries, appDir = getDataDir()) {
81536
81784
  mkdirSync13(dir, { recursive: true });
81537
81785
  const file2 = join38(dir, `${mode}-${Date.now()}.json`);
81538
81786
  const record7 = { version: 1, mode, timestamp: new Date().toISOString(), entries };
81539
- writeFileSync12(file2, `${JSON.stringify(record7, null, 2)}
81787
+ writeFileSync13(file2, `${JSON.stringify(record7, null, 2)}
81540
81788
  `);
81541
81789
  return file2;
81542
81790
  }
@@ -81553,7 +81801,7 @@ function adoptUnmarkedHomes(options = {}) {
81553
81801
  source: "adopted",
81554
81802
  syncedAt: new Date().toISOString()
81555
81803
  };
81556
- writeFileSync12(join38(entry.path, SYNC_MARKER_FILE), `${JSON.stringify(marker, null, 2)}
81804
+ writeFileSync13(join38(entry.path, SYNC_MARKER_FILE), `${JSON.stringify(marker, null, 2)}
81557
81805
  `);
81558
81806
  return { agent: entry.agent, skill: entry.skill, path: entry.path, hash: entry.hash, marker };
81559
81807
  });
@@ -81567,25 +81815,25 @@ function adoptUnmarkedHomes(options = {}) {
81567
81815
  function pruneOwnership(dir) {
81568
81816
  let descriptor;
81569
81817
  try {
81570
- const directory = lstatSync20(dir);
81818
+ const directory = lstatSync21(dir);
81571
81819
  if (!directory.isDirectory())
81572
81820
  return;
81573
- const markerPath = join38(dir, SYNC_MARKER_FILE), markerPathBefore = lstatSync20(markerPath);
81821
+ const markerPath = join38(dir, SYNC_MARKER_FILE), markerPathBefore = lstatSync21(markerPath);
81574
81822
  if (!markerPathBefore.isFile())
81575
81823
  return;
81576
- descriptor = openSync12(markerPath, constants12.O_RDONLY | constants12.O_NOFOLLOW | constants12.O_NONBLOCK);
81577
- const before2 = fstatSync12(descriptor);
81824
+ descriptor = openSync13(markerPath, constants13.O_RDONLY | constants13.O_NOFOLLOW | constants13.O_NONBLOCK);
81825
+ const before2 = fstatSync13(descriptor);
81578
81826
  if (!before2.isFile() || before2.dev !== markerPathBefore.dev || before2.ino !== markerPathBefore.ino || before2.size !== markerPathBefore.size || before2.mtimeMs !== markerPathBefore.mtimeMs || before2.ctimeMs !== markerPathBefore.ctimeMs || before2.size < 1 || before2.size > 65536)
81579
81827
  return;
81580
81828
  const bytes = Buffer.alloc(before2.size + 1);
81581
81829
  let length = 0;
81582
81830
  while (length < bytes.length) {
81583
- const count = readSync11(descriptor, bytes, length, bytes.length - length, length);
81831
+ const count = readSync12(descriptor, bytes, length, bytes.length - length, length);
81584
81832
  if (!count)
81585
81833
  break;
81586
81834
  length += count;
81587
81835
  }
81588
- const after2 = fstatSync12(descriptor), current = lstatSync20(dir), markerPathAfter = lstatSync20(markerPath);
81836
+ const after2 = fstatSync13(descriptor), current = lstatSync21(dir), markerPathAfter = lstatSync21(markerPath);
81589
81837
  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)
81590
81838
  return;
81591
81839
  const text3 = bytes.subarray(0, length).toString("utf8"), marker = JSON.parse(text3);
@@ -81596,7 +81844,7 @@ function pruneOwnership(dir) {
81596
81844
  return;
81597
81845
  } finally {
81598
81846
  if (descriptor !== undefined)
81599
- closeSync12(descriptor);
81847
+ closeSync13(descriptor);
81600
81848
  }
81601
81849
  }
81602
81850
  function pruneStrayHomes(options = {}) {
@@ -81781,7 +82029,7 @@ var init_home_census = __esm(() => {
81781
82029
  });
81782
82030
 
81783
82031
  // src/cli/env-assignment.ts
81784
- import { closeSync as closeSync13, constants as constants13, fstatSync as fstatSync13, ftruncateSync as ftruncateSync2, lstatSync as lstatSync21, openSync as openSync13, readFileSync as readFileSync27, writeSync as writeSync3 } from "fs";
82032
+ import { closeSync as closeSync14, constants as constants14, fstatSync as fstatSync14, ftruncateSync as ftruncateSync2, lstatSync as lstatSync22, openSync as openSync14, readFileSync as readFileSync27, writeSync as writeSync3 } from "fs";
81785
82033
  function serializeValue(value) {
81786
82034
  if (controls.test(value))
81787
82035
  throw new EnvAssignmentError("Environment values cannot contain control characters or newlines.");
@@ -81860,7 +82108,7 @@ function setEnvAssignment(path, assignment) {
81860
82108
  try {
81861
82109
  const previous = (() => {
81862
82110
  try {
81863
- return lstatSync21(path);
82111
+ return lstatSync22(path);
81864
82112
  } catch (error61) {
81865
82113
  if (error61.code === "ENOENT")
81866
82114
  return;
@@ -81869,8 +82117,8 @@ function setEnvAssignment(path, assignment) {
81869
82117
  })();
81870
82118
  if (previous && !previous.isFile())
81871
82119
  throw new EnvAssignmentError("The project .env must be a regular file, not a symlink or special file.");
81872
- descriptor = openSync13(path, previous ? constants13.O_RDWR | constants13.O_NOFOLLOW | constants13.O_NONBLOCK : constants13.O_WRONLY | constants13.O_CREAT | constants13.O_EXCL | constants13.O_NOFOLLOW, 384);
81873
- const opened = fstatSync13(descriptor);
82120
+ descriptor = openSync14(path, previous ? constants14.O_RDWR | constants14.O_NOFOLLOW | constants14.O_NONBLOCK : constants14.O_WRONLY | constants14.O_CREAT | constants14.O_EXCL | constants14.O_NOFOLLOW, 384);
82121
+ const opened = fstatSync14(descriptor);
81874
82122
  if (!opened.isFile() || previous && (opened.ino !== previous.ino || opened.dev !== previous.dev)) {
81875
82123
  throw new EnvAssignmentError("The project .env changed while opening it; retry with a regular file.");
81876
82124
  }
@@ -81897,7 +82145,7 @@ function setEnvAssignment(path, assignment) {
81897
82145
  throw new EnvAssignmentError("Cannot safely read or write the project .env file.");
81898
82146
  } finally {
81899
82147
  if (descriptor !== undefined)
81900
- closeSync13(descriptor);
82148
+ closeSync14(descriptor);
81901
82149
  }
81902
82150
  }
81903
82151
  var INVALID_LAYOUT = "Cannot safely update .env with multiline or unsupported assignments. Use single-line KEY=VALUE entries or edit the file manually.", controls, EnvAssignmentError;
@@ -82415,7 +82663,7 @@ var init_cloud_executions = __esm(() => {
82415
82663
  // node_modules/@hasna/secrets/dist/sdk.js
82416
82664
  import { isIP as isIP3 } from "net";
82417
82665
  import { spawnSync as spawnSync2 } from "child_process";
82418
- import { closeSync as closeSync14, fstatSync as fstatSync14, openSync as openSync14, readFileSync as readFileSync29 } from "fs";
82666
+ import { closeSync as closeSync15, fstatSync as fstatSync15, openSync as openSync15, readFileSync as readFileSync29 } from "fs";
82419
82667
  import { O_NOFOLLOW as O_NOFOLLOW3, O_NONBLOCK as O_NONBLOCK3, O_RDONLY as O_RDONLY3 } from "constants";
82420
82668
  import { createRequire as createRequire2 } from "module";
82421
82669
  import { hostname as osHostname2 } from "os";
@@ -82520,7 +82768,7 @@ function readAppConfigFile2(path) {
82520
82768
  };
82521
82769
  let fd = -1;
82522
82770
  try {
82523
- fd = openSync14(path, O_RDONLY3 | O_NOFOLLOW3 | O_NONBLOCK3);
82771
+ fd = openSync15(path, O_RDONLY3 | O_NOFOLLOW3 | O_NONBLOCK3);
82524
82772
  } catch (error61) {
82525
82773
  const code = error61.code;
82526
82774
  if (code === "ENOENT" || code === "ENOTDIR")
@@ -82530,7 +82778,7 @@ function readAppConfigFile2(path) {
82530
82778
  unsafe(`the path could not be opened (${code ?? "unknown error"})`);
82531
82779
  }
82532
82780
  try {
82533
- const before2 = fstatSync14(fd);
82781
+ const before2 = fstatSync15(fd);
82534
82782
  if (!before2.isFile())
82535
82783
  unsafe("the path is not a regular file");
82536
82784
  if (!configFileModeAllowed2(before2.mode)) {
@@ -82542,14 +82790,14 @@ function readAppConfigFile2(path) {
82542
82790
  if (before2.size > MAX_CREDENTIAL_FILE_BYTES2)
82543
82791
  unsafe("the file exceeds the size limit");
82544
82792
  const bytes = readFileSync29(fd);
82545
- const after2 = fstatSync14(fd);
82793
+ const after2 = fstatSync15(fd);
82546
82794
  if (!configFileReadsCoherent2(before2, after2)) {
82547
82795
  unsafe("the file changed while being read");
82548
82796
  }
82549
82797
  return parseEnvFile2(bytes.toString("utf8"));
82550
82798
  } finally {
82551
82799
  if (fd !== -1)
82552
- closeSync14(fd);
82800
+ closeSync15(fd);
82553
82801
  }
82554
82802
  }
82555
82803
  function readCredentialFile2(path, apiKeyKeys) {
@@ -82599,14 +82847,14 @@ function assertUsableCredential2(appName, source, value) {
82599
82847
  return;
82600
82848
  throw new CredentialResolutionError2(appName, `The credential from ${source} contains characters that cannot be sent in an HTTP header ` + `(a control character or non-ASCII byte). A file written with CR-only line endings is the usual ` + `cause. Rewrite that credential file with one LF-terminated KEY=value line. ` + `The value is not shown here, and is deliberately never logged.`, [source]);
82601
82849
  }
82602
- function sealCredential2(fields) {
82603
- const { apiKey } = fields;
82850
+ function sealCredential2(fields2) {
82851
+ const { apiKey } = fields2;
82604
82852
  const visible = {
82605
- tier: fields.tier,
82606
- source: fields.source,
82607
- deliberate: fields.deliberate,
82608
- diskCandidates: Object.freeze([...fields.diskCandidates]),
82609
- warning: fields.warning
82853
+ tier: fields2.tier,
82854
+ source: fields2.source,
82855
+ deliberate: fields2.deliberate,
82856
+ diskCandidates: Object.freeze([...fields2.diskCandidates]),
82857
+ warning: fields2.warning
82610
82858
  };
82611
82859
  const sealed = { ...visible };
82612
82860
  Object.defineProperty(sealed, "apiKey", {
@@ -82615,9 +82863,9 @@ function sealCredential2(fields) {
82615
82863
  writable: false,
82616
82864
  configurable: false
82617
82865
  });
82618
- if (fields.pointerVaultKey !== undefined) {
82866
+ if (fields2.pointerVaultKey !== undefined) {
82619
82867
  Object.defineProperty(sealed, "pointerVaultKey", {
82620
- value: fields.pointerVaultKey,
82868
+ value: fields2.pointerVaultKey,
82621
82869
  enumerable: false,
82622
82870
  writable: false,
82623
82871
  configurable: false
@@ -82755,7 +83003,7 @@ function keychainConfigValue2(name, env3, options = {}) {
82755
83003
  function snapshotClientEnvironment2(name, env3) {
82756
83004
  const keys2 = clientTransportEnvKeys2(name);
82757
83005
  const ambient = isAmbientEnvironment2(env3);
82758
- const snapshot = Object.create(null);
83006
+ const snapshot2 = Object.create(null);
82759
83007
  for (const key of [
82760
83008
  ...keys2.apiUrlKeys,
82761
83009
  ...keys2.apiKeyKeys,
@@ -82777,17 +83025,17 @@ function snapshotClientEnvironment2(name, env3) {
82777
83025
  if (descriptor.value !== undefined && typeof descriptor.value !== "string") {
82778
83026
  throw new CredentialResolutionError2(name, `${key} must be a string data property.`, [key]);
82779
83027
  }
82780
- snapshot[key] = descriptor.value;
83028
+ snapshot2[key] = descriptor.value;
82781
83029
  }
82782
83030
  if (ambient) {
82783
- Object.defineProperty(snapshot, AMBIENT_ENVIRONMENT2, {
83031
+ Object.defineProperty(snapshot2, AMBIENT_ENVIRONMENT2, {
82784
83032
  value: true,
82785
83033
  enumerable: false,
82786
83034
  writable: false,
82787
83035
  configurable: false
82788
83036
  });
82789
83037
  }
82790
- return Object.freeze(snapshot);
83038
+ return Object.freeze(snapshot2);
82791
83039
  }
82792
83040
  function resolveCredential2(name, env3, options = {}) {
82793
83041
  env3 = snapshotClientEnvironment2(name, env3);
@@ -83715,7 +83963,7 @@ var init_sdk = __esm(() => {
83715
83963
  });
83716
83964
 
83717
83965
  // src/lib/execution-secrets.ts
83718
- import { constants as constants14, closeSync as closeSync15, fstatSync as fstatSync15, openSync as openSync15, readSync as readSync12, realpathSync as realpathSync6 } from "fs";
83966
+ import { constants as constants15, closeSync as closeSync16, fstatSync as fstatSync16, openSync as openSync16, readSync as readSync13, realpathSync as realpathSync6 } from "fs";
83719
83967
  import { hostname as stationHostname } from "os";
83720
83968
  function selectedSecretBindingsTemplate(scope, names, createClient2 = createSecretsClientFromEnv) {
83721
83969
  let secretsAuthority;
@@ -83759,13 +84007,13 @@ function declaredSecretNames(value) {
83759
84007
  function readSelectedSecretBindings(path) {
83760
84008
  let fd;
83761
84009
  try {
83762
- fd = openSync15(path, constants14.O_RDONLY | constants14.O_NOFOLLOW | constants14.O_NONBLOCK);
83763
- const stat2 = fstatSync15(fd);
84010
+ fd = openSync16(path, constants15.O_RDONLY | constants15.O_NOFOLLOW | constants15.O_NONBLOCK);
84011
+ const stat2 = fstatSync16(fd);
83764
84012
  if (!stat2.isFile() || stat2.size > 65536)
83765
84013
  throw new Error;
83766
84014
  const bytes = Buffer.alloc(65537);
83767
84015
  let size2 = 0, count;
83768
- while ((count = readSync12(fd, bytes, size2, bytes.length - size2, null)) > 0) {
84016
+ while ((count = readSync13(fd, bytes, size2, bytes.length - size2, null)) > 0) {
83769
84017
  size2 += count;
83770
84018
  if (size2 > 65536)
83771
84019
  throw new Error;
@@ -83775,7 +84023,7 @@ function readSelectedSecretBindings(path) {
83775
84023
  return refuse("INVALID_SECRET_BINDINGS", "Secret bindings must be a regular JSON file of at most 64 KiB, containing reference names only.");
83776
84024
  } finally {
83777
84025
  if (fd !== undefined)
83778
- closeSync15(fd);
84026
+ closeSync16(fd);
83779
84027
  }
83780
84028
  }
83781
84029
  function validateSelectedSecretBindings(value, scope, names) {
@@ -83982,7 +84230,7 @@ var init_execution_grants = __esm(() => {
83982
84230
  });
83983
84231
 
83984
84232
  // src/lib/execution-grant-client.ts
83985
- import { isDeepStrictEqual as isDeepStrictEqual4 } from "util";
84233
+ import { isDeepStrictEqual as isDeepStrictEqual6 } from "util";
83986
84234
  function id(value) {
83987
84235
  if (!grantIdentifier(value))
83988
84236
  throw new Error("Invalid execution grant profile or revision identifier.");
@@ -84026,26 +84274,26 @@ async function readExecutionGrantPolicy(profileId, revision) {
84026
84274
  return policy;
84027
84275
  }
84028
84276
  async function saveExecutionGrantPolicy(profileId, grants, revision) {
84029
- const snapshot = validateExecutionGrants(grants);
84277
+ const snapshot2 = validateExecutionGrants(grants);
84030
84278
  if (revision !== undefined)
84031
84279
  id(revision);
84032
84280
  const policy = validateExecutionGrantPolicy(await request(`/execution-grants/${id(profileId)}`, {
84033
84281
  method: "PUT",
84034
84282
  headers: revision === undefined ? { "If-None-Match": "*" } : { "If-Match": `"${revision}"` },
84035
- body: JSON.stringify({ grants: snapshot })
84283
+ body: JSON.stringify({ grants: snapshot2 })
84036
84284
  }));
84037
- if (policy.profileId !== profileId || policy.previousRevision !== (revision ?? null) || !isDeepStrictEqual4(policy.grants, snapshot)) {
84285
+ if (policy.profileId !== profileId || policy.previousRevision !== (revision ?? null) || !isDeepStrictEqual6(policy.grants, snapshot2)) {
84038
84286
  throw new Error("The API did not preserve the reviewed execution grant policy; read it before retrying.");
84039
84287
  }
84040
84288
  return policy;
84041
84289
  }
84042
84290
  async function resolveExecutionGrant(input2) {
84043
- const snapshot = validateExecutionGrantRequest(input2);
84044
- const value = await request(`/execution-grants/${id(snapshot.selection.profileId)}/resolve`, { method: "POST", body: JSON.stringify(snapshot) }, snapshot.selection.authority);
84291
+ const snapshot2 = validateExecutionGrantRequest(input2);
84292
+ const value = await request(`/execution-grants/${id(snapshot2.selection.profileId)}/resolve`, { method: "POST", body: JSON.stringify(snapshot2) }, snapshot2.selection.authority);
84045
84293
  if (!grantRecord(value) || Object.keys(value).length !== 3 || !grantIdentifier(value.policyRevision) || !grantIdentifier(value.grantId) || !grantRecord(value.bindings)) {
84046
84294
  throw new SkillSelectionError("INVALID_EXECUTION_GRANT", "The Skills API returned an invalid execution grant.");
84047
84295
  }
84048
- if (!isDeepStrictEqual4(value.bindings.selection, snapshot.selection) || !isDeepStrictEqual4(value.bindings.consumer, snapshot.consumer)) {
84296
+ if (!isDeepStrictEqual6(value.bindings.selection, snapshot2.selection) || !isDeepStrictEqual6(value.bindings.consumer, snapshot2.consumer)) {
84049
84297
  throw new SkillSelectionError("EXECUTION_GRANT_SCOPE_MISMATCH", "The Skills API returned a grant for a different selection or consumer.");
84050
84298
  }
84051
84299
  return value;
@@ -84064,10 +84312,10 @@ __export(exports_selected_run, {
84064
84312
  prepareSelectedSecretBindings: () => prepareSelectedSecretBindings,
84065
84313
  executeSelectedLocal: () => executeSelectedLocal
84066
84314
  });
84067
- import { createHash as createHash19 } from "crypto";
84315
+ import { createHash as createHash21 } from "crypto";
84068
84316
  import { spawn as spawn2 } from "child_process";
84069
- import { mkdirSync as mkdirSync14, mkdtempSync as mkdtempSync4, writeFileSync as writeFileSync13, realpathSync as realpathSync7 } from "fs";
84070
- import { dirname as dirname19, join as join42, resolve as resolve18 } from "path";
84317
+ import { mkdirSync as mkdirSync14, mkdtempSync as mkdtempSync4, writeFileSync as writeFileSync14, realpathSync as realpathSync7 } from "fs";
84318
+ import { dirname as dirname20, join as join42, resolve as resolve18 } from "path";
84071
84319
  import { tmpdir, hostname as stationHostname2 } from "os";
84072
84320
  async function resolveSelectedRun(spec, profileId, options = {}) {
84073
84321
  const context = await resolveSelectionContext(profileId, options);
@@ -84156,8 +84404,8 @@ async function executeSelectedLocal(selected, options = {}) {
84156
84404
  throw new SkillSelectionError("INVALID_BUNDLE_PATH", "The execution bundle path exceeds its limit.");
84157
84405
  });
84158
84406
  const destination = join42(runDirectory, entry.path);
84159
- mkdirSync14(dirname19(destination), { recursive: true, mode: 448 });
84160
- writeFileSync13(destination, entry.bytes, { flag: "wx", mode: entry.mode & 511 });
84407
+ mkdirSync14(dirname20(destination), { recursive: true, mode: 448 });
84408
+ writeFileSync14(destination, entry.bytes, { flag: "wx", mode: entry.mode & 511 });
84161
84409
  }
84162
84410
  env3.SKILLS_INPUT_JSON = input2;
84163
84411
  env3.SKILLS_WORKSPACE_DIR = resolve18(options.cwd ?? process.cwd());
@@ -84190,13 +84438,13 @@ async function executeSelectedLocal(selected, options = {}) {
84190
84438
  selection: selection2,
84191
84439
  target: "local",
84192
84440
  runtime: runtimeName,
84193
- inputDigest: `sha256:${createHash19("sha256").update(input2).digest("hex")}`,
84441
+ inputDigest: `sha256:${createHash21("sha256").update(input2).digest("hex")}`,
84194
84442
  runDirectory,
84195
84443
  ...executionGrant ? { executionGrant } : {},
84196
84444
  ...bindings ? { secretBinding: { schema: bindings.schema, selection: bindings.selection, consumer: bindings.consumer, secretsAuthority: bindings.secretsAuthority, bindings: bindings.bindings } } : {},
84197
84445
  ...result2
84198
84446
  };
84199
- writeFileSync13(join42(runDirectory, ".execution-receipt.json"), JSON.stringify({ ...receipt, stdout: undefined, stderr: undefined }), { mode: 384 });
84447
+ writeFileSync14(join42(runDirectory, ".execution-receipt.json"), JSON.stringify({ ...receipt, stdout: undefined, stderr: undefined }), { mode: 384 });
84200
84448
  return receipt;
84201
84449
  }
84202
84450
  async function subprocess(command, cwd2, env3, input2, timeoutMs) {
@@ -88407,8 +88655,8 @@ var init_runs = __esm(() => {
88407
88655
  });
88408
88656
 
88409
88657
  // src/lib/run-state.ts
88410
- import { createHash as createHash20, randomBytes } from "crypto";
88411
- import { existsSync as existsSync27, mkdirSync as mkdirSync15, readFileSync as readFileSync30, readdirSync as readdirSync16, statSync as statSync15, writeFileSync as writeFileSync14 } from "fs";
88658
+ import { createHash as createHash22, randomBytes } from "crypto";
88659
+ import { existsSync as existsSync27, mkdirSync as mkdirSync15, readFileSync as readFileSync30, readdirSync as readdirSync16, statSync as statSync15, writeFileSync as writeFileSync15 } from "fs";
88412
88660
  import { extname, join as join43, relative as relative6 } from "path";
88413
88661
  function createSkillRun(params, targetDir = process.cwd()) {
88414
88662
  const now3 = new Date;
@@ -88473,15 +88721,15 @@ function updateSkillRun(context, patch) {
88473
88721
  return context.record;
88474
88722
  }
88475
88723
  function writeRunLogs(context, stdout = "", stderr = "") {
88476
- writeFileSync14(join43(context.logsDir, "stdout.log"), stdout);
88477
- writeFileSync14(join43(context.logsDir, "stderr.log"), stderr);
88724
+ writeFileSync15(join43(context.logsDir, "stdout.log"), stdout);
88725
+ writeFileSync15(join43(context.logsDir, "stderr.log"), stderr);
88478
88726
  }
88479
88727
  function appendRunEvent(context, event, data = {}) {
88480
88728
  const line = JSON.stringify({ ts: new Date().toISOString(), event, ...data }) + `
88481
88729
  `;
88482
88730
  const path = join43(context.runDir, "events.ndjson");
88483
88731
  const previous = existsSync27(path) ? readFileSync30(path, "utf-8") : "";
88484
- writeFileSync14(path, previous + line);
88732
+ writeFileSync15(path, previous + line);
88485
88733
  }
88486
88734
  function listSkillRuns(targetDir = process.cwd(), limit = 50) {
88487
88735
  const runsRoot = join43(getProjectStateDir(targetDir), "runs");
@@ -88527,11 +88775,11 @@ function getRunExportDir(runId2, skill, targetDir = process.cwd()) {
88527
88775
  return join43(getProjectStateDir(targetDir), "exports", normalizeSkillName(skill), runId2);
88528
88776
  }
88529
88777
  function writeRunRecord(context) {
88530
- writeFileSync14(join43(context.runDir, "run.json"), JSON.stringify(context.record, null, 2) + `
88778
+ writeFileSync15(join43(context.runDir, "run.json"), JSON.stringify(context.record, null, 2) + `
88531
88779
  `);
88532
88780
  }
88533
88781
  function writeArtifactsManifest(context, artifacts) {
88534
- writeFileSync14(join43(context.runDir, "artifacts.json"), JSON.stringify({ runId: context.record.id, artifacts }, null, 2) + `
88782
+ writeFileSync15(join43(context.runDir, "artifacts.json"), JSON.stringify({ runId: context.record.id, artifacts }, null, 2) + `
88535
88783
  `);
88536
88784
  }
88537
88785
  function collectRunArtifacts(context) {
@@ -88544,7 +88792,7 @@ function collectRunArtifacts(context) {
88544
88792
  artifacts.push({
88545
88793
  path: toProjectRelative(context.targetDir, path),
88546
88794
  mime: mimeForPath(path),
88547
- sha256: createHash20("sha256").update(bytes).digest("hex"),
88795
+ sha256: createHash22("sha256").update(bytes).digest("hex"),
88548
88796
  sizeBytes: stat2.size
88549
88797
  });
88550
88798
  }
@@ -92501,11 +92749,11 @@ var require_codegen = __commonJS((exports) => {
92501
92749
  const rhs = this.rhs === undefined ? "" : ` = ${this.rhs}`;
92502
92750
  return `${varKind} ${this.name}${rhs};` + _n;
92503
92751
  }
92504
- optimizeNames(names, constants15) {
92752
+ optimizeNames(names, constants16) {
92505
92753
  if (!names[this.name.str])
92506
92754
  return;
92507
92755
  if (this.rhs)
92508
- this.rhs = optimizeExpr(this.rhs, names, constants15);
92756
+ this.rhs = optimizeExpr(this.rhs, names, constants16);
92509
92757
  return this;
92510
92758
  }
92511
92759
  get names() {
@@ -92523,10 +92771,10 @@ var require_codegen = __commonJS((exports) => {
92523
92771
  render({ _n }) {
92524
92772
  return `${this.lhs} = ${this.rhs};` + _n;
92525
92773
  }
92526
- optimizeNames(names, constants15) {
92774
+ optimizeNames(names, constants16) {
92527
92775
  if (this.lhs instanceof code_1.Name && !names[this.lhs.str] && !this.sideEffects)
92528
92776
  return;
92529
- this.rhs = optimizeExpr(this.rhs, names, constants15);
92777
+ this.rhs = optimizeExpr(this.rhs, names, constants16);
92530
92778
  return this;
92531
92779
  }
92532
92780
  get names() {
@@ -92592,8 +92840,8 @@ var require_codegen = __commonJS((exports) => {
92592
92840
  optimizeNodes() {
92593
92841
  return `${this.code}` ? this : undefined;
92594
92842
  }
92595
- optimizeNames(names, constants15) {
92596
- this.code = optimizeExpr(this.code, names, constants15);
92843
+ optimizeNames(names, constants16) {
92844
+ this.code = optimizeExpr(this.code, names, constants16);
92597
92845
  return this;
92598
92846
  }
92599
92847
  get names() {
@@ -92623,12 +92871,12 @@ var require_codegen = __commonJS((exports) => {
92623
92871
  }
92624
92872
  return nodes.length > 0 ? this : undefined;
92625
92873
  }
92626
- optimizeNames(names, constants15) {
92874
+ optimizeNames(names, constants16) {
92627
92875
  const { nodes } = this;
92628
92876
  let i = nodes.length;
92629
92877
  while (i--) {
92630
92878
  const n2 = nodes[i];
92631
- if (n2.optimizeNames(names, constants15))
92879
+ if (n2.optimizeNames(names, constants16))
92632
92880
  continue;
92633
92881
  subtractNames(names, n2.names);
92634
92882
  nodes.splice(i, 1);
@@ -92685,12 +92933,12 @@ var require_codegen = __commonJS((exports) => {
92685
92933
  return;
92686
92934
  return this;
92687
92935
  }
92688
- optimizeNames(names, constants15) {
92936
+ optimizeNames(names, constants16) {
92689
92937
  var _a3;
92690
- this.else = (_a3 = this.else) === null || _a3 === undefined ? undefined : _a3.optimizeNames(names, constants15);
92691
- if (!(super.optimizeNames(names, constants15) || this.else))
92938
+ this.else = (_a3 = this.else) === null || _a3 === undefined ? undefined : _a3.optimizeNames(names, constants16);
92939
+ if (!(super.optimizeNames(names, constants16) || this.else))
92692
92940
  return;
92693
- this.condition = optimizeExpr(this.condition, names, constants15);
92941
+ this.condition = optimizeExpr(this.condition, names, constants16);
92694
92942
  return this;
92695
92943
  }
92696
92944
  get names() {
@@ -92715,10 +92963,10 @@ var require_codegen = __commonJS((exports) => {
92715
92963
  render(opts) {
92716
92964
  return `for(${this.iteration})` + super.render(opts);
92717
92965
  }
92718
- optimizeNames(names, constants15) {
92719
- if (!super.optimizeNames(names, constants15))
92966
+ optimizeNames(names, constants16) {
92967
+ if (!super.optimizeNames(names, constants16))
92720
92968
  return;
92721
- this.iteration = optimizeExpr(this.iteration, names, constants15);
92969
+ this.iteration = optimizeExpr(this.iteration, names, constants16);
92722
92970
  return this;
92723
92971
  }
92724
92972
  get names() {
@@ -92756,10 +93004,10 @@ var require_codegen = __commonJS((exports) => {
92756
93004
  render(opts) {
92757
93005
  return `for(${this.varKind} ${this.name} ${this.loop} ${this.iterable})` + super.render(opts);
92758
93006
  }
92759
- optimizeNames(names, constants15) {
92760
- if (!super.optimizeNames(names, constants15))
93007
+ optimizeNames(names, constants16) {
93008
+ if (!super.optimizeNames(names, constants16))
92761
93009
  return;
92762
- this.iterable = optimizeExpr(this.iterable, names, constants15);
93010
+ this.iterable = optimizeExpr(this.iterable, names, constants16);
92763
93011
  return this;
92764
93012
  }
92765
93013
  get names() {
@@ -92804,11 +93052,11 @@ var require_codegen = __commonJS((exports) => {
92804
93052
  (_b = this.finally) === null || _b === undefined || _b.optimizeNodes();
92805
93053
  return this;
92806
93054
  }
92807
- optimizeNames(names, constants15) {
93055
+ optimizeNames(names, constants16) {
92808
93056
  var _a3, _b;
92809
- super.optimizeNames(names, constants15);
92810
- (_a3 = this.catch) === null || _a3 === undefined || _a3.optimizeNames(names, constants15);
92811
- (_b = this.finally) === null || _b === undefined || _b.optimizeNames(names, constants15);
93057
+ super.optimizeNames(names, constants16);
93058
+ (_a3 = this.catch) === null || _a3 === undefined || _a3.optimizeNames(names, constants16);
93059
+ (_b = this.finally) === null || _b === undefined || _b.optimizeNames(names, constants16);
92812
93060
  return this;
92813
93061
  }
92814
93062
  get names() {
@@ -93082,7 +93330,7 @@ var require_codegen = __commonJS((exports) => {
93082
93330
  function addExprNames(names, from) {
93083
93331
  return from instanceof code_1._CodeOrName ? addNames(names, from.names) : names;
93084
93332
  }
93085
- function optimizeExpr(expr, names, constants15) {
93333
+ function optimizeExpr(expr, names, constants16) {
93086
93334
  if (expr instanceof code_1.Name)
93087
93335
  return replaceName(expr);
93088
93336
  if (!canOptimize(expr))
@@ -93097,14 +93345,14 @@ var require_codegen = __commonJS((exports) => {
93097
93345
  return items;
93098
93346
  }, []));
93099
93347
  function replaceName(n2) {
93100
- const c = constants15[n2.str];
93348
+ const c = constants16[n2.str];
93101
93349
  if (c === undefined || names[n2.str] !== 1)
93102
93350
  return n2;
93103
93351
  delete names[n2.str];
93104
93352
  return c;
93105
93353
  }
93106
93354
  function canOptimize(e2) {
93107
- return e2 instanceof code_1._Code && e2._items.some((c) => c instanceof code_1.Name && names[c.str] === 1 && constants15[c.str] !== undefined);
93355
+ return e2 instanceof code_1._Code && e2._items.some((c) => c instanceof code_1.Name && names[c.str] === 1 && constants16[c.str] !== undefined);
93108
93356
  }
93109
93357
  }
93110
93358
  function subtractNames(names, from) {
@@ -100681,7 +100929,7 @@ var init_remote_invitation_recovery = __esm(() => {
100681
100929
  });
100682
100930
 
100683
100931
  // src/lib/remote-private-publications.ts
100684
- import { createHash as createHash21 } from "crypto";
100932
+ import { createHash as createHash23 } from "crypto";
100685
100933
  function checkedPublicationDeclaration(value) {
100686
100934
  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)
100687
100935
  return bad();
@@ -100942,7 +101190,7 @@ var PRIVATE_PUBLICATION_MAX_BYTES, failures2, PrivatePublicationError, bad = ()
100942
101190
  throw new PrivatePublicationError("INVALID_PUBLICATION_INPUT", "Invalid publication input or recovery data.");
100943
101191
  }, invalid5 = () => {
100944
101192
  throw new PrivatePublicationError("INVALID_PUBLICATION_RESPONSE", "The server returned an invalid publication result.");
100945
- }, 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) => createHash21("sha256").update(bytes).digest("hex");
101193
+ }, 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");
100946
101194
  var init_remote_private_publications = __esm(() => {
100947
101195
  init_fleet_credentials();
100948
101196
  init_remote_workspace_selection();
@@ -101219,11 +101467,11 @@ var init_remote_auth = __esm(() => {
101219
101467
  });
101220
101468
 
101221
101469
  // src/lib/workspace-profile.ts
101222
- import { constants as constants15, closeSync as closeSync16, fstatSync as fstatSync16, lstatSync as lstatSync22, mkdirSync as mkdirSync16, mkdtempSync as mkdtempSync5, openSync as openSync16, readFileSync as readFileSync31, renameSync as renameSync9, rmSync as rmSync8, writeFileSync as writeFileSync15 } from "fs";
101223
- import { dirname as dirname20, join as join44 } from "path";
101470
+ import { constants as constants16, closeSync as closeSync17, fstatSync as fstatSync17, lstatSync as lstatSync23, mkdirSync as mkdirSync16, mkdtempSync as mkdtempSync5, openSync as openSync17, readFileSync as readFileSync31, renameSync as renameSync9, rmSync as rmSync8, writeFileSync as writeFileSync16 } from "fs";
101471
+ import { dirname as dirname21, join as join44 } from "path";
101224
101472
  function stat2(path) {
101225
101473
  try {
101226
- return lstatSync22(path);
101474
+ return lstatSync23(path);
101227
101475
  } catch (error61) {
101228
101476
  if (error61.code === "ENOENT")
101229
101477
  return null;
@@ -101233,14 +101481,14 @@ function stat2(path) {
101233
101481
  function safeText(file2) {
101234
101482
  if (stat2(file2) === null)
101235
101483
  return null;
101236
- const fd = openSync16(file2, constants15.O_RDONLY | constants15.O_NOFOLLOW | constants15.O_NONBLOCK);
101484
+ const fd = openSync17(file2, constants16.O_RDONLY | constants16.O_NOFOLLOW | constants16.O_NONBLOCK);
101237
101485
  try {
101238
- const s = fstatSync16(fd);
101486
+ const s = fstatSync17(fd);
101239
101487
  if (!s.isFile() || s.size > 65536 || ![256, 384].includes(s.mode & 4095) || process.getuid && s.uid !== process.getuid())
101240
- return fail2("The selected profile must use bounded owner-only regular files.");
101488
+ return fail3("The selected profile must use bounded owner-only regular files.");
101241
101489
  return readFileSync31(fd, "utf8");
101242
101490
  } finally {
101243
- closeSync16(fd);
101491
+ closeSync17(fd);
101244
101492
  }
101245
101493
  }
101246
101494
  function checkIdentityMetadata(file2, identity4) {
@@ -101251,37 +101499,37 @@ function checkIdentityMetadata(file2, identity4) {
101251
101499
  try {
101252
101500
  value = JSON.parse(text3);
101253
101501
  } catch {
101254
- return fail2("The profile identity metadata is invalid. Sign in again before managing this workspace.");
101502
+ return fail3("The profile identity metadata is invalid. Sign in again before managing this workspace.");
101255
101503
  }
101256
101504
  if (!value || typeof value !== "object" || Array.isArray(value))
101257
- return fail2("The profile identity metadata is invalid.");
101505
+ return fail3("The profile identity metadata is invalid.");
101258
101506
  for (const [key, expected] of Object.entries({ userId: identity4.user.id, orgId: identity4.organization.id })) {
101259
101507
  if (value[key] !== undefined && value[key] !== expected)
101260
- return fail2("The profile identity metadata does not match its authenticated key. Sign in again before managing this workspace.");
101508
+ return fail3("The profile identity metadata does not match its authenticated key. Sign in again before managing this workspace.");
101261
101509
  }
101262
101510
  }
101263
101511
  async function keyIdentity(key, origin) {
101264
101512
  const value = await new RemoteSkillsClient(key, origin).getIdentity();
101265
101513
  if (value.authMethod !== "api_key")
101266
- return fail2("The selected credential is not a workspace API key.");
101514
+ return fail3("The selected credential is not a workspace API key.");
101267
101515
  const user = value.user;
101268
101516
  return parseWorkspaceIdentity(value, workspaceExpectedUserId(user?.id));
101269
101517
  }
101270
101518
  function prepareProfileWorkspace(action, source = process.env) {
101271
101519
  const env3 = { ...source }, origin = getApiUrl(action, env3), profile = selectedSkillsProfile(env3);
101272
- const unchanged2 = captureSkillsCredentialFiles(skillsProfileCredentialFiles(env3));
101520
+ const unchanged3 = captureSkillsCredentialFiles(skillsProfileCredentialFiles(env3));
101273
101521
  return { origin, async resolve() {
101274
- unchanged2();
101522
+ unchanged3();
101275
101523
  if (!profile)
101276
- return { origin, context: undefined, unchanged: unchanged2 };
101524
+ return { origin, context: undefined, unchanged: unchanged3 };
101277
101525
  const connection = await resolveSkillsConnection(env3);
101278
101526
  if (!connection || connection.apiOrigin !== origin)
101279
- return fail2("The selected profile has no usable credential for this server.");
101527
+ return fail3("The selected profile has no usable credential for this server.");
101280
101528
  const identity4 = await keyIdentity(connection.apiKey, origin);
101281
101529
  checkIdentityMetadata(getIdentityFilePath(env3), identity4);
101282
- unchanged2();
101530
+ unchanged3();
101283
101531
  const context = { userId: identity4.user.id, membershipId: identity4.user.membershipId };
101284
- return { origin, context, unchanged: unchanged2 };
101532
+ return { origin, context, unchanged: unchanged3 };
101285
101533
  } };
101286
101534
  }
101287
101535
  async function captureProfileWorkspace(action, source = process.env) {
@@ -101291,9 +101539,9 @@ async function prepareWorkspaceEnrollment(membershipId, source = process.env) {
101291
101539
  workspaceExpectedUserId(membershipId);
101292
101540
  const env3 = { ...source }, profile = selectedSkillsProfile(env3);
101293
101541
  if (!profile)
101294
- return fail2("Workspace login requires an explicit HASNA_PROFILE name.");
101542
+ return fail3("Workspace login requires an explicit HASNA_PROFILE name.");
101295
101543
  if (["HASNA_SKILLS_API_KEY_OVERRIDE", "HASNA_SKILLS_API_KEY_REF", "HASNA_SKILLS_API_KEY", "SKILLS_API_KEY"].some((name) => env3[name]?.trim()))
101296
- return fail2("Clear injected API keys before enrolling a named workspace profile.");
101544
+ return fail3("Clear injected API keys before enrolling a named workspace profile.");
101297
101545
  const origin = getApiUrl("Sign in to a workspace", env3);
101298
101546
  const file2 = getAuthFilePath(env3), identityFile = getIdentityFilePath(env3);
101299
101547
  const paths = [...new Set([...skillsProfileCredentialFiles(env3), file2, identityFile])];
@@ -101304,17 +101552,17 @@ async function prepareWorkspaceEnrollment(membershipId, source = process.env) {
101304
101552
  const credentialBody = (key) => [...lines.filter(Boolean), `HASNA_SKILLS_API_KEY=${key}`, `HASNA_SKILLS_API_URL=${origin}`, `HASNA_SKILLS_BOUND_API_URL=${origin}`, ""].join(`
101305
101553
  `);
101306
101554
  if (Buffer.byteLength(credentialBody("x".repeat(8192)), "utf8") > 65536)
101307
- return fail2("The selected profile has insufficient space for a bounded credential. Reduce its unrelated configuration before signing in.");
101555
+ return fail3("The selected profile has insufficient space for a bounded credential. Reduce its unrelated configuration before signing in.");
101308
101556
  const parents3 = [];
101309
- for (let path = dirname20(file2);; path = dirname20(path)) {
101557
+ for (let path = dirname21(file2);; path = dirname21(path)) {
101310
101558
  const before2 = stat2(path);
101311
101559
  if (before2 && (!before2.isDirectory() || before2.isSymbolicLink()))
101312
- return fail2("The profile directory must not be a symbolic link.");
101560
+ return fail3("The profile directory must not be a symbolic link.");
101313
101561
  parents3.push([path, before2]);
101314
- if (path === dirname20(path))
101562
+ if (path === dirname21(path))
101315
101563
  break;
101316
101564
  }
101317
- const unchanged2 = () => {
101565
+ const unchanged3 = () => {
101318
101566
  unchangedFiles();
101319
101567
  for (const [path, before2] of parents3) {
101320
101568
  const now3 = stat2(path);
@@ -101327,7 +101575,7 @@ async function prepareWorkspaceEnrollment(membershipId, source = process.env) {
101327
101575
  const connection = await resolveSkillsConnection(env3);
101328
101576
  if (connection) {
101329
101577
  if (connection.apiKeyTier !== "profile" || connection.apiOrigin !== origin)
101330
- return fail2("Workspace login must resolve only the explicitly named profile.");
101578
+ return fail3("Workspace login must resolve only the explicitly named profile.");
101331
101579
  expected = await keyIdentity(connection.apiKey, origin);
101332
101580
  checkIdentityMetadata(identityFile, expected);
101333
101581
  }
@@ -101335,47 +101583,47 @@ async function prepareWorkspaceEnrollment(membershipId, source = process.env) {
101335
101583
  if (!(error61 instanceof SkillsFleetCredentialError && error61.code === "MISSING_API_CREDENTIAL" && (old === null || !/^\s*(?:export\s+)?(?:HASNA_SKILLS_API_KEY|SKILLS_API_KEY)\s*=/m.test(old))))
101336
101584
  throw error61;
101337
101585
  }
101338
- unchanged2();
101586
+ unchanged3();
101339
101587
  return {
101340
101588
  profile,
101341
101589
  origin,
101342
101590
  async complete(email4, code) {
101343
- unchanged2();
101591
+ unchanged3();
101344
101592
  if (!email4.includes("@") || !/^\d{6}$/.test(code))
101345
- return fail2("A fresh email and six-digit verification code are required.");
101593
+ return fail3("A fresh email and six-digit verification code are required.");
101346
101594
  if (expected && expected.user.email.toLowerCase() !== email4.toLowerCase())
101347
- return fail2("This profile belongs to another account. Use a different profile or ordinary replacement login.");
101595
+ return fail3("This profile belongs to another account. Use a different profile or ordinary replacement login.");
101348
101596
  let issued = false;
101349
101597
  try {
101350
101598
  const result2 = await new RemoteSkillsAuthClient(origin).verifyCode(email4, code);
101351
101599
  const login = parseWorkspaceLogin(result2, expected?.user.id);
101352
101600
  if (result2.firstLogin === true)
101353
- return fail2("This sign-in created a new account using the server signup policy. Finish ordinary account login before enrolling a workspace profile.");
101601
+ return fail3("This sign-in created a new account using the server signup policy. Finish ordinary account login before enrolling a workspace profile.");
101354
101602
  const session = await new RemoteSkillsClient(login.token, origin).switchWorkspace({ userId: login.userId, membershipId });
101355
101603
  if (session.user.email.toLowerCase() !== email4.toLowerCase())
101356
- return fail2("The verified account does not match the requested email.");
101604
+ return fail3("The verified account does not match the requested email.");
101357
101605
  if (session.user.role === "viewer")
101358
- return fail2("Viewer memberships cannot enroll API keys.");
101359
- unchanged2();
101606
+ return fail3("Viewer memberships cannot enroll API keys.");
101607
+ unchanged3();
101360
101608
  issued = true;
101361
101609
  const created = await new RemoteSkillsClient(session.token, origin).createApiKey("cli");
101362
101610
  const verified = await keyIdentity(created.key, origin);
101363
101611
  if (verified.user.id !== session.user.id || verified.user.membershipId !== membershipId || verified.organization.id !== session.organization.id)
101364
- return fail2("The issued key does not match the selected workspace.");
101365
- unchanged2();
101612
+ return fail3("The issued key does not match the selected workspace.");
101613
+ unchanged3();
101366
101614
  if (!created.key.trim() || /[^\x21-\x7e]/.test(created.key) || created.key.length > 8192)
101367
- return fail2("The server returned an invalid API key.");
101615
+ return fail3("The server returned an invalid API key.");
101368
101616
  const body = credentialBody(created.key);
101369
101617
  if (Buffer.byteLength(body, "utf8") > 65536)
101370
- return fail2("The new profile exceeds the credential reader size limit.");
101618
+ return fail3("The new profile exceeds the credential reader size limit.");
101371
101619
  const identity4 = JSON.stringify({ email: verified.user.email, userId: verified.user.id, orgId: verified.organization.id, orgSlug: verified.organization.slug, apiUrl: origin }, null, 2) + `
101372
101620
  `;
101373
- mkdirSync16(dirname20(file2), { recursive: true, mode: 448 });
101374
- const temp = mkdtempSync5(join44(dirname20(file2), ".workspace-login-"));
101621
+ mkdirSync16(dirname21(file2), { recursive: true, mode: 448 });
101622
+ const temp = mkdtempSync5(join44(dirname21(file2), ".workspace-login-"));
101375
101623
  let identityInstalled = false;
101376
101624
  try {
101377
- writeFileSync15(join44(temp, "credentials"), body, { mode: 384, flag: "wx" });
101378
- writeFileSync15(join44(temp, "identity"), identity4, { mode: 384, flag: "wx" });
101625
+ writeFileSync16(join44(temp, "credentials"), body, { mode: 384, flag: "wx" });
101626
+ writeFileSync16(join44(temp, "identity"), identity4, { mode: 384, flag: "wx" });
101379
101627
  unchangedFiles();
101380
101628
  for (const [path, before2] of parents3) {
101381
101629
  const now3 = stat2(path);
@@ -101392,7 +101640,7 @@ async function prepareWorkspaceEnrollment(membershipId, source = process.env) {
101392
101640
  if (oldIdentity === null)
101393
101641
  rmSync8(identityFile, { force: true });
101394
101642
  else {
101395
- writeFileSync15(join44(temp, "restore"), oldIdentity, { mode: 384, flag: "wx" });
101643
+ writeFileSync16(join44(temp, "restore"), oldIdentity, { mode: 384, flag: "wx" });
101396
101644
  renameSync9(join44(temp, "restore"), identityFile);
101397
101645
  }
101398
101646
  }
@@ -101414,17 +101662,17 @@ async function prepareWorkspaceEnrollment(membershipId, source = process.env) {
101414
101662
  };
101415
101663
  } catch (error61) {
101416
101664
  if (issued)
101417
- return fail2("Workspace key issuance was attempted, but enrollment could not be confirmed. Inspect the selected profile and workspace keys before retrying; do not retry automatically.");
101665
+ return fail3("Workspace key issuance was attempted, but enrollment could not be confirmed. Inspect the selected profile and workspace keys before retrying; do not retry automatically.");
101418
101666
  if (error61 instanceof WorkspaceProfileError)
101419
101667
  throw error61;
101420
- return fail2("Unable to verify and select the workspace. Check the account, membership, selected server and fresh code. No enrollment key was requested.");
101668
+ return fail3("Unable to verify and select the workspace. Check the account, membership, selected server and fresh code. No enrollment key was requested.");
101421
101669
  }
101422
101670
  }
101423
101671
  };
101424
101672
  }
101425
- var WorkspaceProfileError, fail2 = (message) => {
101673
+ var WorkspaceProfileError, fail3 = (message) => {
101426
101674
  throw new WorkspaceProfileError(message);
101427
- }, changed = () => fail2("The selected profile changed during sign-in. No credential was saved; retry with a stable profile.");
101675
+ }, changed = () => fail3("The selected profile changed during sign-in. No credential was saved; retry with a stable profile.");
101428
101676
  var init_workspace_profile = __esm(() => {
101429
101677
  init_auth_store();
101430
101678
  init_fleet_credentials();
@@ -101587,8 +101835,8 @@ var init_recurring_customer = __esm(() => {
101587
101835
  });
101588
101836
 
101589
101837
  // src/lib/recurring-recovery.ts
101590
- import { constants as constants16, closeSync as closeSync17, fsyncSync as fsyncSync4, fstatSync as fstatSync17, lstatSync as lstatSync23, mkdirSync as mkdirSync17, openSync as openSync17, readSync as readSync13, realpathSync as realpathSync8, renameSync as renameSync10, unlinkSync as unlinkSync6, writeFileSync as writeFileSync16 } from "fs";
101591
- import { dirname as dirname21, isAbsolute as isAbsolute17, join as join45, resolve as resolve19 } from "path";
101838
+ import { constants as constants17, closeSync as closeSync18, fsyncSync as fsyncSync5, fstatSync as fstatSync18, lstatSync as lstatSync24, mkdirSync as mkdirSync17, openSync as openSync18, readSync as readSync14, realpathSync as realpathSync8, renameSync as renameSync10, unlinkSync as unlinkSync6, writeFileSync as writeFileSync17 } from "fs";
101839
+ import { dirname as dirname22, isAbsolute as isAbsolute17, join as join45, resolve as resolve19 } from "path";
101592
101840
  import { randomUUID as randomUUID7 } from "crypto";
101593
101841
 
101594
101842
  class RecoveryOwner {
@@ -101598,12 +101846,12 @@ class RecoveryOwner {
101598
101846
  this.directory = directory;
101599
101847
  if (!isAbsolute17(directory) || resolve19(directory) !== directory || realpathSync8(directory) !== directory)
101600
101848
  invalid6();
101601
- for (let path = directory;; path = dirname21(path)) {
101602
- const stat3 = lstatSync23(path);
101849
+ for (let path = directory;; path = dirname22(path)) {
101850
+ const stat3 = lstatSync24(path);
101603
101851
  if (!stat3.isDirectory() || stat3.isSymbolicLink())
101604
101852
  invalid6();
101605
101853
  this.parents.push({ path, dev: stat3.dev, ino: stat3.ino });
101606
- if (path === dirname21(path))
101854
+ if (path === dirname22(path))
101607
101855
  break;
101608
101856
  }
101609
101857
  this.assert();
@@ -101612,59 +101860,59 @@ class RecoveryOwner {
101612
101860
  if (realpathSync8(this.directory) !== this.directory)
101613
101861
  invalid6();
101614
101862
  for (const prior of this.parents) {
101615
- const now3 = lstatSync23(prior.path);
101863
+ const now3 = lstatSync24(prior.path);
101616
101864
  if (!now3.isDirectory() || now3.isSymbolicLink() || now3.dev !== prior.dev || now3.ino !== prior.ino)
101617
101865
  invalid6();
101618
101866
  }
101619
- const own2 = lstatSync23(this.directory);
101867
+ const own2 = lstatSync24(this.directory);
101620
101868
  if ((own2.mode & 511) !== 448 || (own2.mode & 3584) !== 0 || process.getuid && own2.uid !== process.getuid())
101621
101869
  invalid6();
101622
101870
  }
101623
101871
  read(name) {
101624
101872
  this.assert();
101625
- const fd = openSync17(join45(this.directory, name), constants16.O_RDONLY | constants16.O_NOFOLLOW | constants16.O_NONBLOCK);
101873
+ const fd = openSync18(join45(this.directory, name), constants17.O_RDONLY | constants17.O_NOFOLLOW | constants17.O_NONBLOCK);
101626
101874
  try {
101627
- const before2 = fstatSync17(fd);
101875
+ const before2 = fstatSync18(fd);
101628
101876
  if (!before2.isFile() || before2.nlink !== 1 || (before2.mode & 4095) !== 384 || before2.size < 1 || before2.size > 8192 || process.getuid && before2.uid !== process.getuid())
101629
101877
  invalid6();
101630
101878
  const bytes = Buffer.alloc(before2.size + 1);
101631
101879
  let size2 = 0;
101632
101880
  while (size2 < bytes.length) {
101633
- const n2 = readSync13(fd, bytes, size2, bytes.length - size2, size2);
101881
+ const n2 = readSync14(fd, bytes, size2, bytes.length - size2, size2);
101634
101882
  if (!n2)
101635
101883
  break;
101636
101884
  size2 += n2;
101637
101885
  }
101638
- const after2 = fstatSync17(fd), path = lstatSync23(join45(this.directory, name));
101886
+ const after2 = fstatSync18(fd), path = lstatSync24(join45(this.directory, name));
101639
101887
  if (size2 !== before2.size || after2.size !== before2.size || before2.mtimeMs !== after2.mtimeMs || before2.ctimeMs !== after2.ctimeMs || path.dev !== before2.dev || path.ino !== before2.ino || !path.isFile() || path.isSymbolicLink())
101640
101888
  invalid6();
101641
101889
  this.assert();
101642
101890
  return new TextDecoder("utf-8", { fatal: true }).decode(bytes.subarray(0, size2));
101643
101891
  } finally {
101644
- closeSync17(fd);
101892
+ closeSync18(fd);
101645
101893
  }
101646
101894
  }
101647
101895
  write(name, value) {
101648
101896
  this.assert();
101649
101897
  const bytes = canonicalJson2(value, 8192) + `
101650
101898
  `;
101651
- const fd = openSync17(join45(this.directory, name), constants16.O_WRONLY | constants16.O_CREAT | constants16.O_EXCL | constants16.O_NOFOLLOW, 384);
101899
+ const fd = openSync18(join45(this.directory, name), constants17.O_WRONLY | constants17.O_CREAT | constants17.O_EXCL | constants17.O_NOFOLLOW, 384);
101652
101900
  try {
101653
- writeFileSync16(fd, bytes);
101654
- fsyncSync4(fd);
101901
+ writeFileSync17(fd, bytes);
101902
+ fsyncSync5(fd);
101655
101903
  } finally {
101656
- closeSync17(fd);
101904
+ closeSync18(fd);
101657
101905
  }
101658
101906
  this.assert();
101659
101907
  this.sync();
101660
101908
  }
101661
101909
  sync() {
101662
101910
  this.assert();
101663
- const fd = openSync17(this.directory, constants16.O_RDONLY | constants16.O_NOFOLLOW);
101911
+ const fd = openSync18(this.directory, constants17.O_RDONLY | constants17.O_NOFOLLOW);
101664
101912
  try {
101665
- fsyncSync4(fd);
101913
+ fsyncSync5(fd);
101666
101914
  } finally {
101667
- closeSync17(fd);
101915
+ closeSync18(fd);
101668
101916
  }
101669
101917
  }
101670
101918
  saveState(state, expected) {
@@ -101682,20 +101930,20 @@ class RecoveryOwner {
101682
101930
  this.assert();
101683
101931
  let fd;
101684
101932
  try {
101685
- fd = openSync17(join45(this.directory, "operation.lock"), constants16.O_WRONLY | constants16.O_CREAT | constants16.O_EXCL | constants16.O_NOFOLLOW, 384);
101933
+ fd = openSync18(join45(this.directory, "operation.lock"), constants17.O_WRONLY | constants17.O_CREAT | constants17.O_EXCL | constants17.O_NOFOLLOW, 384);
101686
101934
  } catch {
101687
101935
  throw new RecurringCustomerError("RECURRING_RECOVERY_BUSY", "Recovery is locked. Confirm the original process has stopped before explicitly reconciling the retained lock; no request was retried.");
101688
101936
  }
101689
- const owner2 = fstatSync17(fd);
101937
+ const owner2 = fstatSync18(fd);
101690
101938
  try {
101691
- writeFileSync16(fd, JSON.stringify({ pid: process.pid }));
101692
- fsyncSync4(fd);
101939
+ writeFileSync17(fd, JSON.stringify({ pid: process.pid }));
101940
+ fsyncSync5(fd);
101693
101941
  this.sync();
101694
101942
  return await action();
101695
101943
  } finally {
101696
- closeSync17(fd);
101944
+ closeSync18(fd);
101697
101945
  this.assert();
101698
- const now3 = lstatSync23(join45(this.directory, "operation.lock"));
101946
+ const now3 = lstatSync24(join45(this.directory, "operation.lock"));
101699
101947
  if (owner2.dev !== now3.dev || owner2.ino !== now3.ino || !now3.isFile() || now3.isSymbolicLink())
101700
101948
  invalid6();
101701
101949
  unlinkSync6(join45(this.directory, "operation.lock"));
@@ -101731,7 +101979,7 @@ function base2(customer, organizationId) {
101731
101979
  };
101732
101980
  }
101733
101981
  function create3(directory, intent) {
101734
- if (!isAbsolute17(directory) || resolve19(directory) !== directory || realpathSync8(dirname21(directory)) !== dirname21(directory))
101982
+ if (!isAbsolute17(directory) || resolve19(directory) !== directory || realpathSync8(dirname22(directory)) !== dirname22(directory))
101735
101983
  invalid6();
101736
101984
  mkdirSync17(directory, { mode: 448 });
101737
101985
  const owner2 = new RecoveryOwner(directory), checked = intentSchema.parse(intent), intentSha256 = canonicalJsonSha256(checked);
@@ -101790,7 +102038,7 @@ async function continueRecurringRecovery(customer, directory, options) {
101790
102038
  pending = state.phase === "pending";
101791
102039
  bindRecurringRecovery(customer, intent);
101792
102040
  await customer.assertCurrent();
101793
- const save = (next) => {
102041
+ const save2 = (next) => {
101794
102042
  owner2.saveState(next, stateText);
101795
102043
  state = next;
101796
102044
  stateText = owner2.read("state.json");
@@ -101814,7 +102062,7 @@ async function continueRecurringRecovery(customer, directory, options) {
101814
102062
  } else {
101815
102063
  const consent2 = consentMatches(await customer.call("get", { consentId: intent.consentId }), intent);
101816
102064
  if (consent2.revokedAt !== null) {
101817
- save({ ...state, phase: "observed", consentId: consent2.consentId });
102065
+ save2({ ...state, phase: "observed", consentId: consent2.consentId });
101818
102066
  return result2(consent2);
101819
102067
  }
101820
102068
  if (!captured.confirm)
@@ -101832,20 +102080,20 @@ async function continueRecurringRecovery(customer, directory, options) {
101832
102080
  owner2.assert();
101833
102081
  await active.assertCurrent();
101834
102082
  const previousUnknown = pending;
101835
- save({ ...state, phase: "pending", consentId: null });
102083
+ save2({ ...state, phase: "pending", consentId: null });
101836
102084
  pending = true;
101837
102085
  let response;
101838
102086
  try {
101839
102087
  response = intent.operation === "activate" ? await active.call("activate", { draftId: intent.draftId, approval: intent.approval }) : await active.call("revoke", { consentId: intent.consentId });
101840
102088
  } catch (error61) {
101841
102089
  if (!previousUnknown && (error61 instanceof RemoteRecurringError || error61 instanceof RemoteRecurringReadError || error61 instanceof RemoteRecurringUnavailableError || error61 instanceof RecurringInputError)) {
101842
- save({ ...state, phase: "prepared", consentId: null });
102090
+ save2({ ...state, phase: "prepared", consentId: null });
101843
102091
  pending = false;
101844
102092
  }
101845
102093
  throw error61;
101846
102094
  }
101847
102095
  const consentId = "consent" in response ? response.consent.consentId : response.consentId;
101848
- save({ ...state, phase: "observed", consentId });
102096
+ save2({ ...state, phase: "observed", consentId });
101849
102097
  return result2(response);
101850
102098
  });
101851
102099
  pending = false;
@@ -101856,7 +102104,7 @@ async function continueRecurringRecovery(customer, directory, options) {
101856
102104
  throw error61;
101857
102105
  }
101858
102106
  }
101859
- var uuid12, sha2, common2, intentSchema, stateSchema, invalid6 = () => {
102107
+ var uuid12, sha3, common2, intentSchema, stateSchema, invalid6 = () => {
101860
102108
  throw new RecurringCustomerError("RECURRING_RECOVERY_INVALID", "The original recovery directory or record is invalid or changed. Preserve it; do not create a replacement activation automatically.");
101861
102109
  };
101862
102110
  var init_recurring_recovery = __esm(() => {
@@ -101866,7 +102114,7 @@ var init_recurring_recovery = __esm(() => {
101866
102114
  init_remote_recurring();
101867
102115
  init_recurring_customer();
101868
102116
  uuid12 = exports_external.string().regex(/^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/);
101869
- sha2 = exports_external.string().regex(/^[a-f0-9]{64}$/);
102117
+ sha3 = exports_external.string().regex(/^[a-f0-9]{64}$/);
101870
102118
  common2 = exports_external.object({
101871
102119
  contractVersion: exports_external.literal(1),
101872
102120
  apiOrigin: exports_external.string().min(1).max(4096),
@@ -101879,7 +102127,7 @@ var init_recurring_recovery = __esm(() => {
101879
102127
  common2.extend({
101880
102128
  operation: exports_external.literal("activate"),
101881
102129
  draftId: uuid12,
101882
- termsSha256: sha2,
102130
+ termsSha256: sha3,
101883
102131
  approvalDeadline: exports_external.string().datetime(),
101884
102132
  approval: recurringActivationSchema
101885
102133
  }).strict(),
@@ -101887,7 +102135,7 @@ var init_recurring_recovery = __esm(() => {
101887
102135
  ]);
101888
102136
  stateSchema = exports_external.object({
101889
102137
  contractVersion: exports_external.literal(1),
101890
- intentSha256: sha2,
102138
+ intentSha256: sha3,
101891
102139
  phase: exports_external.enum(["prepared", "pending", "observed"]),
101892
102140
  consentId: uuid12.nullable()
101893
102141
  }).strict();
@@ -103917,14 +104165,14 @@ var init_operation_tools = __esm(() => {
103917
104165
 
103918
104166
  // src/lib/feedback.ts
103919
104167
  import { appendFileSync as appendFileSync2, existsSync as existsSync29, mkdirSync as mkdirSync18 } from "fs";
103920
- import { dirname as dirname22, join as join47 } from "path";
104168
+ import { dirname as dirname23, join as join47 } from "path";
103921
104169
  import { Database } from "bun:sqlite";
103922
104170
  function getFeedbackDbPath() {
103923
104171
  return join47(getDataDir(), "skills.db");
103924
104172
  }
103925
104173
  function getFeedbackDb() {
103926
104174
  const dbPath = getFeedbackDbPath();
103927
- const dir = dirname22(dbPath);
104175
+ const dir = dirname23(dbPath);
103928
104176
  if (!existsSync29(dir))
103929
104177
  mkdirSync18(dir, { recursive: true });
103930
104178
  const db = new Database(dbPath);
@@ -103953,7 +104201,7 @@ function saveFeedback(input2) {
103953
104201
  const category = input2.category ?? "general";
103954
104202
  if (isApiMode()) {
103955
104203
  const path = join47(getDataDir(), "feedback.jsonl");
103956
- const dir = dirname22(path);
104204
+ const dir = dirname23(path);
103957
104205
  if (!existsSync29(dir))
103958
104206
  mkdirSync18(dir, { recursive: true });
103959
104207
  appendFileSync2(path, JSON.stringify({ message, category, email: input2.email ?? null, agent: input2.agent ?? null, version: input2.version ?? null, createdAt: new Date().toISOString() }) + `
@@ -104116,7 +104364,7 @@ var init_resource_meta_tools = __esm(() => {
104116
104364
  });
104117
104365
 
104118
104366
  // src/lib/scheduler.ts
104119
- import { existsSync as existsSync30, readFileSync as readFileSync32, writeFileSync as writeFileSync17, mkdirSync as mkdirSync19 } from "fs";
104367
+ import { existsSync as existsSync30, readFileSync as readFileSync32, writeFileSync as writeFileSync18, mkdirSync as mkdirSync19 } from "fs";
104120
104368
  import { join as join48 } from "path";
104121
104369
  function getSchedulesPath(targetDir = process.cwd()) {
104122
104370
  return join48(targetDir, ".skills", "schedules.json");
@@ -104135,7 +104383,7 @@ function saveSchedules(data, targetDir = process.cwd()) {
104135
104383
  const dir = join48(targetDir, ".skills");
104136
104384
  if (!existsSync30(dir))
104137
104385
  mkdirSync19(dir, { recursive: true });
104138
- writeFileSync17(path, JSON.stringify(data, null, 2));
104386
+ writeFileSync18(path, JSON.stringify(data, null, 2));
104139
104387
  }
104140
104388
  function validateCronField(expr, min2, max2, label) {
104141
104389
  for (const part of expr.split(",")) {
@@ -104175,11 +104423,11 @@ function validateCronField(expr, min2, max2, label) {
104175
104423
  return { valid: true };
104176
104424
  }
104177
104425
  function validateCron(expr) {
104178
- const fields = expr.trim().split(/\s+/);
104179
- if (fields.length !== 5) {
104180
- return { valid: false, error: `Expected 5 fields, got ${fields.length}. Format: "minute hour day-of-month month day-of-week"` };
104426
+ const fields2 = expr.trim().split(/\s+/);
104427
+ if (fields2.length !== 5) {
104428
+ return { valid: false, error: `Expected 5 fields, got ${fields2.length}. Format: "minute hour day-of-month month day-of-week"` };
104181
104429
  }
104182
- const [minuteF, hourF, domF, monthF, dowF] = fields;
104430
+ const [minuteF, hourF, domF, monthF, dowF] = fields2;
104183
104431
  const checks4 = [
104184
104432
  { expr: minuteF, min: 0, max: 59, label: "minute" },
104185
104433
  { expr: hourF, min: 0, max: 23, label: "hour" },
@@ -104431,16 +104679,16 @@ var init_schedule_tools = __esm(() => {
104431
104679
  });
104432
104680
 
104433
104681
  // src/lib/native-storage.ts
104434
- import { createHash as createHash22, createHmac as createHmac3 } from "crypto";
104682
+ import { createHash as createHash24, createHmac as createHmac3 } from "crypto";
104435
104683
  import {
104436
104684
  existsSync as existsSync31,
104437
104685
  mkdirSync as mkdirSync20,
104438
104686
  readFileSync as readFileSync33,
104439
104687
  readdirSync as readdirSync18,
104440
104688
  statSync as statSync17,
104441
- writeFileSync as writeFileSync18
104689
+ writeFileSync as writeFileSync19
104442
104690
  } from "fs";
104443
- import { dirname as dirname23, join as join49, normalize as normalize3, relative as relative7, sep as sep7 } from "path";
104691
+ import { dirname as dirname24, join as join49, normalize as normalize3, relative as relative7, sep as sep7 } from "path";
104444
104692
  function resolveSkillsNativeStorageConfig(env3 = process.env) {
104445
104693
  assertNoRetiredModeEnvVars(env3, {
104446
104694
  app: SKILLS_ENV_NAMESPACE,
@@ -104508,7 +104756,7 @@ function exportSkillsLocalSnapshot(targetDir = process.cwd(), options = {}) {
104508
104756
  files.push({
104509
104757
  path: relativePath,
104510
104758
  sizeBytes: bytes.byteLength,
104511
- sha256: createHash22("sha256").update(bytes).digest("hex"),
104759
+ sha256: createHash24("sha256").update(bytes).digest("hex"),
104512
104760
  ...options.includeFileContents ? { contentBase64: Buffer.from(bytes).toString("base64") } : {}
104513
104761
  });
104514
104762
  }
@@ -104519,9 +104767,9 @@ function exportSkillsLocalSnapshot(targetDir = process.cwd(), options = {}) {
104519
104767
  files: files.sort((a, b) => a.path.localeCompare(b.path))
104520
104768
  };
104521
104769
  }
104522
- function planSkillsS3SnapshotUpload(snapshot, options = {}) {
104770
+ function planSkillsS3SnapshotUpload(snapshot2, options = {}) {
104523
104771
  const prefix = normalizeS3Prefix(options.prefix);
104524
- return snapshot.files.map((file2) => ({
104772
+ return snapshot2.files.map((file2) => ({
104525
104773
  path: file2.path,
104526
104774
  key: [prefix, file2.path.replace(/^\.?\//, "")].filter(Boolean).join("/"),
104527
104775
  sizeBytes: file2.sizeBytes,
@@ -104662,14 +104910,14 @@ function registerStorageTools(server) {
104662
104910
  }, async ({ directory: directory2, includeSchemaSql }) => {
104663
104911
  const targetDir = directory2 || process.cwd();
104664
104912
  const config2 = resolveStorageConfig();
104665
- const snapshot = exportSkillsLocalSnapshot(targetDir, { includeFileContents: false });
104666
- const s3Plan = config2.s3Bucket ? planSkillsS3SnapshotUpload(snapshot, { prefix: config2.s3Prefix }) : [];
104913
+ const snapshot2 = exportSkillsLocalSnapshot(targetDir, { includeFileContents: false });
104914
+ const s3Plan = config2.s3Bucket ? planSkillsS3SnapshotUpload(snapshot2, { prefix: config2.s3Prefix }) : [];
104667
104915
  return mcpJson({
104668
104916
  package: "skills",
104669
104917
  noNetwork: true,
104670
104918
  databaseConfigured: Boolean(config2.databaseUrl),
104671
104919
  s3Configured: Boolean(config2.s3Bucket),
104672
- snapshotFileCount: snapshot.files.length,
104920
+ snapshotFileCount: snapshot2.files.length,
104673
104921
  s3ObjectCount: s3Plan.length,
104674
104922
  env: {
104675
104923
  databaseUrl: SKILLS_NATIVE_STORAGE_ENV.databaseUrl,
@@ -104800,73 +105048,73 @@ var init_private_publication_customer = __esm(() => {
104800
105048
  });
104801
105049
 
104802
105050
  // src/lib/private-publication-recovery.ts
104803
- import { constants as constants17, closeSync as closeSync18, fsyncSync as fsyncSync5, fstatSync as fstatSync18, lstatSync as lstatSync24, mkdirSync as mkdirSync21, openSync as openSync18, readSync as readSync14, realpathSync as realpathSync9, renameSync as renameSync11, unlinkSync as unlinkSync7, writeFileSync as writeFileSync19 } from "fs";
104804
- import { dirname as dirname24, isAbsolute as isAbsolute19, join as join50, resolve as resolve20 } from "path";
105051
+ import { constants as constants18, closeSync as closeSync19, fsyncSync as fsyncSync6, fstatSync as fstatSync19, lstatSync as lstatSync25, mkdirSync as mkdirSync21, openSync as openSync19, readSync as readSync15, realpathSync as realpathSync9, renameSync as renameSync11, unlinkSync as unlinkSync7, writeFileSync as writeFileSync20 } from "fs";
105052
+ import { dirname as dirname25, isAbsolute as isAbsolute19, join as join50, resolve as resolve20 } from "path";
104805
105053
  import { randomUUID as randomUUID8 } from "crypto";
104806
105054
  function safeDirectory(directory2) {
104807
105055
  if (!isAbsolute19(directory2) || directory2 !== resolve20(directory2) || realpathSync9(directory2) !== directory2)
104808
- return fail3();
104809
- for (let path = directory2;; path = dirname24(path)) {
104810
- const stat3 = lstatSync24(path);
105056
+ return fail4();
105057
+ for (let path = directory2;; path = dirname25(path)) {
105058
+ const stat3 = lstatSync25(path);
104811
105059
  if (!stat3.isDirectory() || stat3.isSymbolicLink())
104812
- return fail3();
104813
- if (path === dirname24(path))
105060
+ return fail4();
105061
+ if (path === dirname25(path))
104814
105062
  break;
104815
105063
  }
104816
- const own2 = lstatSync24(directory2);
105064
+ const own2 = lstatSync25(directory2);
104817
105065
  if ((own2.mode & 63) !== 0 || process.getuid && own2.uid !== process.getuid())
104818
- return fail3();
105066
+ return fail4();
104819
105067
  return { dev: own2.dev, ino: own2.ino };
104820
105068
  }
104821
105069
  function unchangedDirectory(directory2, identity4) {
104822
105070
  const now3 = safeDirectory(directory2);
104823
105071
  if (now3.dev !== identity4.dev || now3.ino !== identity4.ino)
104824
- return fail3();
105072
+ return fail4();
104825
105073
  }
104826
105074
  function readOwned(directory2, name, max2) {
104827
105075
  const identity4 = safeDirectory(directory2), file2 = join50(directory2, name);
104828
- const fd = openSync18(file2, constants17.O_RDONLY | constants17.O_NOFOLLOW);
105076
+ const fd = openSync19(file2, constants18.O_RDONLY | constants18.O_NOFOLLOW);
104829
105077
  try {
104830
- const stat3 = fstatSync18(fd);
105078
+ const stat3 = fstatSync19(fd);
104831
105079
  if (!stat3.isFile() || stat3.nlink !== 1 || stat3.size > max2 || stat3.size < 1 || (stat3.mode & 63) !== 0 || process.getuid && stat3.uid !== process.getuid())
104832
- return fail3();
105080
+ return fail4();
104833
105081
  const buffer = Buffer.alloc(Math.min(max2, stat3.size) + 1);
104834
105082
  let length = 0;
104835
105083
  while (length < buffer.length) {
104836
- const count = readSync14(fd, buffer, length, buffer.length - length, length);
105084
+ const count = readSync15(fd, buffer, length, buffer.length - length, length);
104837
105085
  if (count === 0)
104838
105086
  break;
104839
105087
  length += count;
104840
105088
  }
104841
- const bytes = buffer.subarray(0, length), after2 = fstatSync18(fd);
105089
+ const bytes = buffer.subarray(0, length), after2 = fstatSync19(fd);
104842
105090
  unchangedDirectory(directory2, identity4);
104843
105091
  if (bytes.length !== stat3.size || stat3.size !== after2.size || stat3.mtimeMs !== after2.mtimeMs || stat3.ctimeMs !== after2.ctimeMs)
104844
- return fail3();
105092
+ return fail4();
104845
105093
  return bytes;
104846
105094
  } finally {
104847
- closeSync18(fd);
105095
+ closeSync19(fd);
104848
105096
  }
104849
105097
  }
104850
105098
  function writeOwned(directory2, name, bytes) {
104851
- const fd = openSync18(join50(directory2, name), constants17.O_WRONLY | constants17.O_CREAT | constants17.O_EXCL | constants17.O_NOFOLLOW, 384);
105099
+ const fd = openSync19(join50(directory2, name), constants18.O_WRONLY | constants18.O_CREAT | constants18.O_EXCL | constants18.O_NOFOLLOW, 384);
104852
105100
  try {
104853
- writeFileSync19(fd, bytes);
104854
- fsyncSync5(fd);
105101
+ writeFileSync20(fd, bytes);
105102
+ fsyncSync6(fd);
104855
105103
  } finally {
104856
- closeSync18(fd);
105104
+ closeSync19(fd);
104857
105105
  }
104858
105106
  }
104859
- function save(directory2, value) {
105107
+ function save2(directory2, value) {
104860
105108
  const identity4 = safeDirectory(directory2), temporary = `.receipt-${randomUUID8()}.json`;
104861
105109
  writeOwned(directory2, temporary, JSON.stringify(value) + `
104862
105110
  `);
104863
105111
  unchangedDirectory(directory2, identity4);
104864
105112
  renameSync11(join50(directory2, temporary), join50(directory2, "receipt.json"));
104865
- const fd = openSync18(directory2, constants17.O_RDONLY | constants17.O_NOFOLLOW);
105113
+ const fd = openSync19(directory2, constants18.O_RDONLY | constants18.O_NOFOLLOW);
104866
105114
  try {
104867
- fsyncSync5(fd);
105115
+ fsyncSync6(fd);
104868
105116
  } finally {
104869
- closeSync18(fd);
105117
+ closeSync19(fd);
104870
105118
  }
104871
105119
  }
104872
105120
  function bind2(client2, receipt) {
@@ -104877,22 +105125,22 @@ async function locked(directory2, action) {
104877
105125
  const identity4 = safeDirectory(directory2), file2 = join50(directory2, "operation.lock");
104878
105126
  let fd;
104879
105127
  try {
104880
- fd = openSync18(file2, constants17.O_WRONLY | constants17.O_CREAT | constants17.O_EXCL | constants17.O_NOFOLLOW, 384);
105128
+ fd = openSync19(file2, constants18.O_WRONLY | constants18.O_CREAT | constants18.O_EXCL | constants18.O_NOFOLLOW, 384);
104881
105129
  } catch {
104882
105130
  throw new PrivatePublicationError("PUBLICATION_RECOVERY_BUSY", "Another operation holds this recovery directory. If it crashed, confirm that process has stopped before explicitly removing operation.lock and resuming.");
104883
105131
  }
104884
- const lock = fstatSync18(fd);
105132
+ const lock = fstatSync19(fd);
104885
105133
  try {
104886
- writeFileSync19(fd, JSON.stringify({ pid: process.pid }) + `
105134
+ writeFileSync20(fd, JSON.stringify({ pid: process.pid }) + `
104887
105135
  `);
104888
- fsyncSync5(fd);
105136
+ fsyncSync6(fd);
104889
105137
  return await action();
104890
105138
  } finally {
104891
- closeSync18(fd);
105139
+ closeSync19(fd);
104892
105140
  unchangedDirectory(directory2, identity4);
104893
- const now3 = lstatSync24(file2);
105141
+ const now3 = lstatSync25(file2);
104894
105142
  if (now3.dev !== lock.dev || now3.ino !== lock.ino || !now3.isFile() || now3.isSymbolicLink())
104895
- fail3();
105143
+ fail4();
104896
105144
  unlinkSync7(file2);
104897
105145
  }
104898
105146
  }
@@ -104900,23 +105148,23 @@ function readPrivatePublicationRecovery(directory2) {
104900
105148
  try {
104901
105149
  const value = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(readOwned(directory2, "receipt.json", 65536)));
104902
105150
  if (!value || typeof value !== "object" || Array.isArray(value) || Object.keys(value).sort().join(",") !== ["contractVersion", "apiOrigin", "organizationId", "userId", "membershipId", "skillId", "declaration", "phase", "intent"].sort().join(",") || value.contractVersion !== 1 || ![value.organizationId, value.userId, value.membershipId, value.skillId].every(publicationUuid) || typeof value.apiOrigin !== "string" || normalizeSkillsApiOrigin(value.apiOrigin) !== value.apiOrigin || !["prepared", "begin_uncertain", "awaiting_upload", "upload_uncertain", "uploaded", "finalize_uncertain", "observed"].includes(value.phase))
104903
- return fail3();
105151
+ return fail4();
104904
105152
  value.declaration = checkedPublicationDeclaration(value.declaration);
104905
105153
  if (value.intent !== null)
104906
105154
  value.intent = checkedPublicationView(value.intent, value.skillId, undefined, value.declaration);
104907
105155
  if (value.intent === null && !["prepared", "begin_uncertain"].includes(value.phase))
104908
- return fail3();
105156
+ return fail4();
104909
105157
  const bytes = readOwned(directory2, "bundle.tgz", PRIVATE_PUBLICATION_MAX_BYTES);
104910
105158
  if (bytes.length !== value.declaration.archiveByteSize || publicationSha256(bytes) !== value.declaration.archiveSha256)
104911
- return fail3();
105159
+ return fail4();
104912
105160
  return { receipt: value, bytes };
104913
105161
  } catch {
104914
- return fail3();
105162
+ return fail4();
104915
105163
  }
104916
105164
  }
104917
105165
  async function preparePrivatePublication(client2, sourceDirectory, recoveryDirectory, input2) {
104918
105166
  if (!publicationUuid(input2.skillId) || !(input2.expectedCurrentVersionId === null || publicationUuid(input2.expectedCurrentVersionId)) || input2.idempotencyKey !== undefined && !publicationUuid(input2.idempotencyKey))
104919
- return fail3();
105167
+ return fail4();
104920
105168
  const packed = packSkillBundle(sourceDirectory, { maxUnpackedBytes: 32 * 1024 * 1024 });
104921
105169
  const inspected = await inspectSkillBundle(packed.bytes, { limits: { compressedBytes: PRIVATE_PUBLICATION_MAX_BYTES } });
104922
105170
  const manifest = inspected.entries.find((entry) => entry.path === "skill.json");
@@ -104942,18 +105190,18 @@ async function preparePrivatePublication(client2, sourceDirectory, recoveryDirec
104942
105190
  phase: "prepared",
104943
105191
  intent: null
104944
105192
  };
104945
- if (!isAbsolute19(recoveryDirectory) || resolve20(recoveryDirectory) !== recoveryDirectory || realpathSync9(dirname24(recoveryDirectory)) !== dirname24(recoveryDirectory))
104946
- return fail3();
105193
+ if (!isAbsolute19(recoveryDirectory) || resolve20(recoveryDirectory) !== recoveryDirectory || realpathSync9(dirname25(recoveryDirectory)) !== dirname25(recoveryDirectory))
105194
+ return fail4();
104947
105195
  mkdirSync21(recoveryDirectory, { mode: 448 });
104948
105196
  safeDirectory(recoveryDirectory);
104949
- const parent = openSync18(dirname24(recoveryDirectory), constants17.O_RDONLY | constants17.O_NOFOLLOW);
105197
+ const parent = openSync19(dirname25(recoveryDirectory), constants18.O_RDONLY | constants18.O_NOFOLLOW);
104950
105198
  try {
104951
- fsyncSync5(parent);
105199
+ fsyncSync6(parent);
104952
105200
  } finally {
104953
- closeSync18(parent);
105201
+ closeSync19(parent);
104954
105202
  }
104955
105203
  writeOwned(recoveryDirectory, "bundle.tgz", packed.bytes);
104956
- save(recoveryDirectory, receipt);
105204
+ save2(recoveryDirectory, receipt);
104957
105205
  return receipt;
104958
105206
  }
104959
105207
  function privatePublicationResult(directory2, receipt) {
@@ -104974,7 +105222,7 @@ async function continuePrivatePublication(client2, directory2, options) {
104974
105222
  if (options.confirm !== true)
104975
105223
  throw new PrivatePublicationError("PUBLICATION_CONFIRM_REQUIRED", "Explicit upload confirmation is required.");
104976
105224
  if (options.waitMs !== undefined && (!Number.isSafeInteger(options.waitMs) || options.waitMs < 0 || options.waitMs > 300000))
104977
- return fail3();
105225
+ return fail4();
104978
105226
  return locked(directory2, () => continueLocked(client2, directory2, options));
104979
105227
  }
104980
105228
  async function continueLocked(client2, directory2, options) {
@@ -104982,40 +105230,40 @@ async function continueLocked(client2, directory2, options) {
104982
105230
  bind2(client2, receipt);
104983
105231
  if (!receipt.intent) {
104984
105232
  receipt.phase = "begin_uncertain";
104985
- save(directory2, receipt);
105233
+ save2(directory2, receipt);
104986
105234
  receipt.intent = await client2.begin(receipt.skillId, receipt.declaration);
104987
105235
  receipt.phase = "awaiting_upload";
104988
- save(directory2, receipt);
105236
+ save2(directory2, receipt);
104989
105237
  } else {
104990
105238
  receipt.intent = checkedPublicationView(await client2.get(receipt.skillId, receipt.intent.id), receipt.skillId, receipt.intent.id, receipt.declaration);
104991
- save(directory2, receipt);
105239
+ save2(directory2, receipt);
104992
105240
  }
104993
105241
  if (receipt.intent.state === "awaiting_upload") {
104994
105242
  if (receipt.phase === "awaiting_upload") {
104995
105243
  receipt.phase = "upload_uncertain";
104996
- save(directory2, receipt);
105244
+ save2(directory2, receipt);
104997
105245
  try {
104998
105246
  await client2.upload(receipt.skillId, receipt.intent, bytes);
104999
105247
  } catch (error61) {
105000
105248
  if (error61 instanceof PrivatePublicationError && !error61.uncertain) {
105001
105249
  receipt.phase = "awaiting_upload";
105002
- save(directory2, receipt);
105250
+ save2(directory2, receipt);
105003
105251
  }
105004
105252
  throw error61;
105005
105253
  }
105006
105254
  receipt.phase = "uploaded";
105007
- save(directory2, receipt);
105255
+ save2(directory2, receipt);
105008
105256
  }
105009
105257
  receipt.phase = "finalize_uncertain";
105010
- save(directory2, receipt);
105258
+ save2(directory2, receipt);
105011
105259
  receipt.intent = checkedPublicationView(await client2.finalize(receipt.skillId, receipt.intent.id), receipt.skillId, receipt.intent.id, receipt.declaration);
105012
105260
  receipt.phase = "observed";
105013
- save(directory2, receipt);
105261
+ save2(directory2, receipt);
105014
105262
  }
105015
105263
  if (options.waitMs !== undefined && options.waitMs > 0 && ["queued", "verifying"].includes(receipt.intent.state)) {
105016
105264
  receipt.intent = checkedPublicationView(await client2.wait(receipt.skillId, receipt.intent.id, { timeoutMs: options.waitMs }), receipt.skillId, receipt.intent.id, receipt.declaration);
105017
105265
  receipt.phase = "observed";
105018
- save(directory2, receipt);
105266
+ save2(directory2, receipt);
105019
105267
  }
105020
105268
  return privatePublicationResult(directory2, receipt);
105021
105269
  }
@@ -105027,12 +105275,12 @@ async function inspectLocked(client2, directory2, cancel) {
105027
105275
  bind2(client2, receipt);
105028
105276
  if (receipt.intent) {
105029
105277
  receipt.intent = checkedPublicationView(await (cancel ? client2.cancel(receipt.skillId, receipt.intent.id) : client2.get(receipt.skillId, receipt.intent.id)), receipt.skillId, receipt.intent.id, receipt.declaration);
105030
- save(directory2, receipt);
105278
+ save2(directory2, receipt);
105031
105279
  } else if (cancel)
105032
105280
  throw new PrivatePublicationError("PUBLICATION_INTENT_UNKNOWN", "Reconcile the saved begin request with publication resume before cancelling its intent.");
105033
105281
  return privatePublicationResult(directory2, receipt);
105034
105282
  }
105035
- var fail3 = () => {
105283
+ var fail4 = () => {
105036
105284
  throw new PrivatePublicationError("PUBLICATION_RECOVERY_INVALID", "The recovery directory is invalid or changed. Preserve it and inspect the existing intent; do not start a replacement automatically.");
105037
105285
  };
105038
105286
  var init_private_publication_recovery = __esm(() => {
@@ -105404,9 +105652,9 @@ var init_mcp2 = __esm(() => {
105404
105652
  });
105405
105653
 
105406
105654
  // src/cli/commands/runtime-mcp.ts
105407
- import { existsSync as existsSync32, mkdirSync as mkdirSync22, readFileSync as readFileSync34, writeFileSync as writeFileSync20 } from "fs";
105655
+ import { existsSync as existsSync32, mkdirSync as mkdirSync22, readFileSync as readFileSync34, writeFileSync as writeFileSync21 } from "fs";
105408
105656
  import { homedir as homedir9 } from "os";
105409
- import { dirname as dirname25, join as join51 } from "path";
105657
+ import { dirname as dirname26, join as join51 } from "path";
105410
105658
  async function handleMcp(options) {
105411
105659
  if (options.register) {
105412
105660
  let agents;
@@ -105580,8 +105828,8 @@ function writeJsonObject(path, data) {
105580
105828
  `);
105581
105829
  }
105582
105830
  function writeTextFile(path, content) {
105583
- mkdirSync22(dirname25(path), { recursive: true });
105584
- writeFileSync20(path, content.endsWith(`
105831
+ mkdirSync22(dirname26(path), { recursive: true });
105832
+ writeFileSync21(path, content.endsWith(`
105585
105833
  `) ? content : `${content}
105586
105834
  `);
105587
105835
  }
@@ -105690,8 +105938,8 @@ var exports_runtime = {};
105690
105938
  __export(exports_runtime, {
105691
105939
  registerRuntime: () => registerRuntime
105692
105940
  });
105693
- import { createHash as createHash23, randomUUID as randomUUID9 } from "crypto";
105694
- import { lstatSync as lstatSync25, mkdirSync as mkdirSync23, readFileSync as readFileSync35, realpathSync as realpathSync10, writeFileSync as writeFileSync21 } from "fs";
105941
+ import { createHash as createHash25, randomUUID as randomUUID9 } from "crypto";
105942
+ import { lstatSync as lstatSync26, mkdirSync as mkdirSync23, readFileSync as readFileSync35, realpathSync as realpathSync10, writeFileSync as writeFileSync22 } from "fs";
105695
105943
  import { basename as basename11, isAbsolute as isAbsolute21, join as join52 } from "path";
105696
105944
  import { createInterface } from "readline";
105697
105945
  function registerRuntime(parent) {
@@ -105731,9 +105979,9 @@ function registerRuntime(parent) {
105731
105979
  if (!expected)
105732
105980
  throw new Error("Cloud artifact not found");
105733
105981
  const bytes = await client2.download(id2, name);
105734
- if (bytes.length !== expected.byteSize || createHash23("sha256").update(bytes).digest("hex") !== expected.sha256)
105982
+ if (bytes.length !== expected.byteSize || createHash25("sha256").update(bytes).digest("hex") !== expected.sha256)
105735
105983
  throw new Error("Cloud artifact integrity verification failed");
105736
- writeFileSync21(options.output, bytes, { flag: "wx", mode: 384 });
105984
+ writeFileSync22(options.output, bytes, { flag: "wx", mode: 384 });
105737
105985
  console.log(JSON.stringify({ path: options.output, sha256: expected.sha256, byteSize: bytes.length }));
105738
105986
  } catch (error61) {
105739
105987
  console.error(JSON.stringify({ error: error61.message }));
@@ -106139,7 +106387,7 @@ async function handleRun(name, args2, options, separatorBeforeSkill) {
106139
106387
  try {
106140
106388
  parsePollingOptions(options);
106141
106389
  inputFiles = (options.file ?? []).map((path) => {
106142
- const info = lstatSync25(path);
106390
+ const info = lstatSync26(path);
106143
106391
  if (!info.isFile() || info.size > 20 * 1024 * 1024)
106144
106392
  throw new Error("Input must be a regular file no larger than 20 MiB");
106145
106393
  return { name: basename11(path), bytes: new Uint8Array(readFileSync35(path)) };
@@ -106530,7 +106778,7 @@ async function handleExportsDownload(runId2, options) {
106530
106778
  const relativePath = safeArtifactRelativePath(typeof artifact.relativePath === "string" ? artifact.relativePath : artifact.fileName, String(artifact.fileName || artifactId));
106531
106779
  const outputPath = join52(exportDir, relativePath);
106532
106780
  ensureSafeExportParent(exportDir, relativePath);
106533
- writeFileSync21(outputPath, verified.bytes, { flag: "wx", mode: 384 });
106781
+ writeFileSync22(outputPath, verified.bytes, { flag: "wx", mode: 384 });
106534
106782
  downloaded.push({ id: artifactId, path: outputPath, byteSize: verified.byteSize });
106535
106783
  }
106536
106784
  const payload = {
@@ -106569,7 +106817,7 @@ function ensureSafeExportParent(root2, relativePath) {
106569
106817
  if (part)
106570
106818
  parent = join52(parent, part);
106571
106819
  try {
106572
- if (!lstatSync25(parent).isDirectory() || lstatSync25(parent).isSymbolicLink())
106820
+ if (!lstatSync26(parent).isDirectory() || lstatSync26(parent).isSymbolicLink())
106573
106821
  throw new Error("Unsafe artifact directory");
106574
106822
  } catch (error61) {
106575
106823
  if (error61.code !== "ENOENT")
@@ -106861,30 +107109,30 @@ var exports_recurring = {};
106861
107109
  __export(exports_recurring, {
106862
107110
  registerRecurringCommands: () => registerRecurringCommands
106863
107111
  });
106864
- import { constants as constants18, closeSync as closeSync19, fstatSync as fstatSync19, lstatSync as lstatSync26, openSync as openSync19, readSync as readSync15 } from "fs";
107112
+ import { constants as constants19, closeSync as closeSync20, fstatSync as fstatSync20, lstatSync as lstatSync27, openSync as openSync20, readSync as readSync16 } from "fs";
106865
107113
  import { createInterface as createInterface2 } from "readline";
106866
107114
  function readRequest(path) {
106867
- const fd = openSync19(path, constants18.O_RDONLY | constants18.O_NOFOLLOW | constants18.O_NONBLOCK);
107115
+ const fd = openSync20(path, constants19.O_RDONLY | constants19.O_NOFOLLOW | constants19.O_NONBLOCK);
106868
107116
  try {
106869
- const before2 = fstatSync19(fd);
107117
+ const before2 = fstatSync20(fd);
106870
107118
  if (!before2.isFile() || before2.size > 1048576 || before2.size < 1)
106871
107119
  throw new RecurringInputError;
106872
107120
  const bytes = Buffer.alloc(before2.size + 1);
106873
107121
  let length = 0;
106874
107122
  while (length < bytes.length) {
106875
- const n2 = readSync15(fd, bytes, length, bytes.length - length, length);
107123
+ const n2 = readSync16(fd, bytes, length, bytes.length - length, length);
106876
107124
  if (!n2)
106877
107125
  break;
106878
107126
  length += n2;
106879
107127
  }
106880
- const after2 = fstatSync19(fd), current = lstatSync26(path);
107128
+ const after2 = fstatSync20(fd), current = lstatSync27(path);
106881
107129
  if (length !== before2.size || after2.size !== before2.size || before2.mtimeMs !== after2.mtimeMs || before2.ctimeMs !== after2.ctimeMs || current.dev !== before2.dev || current.ino !== before2.ino || !current.isFile() || current.isSymbolicLink())
106882
107130
  throw new RecurringInputError;
106883
107131
  return JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(bytes.subarray(0, length)));
106884
107132
  } catch {
106885
107133
  throw new RecurringInputError;
106886
107134
  } finally {
106887
- closeSync19(fd);
107135
+ closeSync20(fd);
106888
107136
  }
106889
107137
  }
106890
107138
  async function acceptAtTerminal(draft) {
@@ -107310,22 +107558,22 @@ var init_portable_snapshot_filter = __esm(() => {
107310
107558
  });
107311
107559
 
107312
107560
  // src/lib/station-snapshot.ts
107313
- import { createHash as createHash24 } from "crypto";
107561
+ import { createHash as createHash26 } from "crypto";
107314
107562
  import {
107315
107563
  copyFileSync,
107316
107564
  mkdirSync as mkdirSync24,
107317
107565
  readFileSync as readFileSync36,
107318
107566
  statSync as statSync19,
107319
- writeFileSync as writeFileSync22
107567
+ writeFileSync as writeFileSync23
107320
107568
  } from "fs";
107321
- import { dirname as dirname27, isAbsolute as isAbsolute22, relative as relative8, resolve as resolve21, sep as sep9 } from "path";
107569
+ import { dirname as dirname28, isAbsolute as isAbsolute22, relative as relative8, resolve as resolve21, sep as sep9 } from "path";
107322
107570
  function validateStationId(stationId) {
107323
107571
  if (!/^[a-z0-9-]+$/.test(stationId)) {
107324
107572
  throw new StationSnapshotError("INVALID_STATION", `station id must be a slug, got: ${stationId}`);
107325
107573
  }
107326
107574
  }
107327
107575
  function sha256File(filePath) {
107328
- return createHash24("sha256").update(readFileSync36(filePath)).digest("hex");
107576
+ return createHash26("sha256").update(readFileSync36(filePath)).digest("hex");
107329
107577
  }
107330
107578
  function scanHome(definition, homesRoot) {
107331
107579
  const homePath = homePathFor(definition, homesRoot);
@@ -107446,11 +107694,11 @@ function writeStationSnapshot(options) {
107446
107694
  let written = 0;
107447
107695
  for (const plan of untouched) {
107448
107696
  const destination = resolve21(repoRoot, plan.destination);
107449
- mkdirSync24(dirname27(destination), { recursive: true });
107697
+ mkdirSync24(dirname28(destination), { recursive: true });
107450
107698
  copyFileSync(plan.source.fullPath, destination);
107451
107699
  written += 1;
107452
107700
  }
107453
- const unchanged2 = plans.length - untouched.length;
107701
+ const unchanged3 = plans.length - untouched.length;
107454
107702
  const manifest = {
107455
107703
  schema: STATION_SYNC_MANIFEST_SCHEMA,
107456
107704
  stationId: options.stationId,
@@ -107458,20 +107706,20 @@ function writeStationSnapshot(options) {
107458
107706
  producer: STATION_SNAPSHOT_PRODUCER,
107459
107707
  stats: {
107460
107708
  written,
107461
- unchanged: unchanged2,
107709
+ unchanged: unchanged3,
107462
107710
  files: plans.length,
107463
107711
  bytes: totalBytes
107464
107712
  },
107465
107713
  files: manifestFiles
107466
107714
  };
107467
107715
  const manifestPath = resolve21(repoRoot, "resources", options.stationId, "skills", "sync-manifest.json");
107468
- mkdirSync24(dirname27(manifestPath), { recursive: true });
107469
- writeFileSync22(manifestPath, `${JSON.stringify(manifest, null, 2)}
107716
+ mkdirSync24(dirname28(manifestPath), { recursive: true });
107717
+ writeFileSync23(manifestPath, `${JSON.stringify(manifest, null, 2)}
107470
107718
  `);
107471
107719
  return {
107472
107720
  ...base3,
107473
107721
  mode: "populate",
107474
- stats: { files: plans.length, bytes: totalBytes, written, unchanged: unchanged2 },
107722
+ stats: { files: plans.length, bytes: totalBytes, written, unchanged: unchanged3 },
107475
107723
  manifestPath
107476
107724
  };
107477
107725
  }
@@ -107932,7 +108180,7 @@ async function connectCodexHookRpc(options) {
107932
108180
  });
107933
108181
  const pending = new Map;
107934
108182
  let nextId = 1, buffer = Buffer.alloc(0), stopped = false, diagnosticBytes = 0;
107935
- const fail4 = () => {
108183
+ const fail5 = () => {
107936
108184
  stopped = true;
107937
108185
  for (const value of pending.values()) {
107938
108186
  clearTimeout(value.timer);
@@ -107940,19 +108188,19 @@ async function connectCodexHookRpc(options) {
107940
108188
  }
107941
108189
  pending.clear();
107942
108190
  };
107943
- child.on("error", fail4);
107944
- child.on("exit", fail4);
107945
- child.stdin.on("error", fail4);
108191
+ child.on("error", fail5);
108192
+ child.on("exit", fail5);
108193
+ child.stdin.on("error", fail5);
107946
108194
  child.stderr.on("data", (bytes) => {
107947
108195
  diagnosticBytes += bytes.length;
107948
108196
  if (diagnosticBytes > 2 * 1024 * 1024) {
107949
- fail4();
108197
+ fail5();
107950
108198
  child.kill();
107951
108199
  }
107952
108200
  });
107953
108201
  child.stdout.on("data", (bytes) => {
107954
108202
  if (buffer.length + bytes.length > 8 * 1024 * 1024) {
107955
- fail4();
108203
+ fail5();
107956
108204
  child.kill();
107957
108205
  return;
107958
108206
  }
@@ -107967,12 +108215,12 @@ async function connectCodexHookRpc(options) {
107967
108215
  try {
107968
108216
  value = JSON.parse(line.toString("utf8"));
107969
108217
  } catch {
107970
- fail4();
108218
+ fail5();
107971
108219
  child.kill();
107972
108220
  return;
107973
108221
  }
107974
108222
  if (!value || typeof value !== "object" || Array.isArray(value)) {
107975
- fail4();
108223
+ fail5();
107976
108224
  child.kill();
107977
108225
  return;
107978
108226
  }
@@ -107996,7 +108244,7 @@ async function connectCodexHookRpc(options) {
107996
108244
  return new Promise((resolve22, reject2) => {
107997
108245
  const id2 = nextId++;
107998
108246
  const timer = setTimeout(() => {
107999
- fail4();
108247
+ fail5();
108000
108248
  child.kill();
108001
108249
  }, 20000);
108002
108250
  pending.set(id2, { resolve: resolve22, reject: reject2, timer });
@@ -108005,7 +108253,7 @@ async function connectCodexHookRpc(options) {
108005
108253
  });
108006
108254
  },
108007
108255
  async close() {
108008
- fail4();
108256
+ fail5();
108009
108257
  child.stdin.end();
108010
108258
  if (child.exitCode !== null || child.signalCode !== null)
108011
108259
  return;
@@ -108036,203 +108284,10 @@ var init_codex_hook_rpc = __esm(() => {
108036
108284
  SUPPORTED_CODEX_HOOK_VERSIONS = ["codex-cli 0.153.0", "codex-cli 0.154.0", "codex-cli 0.155.0", "codex-cli 0.155.1"];
108037
108285
  });
108038
108286
 
108039
- // src/lib/codex-hook-trust-layout.ts
108040
- import { isDeepStrictEqual as isDeepStrictEqual5 } from "util";
108041
- function codexTrustTextWitness(text3, keys3, canonicalize = true) {
108042
- const parsed = Bun.TOML.parse(text3), wanted = new Set(keys3);
108043
- const headers = [...text3.matchAll(/^[ \t]*(\[[^\r\n]+\])[ \t]*(#[^\r\n]*)?(?:\r?\n|$)/gm)];
108044
- if (headers.length > 512)
108045
- throw fail4();
108046
- let root2 = parsed;
108047
- for (const header of headers) {
108048
- try {
108049
- root2 = Bun.TOML.parse(text3.slice(0, header.index));
108050
- break;
108051
- } catch {}
108052
- }
108053
- if (root2.hooks !== undefined)
108054
- throw fail4();
108055
- const replacements2 = [];
108056
- const stateSections = [];
108057
- for (const [index, header] of headers.entries()) {
108058
- let shape;
108059
- try {
108060
- shape = Bun.TOML.parse(header[1]);
108061
- } catch {
108062
- continue;
108063
- }
108064
- const state = shape.hooks?.state;
108065
- if (!state || Object.keys(shape).length !== 1 || Object.keys(shape.hooks).length !== 1)
108066
- continue;
108067
- const names = Object.keys(state), start = header.index, end = headers[index + 1]?.index ?? text3.length;
108068
- if (names.length === 0) {
108069
- replacements2.push({ start, end: start + header[0].length, comments: header[2] ? header[2] + `
108070
- ` : "" });
108071
- stateSections.push({ start, end: start + header[0].length });
108072
- } else if (names.length === 1 && !Object.keys(state[names[0]]).length) {
108073
- stateSections.push({ start, end });
108074
- if (!wanted.has(names[0])) {
108075
- replacements2.push({ start, end: start + header[0].length, comments: `[hooks.state.${JSON.stringify(names[0])}]${header[2] ? " " + header[2] : ""}
108076
- ` });
108077
- continue;
108078
- }
108079
- const comments = header[2] ? [header[2]] : [];
108080
- for (const line of text3.slice(start + header[0].length, end).split(/\r?\n/)) {
108081
- if (!line.trim())
108082
- continue;
108083
- if (/^[ \t]*#/.test(line)) {
108084
- comments.push(line);
108085
- continue;
108086
- }
108087
- const field2 = /^[ \t]*(?:enabled|trusted_hash)[ \t]*=[ \t]*(?:true|false|"(?:[^"\\]|\\.)*"|'[^']*')[ \t]*(#[^\r\n]*)?$/.exec(line);
108088
- if (!field2)
108089
- throw fail4();
108090
- if (field2[1])
108091
- comments.push(field2[1]);
108092
- }
108093
- replacements2.push({ start, end, comments: comments.join(`
108094
- `) + `
108095
- ` });
108096
- }
108097
- }
108098
- let noState = text3;
108099
- for (const span of [...stateSections].reverse())
108100
- noState = noState.slice(0, span.start) + noState.slice(span.end);
108101
- const expected = structuredClone(parsed);
108102
- if (expected.hooks)
108103
- delete expected.hooks.state;
108104
- try {
108105
- if (!isDeepStrictEqual5(prune(Bun.TOML.parse(noState)), prune(expected)))
108106
- throw fail4();
108107
- } catch {
108108
- throw fail4();
108109
- }
108110
- let result2 = text3;
108111
- for (const span of replacements2.reverse())
108112
- result2 = result2.slice(0, span.start) + span.comments + result2.slice(span.end);
108113
- return (canonicalize ? canonicalizeTableOrder(result2) : result2).split(/\r?\n/).filter((line) => line.trim()).join(`
108114
- `);
108115
- }
108116
- function codexTrustReconcileWitness(text3, keys3) {
108117
- return codexTrustTextWitness(text3, keys3, false).replace(/[ \t]+$/gm, "");
108118
- }
108119
- function codexTrustUnmanagedSemantic(text3, keys3) {
108120
- const parsed = structuredClone(Bun.TOML.parse(text3));
108121
- for (const key of keys3)
108122
- if (parsed.hooks?.state?.[key] !== undefined)
108123
- delete parsed.hooks.state[key];
108124
- return JSON.stringify(stableSemantic(prune(parsed)));
108125
- }
108126
- var fail4 = () => new Error('CODEX_HOOK_TRUST_UNSUPPORTED_LAYOUT: preserve and convert hook trust to ordinary [hooks.state."<key>"] tables before enrollment'), prune = (value) => {
108127
- if (value.hooks?.state && !Object.keys(value.hooks.state).length)
108128
- delete value.hooks.state;
108129
- if (value.hooks && !Object.keys(value.hooks).length)
108130
- delete value.hooks;
108131
- return value;
108132
- }, canonicalizeTableOrder = (text3) => {
108133
- const headers = [...text3.matchAll(/^[ \t]*(\[\[?[^\r\n]+\]\]?)[ \t]*(#[^\r\n]*)?(?:\r?\n|$)/gm)];
108134
- if (!headers.length)
108135
- return text3;
108136
- const keys3 = headers.map((header) => header[1].trim());
108137
- const repeated = keys3.filter((key) => !key.startsWith("[[")).filter((key, index, simple2) => simple2.indexOf(key) !== index);
108138
- const arrayKeys = keys3.filter((key) => key.startsWith("[["));
108139
- const plain = keys3.map((key) => key.replace(/^\[\[?/, "").replace(/\]\]?$/, "").trim());
108140
- const parentChild = plain.some((key, index) => plain.some((other, otherIndex) => index !== otherIndex && (other.startsWith(`${key}.`) || key.startsWith(`${other}.`))));
108141
- if (repeated.length || parentChild)
108142
- return text3;
108143
- if (!arrayKeys.length) {
108144
- const first2 = headers[0].index;
108145
- const prefix2 = text3.slice(0, first2);
108146
- const blocks2 = headers.map((header, index) => ({
108147
- key: header[1],
108148
- order: index,
108149
- text: text3.slice(header.index, headers[index + 1]?.index ?? text3.length)
108150
- }));
108151
- blocks2.sort((a, b) => a.key.localeCompare(b.key) || a.order - b.order);
108152
- return prefix2 + blocks2.map((block) => block.text).join("");
108153
- }
108154
- const first = headers[0].index;
108155
- const prefix = text3.slice(0, first);
108156
- const blocks = headers.map((header, index) => ({
108157
- key: header[1],
108158
- order: index,
108159
- text: text3.slice(header.index, headers[index + 1]?.index ?? text3.length)
108160
- }));
108161
- const simple = blocks.filter((block) => !block.key.startsWith("[["));
108162
- const arrays = blocks.filter((block) => block.key.startsWith("[["));
108163
- return prefix + [...simple, ...arrays].map((block) => block.text).join("");
108164
- }, stableSemantic = (value) => {
108165
- if (Array.isArray(value))
108166
- return value.map(stableSemantic);
108167
- if (value && typeof value === "object")
108168
- return Object.fromEntries(Object.keys(value).sort().map((key) => [key, stableSemantic(value[key])]));
108169
- return value;
108170
- };
108171
- var init_codex_hook_trust_layout = () => {};
108172
-
108173
- // src/lib/codex-hook-trust-files.ts
108174
- import { closeSync as closeSync20, constants as constants19, fstatSync as fstatSync20, fsyncSync as fsyncSync6, lstatSync as lstatSync27, openSync as openSync20, readSync as readSync16, writeFileSync as writeFileSync23 } from "fs";
108175
- import { createHash as createHash25 } from "crypto";
108176
- import { dirname as dirname28 } from "path";
108177
- function need4(value, code2) {
108178
- if (!value)
108179
- throw new Error(`CODEX_HOOK_TRUST_${code2}`);
108180
- }
108181
- function safeParents(file2) {
108182
- for (let p = dirname28(file2);; p = dirname28(p)) {
108183
- const s = lstatSync27(p);
108184
- need4(s.isDirectory() && !s.isSymbolicLink(), "UNSAFE_PARENT");
108185
- need4((s.mode & 18) === 0 || s.uid === 0 && (s.mode & 512) !== 0, "UNSAFE_PARENT");
108186
- if (dirname28(p) === p)
108187
- break;
108188
- }
108189
- }
108190
- function snapshot(file2, privateFile = false, options = {}) {
108191
- const readOnlyPackage = options.readOnlyPackage === true && !privateFile;
108192
- safeParents(file2);
108193
- const initial2 = lstatSync27(file2, { bigint: true });
108194
- need4(initial2.isFile() && initial2.uid === BigInt(process.getuid()) && (initial2.nlink === 1n || readOnlyPackage && initial2.nlink > 1n) && (initial2.mode & 0o022n) === 0n && (!privateFile || (initial2.mode & 0o777n) === 0o600n), "UNSAFE_FILE");
108195
- need4(initial2.size <= 8n * 1024n * 1024n, "FILE_BOUND");
108196
- const fd = openSync20(file2, constants19.O_RDONLY | constants19.O_NOFOLLOW | constants19.O_NONBLOCK);
108197
- try {
108198
- const before2 = fstatSync20(fd, { bigint: true });
108199
- need4(sameStat(initial2, before2), "INPUT_CHANGED");
108200
- const bytes = Buffer.alloc(Number(before2.size) + 1);
108201
- let length = 0;
108202
- while (length < bytes.length) {
108203
- const n2 = readSync16(fd, bytes, length, bytes.length - length, null);
108204
- if (!n2)
108205
- break;
108206
- length += n2;
108207
- }
108208
- need4(length === Number(before2.size) && sameStat(before2, fstatSync20(fd, { bigint: true })) && sameStat(before2, lstatSync27(file2, { bigint: true })), "INPUT_CHANGED");
108209
- const content = bytes.subarray(0, length), text3 = new TextDecoder("utf-8", { fatal: true }).decode(content);
108210
- return { file: file2, privateFile, readOnlyPackage, text: text3, bytes: content, stat: before2, sha256: createHash25("sha256").update(content).digest("hex") };
108211
- } finally {
108212
- closeSync20(fd);
108213
- }
108214
- }
108215
- function unchanged2(before2) {
108216
- const after2 = snapshot(before2.file, before2.privateFile, before2.readOnlyPackage ? { readOnlyPackage: true } : {});
108217
- need4(sameStat(before2.stat, after2.stat) && after2.sha256 === before2.sha256, "INPUT_CHANGED");
108218
- }
108219
- function save2(file2, content) {
108220
- safeParents(file2);
108221
- const fd = openSync20(file2, constants19.O_WRONLY | constants19.O_CREAT | constants19.O_EXCL | constants19.O_NOFOLLOW, 384);
108222
- try {
108223
- writeFileSync23(fd, content);
108224
- fsyncSync6(fd);
108225
- } finally {
108226
- closeSync20(fd);
108227
- }
108228
- }
108229
- var sameStat = (a, b) => ["dev", "ino", "uid", "nlink", "mode", "size", "mtimeNs", "ctimeNs"].every((key) => a[key] === b[key]);
108230
- var init_codex_hook_trust_files = () => {};
108231
-
108232
108287
  // src/lib/codex-hook-trust-identity.ts
108233
108288
  import { realpathSync as realpathSync12 } from "fs";
108234
108289
  import { dirname as dirname29, isAbsolute as isAbsolute24, join as join55 } from "path";
108235
- import { isDeepStrictEqual as isDeepStrictEqual6 } from "util";
108290
+ import { isDeepStrictEqual as isDeepStrictEqual7 } from "util";
108236
108291
  function inspectRecordedSkillsCli(command, expected) {
108237
108292
  need4(isAbsolute24(command) && !command.includes("\x00"), "RECONCILE_RECORDED_COMMAND_REQUIRED");
108238
108293
  const resolved = realpathSync12(command);
@@ -108242,7 +108297,7 @@ function inspectRecordedSkillsCli(command, expected) {
108242
108297
  need4(pkg.name === "@hasna/skills" && /^\d+\.\d+\.\d+$/.test(pkg.version) && pkg.bin?.skills === "bin/index.js" && resolved === join55(dirname29(manifest.file), "bin/index.js"), "SKILLS_PACKAGE_MISMATCH");
108243
108298
  need4((cli.stat.mode & 0o100n) !== 0n, "SKILLS_COMMAND_NOT_EXECUTABLE");
108244
108299
  const receipt = { path: resolved, version: pkg.version, sha256: cli.sha256, manifestSha256: manifest.sha256 };
108245
- need4(isDeepStrictEqual6(receipt, expected), "RECONCILE_SKILLS_BINDING_CHANGED");
108300
+ need4(isDeepStrictEqual7(receipt, expected), "RECONCILE_SKILLS_BINDING_CHANGED");
108246
108301
  return { receipt, recheck() {
108247
108302
  need4(realpathSync12(command) === resolved, "SKILLS_COMMAND_CHANGED");
108248
108303
  unchanged2(cli);
@@ -108278,19 +108333,19 @@ var init_codex_hook_trust_identity = __esm(() => {
108278
108333
  });
108279
108334
 
108280
108335
  // src/lib/codex-hook-policy-recovery.ts
108281
- import { isDeepStrictEqual as isDeepStrictEqual7 } from "util";
108336
+ import { isDeepStrictEqual as isDeepStrictEqual8 } from "util";
108282
108337
  function reviewedClaudeDiscoveryChange(beforeText, currentText, options) {
108283
108338
  need4(typeof options.reason === "string" && options.reason.trim().length > 0 && options.reason.length <= 512 && !/[\x00-\x1f\x7f]/.test(options.reason), "RECONCILE_RECOVERY_REASON_REQUIRED");
108284
108339
  need4(options.reviewedPlanDigest === undefined || /^[a-f0-9]{64}$/.test(options.reviewedPlanDigest), "RECONCILE_RECOVERY_PLAN_CHANGED");
108285
108340
  const before2 = parseManagedSkillPolicy(beforeText), current = parseManagedSkillPolicy(currentText);
108286
108341
  const oldDiscovery = before2.bridge?.discovery?.claude, newDiscovery = current.bridge?.discovery?.claude;
108287
108342
  need4(oldDiscovery?.agent === "claude" && newDiscovery?.agent === "claude" && oldDiscovery.method === "reviewed" && newDiscovery.method === "reviewed", "RECONCILE_POLICY_CHANGED");
108288
- const changes = ["roots", "sources"].filter((key) => !isDeepStrictEqual7(oldDiscovery[key], newDiscovery[key])).map((key) => ({ path: `bridge.discovery.claude.${key}`, before: oldDiscovery[key], after: newDiscovery[key] }));
108343
+ const changes = ["roots", "sources"].filter((key) => !isDeepStrictEqual8(oldDiscovery[key], newDiscovery[key])).map((key) => ({ path: `bridge.discovery.claude.${key}`, before: oldDiscovery[key], after: newDiscovery[key] }));
108289
108344
  need4(changes.length > 0, "RECONCILE_POLICY_CHANGED");
108290
108345
  const compared = structuredClone(current);
108291
108346
  compared.bridge.discovery.claude.roots = oldDiscovery.roots;
108292
108347
  compared.bridge.discovery.claude.sources = oldDiscovery.sources;
108293
- need4(isDeepStrictEqual7(before2, compared), "RECONCILE_POLICY_CHANGED");
108348
+ need4(isDeepStrictEqual8(before2, compared), "RECONCILE_POLICY_CHANGED");
108294
108349
  verifyAgentDiscovery(newDiscovery);
108295
108350
  return { reason: options.reason, changes };
108296
108351
  }
@@ -108302,21 +108357,21 @@ var init_codex_hook_policy_recovery = __esm(() => {
108302
108357
 
108303
108358
  // src/lib/agent-codex-trust.ts
108304
108359
  import { lstatSync as lstatSync28, mkdirSync as mkdirSync25, readdirSync as readdirSync20, readFileSync as readFileSync37, realpathSync as realpathSync13, statSync as statSync21 } from "fs";
108305
- import { createHash as createHash26, randomUUID as randomUUID10 } from "crypto";
108360
+ import { createHash as createHash27, randomUUID as randomUUID10 } from "crypto";
108306
108361
  import { execFileSync } from "child_process";
108307
108362
  import { dirname as dirname30, isAbsolute as isAbsolute25, join as join56, resolve as resolve22 } from "path";
108308
108363
  import { homedir as homedir11 } from "os";
108309
- import { isDeepStrictEqual as isDeepStrictEqual8 } from "util";
108364
+ import { isDeepStrictEqual as isDeepStrictEqual9 } from "util";
108310
108365
  function verifyReleaseArtifact(proof, skillsCli) {
108311
108366
  need4(isAbsolute25(proof.packageTarPath) && !proof.packageTarPath.includes("\x00"), "RECONCILE_RELEASE_PROVENANCE_PATH");
108312
108367
  const tarPath = realpathSync13(proof.packageTarPath);
108313
108368
  need4(statSync21(tarPath).isFile(), "RECONCILE_RELEASE_PROVENANCE_PATH");
108314
108369
  const tarBytes = readFileSync37(tarPath);
108315
- need4(tarBytes.byteLength === proof.packageTarBytes && createHash26("sha256").update(tarBytes).digest("hex") === proof.packageTarSha256, "RECONCILE_RELEASE_ARTIFACT_CHANGED");
108370
+ need4(tarBytes.byteLength === proof.packageTarBytes && createHash27("sha256").update(tarBytes).digest("hex") === proof.packageTarSha256, "RECONCILE_RELEASE_ARTIFACT_CHANGED");
108316
108371
  const packageRoot = dirname30(dirname30(realpathSync13(skillsCli.receipt.path)));
108317
108372
  const manifest = readFileSync37(join56(packageRoot, "package.json"));
108318
- need4(createHash26("sha256").update(manifest).digest("hex") === skillsCli.receipt.manifestSha256 && skillsCli.receipt.manifestSha256 === proof.manifestSha256, "RECONCILE_RELEASE_MANIFEST_CHANGED");
108319
- need4(createHash26("sha256").update(readFileSync37(skillsCli.receipt.path)).digest("hex") === proof.executableSha256 && skillsCli.receipt.sha256 === proof.executableSha256, "RECONCILE_RELEASE_EXECUTABLE_CHANGED");
108373
+ need4(createHash27("sha256").update(manifest).digest("hex") === skillsCli.receipt.manifestSha256 && skillsCli.receipt.manifestSha256 === proof.manifestSha256, "RECONCILE_RELEASE_MANIFEST_CHANGED");
108374
+ need4(createHash27("sha256").update(readFileSync37(skillsCli.receipt.path)).digest("hex") === proof.executableSha256 && skillsCli.receipt.sha256 === proof.executableSha256, "RECONCILE_RELEASE_EXECUTABLE_CHANGED");
108320
108375
  const members2 = [["package/package.json", manifest], ["package/bin/index.js", readFileSync37(skillsCli.receipt.path)]];
108321
108376
  for (const [member, expected] of members2) {
108322
108377
  let actual;
@@ -108348,7 +108403,7 @@ async function reconcileCodexNativeHooks(options, connect = connectCodexHookRpc)
108348
108403
  const configSha256 = intent.configSha256 ?? configBefore.sha256, configVersion = intent.configVersion ?? intent.expectedVersion;
108349
108404
  const digestInput = { version: 1, home: intent.home ?? home, configPath: intent.configPath, ...intent.nativeConfigPath !== undefined ? { nativeConfigPath: intent.nativeConfigPath } : {}, configSha256, configVersion, policySha256: intent.policySha256, hooksSha256: intent.hooksSha256, skillsCli: intent.skillsCli, nativeVersion: intent.nativeVersion, declarations, admitted };
108350
108405
  need4(makePlanDigest(digestInput) === intent.planDigest, "RECONCILE_PLAN_CHANGED");
108351
- need4(isDeepStrictEqual8(intent.hooks, admitted.filter((hook) => !hook.enabled || hook.trustStatus !== "trusted")), "RECONCILE_INTENT_HOOKS_CHANGED");
108406
+ need4(isDeepStrictEqual9(intent.hooks, admitted.filter((hook) => !hook.enabled || hook.trustStatus !== "trusted")), "RECONCILE_INTENT_HOOKS_CHANGED");
108352
108407
  need4(configBefore.sha256 === (intent.beforeSha256 ?? intent.configSha256) && hooksBefore.sha256 === intent.hooksSha256 && policyBefore.sha256 === intent.policySha256, "RECONCILE_JOURNAL_CHANGED");
108353
108408
  const policyCurrent = snapshot(join56(dataDir3, "agent-policy.json"), true);
108354
108409
  const recovery = options.claudeDiscoveryRecovery;
@@ -108358,7 +108413,7 @@ async function reconcileCodexNativeHooks(options, connect = connectCodexHookRpc)
108358
108413
  if (policyCurrent.sha256 !== policyBefore.sha256 && !recovery) {
108359
108414
  need4(options.supersedeBinding === true, "RECONCILE_POLICY_CHANGED");
108360
108415
  const oldPolicy = JSON.parse(policyBefore.text), currentPolicy = JSON.parse(policyCurrent.text);
108361
- need4(isDeepStrictEqual8(withoutCodexCommand(oldPolicy), withoutCodexCommand(currentPolicy)), "RECONCILE_POLICY_CHANGED");
108416
+ need4(isDeepStrictEqual9(withoutCodexCommand(oldPolicy), withoutCodexCommand(currentPolicy)), "RECONCILE_POLICY_CHANGED");
108362
108417
  supersededBinding = true;
108363
108418
  }
108364
108419
  if (supersededBinding || recovery) {
@@ -108371,7 +108426,7 @@ async function reconcileCodexNativeHooks(options, connect = connectCodexHookRpc)
108371
108426
  const witnessSame = codexTrustReconcileWitness(configBefore.text, managedKeys) === codexTrustReconcileWitness(currentConfig.text, managedKeys);
108372
108427
  const unmanagedSame = codexTrustUnmanagedSemantic(configBefore.text, managedKeys) === codexTrustUnmanagedSemantic(currentConfig.text, managedKeys);
108373
108428
  need4(unmanagedSame && (witnessSame || supersededBinding), "RECONCILE_UNRELATED_CONFIG_CHANGED");
108374
- const before2 = structure(configBefore.text), current = structure(currentConfig.text), expectedConfig = structuredClone(before2);
108429
+ const before2 = structure2(configBefore.text), current = structure2(currentConfig.text), expectedConfig = structuredClone(before2);
108375
108430
  expectedConfig.hooks ??= {};
108376
108431
  expectedConfig.hooks.state ??= {};
108377
108432
  for (const hook of intent.hooks)
@@ -108382,16 +108437,17 @@ async function reconcileCodexNativeHooks(options, connect = connectCodexHookRpc)
108382
108437
  need4(state?.enabled === true && typeof state.trusted_hash === "string" && /^sha256:[a-f0-9]{64}$/.test(state.trusted_hash), "RECONCILE_CONFIG_DRIFT");
108383
108438
  }
108384
108439
  } else
108385
- need4(isDeepStrictEqual8(expectedConfig, current), "RECONCILE_CONFIG_DRIFT");
108440
+ need4(isDeepStrictEqual9(expectedConfig, current), "RECONCILE_CONFIG_DRIFT");
108386
108441
  const policy = parseManagedSkillPolicy(policyCurrent.text), binding = policy.bridge;
108387
- assertManagedAgentBridge("codex", { home, dataDir: dataDir3, projectDir: home });
108442
+ const configDiscoveryRecovery = recovery && binding.discovery?.codex ? createCodexHookDiscoveryRecovery(binding.discovery.codex, configBefore, currentConfig, intent.hooks) : undefined;
108443
+ assertManagedAgentBridge("codex", { home, dataDir: dataDir3, projectDir: home, codexDiscoveryRecovery: configDiscoveryRecovery });
108388
108444
  const recoveryCli = recovery ? bindSkillsCli("skills", options.reviewedSkillsCli) : undefined;
108389
108445
  if (recoveryCli)
108390
108446
  verifyReleaseArtifact(options.releaseProof, recoveryCli);
108391
108447
  const skillsCli = recovery ? inspectRecordedSkillsCli(binding.commands.codex, intent.skillsCli) : bindSkillsCli(binding.commands.codex, options.reviewedSkillsCli);
108392
108448
  if (supersededBinding)
108393
108449
  verifyReleaseArtifact(options.releaseProof, skillsCli);
108394
- const skillsBindingChanged = !isDeepStrictEqual8(skillsCli.receipt, intent.skillsCli);
108450
+ const skillsBindingChanged = !isDeepStrictEqual9(skillsCli.receipt, intent.skillsCli);
108395
108451
  need4(!skillsBindingChanged || supersededBinding, "RECONCILE_SKILLS_BINDING_CHANGED");
108396
108452
  const alias = binding.rootAliases?.find((item) => item.agent === "codex"), physicalRoot = alias?.target ?? join56(home, ".codex"), hooksPath = join56(physicalRoot, "hooks.json");
108397
108453
  need4(resolve22(intent.configPath) === resolve22(join56(physicalRoot, "config.toml")), "RECONCILE_CONFIG_PATH_CHANGED");
@@ -108404,7 +108460,7 @@ async function reconcileCodexNativeHooks(options, connect = connectCodexHookRpc)
108404
108460
  const currentDeclarations = JSON.parse(hooksCurrent.text).hooks;
108405
108461
  for (const [event, [nativeEvent]] of Object.entries(eventNames)) {
108406
108462
  const command = renderAgentHookCommand(binding.commands.codex, "codex", binding.profiles.codex, event);
108407
- need4(isDeepStrictEqual8(currentDeclarations?.[event], [{ hooks: [{ type: "command", command, timeout: 15 }] }]), "RECONCILE_BINDING_HOOK_CHANGED");
108463
+ need4(isDeepStrictEqual9(currentDeclarations?.[event], [{ hooks: [{ type: "command", command, timeout: 15 }] }]), "RECONCILE_BINDING_HOOK_CHANGED");
108408
108464
  }
108409
108465
  }
108410
108466
  rpc = await connect({ command: options.codexCommand ?? "codex", home, codexHome });
@@ -108427,9 +108483,9 @@ async function reconcileCodexNativeHooks(options, connect = connectCodexHookRpc)
108427
108483
  delete identity4.command;
108428
108484
  return identity4;
108429
108485
  };
108430
- need4(isDeepStrictEqual8(stable(actual), stable(expected)), "RECONCILE_NATIVE_IDENTITY_CHANGED");
108486
+ need4(isDeepStrictEqual9(stable(actual), stable(expected)), "RECONCILE_NATIVE_IDENTITY_CHANGED");
108431
108487
  if (!plannedKeys.has(expected.key))
108432
- need4(isDeepStrictEqual8(actual, expected), "RECONCILE_UNRELATED_HOOK_CHANGED");
108488
+ need4(isDeepStrictEqual9(actual, expected), "RECONCILE_UNRELATED_HOOK_CHANGED");
108433
108489
  }
108434
108490
  for (const wanted of intent.hooks) {
108435
108491
  const matches2 = nativeHooks.filter((h2) => h2.key === wanted.key || h2.key === wanted.key.replace(join56(home, ".codex/hooks.json"), hooksPath));
@@ -108446,12 +108502,12 @@ async function reconcileCodexNativeHooks(options, connect = connectCodexHookRpc)
108446
108502
  }
108447
108503
  const config2 = await rpc.request("config/read", { includeLayers: true, cwd: home });
108448
108504
  const layers = config2?.layers?.filter((layer) => layer.name?.type === "user" && layer.name.file === nativeConfigPath && !layer.name.profile);
108449
- need4(layers?.length === 1 && !layers[0].disabledReason && isDeepStrictEqual8(layers[0].config, current), "RECONCILE_NATIVE_CONFIG_MISMATCH");
108505
+ need4(layers?.length === 1 && !layers[0].disabledReason && isDeepStrictEqual9(layers[0].config, current), "RECONCILE_NATIVE_CONFIG_MISMATCH");
108450
108506
  const finalDiscovery = await rpc.request("hooks/list", { cwds: [home] });
108451
- need4(Array.isArray(finalDiscovery?.data) && finalDiscovery.data.length === 1 && finalDiscovery.data[0].cwd === home && !finalDiscovery.data[0].errors?.length && !finalDiscovery.data[0].warnings?.length && (!recordedNativeHooks || isDeepStrictEqual8(finalDiscovery.data[0].hooks.map(safeNativeHook), nativeHooks.map(safeNativeHook))), "RECONCILE_NATIVE_STATE_CHANGED");
108507
+ need4(Array.isArray(finalDiscovery?.data) && finalDiscovery.data.length === 1 && finalDiscovery.data[0].cwd === home && !finalDiscovery.data[0].errors?.length && !finalDiscovery.data[0].warnings?.length && (!recordedNativeHooks || isDeepStrictEqual9(finalDiscovery.data[0].hooks.map(safeNativeHook), nativeHooks.map(safeNativeHook))), "RECONCILE_NATIVE_STATE_CHANGED");
108452
108508
  const finalConfig = await rpc.request("config/read", { includeLayers: true, cwd: home });
108453
108509
  const finalLayers = finalConfig?.layers?.filter((layer) => layer.name?.type === "user" && layer.name.file === nativeConfigPath && !layer.name.profile);
108454
- need4(finalLayers?.length === 1 && !finalLayers[0].disabledReason && isDeepStrictEqual8(finalLayers[0].config, current), "RECONCILE_NATIVE_CONFIG_CHANGED");
108510
+ need4(finalLayers?.length === 1 && !finalLayers[0].disabledReason && isDeepStrictEqual9(finalLayers[0].config, current), "RECONCILE_NATIVE_CONFIG_CHANGED");
108455
108511
  if (recovery) {
108456
108512
  for (const response of [config2, finalConfig]) {
108457
108513
  const layerIndex = response.layers.findIndex((layer) => layer.name?.type === "user" && layer.name.file === nativeConfigPath && !layer.name.profile);
@@ -108470,16 +108526,16 @@ async function reconcileCodexNativeHooks(options, connect = connectCodexHookRpc)
108470
108526
  unchanged2(hooksCurrent);
108471
108527
  unchanged2(currentConfig);
108472
108528
  skillsCli.recheck();
108473
- assertManagedAgentBridge("codex", { home, dataDir: dataDir3, projectDir: home });
108474
- const recoveryPlan = recovery ? { version: 1, kind: "claude-discovery-only", journal, journalIntentSha256: intentFile.sha256, stoppedSha256: stoppedFile.sha256, originalPlanDigest: intent.planDigest, policyBeforeSha256: policyBefore.sha256, policyCurrentSha256: policyCurrent.sha256, configBeforeSha256: configBefore.sha256, configCurrentSha256: currentConfig.sha256, hooksSha256: hooksCurrent.sha256, nativeConfigPath, nativeVersion: rpc.version, nativeInventorySha256: makePlanDigest(nativeHooks.map(safeNativeHook)), recordedNativeInventorySha256: makePlanDigest(recordedNativeHooks), boundSkillsCli: skillsCli.receipt, recoveryCli: recoveryCli.receipt, releaseProof: options.releaseProof, ...policyChange } : undefined;
108529
+ assertManagedAgentBridge("codex", { home, dataDir: dataDir3, projectDir: home, codexDiscoveryRecovery: configDiscoveryRecovery });
108530
+ const recoveryPlan = recovery ? { version: 1, kind: "claude-discovery-only", journal, journalIntentSha256: intentFile.sha256, stoppedSha256: stoppedFile.sha256, originalPlanDigest: intent.planDigest, policyBeforeSha256: policyBefore.sha256, policyCurrentSha256: policyCurrent.sha256, configBeforeSha256: configBefore.sha256, configCurrentSha256: currentConfig.sha256, ...configDiscoveryRecovery ? { configDiscoveryRecovery } : {}, hooksSha256: hooksCurrent.sha256, nativeConfigPath, nativeVersion: rpc.version, nativeInventorySha256: makePlanDigest(nativeHooks.map(safeNativeHook)), recordedNativeInventorySha256: makePlanDigest(recordedNativeHooks), boundSkillsCli: skillsCli.receipt, recoveryCli: recoveryCli.receipt, releaseProof: options.releaseProof, ...policyChange } : undefined;
108475
108531
  const recoveryPlanDigest = recoveryPlan ? makePlanDigest(recoveryPlan) : undefined;
108476
108532
  if (recovery?.reviewedPlanDigest !== undefined)
108477
108533
  need4(recovery.reviewedPlanDigest === recoveryPlanDigest, "RECONCILE_RECOVERY_PLAN_CHANGED");
108478
108534
  const preview2 = !!recovery && recovery.reviewedPlanDigest === undefined;
108479
- const receipt = { version: 1, status: preview2 ? "recovery-review-required" : supersededBinding ? "superseded" : "reconciled", reconciled: !preview2, supersededBinding, automaticRollback: false, journal, planDigest: intent.planDigest, nativeVersion: rpc.version, nativeStateVerified: !nativeTrustPending, nativeTrustPending, nativeExecutionVerified: false, configSha256: currentConfig.sha256, hooksSha256: hooksCurrent.sha256, policySha256: policyBefore.sha256, policyBeforeSha256: policyBefore.sha256, policyCurrentSha256: policyCurrent.sha256, previousSkillsCli: intent.skillsCli, skillsCli: skillsCli.receipt, releaseProof: options.releaseProof, nativeInventoryScope: recordedNativeHooks ? "complete" : "declared-managed-hooks-only", unrelatedNativeHooksPreserved: !!recordedNativeHooks, unrelatedSettingsAndCommentsPreserved: true, ...recoveryPlan ? { recoveryPlan, recoveryPlanDigest } : {} };
108535
+ const receipt = { version: 1, status: preview2 ? "recovery-review-required" : supersededBinding ? "superseded" : "reconciled", reconciled: !preview2, supersededBinding, automaticRollback: false, journal, planDigest: intent.planDigest, nativeVersion: rpc.version, nativeStateVerified: !nativeTrustPending, nativeTrustPending, bindingRefreshRequired: !!configDiscoveryRecovery, nativeExecutionVerified: false, configSha256: currentConfig.sha256, hooksSha256: hooksCurrent.sha256, policySha256: policyBefore.sha256, policyBeforeSha256: policyBefore.sha256, policyCurrentSha256: policyCurrent.sha256, previousSkillsCli: intent.skillsCli, skillsCli: skillsCli.receipt, releaseProof: options.releaseProof, nativeInventoryScope: recordedNativeHooks ? "complete" : "declared-managed-hooks-only", unrelatedNativeHooksPreserved: !!recordedNativeHooks, unrelatedSettingsAndCommentsPreserved: true, ...recoveryPlan ? { recoveryPlan, recoveryPlanDigest } : {} };
108480
108536
  if (preview2)
108481
108537
  return receipt;
108482
- save2(join56(journal, "receipt.json"), json2(receipt));
108538
+ save(join56(journal, "receipt.json"), json2(receipt));
108483
108539
  return receipt;
108484
108540
  } catch (error61) {
108485
108541
  const message = error61 instanceof Error && error61.message.startsWith("CODEX_HOOK_TRUST_") ? error61.message : "CODEX_HOOK_TRUST_RECONCILE_REFUSED";
@@ -108500,14 +108556,14 @@ async function enrollCodexNativeHooks(options = {}, connect = connectCodexHookRp
108500
108556
  need4(options.codexHome === undefined || isAbsolute25(options.codexHome) && [join56(home, ".codex"), physicalRoot].includes(options.codexHome), "NATIVE_HOME_NOT_ADMITTED");
108501
108557
  const codexHome = options.codexHome === undefined ? undefined : physicalRoot;
108502
108558
  const nativeConfigPath = join56(codexHome ?? join56(home, ".codex"), "config.toml");
108503
- const hooksFile = snapshot(hooksPath), configFile = snapshot(configPath, true), original = structure(configFile.text);
108559
+ const hooksFile = snapshot(hooksPath), configFile = snapshot(configPath, true), original = structure2(configFile.text);
108504
108560
  const declarations = JSON.parse(hooksFile.text).hooks, expected = [];
108505
108561
  for (const [event, [nativeEvent, label]] of Object.entries(eventNames)) {
108506
108562
  const command = renderAgentHookCommand(binding.commands.codex, "codex", binding.profiles.codex, event);
108507
108563
  const groups = declarations[event];
108508
108564
  need4(Array.isArray(groups), "DECLARATION_CHANGED");
108509
108565
  const matches2 = groups.flatMap((group, gi) => (group.hooks ?? []).flatMap((entry, hi) => entry.command === command ? [{ group, entry, gi, hi }] : []));
108510
- need4(matches2.length === 1 && isDeepStrictEqual8(matches2[0].group, { hooks: [{ type: "command", command, timeout: 15 }] }), "DECLARATION_CHANGED");
108566
+ need4(matches2.length === 1 && isDeepStrictEqual9(matches2[0].group, { hooks: [{ type: "command", command, timeout: 15 }] }), "DECLARATION_CHANGED");
108511
108567
  expected.push({ event: nativeEvent, key: `${join56(home, ".codex/hooks.json")}:${label}:${matches2[0].gi}:${matches2[0].hi}`, command });
108512
108568
  }
108513
108569
  codexTrustTextWitness(configFile.text, expected.map((h) => h.key));
@@ -108531,7 +108587,7 @@ async function enrollCodexNativeHooks(options = {}, connect = connectCodexHookRp
108531
108587
  const discovered = await list2(), admitted = admit(discovered);
108532
108588
  const config2 = await rpc.request("config/read", { includeLayers: true, cwd: home });
108533
108589
  const layers = config2?.layers?.filter((layer) => layer.name?.type === "user" && layer.name.file === nativeConfigPath && !layer.name.profile);
108534
- need4(layers?.length === 1 && /^sha256:[a-f0-9]{64}$/.test(layers[0].version) && !layers[0].disabledReason && isDeepStrictEqual8(layers[0].config, original), "NATIVE_CONFIG_MISMATCH");
108590
+ need4(layers?.length === 1 && /^sha256:[a-f0-9]{64}$/.test(layers[0].version) && !layers[0].disabledReason && isDeepStrictEqual9(layers[0].config, original), "NATIVE_CONFIG_MISMATCH");
108535
108591
  need4(config2.config && config2.config.features?.hooks !== false, "NATIVE_HOOKS_DISABLED");
108536
108592
  need4(config2.layers.slice(0, config2.layers.indexOf(layers[0])).every((layer) => layer.config?.hooks === undefined && layer.config?.features?.hooks === undefined), "NATIVE_CONFIG_OVERRIDDEN");
108537
108593
  const keys3 = admitted.map((h) => h.key), planned = admitted.filter((h) => !h.enabled || h.trustStatus !== "trusted");
@@ -108546,7 +108602,7 @@ async function enrollCodexNativeHooks(options = {}, connect = connectCodexHookRp
108546
108602
  checkInputs();
108547
108603
  const digestInput = { version: 1, home, configPath, ...nativeConfigPath !== configPath ? { nativeConfigPath } : {}, configSha256: configFile.sha256, configVersion: layers[0].version, policySha256: policyFile.sha256, hooksSha256: hooksFile.sha256, skillsCli: skillsCli.receipt, nativeVersion: rpc.version, declarations: expected, admitted };
108548
108604
  const planDigest = makePlanDigest(digestInput);
108549
- const baseReceipt = { planDigest, skillsCli: skillsCli.receipt, nativeVersion: rpc.version, nativeConfigPath, ownedNativeProcessId: rpc.processId, agent: "codex", applied: false, planned, nativeEligible: planned.length === 0, transport: "owned-stdio-process", existingSessionsReloaded: false, nativeExecutionVerified: false };
108605
+ const baseReceipt = { planDigest, skillsCli: skillsCli.receipt, nativeVersion: rpc.version, nativeConfigPath, ownedNativeProcessId: rpc.processId, agent: "codex", applied: false, planned, nativeEligible: planned.length === 0, bindingRefreshRequired: false, transport: "owned-stdio-process", existingSessionsReloaded: false, nativeExecutionVerified: false };
108550
108606
  if (options.apply)
108551
108607
  need4(options.reviewedPlanDigest === planDigest, "PLAN_CHANGED: run the dry-run again and pass its reviewed --plan-digest with --apply");
108552
108608
  const parent = join56(dataDir3, "native-hook-trust");
@@ -108566,11 +108622,11 @@ async function enrollCodexNativeHooks(options = {}, connect = connectCodexHookRp
108566
108622
  mkdirSync25(parent, { mode: 448 });
108567
108623
  journal = join56(parent, randomUUID10());
108568
108624
  mkdirSync25(journal, { mode: 448 });
108569
- save2(join56(journal, "config.before.toml"), configFile.bytes);
108570
- save2(join56(journal, "hooks.before.json"), hooksFile.bytes);
108571
- save2(join56(journal, "policy.before.json"), policyFile.bytes);
108572
- save2(join56(journal, "intent.json"), json2({ ...digestInput, planDigest, hooks: planned, nativeHooks: discovered.map(safeNativeHook) }));
108573
- need4(isDeepStrictEqual8(admit(await list2()), admitted), "NATIVE_DISCOVERY_CHANGED");
108625
+ save(join56(journal, "config.before.toml"), configFile.bytes);
108626
+ save(join56(journal, "hooks.before.json"), hooksFile.bytes);
108627
+ save(join56(journal, "policy.before.json"), policyFile.bytes);
108628
+ save(join56(journal, "intent.json"), json2({ ...digestInput, planDigest, hooks: planned, nativeHooks: discovered.map(safeNativeHook) }));
108629
+ need4(isDeepStrictEqual9(admit(await list2()), admitted), "NATIVE_DISCOVERY_CHANGED");
108574
108630
  checkInputs();
108575
108631
  let result2;
108576
108632
  try {
@@ -108584,25 +108640,30 @@ async function enrollCodexNativeHooks(options = {}, connect = connectCodexHookRp
108584
108640
  expectedConfig.hooks.state ??= {};
108585
108641
  for (const h of planned)
108586
108642
  expectedConfig.hooks.state[h.key] = { ...expectedConfig.hooks.state[h.key], enabled: true, trusted_hash: h.currentHash };
108587
- need4(isDeepStrictEqual8(structure(after2.text), expectedConfig) && codexTrustTextWitness(after2.text, keys3) === preservationText, "PRESERVATION_FAILED");
108643
+ need4(isDeepStrictEqual9(structure2(after2.text), expectedConfig) && codexTrustTextWitness(after2.text, keys3) === preservationText, "PRESERVATION_FAILED");
108644
+ const savedConfig = snapshot(join56(journal, "config.before.toml"), true);
108645
+ need4(savedConfig.sha256 === configFile.sha256, "JOURNAL_CHANGED");
108646
+ const discoveryTransition = binding.discovery?.codex ? createCodexHookDiscoveryRecovery(binding.discovery.codex, savedConfig, after2, planned) : undefined;
108588
108647
  unchanged2(policyFile);
108589
108648
  unchanged2(hooksFile);
108590
- assertManagedAgentBridge("codex", { home, dataDir: dataDir3, projectDir: home });
108649
+ assertManagedAgentBridge("codex", { home, dataDir: dataDir3, projectDir: home, codexDiscoveryRecovery: discoveryTransition });
108591
108650
  const current = await list2(), confirmed = admit(current);
108592
- need4(confirmed.every((h) => h.enabled && h.trustStatus === "trusted") && isDeepStrictEqual8(confirmed.map((h) => [h.key, h.currentHash]), admitted.map((h) => [h.key, h.currentHash])), "NATIVE_NOT_ELIGIBLE");
108593
- need4(isDeepStrictEqual8(current.filter((h) => !keys3.includes(h.key)), discovered.filter((h) => !keys3.includes(h.key))), "UNRELATED_HOOK_CHANGED");
108651
+ need4(confirmed.every((h) => h.enabled && h.trustStatus === "trusted") && isDeepStrictEqual9(confirmed.map((h) => [h.key, h.currentHash]), admitted.map((h) => [h.key, h.currentHash])), "NATIVE_NOT_ELIGIBLE");
108652
+ need4(isDeepStrictEqual9(current.filter((h) => !keys3.includes(h.key)), discovered.filter((h) => !keys3.includes(h.key))), "UNRELATED_HOOK_CHANGED");
108594
108653
  unchanged2(after2);
108654
+ unchanged2(savedConfig);
108595
108655
  unchanged2(hooksFile);
108596
108656
  unchanged2(policyFile);
108597
108657
  skillsCli.recheck();
108598
- const receipt = { ...baseReceipt, applied: true, nativeEligible: true, nativeConfigVersion: result2.version, journal, beforeSha256: configFile.sha256, afterSha256: after2.sha256, unrelatedSettingsAndCommentsPreserved: true };
108599
- save2(join56(journal, "receipt.json"), json2(receipt));
108658
+ assertManagedAgentBridge("codex", { home, dataDir: dataDir3, projectDir: home, codexDiscoveryRecovery: discoveryTransition });
108659
+ const receipt = { ...baseReceipt, applied: true, nativeEligible: true, bindingRefreshRequired: !!discoveryTransition, ...discoveryTransition ? { discoveryTransition } : {}, nativeConfigVersion: result2.version, journal, beforeSha256: configFile.sha256, afterSha256: after2.sha256, unrelatedSettingsAndCommentsPreserved: true };
108660
+ save(join56(journal, "receipt.json"), json2(receipt));
108600
108661
  return receipt;
108601
108662
  } catch (error61) {
108602
108663
  const message = error61 instanceof Error && error61.message.startsWith("CODEX_HOOK_TRUST_") ? error61.message : "CODEX_HOOK_TRUST_REFUSED: verify managed bridge installation and native Codex support";
108603
108664
  if (journal) {
108604
108665
  try {
108605
- save2(join56(journal, "stopped.json"), json2({ error: message.split(":")[0], automaticRollback: false, reconcileBeforeRetry: true }));
108666
+ save(join56(journal, "stopped.json"), json2({ error: message.split(":")[0], automaticRollback: false, reconcileBeforeRetry: true }));
108606
108667
  } catch {}
108607
108668
  }
108608
108669
  throw new Error(message);
@@ -108611,7 +108672,7 @@ async function enrollCodexNativeHooks(options = {}, connect = connectCodexHookRp
108611
108672
  }
108612
108673
  }
108613
108674
  var json2 = (value) => JSON.stringify(value, null, 2) + `
108614
- `, structure = (text3) => JSON.parse(JSON.stringify(Bun.TOML.parse(text3))), eventNames, makePlanDigest = (value) => createHash26("sha256").update(json2(value)).digest("hex"), safeNativeHook = (hook) => ({ key: hook.key, eventName: hook.eventName, handlerType: hook.handlerType, command: hook.command, matcher: hook.matcher, timeoutSec: hook.timeoutSec, async: hook.async, statusMessage: hook.statusMessage, additionalContextLimit: hook.additionalContextLimit, sourcePath: hook.sourcePath, source: hook.source, pluginId: hook.pluginId, isManaged: hook.isManaged, currentHash: hook.currentHash, enabled: hook.enabled, trustStatus: hook.trustStatus }), withoutCodexCommand = (value) => {
108675
+ `, structure2 = (text3) => JSON.parse(JSON.stringify(Bun.TOML.parse(text3))), eventNames, makePlanDigest = (value) => createHash27("sha256").update(json2(value)).digest("hex"), safeNativeHook = (hook) => ({ key: hook.key, eventName: hook.eventName, handlerType: hook.handlerType, command: hook.command, matcher: hook.matcher, timeoutSec: hook.timeoutSec, async: hook.async, statusMessage: hook.statusMessage, additionalContextLimit: hook.additionalContextLimit, sourcePath: hook.sourcePath, source: hook.source, pluginId: hook.pluginId, isManaged: hook.isManaged, currentHash: hook.currentHash, enabled: hook.enabled, trustStatus: hook.trustStatus }), withoutCodexCommand = (value) => {
108615
108676
  const copy = structuredClone(value);
108616
108677
  if (copy?.bridge?.commands && Object.hasOwn(copy.bridge.commands, "codex"))
108617
108678
  copy.bridge.commands.codex = "<reviewed-codex-binding>";
@@ -108621,6 +108682,7 @@ var init_agent_codex_trust = __esm(() => {
108621
108682
  init_config();
108622
108683
  init_managed_policy();
108623
108684
  init_agent_integration();
108685
+ init_codex_hook_discovery_recovery();
108624
108686
  init_agent_adapters();
108625
108687
  init_codex_hook_rpc();
108626
108688
  init_codex_hook_trust_layout();
@@ -108805,7 +108867,7 @@ function registerAgentIntegration(parent) {
108805
108867
  if (options.json)
108806
108868
  await writeCliOutput(JSON.stringify(result2));
108807
108869
  else
108808
- await writeCliOutput(result2.applied ? `Enrolled ${result2.planned.length} Skills hook(s) for new Codex processes. Existing sessions were not reloaded; use their native hook controls.` : result2.planned.length ? `Planned ${result2.planned.length} native hook trust change(s). Review the --json plan, then use --apply --plan-digest ${result2.planDigest}.` : "The managed Skills hooks are enabled and trusted for new Codex processes. Existing session dispatch was not checked.");
108870
+ await writeCliOutput(result2.applied ? result2.bindingRefreshRequired ? `Enrolled ${result2.planned.length} native Skills hook trust state(s). Managed context remains blocked: review the current configuration and run skills hook install with fresh --discovery-inputs and the same --command. Policy was not changed. Existing sessions were not reloaded.` : `Enrolled ${result2.planned.length} Skills hook(s) for new Codex processes. Existing sessions were not reloaded; use their native hook controls.` : result2.planned.length ? `Planned ${result2.planned.length} native hook trust change(s). Review the --json plan, then use --apply --plan-digest ${result2.planDigest}.` : "The managed Skills hooks are enabled and trusted for new Codex processes. Existing session dispatch was not checked.");
108809
108871
  } catch (error61) {
108810
108872
  console.error(error61.message);
108811
108873
  process.exitCode = 1;
@@ -108826,7 +108888,7 @@ function registerAgentIntegration(parent) {
108826
108888
  if (options.json)
108827
108889
  await writeCliOutput(JSON.stringify(result2));
108828
108890
  else
108829
- await writeCliOutput(result2.reconciled ? `Reconciled native Codex trust journal ${result2.journal}. No native configuration was written.` : `Recovery remains pending. Review the private --json plan, then repeat with --recovery-plan-digest ${result2.recoveryPlanDigest}.`);
108891
+ await writeCliOutput(result2.reconciled ? result2.bindingRefreshRequired ? `Reconciled native Codex trust journal ${result2.journal}. Managed context remains blocked: install the reviewed binding with fresh --discovery-inputs before using ordinary hooks. Policy was not changed. No native configuration was written.` : `Reconciled native Codex trust journal ${result2.journal}. No native configuration was written.` : `Recovery remains pending. Review the private --json plan, then repeat with --recovery-plan-digest ${result2.recoveryPlanDigest}.`);
108830
108892
  } catch (error61) {
108831
108893
  console.error(error61.message);
108832
108894
  process.exitCode = 1;
@@ -109235,7 +109297,7 @@ var init_grants = __esm(() => {
109235
109297
  });
109236
109298
 
109237
109299
  // src/lib/station-hydrate.ts
109238
- import { createHash as createHash27 } from "crypto";
109300
+ import { createHash as createHash28 } from "crypto";
109239
109301
  import {
109240
109302
  copyFileSync as copyFileSync2,
109241
109303
  mkdirSync as mkdirSync26,
@@ -109438,7 +109500,7 @@ function skillSha256(skill) {
109438
109500
  return sha256File(skill.files[0].winner.fullPath);
109439
109501
  }
109440
109502
  const joined = skill.files.map((file2) => sha256File(file2.winner.fullPath));
109441
- return createHash27("sha256").update(joined.sort().join(`
109503
+ return createHash28("sha256").update(joined.sort().join(`
109442
109504
  `)).digest("hex");
109443
109505
  }
109444
109506
  function writeStationHydration(options) {
@@ -109595,7 +109657,7 @@ var init_hydrate = __esm(() => {
109595
109657
  });
109596
109658
 
109597
109659
  // src/lib/prepare-skill.ts
109598
- import { createHash as createHash28, randomUUID as randomUUID11 } from "crypto";
109660
+ import { createHash as createHash29, randomUUID as randomUUID11 } from "crypto";
109599
109661
  import { chmodSync as chmodSync3, existsSync as existsSync34, lstatSync as lstatSync29, mkdirSync as mkdirSync27, mkdtempSync as mkdtempSync6, readFileSync as readFileSync40, readdirSync as readdirSync22, renameSync as renameSync12, rmSync as rmSync9, writeFileSync as writeFileSync27 } from "fs";
109600
109662
  import { tmpdir as tmpdir2 } from "os";
109601
109663
  import { dirname as dirname32, isAbsolute as isAbsolute27, join as join58, relative as relative9, resolve as resolve24, sep as sep11 } from "path";
@@ -109793,7 +109855,7 @@ function snapshot2(root2) {
109793
109855
  if (rootStat.isSymbolicLink() || !rootStat.isDirectory())
109794
109856
  throw new Error("Skill root must be a real directory, not a symlink.");
109795
109857
  const files = [], directories = [];
109796
- const hash4 = createHash28("sha256").update(`${rootStat.dev}:${rootStat.ino}\x00`);
109858
+ const hash4 = createHash29("sha256").update(`${rootStat.dev}:${rootStat.ino}\x00`);
109797
109859
  let count = 0, bytes = 0;
109798
109860
  const walk2 = (relative10) => {
109799
109861
  for (const name of readdirSync22(join58(root2, relative10)).sort()) {
@@ -111010,6 +111072,10 @@ function stringField2(value) {
111010
111072
  function recordField(value) {
111011
111073
  return isRecord7(value) ? value : undefined;
111012
111074
  }
111075
+ function identityApiKey(live) {
111076
+ const root2 = recordField(live);
111077
+ return root2 && Object.hasOwn(root2, "apiKey") ? root2.apiKey : recordField(root2?.data)?.apiKey;
111078
+ }
111013
111079
  function authIdentityPayload(authSource, live, cached2, offline = false) {
111014
111080
  const root2 = recordField(live) ?? {};
111015
111081
  const data = recordField(root2.data);
@@ -111021,11 +111087,11 @@ function authIdentityPayload(authSource, live, cached2, offline = false) {
111021
111087
  const userId = stringField2(user?.id) ?? cached2?.userId;
111022
111088
  const orgId = stringField2(organization2?.id) ?? cached2?.orgId;
111023
111089
  const role3 = stringField2(user?.role);
111024
- const apiKey = recordField(root2.apiKey) ?? recordField(data?.apiKey);
111090
+ const apiKey = recordField(identityApiKey(live));
111025
111091
  const apiKeyId = stringField2(apiKey?.id);
111026
111092
  const apiKeyScopes = apiKey?.scopes;
111027
111093
  const safeApiKeyId = apiKeyId && /^[A-Za-z0-9_-]{1,256}$/.test(apiKeyId) ? apiKeyId : undefined;
111028
- const safeApiKeyScopes = Array.isArray(apiKeyScopes) && apiKeyScopes.length <= 32 && apiKeyScopes.every((scope) => typeof scope === "string" && scope.length <= 128 && /^(?:\*|[a-z][a-z0-9_-]*:(?:\*|[a-z][a-z0-9_-]*))$/.test(scope)) ? [...new Set(apiKeyScopes)] : undefined;
111094
+ const safeApiKeyScopes = Array.isArray(apiKeyScopes) && apiKeyScopes.length <= 32 && apiKeyScopes.every((scope) => typeof scope === "string" && scope.length <= 128 && /^(?:\*|[a-z][a-z0-9_-]*:(?:\*|[a-z][a-z0-9_-]*))$/.test(scope)) ? [...apiKeyScopes] : undefined;
111029
111095
  return {
111030
111096
  status: "authenticated",
111031
111097
  authSource,
@@ -111493,8 +111559,10 @@ function registerAuth(parent) {
111493
111559
  access = await new RemoteSkillsClient(fleet.apiKey, fleet.apiOrigin).getCapabilities();
111494
111560
  } catch {}
111495
111561
  payload.permissions = { publish: access?.permissions?.publish ?? null, profilesWrite: access?.permissions?.profilesWrite ?? null };
111496
- if (access?.scopes)
111562
+ const apiKey = identityApiKey(res);
111563
+ if (access?.scopes && (apiKey === undefined || isRecord7(apiKey) && !Object.hasOwn(apiKey, "scopes"))) {
111497
111564
  payload.scopes = access.scopes;
111565
+ }
111498
111566
  if (options.json) {
111499
111567
  console.log(JSON.stringify(payload, null, 2));
111500
111568
  } else {