@hasna/skills 0.10.63 → 0.10.65

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/mcp.js CHANGED
@@ -23,7 +23,7 @@ var package_default;
23
23
  var init_package = __esm(() => {
24
24
  package_default = {
25
25
  name: "@hasna/skills",
26
- version: "0.10.63",
26
+ version: "0.10.65",
27
27
  description: "Skills library for AI coding agents",
28
28
  type: "module",
29
29
  bin: {
@@ -23088,6 +23088,53 @@ function assertAgentPolicyCollections(policy) {
23088
23088
  requireBound(directory.sha256 === null || typeof directory.sha256 === "string" && /^[a-f0-9]{64}$/.test(directory.sha256));
23089
23089
  }
23090
23090
  }
23091
+ if (value.codexSemanticCache !== undefined) {
23092
+ const proof = record2(value.codexSemanticCache, 8), witness = record2(proof.witness, 6);
23093
+ requireBound(agent === "codex" && value.agent === "codex" && value.method === "reviewed" && Object.keys(proof).length === 8 && proof.schema === "hasna.codex-semantic-cache-discovery.v1" && typeof proof.previousPolicySha256 === "string" && /^[a-f0-9]{64}$/.test(proof.previousPolicySha256) && Object.keys(witness).length === 6 && witness.schema === "hasna.codex-semantic-cache-witness.v1" && typeof witness.sha256 === "string" && /^[a-f0-9]{64}$/.test(witness.sha256));
23094
+ text(proof.configPath);
23095
+ requireBound(isAbsolute5(proof.configPath) && resolve4(proof.configPath) === proof.configPath && basename5(proof.configPath) === "config.toml");
23096
+ text(witness.cacheRoot);
23097
+ requireBound(isAbsolute5(witness.cacheRoot) && resolve4(witness.cacheRoot) === witness.cacheRoot);
23098
+ if (proof.hookRootAlias !== null) {
23099
+ requireBound(object2(proof.hookRootAlias) && Object.keys(proof.hookRootAlias).length === 2);
23100
+ for (const key of ["alias", "target"]) {
23101
+ text(proof.hookRootAlias[key]);
23102
+ requireBound(isAbsolute5(proof.hookRootAlias[key]) && resolve4(proof.hookRootAlias[key]) === proof.hookRootAlias[key]);
23103
+ }
23104
+ }
23105
+ const parents2 = array2(proof.appOnlyParents, 4096);
23106
+ for (const parent of parents2) {
23107
+ requireBound(object2(parent) && Object.keys(parent).length === 5 && parent.role === "app-only");
23108
+ for (const key of ["pluginId", "namespace", "pluginParent", "remotePluginId"])
23109
+ text(parent[key]);
23110
+ requireBound(isAbsolute5(parent.pluginParent) && resolve4(parent.pluginParent) === parent.pluginParent);
23111
+ }
23112
+ for (const row of [...array2(witness.controls, 4096), ...array2(witness.appOnlyParents, 4096)]) {
23113
+ requireBound(object2(row));
23114
+ for (const key of ["pluginId", "namespace", "pluginParent"])
23115
+ text(row[key]);
23116
+ for (const key of ["manifestSha256", "appSha256", "mcpSha256", "receiptSha256"])
23117
+ if (row[key] !== undefined)
23118
+ requireBound(typeof row[key] === "string" && /^[a-f0-9]{64}$/.test(row[key]));
23119
+ }
23120
+ for (const skill of array2(witness.skills, 4096)) {
23121
+ requireBound(object2(skill));
23122
+ for (const key of ["name", "pluginId", "namespace", "pluginParent"])
23123
+ text(skill[key]);
23124
+ for (const rule of array2(skill.disabledRules, 4096))
23125
+ text(rule);
23126
+ }
23127
+ for (const source of array2(proof.supersededSources, AGENT_POLICY_LIMITS.discoverySources)) {
23128
+ requireBound(object2(source));
23129
+ text(source.path);
23130
+ requireBound(source.sha256 === null || typeof source.sha256 === "string" && /^[a-f0-9]{64}$/.test(source.sha256));
23131
+ }
23132
+ for (const directory of array2(proof.supersededDirectories, AGENT_POLICY_LIMITS.discoveryDirectories)) {
23133
+ requireBound(object2(directory));
23134
+ text(directory.path);
23135
+ requireBound(directory.sha256 === null || typeof directory.sha256 === "string" && /^[a-f0-9]{64}$/.test(directory.sha256));
23136
+ }
23137
+ }
23091
23138
  for (const root of array2(value.roots, AGENT_POLICY_LIMITS.discoveryRoots))
23092
23139
  text(root);
23093
23140
  for (const source of array2(value.sources, AGENT_POLICY_LIMITS.discoverySources)) {
@@ -23095,12 +23142,12 @@ function assertAgentPolicyCollections(policy) {
23095
23142
  text(source.path);
23096
23143
  requireBound(source.sha256 === null || typeof source.sha256 === "string" && /^[a-f0-9]{64}$/.test(source.sha256));
23097
23144
  if (source.hashMode !== undefined)
23098
- requireBound(["bytes", "path-bytes", "claude-plugin-manifest-v1", "claude-plugin-registry", "claude-marketplace-registry", "claude-settings-v1", "claude-settings-v2", "claude-settings-v3", "claude-settings-v4", "claude-marketplace-registry-v2", "codex-settings-v1", "codex-settings-v2", "codex-settings-v3", "codex-settings-v4", "sumi-settings-v1", "claude-marketplace-entry-v1"].includes(source.hashMode) && source.format === undefined && source.fields === undefined && (source.hashMode === "bytes" || source.sha256 !== null));
23145
+ requireBound(["bytes", "path-bytes", "claude-plugin-manifest-v1", "claude-plugin-registry", "claude-marketplace-registry", "claude-settings-v1", "claude-settings-v2", "claude-settings-v3", "claude-settings-v4", "claude-marketplace-registry-v2", "codex-settings-v1", "codex-settings-v2", "codex-settings-v3", "codex-settings-v4", "codex-settings-v5", "sumi-settings-v1", "claude-marketplace-entry-v1"].includes(source.hashMode) && source.format === undefined && source.fields === undefined && (source.hashMode === "bytes" || source.sha256 !== null));
23099
23146
  if (source.hashMode === "claude-plugin-manifest-v1")
23100
23147
  requireBound(agent === "claude" && value.agent === "claude" && ["automatic", "reviewed"].includes(value.method) && !/[\x00-\x1f\x7f]/.test(source.path) && isAbsolute5(source.path) && resolve4(source.path) === source.path && source.path.endsWith(join10(sep3, ".claude-plugin", "plugin.json")) && source.managedPlugins === undefined);
23101
23148
  if (source.hashMode === "sumi-settings-v1")
23102
23149
  requireBound(agent === "sumi" && value.agent === "sumi" && value.method === "reviewed" && !/[\x00-\x1f\x7f]/.test(source.path) && isAbsolute5(source.path) && resolve4(source.path) === source.path && basename5(source.path) === "sumi.json");
23103
- if (source.hashMode === "codex-settings-v1" || source.hashMode === "codex-settings-v2" || (source.hashMode === "codex-settings-v3" || source.hashMode === "codex-settings-v4"))
23150
+ if (source.hashMode === "codex-settings-v1" || source.hashMode === "codex-settings-v2" || (source.hashMode === "codex-settings-v3" || source.hashMode === "codex-settings-v4" || source.hashMode === "codex-settings-v5"))
23104
23151
  requireBound(agent === "codex" && value.agent === "codex" && value.method === "reviewed" && !/[\x00-\x1f\x7f]/.test(source.path) && isAbsolute5(source.path) && resolve4(source.path) === source.path && basename5(source.path) === "config.toml");
23105
23152
  if (source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || (source.hashMode === "claude-settings-v3" || source.hashMode === "claude-settings-v4"))
23106
23153
  requireBound(agent === "claude" && value.agent === "claude" && value.method === "reviewed" && !/[\x00-\x1f\x7f]/.test(source.path) && isAbsolute5(source.path) && resolve4(source.path) === source.path && basename5(source.path) === "settings.json");
@@ -32731,6 +32778,7 @@ var init_codex_hook_rpc = __esm(() => {
32731
32778
  });
32732
32779
 
32733
32780
  // src/lib/codex-native-skill-catalog.ts
32781
+ import { realpathSync as realpathSync4 } from "fs";
32734
32782
  import { isAbsolute as isAbsolute10, normalize as normalize2 } from "path";
32735
32783
  function codexPluginSourceIsConfigControlled(plugin) {
32736
32784
  const remoteRealms = ["openai-curated-remote", "created-by-me-remote", "workspace-directory", "workspace-shared-with-me", "workspace-shared-with-me-private", "workspace-shared-with-me-unlisted"];
@@ -32779,6 +32827,43 @@ function projectCodexInstalledPluginEntries(value) {
32779
32827
  };
32780
32828
  });
32781
32829
  }
32830
+ function canonicalPath(path) {
32831
+ try {
32832
+ return realpathSync4(path);
32833
+ } catch {
32834
+ return normalize2(path);
32835
+ }
32836
+ }
32837
+ function isCodexNativeSkillDisabled(skill, rules) {
32838
+ if (!scalar(skill.name, MAX_NAME_BYTES) || !absolutePath2(skill.path))
32839
+ refuse();
32840
+ if (rules === undefined)
32841
+ return false;
32842
+ if (!Array.isArray(rules) || rules.length > MAX_SKILLS)
32843
+ refuse();
32844
+ let disabled = false;
32845
+ for (const rule of rules) {
32846
+ if (!object5(rule) || typeof rule.enabled !== "boolean")
32847
+ refuse();
32848
+ const hasName = rule.name !== undefined && rule.name !== null;
32849
+ const hasPath = rule.path !== undefined && rule.path !== null;
32850
+ if (hasName === hasPath)
32851
+ refuse();
32852
+ let matches;
32853
+ if (hasName) {
32854
+ if (typeof rule.name !== "string" || !scalar(rule.name.trim(), MAX_NAME_BYTES))
32855
+ refuse();
32856
+ matches = rule.name.trim() === skill.name;
32857
+ } else {
32858
+ if (!absolutePath2(rule.path))
32859
+ refuse();
32860
+ matches = canonicalPath(rule.path) === canonicalPath(skill.path);
32861
+ }
32862
+ if (matches)
32863
+ disabled = !rule.enabled;
32864
+ }
32865
+ return disabled;
32866
+ }
32782
32867
  var MAX_SKILLS = 4096, MAX_NAME_BYTES = 1024, MAX_PATH_BYTES = 16384, MAX_PLUGIN_ID_BYTES = 1024, object5 = (value) => value !== null && typeof value === "object" && !Array.isArray(value), scalar = (value, max) => typeof value === "string" && value.length > 0 && value.trim() === value && Buffer.byteLength(value, "utf8") <= max && !/[\u0000-\u001f\u007f]/u.test(value), remotePluginIdentifier = (value) => typeof value === "string" && /^[A-Za-z0-9_~-]{1,1024}$/.test(value), absolutePath2 = (value) => scalar(value, MAX_PATH_BYTES) && isAbsolute10(value);
32783
32868
  var init_codex_native_skill_catalog = __esm(() => {
32784
32869
  init_codex_hook_rpc();
@@ -32788,13 +32873,13 @@ var init_codex_native_skill_catalog = __esm(() => {
32788
32873
 
32789
32874
  // src/lib/codex-plugin-skill-controls.ts
32790
32875
  import { basename as basename6, dirname as dirname12, join as join18, relative as relative5, resolve as resolve11, sep as sep6 } from "path";
32791
- import { lstatSync as lstatSync12, readdirSync as readdirSync6, readlinkSync as readlinkSync3, realpathSync as realpathSync4 } from "fs";
32876
+ import { lstatSync as lstatSync12, readdirSync as readdirSync6, readlinkSync as readlinkSync3, realpathSync as realpathSync5 } from "fs";
32792
32877
  function refuse2() {
32793
32878
  throw new Error("CODEX_NATIVE_SKILL_IDENTITY_UNSUPPORTED: review native plugin names and hook controls");
32794
32879
  }
32795
32880
  function remoteInstallationMatches(parent, remotePluginId, read) {
32796
32881
  try {
32797
- if (!remotePluginIdentifier(remotePluginId) || !lstatSync12(parent).isDirectory() || realpathSync4(parent) !== parent)
32882
+ if (!remotePluginIdentifier(remotePluginId) || !lstatSync12(parent).isDirectory() || realpathSync5(parent) !== parent)
32798
32883
  return false;
32799
32884
  const path = join18(parent, ".codex-remote-plugin-install.json"), stat = lstatSync12(path, { throwIfNoEntry: false });
32800
32885
  if (!stat?.isFile() || stat.isSymbolicLink() || stat.size > 16384)
@@ -32871,6 +32956,9 @@ function isBundledCleanupHooks(root, namespace, value) {
32871
32956
  }
32872
32957
  return true;
32873
32958
  }
32959
+ function readCodexPluginRootControls(root, read) {
32960
+ return rootControls(root, read);
32961
+ }
32874
32962
  function rootControls(root, read) {
32875
32963
  const manifestPath = join18(root, ".codex-plugin/plugin.json"), manifestFile = lstatSync12(manifestPath, { throwIfNoEntry: false });
32876
32964
  if (!lstatSync12(join18(root, ".codex-plugin"), { throwIfNoEntry: false })?.isDirectory() || !manifestFile?.isFile() || manifestFile.size > 1024 * 1024)
@@ -32893,7 +32981,7 @@ function rootControls(root, read) {
32893
32981
  const mcp = join18(root, ".mcp.json"), mcpPresent = lstatSync12(mcp, { throwIfNoEntry: false });
32894
32982
  if (manifest.hooks !== undefined && (manifest.mcpServers !== undefined || mcpPresent))
32895
32983
  refuse2();
32896
- if (mcpPresent && (!mcpPresent.isFile() || mcpPresent.isSymbolicLink() || mcpPresent.size > 1024 * 1024 || realpathSync4(mcp) !== mcp))
32984
+ if (mcpPresent && (!mcpPresent.isFile() || mcpPresent.isSymbolicLink() || mcpPresent.size > 1024 * 1024 || realpathSync5(mcp) !== mcp))
32897
32985
  refuse2();
32898
32986
  if (Boolean(mcpPresent) !== (manifest.mcpServers !== undefined))
32899
32987
  refuse2();
@@ -32906,6 +32994,76 @@ function rootControls(root, read) {
32906
32994
  const appSha256 = present ? appControls(app, read) : undefined;
32907
32995
  return { namespace: manifest.name, manifestSha256, ...appSha256 ? { appSha256 } : {}, ...mcpSha256 ? { mcpSha256 } : {} };
32908
32996
  }
32997
+ function documentIdentity(document2, cache, read) {
32998
+ if (!document2.startsWith(cache + sep6) || !document2.endsWith(sep6 + "SKILL.md"))
32999
+ refuse2();
33000
+ const text2 = read(document2);
33001
+ if (Buffer.byteLength(text2) > 1024 * 1024)
33002
+ refuse2();
33003
+ const lines = text2.split(/\r?\n/);
33004
+ if (lines[0]?.trim() !== "---")
33005
+ refuse2();
33006
+ const end = lines.findIndex((line, i) => i > 0 && line.trim() === "---");
33007
+ if (end < 2)
33008
+ refuse2();
33009
+ const yaml = lines.slice(1, end).join(`
33010
+ `);
33011
+ if (/(?:^|\s)[&*!]|<<\s*:/.test(yaml) || lines.slice(1, end).filter((line) => /^name\s*:/.test(line)).length !== 1)
33012
+ refuse2();
33013
+ let front;
33014
+ try {
33015
+ front = Bun.YAML.parse(yaml);
33016
+ } catch {
33017
+ refuse2();
33018
+ }
33019
+ if (!front || typeof front !== "object" || !identifier2(front.name) || typeof front.description !== "string" || !front.description.trim())
33020
+ refuse2();
33021
+ for (let root = dirname12(document2), depth = 0;root.startsWith(cache + sep6) && depth < 12; root = dirname12(root), depth++) {
33022
+ const path = join18(root, ".codex-plugin", "plugin.json");
33023
+ if (!lstatSync12(path, { throwIfNoEntry: false }))
33024
+ continue;
33025
+ const manifestFile = lstatSync12(path);
33026
+ if (!lstatSync12(join18(root, ".codex-plugin")).isDirectory() || !manifestFile.isFile() || manifestFile.size > 1024 * 1024)
33027
+ refuse2();
33028
+ let manifest;
33029
+ try {
33030
+ const text3 = read(path);
33031
+ hashNativeJsonControls(text3);
33032
+ manifest = JSON.parse(text3);
33033
+ } catch {
33034
+ refuse2();
33035
+ }
33036
+ if (!manifest || typeof manifest !== "object" || Array.isArray(manifest) || !identifier2(manifest.name))
33037
+ refuse2();
33038
+ const declaredVersion = manifest.version === undefined ? "" : typeof manifest.version === "string" ? manifest.version.trim() : null;
33039
+ if (declaredVersion === null || (declaredVersion ? declaredVersion !== basename6(root) : basename6(root) !== CODEX_DEFAULT_AGENT_PLUGIN_VERSION))
33040
+ refuse2();
33041
+ return { name: `${manifest.name}:${front.name}`, namespace: manifest.name, pluginParent: dirname12(root), root };
33042
+ }
33043
+ refuse2();
33044
+ }
33045
+ function identity3(document2, cache, read) {
33046
+ const parsed = documentIdentity(document2, cache, read);
33047
+ const controls = rootControls(parsed.root, read);
33048
+ if (controls.namespace !== parsed.namespace)
33049
+ refuse2();
33050
+ return { name: parsed.name, pluginParent: parsed.pluginParent, ...controls };
33051
+ }
33052
+ function classifyCodexPluginCacheDocument(document2, cache, read) {
33053
+ if (!document2.startsWith(cache + sep6))
33054
+ return null;
33055
+ try {
33056
+ const located = documentIdentity(document2, cache, read), parsed = identity3(document2, cache, read);
33057
+ if (!lstatSync12(document2).isFile() || realpathSync5(document2) !== document2 || realpathSync5(located.root) !== located.root || realpathSync5(located.pluginParent) !== located.pluginParent || realpathSync5(join18(located.root, ".codex-plugin/plugin.json")) !== join18(located.root, ".codex-plugin/plugin.json"))
33058
+ return null;
33059
+ const parts = relative5(cache, parsed.pluginParent).split(sep6);
33060
+ if (parts.length !== 2 || parts.some((part) => !identifier2(part)) || parts[1] !== parsed.namespace)
33061
+ return null;
33062
+ return { name: parsed.name, namespace: parsed.namespace, pluginId: `${parts[1]}@${parts[0]}`, pluginParent: parsed.pluginParent, root: located.root, manifestSha256: parsed.manifestSha256 };
33063
+ } catch {
33064
+ return null;
33065
+ }
33066
+ }
32909
33067
  function reviewedDisabledCodexPluginParent(cache, parent, controls, rules) {
32910
33068
  try {
32911
33069
  const parts = relative5(cache, parent).split(sep6), enrolled = controls.filter((control) => control.pluginParent === parent);
@@ -32969,7 +33127,7 @@ function reviewedCodexPluginCapabilitiesUnchanged(cache, controls, read, rules)
32969
33127
  for (const parent of new Set(controls.map((control) => control.pluginParent))) {
32970
33128
  if (absentDisabledCodexPluginParent(cache, parent, controls, rules))
32971
33129
  continue;
32972
- if (!parent.startsWith(cache + sep6) || !lstatSync12(parent, { throwIfNoEntry: false })?.isDirectory() || realpathSync4(parent) !== parent)
33130
+ if (!parent.startsWith(cache + sep6) || !lstatSync12(parent, { throwIfNoEntry: false })?.isDirectory() || realpathSync5(parent) !== parent)
32973
33131
  return false;
32974
33132
  for (const control of controls.filter((control2) => control2.pluginParent === parent)) {
32975
33133
  if (control.remotePluginId !== undefined && !remoteInstallationMatches(parent, control.remotePluginId, read))
@@ -32983,7 +33141,7 @@ function reviewedCodexPluginCapabilitiesUnchanged(cache, controls, read, rules)
32983
33141
  let root = join18(parent, name), stat = lstatSync12(root);
32984
33142
  if (stat.isSymbolicLink()) {
32985
33143
  const target = resolve11(parent, readlinkSync3(root));
32986
- if (name !== "latest" || dirname12(target) !== parent || !lstatSync12(target).isDirectory() || realpathSync4(target) !== target)
33144
+ if (name !== "latest" || dirname12(target) !== parent || !lstatSync12(target).isDirectory() || realpathSync5(target) !== target)
32987
33145
  return false;
32988
33146
  root = target;
32989
33147
  stat = lstatSync12(root);
@@ -33003,10 +33161,10 @@ function reviewedCodexPluginCapabilitiesUnchanged(cache, controls, read, rules)
33003
33161
  function sourceInputUnchanged(input2, cache, read) {
33004
33162
  try {
33005
33163
  const parts = relative5(cache, input2.pluginParent).split(sep6);
33006
- if (parts.length !== 2 || parts.some((part) => !identifier2(part)) || parts[1] !== input2.namespace || input2.pluginId !== `${parts[1]}@${parts[0]}` || !codexPluginSourceIsConfigControlled({ id: input2.pluginId, sourceType: "local", sourceSha256: input2.sourceSha256 }) || input2.sourceSha256 !== hashNativeJsonControls(JSON.stringify({ type: "local", path: input2.sourceRoot })) || resolve11(input2.sourceRoot) !== input2.sourceRoot || !lstatSync12(input2.sourceRoot).isDirectory() || realpathSync4(input2.sourceRoot) !== input2.sourceRoot || input2.sourceRoot === cache || input2.sourceRoot.startsWith(cache + sep6) || cache.startsWith(input2.sourceRoot + sep6))
33164
+ if (parts.length !== 2 || parts.some((part) => !identifier2(part)) || parts[1] !== input2.namespace || input2.pluginId !== `${parts[1]}@${parts[0]}` || !codexPluginSourceIsConfigControlled({ id: input2.pluginId, sourceType: "local", sourceSha256: input2.sourceSha256 }) || input2.sourceSha256 !== hashNativeJsonControls(JSON.stringify({ type: "local", path: input2.sourceRoot })) || resolve11(input2.sourceRoot) !== input2.sourceRoot || !lstatSync12(input2.sourceRoot).isDirectory() || realpathSync5(input2.sourceRoot) !== input2.sourceRoot || input2.sourceRoot === cache || input2.sourceRoot.startsWith(cache + sep6) || cache.startsWith(input2.sourceRoot + sep6))
33007
33165
  return false;
33008
33166
  const path = join18(input2.sourceRoot, ".codex-plugin/plugin.json"), stat = lstatSync12(path);
33009
- if (!stat.isFile() || stat.size > 1024 * 1024 || realpathSync4(path) !== path)
33167
+ if (!stat.isFile() || stat.size > 1024 * 1024 || realpathSync5(path) !== path)
33010
33168
  return false;
33011
33169
  const text2 = read(path);
33012
33170
  hashNativeJsonControls(text2);
@@ -33300,6 +33458,8 @@ function normalize3(config2, version2 = 2) {
33300
33458
  if (isRecord3(profile))
33301
33459
  inference(profile, version2);
33302
33460
  }
33461
+ if (version2 === 5)
33462
+ projectStatusLine(config2);
33303
33463
  }
33304
33464
  function disablesOneSkill(entry) {
33305
33465
  if (!isRecord3(entry) || entry.enabled !== false)
@@ -33437,6 +33597,14 @@ function projectModelAvailabilityNux(config2, text2) {
33437
33597
  }
33438
33598
  return { config: config2, numericSource: text2 };
33439
33599
  }
33600
+ function projectStatusLine(config2) {
33601
+ const tui = config2.tui;
33602
+ if (!isRecord3(tui) || !Array.isArray(tui.status_line) || !tui.status_line.every((item) => typeof item === "string"))
33603
+ return;
33604
+ delete tui.status_line;
33605
+ if (!Object.keys(tui).length)
33606
+ delete config2.tui;
33607
+ }
33440
33608
  function settingsDigest2(text2, version2 = 2) {
33441
33609
  let config2;
33442
33610
  try {
@@ -33446,7 +33614,7 @@ function settingsDigest2(text2, version2 = 2) {
33446
33614
  }
33447
33615
  need5(isRecord3(config2));
33448
33616
  const mcp = version2 >= 3 ? projectRegularCodexMcp(config2, text2) : { config: config2, numericSource: text2 };
33449
- const projected = version2 === 4 ? projectModelAvailabilityNux(mcp.config, mcp.numericSource) : mcp;
33617
+ const projected = version2 >= 4 ? projectModelAvailabilityNux(mcp.config, mcp.numericSource) : mcp;
33450
33618
  normalize3(projected.config, version2);
33451
33619
  return sha2(`hasna.skills.codex-settings.v${version2}\x00${JSON.stringify([canonical6(projected.config), numericTokens2(projected.numericSource)])}`);
33452
33620
  }
@@ -33475,6 +33643,14 @@ function hashCodexSettingsReplacementV4(text2, budget2 = { remaining: 256 * 1024
33475
33643
  function captureCodexSettingsV4(path, budget2 = { remaining: 256 * 1024 * 1024 }) {
33476
33644
  return { path, hashMode: "codex-settings-v4", sha256: settingsDigest2(readNativeSettingsWitnessFile(path, budget2, "config.toml"), 4) };
33477
33645
  }
33646
+ function hashCodexSettingsReplacementV5(text2, budget2 = { remaining: 256 * 1024 * 1024 }) {
33647
+ need5(Buffer.byteLength(text2) <= 1024 * 1024 && budget2.remaining >= Buffer.byteLength(text2));
33648
+ budget2.remaining -= Buffer.byteLength(text2);
33649
+ return settingsDigest2(text2, 5);
33650
+ }
33651
+ function captureCodexSettingsV5(path, budget2 = { remaining: 256 * 1024 * 1024 }) {
33652
+ return { path, hashMode: "codex-settings-v5", sha256: settingsDigest2(readNativeSettingsWitnessFile(path, budget2, "config.toml"), 5) };
33653
+ }
33478
33654
  var sha2 = (text2) => createHash13("sha256").update(text2).digest("hex"), EFFORT2, VERBOSITY2, MODEL, CODEX_DISCOVERY_PROJECTION_FIELDS, INFERENCE;
33479
33655
  var init_codex_settings_witness = __esm(() => {
33480
33656
  init_codex_settings_witness_v1();
@@ -33488,9 +33664,575 @@ var init_codex_settings_witness = __esm(() => {
33488
33664
  INFERENCE = ["model", "model_reasoning_effort", "model_verbosity"];
33489
33665
  });
33490
33666
 
33667
+ // src/lib/codex-semantic-cache-witness.ts
33668
+ import { createHash as createHash14 } from "crypto";
33669
+ import { constants as constants7, closeSync as closeSync10, fstatSync as fstatSync10, lstatSync as lstatSync13, openSync as openSync10, readSync as readSync5, readdirSync as readdirSync7, realpathSync as realpathSync6 } from "fs";
33670
+ import { dirname as dirname13, isAbsolute as isAbsolute11, join as join19, relative as relative6, resolve as resolve12, sep as sep7 } from "path";
33671
+ function defaultRead(path) {
33672
+ const before = lstatSync13(path, { throwIfNoEntry: false, bigint: true });
33673
+ if (before === undefined)
33674
+ return refuse3();
33675
+ if (!before.isFile() || before.isSymbolicLink() || before.size > BigInt(MAX_DOCUMENT_BYTES))
33676
+ refuse3();
33677
+ let fd;
33678
+ try {
33679
+ fd = openSync10(path, constants7.O_RDONLY | (constants7.O_NOFOLLOW ?? 0));
33680
+ } catch {
33681
+ return refuse3();
33682
+ }
33683
+ try {
33684
+ const opened = fstatSync10(fd, { bigint: true });
33685
+ if (!opened.isFile() || opened.dev !== before.dev || opened.ino !== before.ino || opened.size !== before.size || opened.size > BigInt(MAX_DOCUMENT_BYTES))
33686
+ refuse3();
33687
+ const chunks = [];
33688
+ let total = 0;
33689
+ while (total <= MAX_DOCUMENT_BYTES) {
33690
+ const chunk = Buffer.alloc(Math.min(64 * 1024, MAX_DOCUMENT_BYTES + 1 - total));
33691
+ const count = readSync5(fd, chunk, 0, chunk.length, null);
33692
+ if (!count)
33693
+ break;
33694
+ total += count;
33695
+ if (total > MAX_DOCUMENT_BYTES)
33696
+ refuse3();
33697
+ chunks.push(chunk.subarray(0, count));
33698
+ }
33699
+ const after = fstatSync10(fd, { bigint: true });
33700
+ if (after.dev !== opened.dev || after.ino !== opened.ino || after.size !== opened.size || after.mtimeNs !== opened.mtimeNs || after.ctimeNs !== opened.ctimeNs || BigInt(total) !== after.size)
33701
+ refuse3();
33702
+ return Buffer.concat(chunks, total).toString("utf8");
33703
+ } finally {
33704
+ closeSync10(fd);
33705
+ }
33706
+ }
33707
+ function canonical7(value) {
33708
+ if (value === null || typeof value !== "object")
33709
+ return JSON.stringify(value);
33710
+ if (Array.isArray(value))
33711
+ return `[${value.map(canonical7).join(",")}]`;
33712
+ const object6 = value;
33713
+ return `{${Object.keys(object6).sort().map((key) => `${JSON.stringify(key)}:${canonical7(object6[key])}`).join(",")}}`;
33714
+ }
33715
+ function hash3(value) {
33716
+ return createHash14("sha256").update(canonical7(value)).digest("hex");
33717
+ }
33718
+ function plainObject(value) {
33719
+ return Boolean(value && typeof value === "object" && !Array.isArray(value));
33720
+ }
33721
+ function exactKeys(value, required2, optional2 = []) {
33722
+ const keys = Object.keys(value).sort();
33723
+ return required2.every((key) => Object.hasOwn(value, key)) && keys.every((key) => required2.includes(key) || optional2.includes(key));
33724
+ }
33725
+ function validPluginParent(cacheRoot, pluginParent, namespace, pluginId) {
33726
+ if (!isAbsolute11(pluginParent) || resolve12(pluginParent) !== pluginParent)
33727
+ return false;
33728
+ const parts = relative6(cacheRoot, pluginParent).split(sep7);
33729
+ return parts.length === 2 && parts.every(identifier3) && parts[1] === namespace && pluginId === `${namespace}@${parts[0]}`;
33730
+ }
33731
+ function assertWitnessShape(value) {
33732
+ if (!plainObject(value) || !exactKeys(value, ["schema", "cacheRoot", "controls", "appOnlyParents", "skills", "sha256"]) || value.schema !== CODEX_SEMANTIC_CACHE_WITNESS_SCHEMA || typeof value.cacheRoot !== "string" || !isAbsolute11(value.cacheRoot) || resolve12(value.cacheRoot) !== value.cacheRoot || !digest(value.sha256) || !Array.isArray(value.controls) || value.controls.length === 0 || value.controls.length > 4096 || !Array.isArray(value.appOnlyParents) || value.appOnlyParents.length > 4096 || !Array.isArray(value.skills) || value.skills.length === 0 || value.skills.length > 4096)
33733
+ refuse3();
33734
+ const witness = value;
33735
+ const controlParents = new Set;
33736
+ for (const candidate of witness.controls) {
33737
+ if (!plainObject(candidate))
33738
+ refuse3();
33739
+ const row = candidate;
33740
+ if (!exactKeys(row, ["pluginId", "namespace", "pluginParent", "manifestSha256"], ["remotePluginId", "receiptSha256", "appSha256", "mcpSha256"]) || !identifier3(row.namespace) || typeof row.pluginId !== "string" || !/^[A-Za-z0-9_-]{1,64}@[A-Za-z0-9_-]{1,64}$/.test(row.pluginId) || typeof row.pluginParent !== "string" || !validPluginParent(String(witness.cacheRoot), row.pluginParent, row.namespace, row.pluginId) || !digest(row.manifestSha256) || row.appSha256 !== undefined && !digest(row.appSha256) || row.mcpSha256 !== undefined && !digest(row.mcpSha256) || row.receiptSha256 !== undefined && !digest(row.receiptSha256) || row.remotePluginId !== undefined && (typeof row.remotePluginId !== "string" || !/^[A-Za-z0-9_~-]{1,1024}$/.test(row.remotePluginId)) || row.remotePluginId === undefined !== (row.receiptSha256 === undefined) || controlParents.has(row.pluginParent))
33741
+ refuse3();
33742
+ controlParents.add(row.pluginParent);
33743
+ }
33744
+ const appOnlyParentPaths = new Set;
33745
+ for (const candidate of witness.appOnlyParents) {
33746
+ if (!plainObject(candidate))
33747
+ refuse3();
33748
+ const row = candidate;
33749
+ if (!exactKeys(row, ["role", "pluginId", "namespace", "pluginParent", "remotePluginId", "receiptSha256", "manifestSha256", "appSha256"], ["mcpSha256"]) || row.role !== "app-only" || !identifier3(row.namespace) || typeof row.pluginId !== "string" || !/^[A-Za-z0-9_-]{1,64}@[A-Za-z0-9_-]{1,64}$/.test(row.pluginId) || typeof row.pluginParent !== "string" || !validPluginParent(String(witness.cacheRoot), row.pluginParent, row.namespace, row.pluginId) || typeof row.remotePluginId !== "string" || !/^[A-Za-z0-9_~-]{1,1024}$/.test(row.remotePluginId) || !digest(row.receiptSha256) || !digest(row.manifestSha256) || !digest(row.appSha256) || row.mcpSha256 !== undefined && !digest(row.mcpSha256) || appOnlyParentPaths.has(row.pluginParent) || controlParents.has(row.pluginParent))
33750
+ refuse3();
33751
+ appOnlyParentPaths.add(row.pluginParent);
33752
+ }
33753
+ const skillNames = new Set;
33754
+ const qualifiedNames = new Set;
33755
+ for (const candidate of witness.skills) {
33756
+ if (!plainObject(candidate))
33757
+ refuse3();
33758
+ const row = candidate;
33759
+ if (!exactKeys(row, ["name", "pluginId", "namespace", "pluginParent", "disabledRules"]) || typeof row.name !== "string" || !row.name.startsWith(`${String(row.namespace)}:`) || !identifier3(row.name.slice(String(row.namespace).length + 1)) || !identifier3(row.namespace) || typeof row.pluginId !== "string" || !/^[A-Za-z0-9_-]{1,64}@[A-Za-z0-9_-]{1,64}$/.test(row.pluginId) || typeof row.pluginParent !== "string" || !validPluginParent(String(witness.cacheRoot), row.pluginParent, String(row.namespace), row.pluginId) || !Array.isArray(row.disabledRules) || row.disabledRules.length !== 1 || row.disabledRules.some((rule) => rule !== `name:${String(row.name)}=disabled`) || !controlParents.has(row.pluginParent))
33760
+ refuse3();
33761
+ const qualified = `${row.pluginId}\x00${row.name}`;
33762
+ if (qualifiedNames.has(qualified) || skillNames.has(row.name))
33763
+ refuse3();
33764
+ qualifiedNames.add(qualified);
33765
+ skillNames.add(row.name);
33766
+ }
33767
+ const projection = {
33768
+ schema: witness.schema,
33769
+ cacheRoot: witness.cacheRoot,
33770
+ controls: witness.controls,
33771
+ appOnlyParents: witness.appOnlyParents,
33772
+ skills: witness.skills
33773
+ };
33774
+ if (hash3(projection) !== witness.sha256)
33775
+ refuse3();
33776
+ }
33777
+ function assertCanonicalDirectory(path) {
33778
+ if (resolve12(path) !== path || realpathSync6(path) !== path)
33779
+ refuse3();
33780
+ for (let cursor = path;; cursor = dirname13(cursor)) {
33781
+ const stat = lstatSync13(cursor, { throwIfNoEntry: false });
33782
+ if (stat && (!stat.isDirectory() || stat.isSymbolicLink()))
33783
+ refuse3();
33784
+ if (dirname13(cursor) === cursor)
33785
+ break;
33786
+ }
33787
+ }
33788
+ function walkSafeTree(path, state, depth = 0, root = path) {
33789
+ if (depth > 64 || ++state.entries > 16384)
33790
+ refuse3();
33791
+ const names = readdirSync7(path).sort();
33792
+ const files = [];
33793
+ for (const name of names) {
33794
+ if (!name || name === "." || name === ".." || name.includes(sep7) || ++state.entries > 16384)
33795
+ refuse3();
33796
+ const child2 = join19(path, name), stat = lstatSync13(child2, { bigint: true });
33797
+ state.members.push(child2);
33798
+ state.signature.push(`${relative6(root, child2)}\x00${stat.mode}\x00${stat.dev}\x00${stat.ino}\x00${stat.isDirectory() ? 0 : stat.size}`);
33799
+ state.timestamps.set(child2, `${stat.mtimeNs}\x00${stat.ctimeNs}`);
33800
+ if (stat.isSymbolicLink())
33801
+ refuse3();
33802
+ if (stat.isDirectory())
33803
+ files.push(...walkSafeTree(child2, state, depth + 1, root));
33804
+ else if (stat.isFile())
33805
+ files.push(child2);
33806
+ else
33807
+ refuse3();
33808
+ }
33809
+ return files;
33810
+ }
33811
+ function treeSnapshot(cacheRoot) {
33812
+ const state = { entries: 0, members: [], signature: [], timestamps: new Map };
33813
+ const rootStat = lstatSync13(cacheRoot, { throwIfNoEntry: false, bigint: true });
33814
+ if (rootStat === undefined)
33815
+ return refuse3();
33816
+ if (!rootStat.isDirectory() || rootStat.isSymbolicLink() || realpathSync6(cacheRoot) !== cacheRoot)
33817
+ refuse3();
33818
+ state.signature.push(`.\x00${rootStat.mode}\x00${rootStat.dev}\x00${rootStat.ino}`);
33819
+ state.timestamps.set(cacheRoot, `${rootStat.mtimeNs}\x00${rootStat.ctimeNs}`);
33820
+ const files = walkSafeTree(cacheRoot, state);
33821
+ return { files, state };
33822
+ }
33823
+ function assertSameTree(before, after, semanticPaths) {
33824
+ if (canonical7([...before.members].sort()) !== canonical7([...after.members].sort()) || canonical7([...before.signature].sort()) !== canonical7([...after.signature].sort()))
33825
+ refuse3();
33826
+ for (const path of semanticPaths)
33827
+ if (before.timestamps.get(path) !== after.timestamps.get(path))
33828
+ refuse3();
33829
+ }
33830
+ function trackedBoundedRead(read) {
33831
+ const observed = new Map;
33832
+ const stableStat = (path, max) => {
33833
+ const stat = lstatSync13(path, { throwIfNoEntry: false, bigint: true });
33834
+ if (stat === undefined)
33835
+ return refuse3();
33836
+ if (!stat.isFile() || stat.isSymbolicLink() || stat.size > BigInt(max) || realpathSync6(path) !== path)
33837
+ refuse3();
33838
+ return stat;
33839
+ };
33840
+ const guarded = (path) => {
33841
+ const max = path.endsWith(".codex-remote-plugin-install.json") ? MAX_RECEIPT_BYTES : MAX_DOCUMENT_BYTES;
33842
+ const before = stableStat(path, max);
33843
+ const text2 = read(path);
33844
+ if (Buffer.byteLength(text2, "utf8") > max)
33845
+ refuse3();
33846
+ const after = stableStat(path, max);
33847
+ if (after.dev !== before.dev || after.ino !== before.ino || after.size !== before.size || after.mtimeNs !== before.mtimeNs || after.ctimeNs !== before.ctimeNs)
33848
+ refuse3();
33849
+ const sha3 = createHash14("sha256").update(text2).digest("hex");
33850
+ const prior = observed.get(path);
33851
+ if (prior !== undefined && prior !== sha3)
33852
+ refuse3();
33853
+ observed.set(path, sha3);
33854
+ return text2;
33855
+ };
33856
+ return {
33857
+ read: guarded,
33858
+ verify: () => {
33859
+ for (const [path, expected] of observed) {
33860
+ const max = path.endsWith(".codex-remote-plugin-install.json") ? MAX_RECEIPT_BYTES : MAX_DOCUMENT_BYTES;
33861
+ const before = stableStat(path, max);
33862
+ const text2 = read(path);
33863
+ const after = stableStat(path, max);
33864
+ if (Buffer.byteLength(text2, "utf8") > max || createHash14("sha256").update(text2).digest("hex") !== expected || after.dev !== before.dev || after.ino !== before.ino || after.size !== before.size || after.mtimeNs !== before.mtimeNs || after.ctimeNs !== before.ctimeNs)
33865
+ refuse3();
33866
+ }
33867
+ },
33868
+ paths: () => [...observed.keys()]
33869
+ };
33870
+ }
33871
+ function controlProjection(controls, read) {
33872
+ const byPlugin = new Map;
33873
+ for (const control of controls) {
33874
+ if (!control || !identifier3(control.namespace) || typeof control.pluginId !== "string" || !/^[A-Za-z0-9_-]{1,64}@[A-Za-z0-9_-]{1,64}$/.test(control.pluginId) || typeof control.pluginParent !== "string" || !control.name.startsWith(`${control.namespace}:`) || !identifier3(control.name.slice(control.namespace.length + 1)))
33875
+ refuse3();
33876
+ if (!digest(control.manifestSha256) || control.appSha256 !== undefined && !digest(control.appSha256) || control.mcpSha256 !== undefined && !digest(control.mcpSha256) || control.remotePluginId !== undefined && (typeof control.remotePluginId !== "string" || !/^[A-Za-z0-9_~-]{1,1024}$/.test(control.remotePluginId)))
33877
+ refuse3();
33878
+ const key = `${control.pluginId}\x00${control.pluginParent}`;
33879
+ const row = {
33880
+ pluginId: control.pluginId,
33881
+ namespace: control.namespace,
33882
+ pluginParent: control.pluginParent,
33883
+ ...control.remotePluginId === undefined ? {} : { remotePluginId: control.remotePluginId },
33884
+ manifestSha256: control.manifestSha256,
33885
+ ...control.appSha256 === undefined ? {} : { appSha256: control.appSha256 },
33886
+ ...control.mcpSha256 === undefined ? {} : { mcpSha256: control.mcpSha256 }
33887
+ };
33888
+ if (row.remotePluginId !== undefined) {
33889
+ const receipt = join19(row.pluginParent, ".codex-remote-plugin-install.json"), stat = lstatSync13(receipt, { throwIfNoEntry: false });
33890
+ if (!stat?.isFile() || stat.isSymbolicLink() || stat.size > 16384)
33891
+ refuse3();
33892
+ try {
33893
+ const receiptText = read(receipt), value = JSON.parse(receiptText);
33894
+ if (!value || Array.isArray(value) || typeof value !== "object" || Object.keys(value).length !== 2 || value.schema_version !== 1 || value.remote_plugin_id !== row.remotePluginId)
33895
+ refuse3();
33896
+ row.receiptSha256 = createHash14("sha256").update(receiptText).digest("hex");
33897
+ } catch {
33898
+ refuse3();
33899
+ }
33900
+ }
33901
+ const previous = byPlugin.get(key);
33902
+ if (previous && canonical7(previous) !== canonical7(row))
33903
+ refuse3();
33904
+ byPlugin.set(key, row);
33905
+ }
33906
+ if (!byPlugin.size || byPlugin.size > 4096)
33907
+ refuse3();
33908
+ return [...byPlugin.values()].sort((a, b) => a.pluginId.localeCompare(b.pluginId) || a.pluginParent.localeCompare(b.pluginParent));
33909
+ }
33910
+ function appOnlyParentProjection(cacheRoot, parents2, read) {
33911
+ if (!Array.isArray(parents2) || parents2.length > 4096)
33912
+ refuse3();
33913
+ const seen = new Set, rows = [];
33914
+ for (const parent of parents2) {
33915
+ if (!parent || Object.keys(parent).sort().join(",") !== "namespace,pluginId,pluginParent,remotePluginId,role" || parent.role !== "app-only" || !identifier3(parent.namespace) || !/^[A-Za-z0-9_-]{1,64}@[A-Za-z0-9_-]{1,64}$/.test(parent.pluginId) || typeof parent.pluginParent !== "string" || typeof parent.remotePluginId !== "string" || !/^[A-Za-z0-9_~-]{1,1024}$/.test(parent.remotePluginId))
33916
+ refuse3();
33917
+ const parts = relative6(cacheRoot, parent.pluginParent).split(sep7);
33918
+ if (resolve12(parent.pluginParent) !== parent.pluginParent || parts.length !== 2 || parts.some((part) => !identifier3(part)) || parent.pluginId !== `${parent.namespace}@${parts[0]}` || parts[1] !== parent.namespace || seen.has(parent.pluginParent))
33919
+ refuse3();
33920
+ seen.add(parent.pluginParent);
33921
+ const parentStat = lstatSync13(parent.pluginParent, { throwIfNoEntry: false });
33922
+ if (!parentStat?.isDirectory() || parentStat.isSymbolicLink() || realpathSync6(parent.pluginParent) !== parent.pluginParent)
33923
+ refuse3();
33924
+ const receipt = join19(parent.pluginParent, ".codex-remote-plugin-install.json"), receiptStat = lstatSync13(receipt, { throwIfNoEntry: false });
33925
+ if (!receiptStat?.isFile() || receiptStat.isSymbolicLink() || receiptStat.size > 16384)
33926
+ refuse3();
33927
+ let receiptText = "";
33928
+ try {
33929
+ receiptText = read(receipt);
33930
+ hashNativeJsonControls(receiptText);
33931
+ const value = JSON.parse(receiptText);
33932
+ if (!value || Array.isArray(value) || typeof value !== "object" || Object.keys(value).length !== 2 || value.schema_version !== 1 || value.remote_plugin_id !== parent.remotePluginId)
33933
+ refuse3();
33934
+ } catch {
33935
+ refuse3();
33936
+ }
33937
+ const versions2 = readdirSync7(parent.pluginParent).filter((name) => name !== ".codex-remote-plugin-install.json");
33938
+ if (!versions2.length || versions2.length > 4096)
33939
+ refuse3();
33940
+ const materializations = versions2.map((version2) => {
33941
+ if (!/^[A-Za-z0-9][A-Za-z0-9._+-]{0,127}$/.test(version2))
33942
+ refuse3();
33943
+ const root = join19(parent.pluginParent, version2), stat = lstatSync13(root, { throwIfNoEntry: false });
33944
+ if (!stat?.isDirectory() || stat.isSymbolicLink() || realpathSync6(root) !== root)
33945
+ refuse3();
33946
+ const rootControls2 = readCodexPluginRootControls(root, read);
33947
+ if (rootControls2.namespace !== parent.namespace || !digest(rootControls2.manifestSha256) || !digest(rootControls2.appSha256) || rootControls2.mcpSha256 !== undefined && !digest(rootControls2.mcpSha256))
33948
+ refuse3();
33949
+ return {
33950
+ manifestSha256: rootControls2.manifestSha256,
33951
+ appSha256: rootControls2.appSha256,
33952
+ ...rootControls2.mcpSha256 === undefined ? {} : { mcpSha256: rootControls2.mcpSha256 }
33953
+ };
33954
+ });
33955
+ const first = materializations[0];
33956
+ if (materializations.some((item) => canonical7(item) !== canonical7(first)))
33957
+ refuse3();
33958
+ rows.push({ ...parent, receiptSha256: createHash14("sha256").update(receiptText).digest("hex"), ...first });
33959
+ }
33960
+ return rows.sort((a, b) => a.pluginId.localeCompare(b.pluginId) || a.pluginParent.localeCompare(b.pluginParent));
33961
+ }
33962
+ function assertParents(cacheRoot, controls, appOnlyParents, files, members2) {
33963
+ const expected = new Set;
33964
+ const expectedMarkets = new Set;
33965
+ for (const control of [...controls, ...appOnlyParents]) {
33966
+ const rel = relative6(cacheRoot, control.pluginParent), parts = rel.split(sep7);
33967
+ if (resolve12(control.pluginParent) !== control.pluginParent || parts.length !== 2 || parts.some((part) => !identifier3(part)) || control.pluginId !== `${control.namespace}@${parts[0]}` || parts[1] !== control.namespace)
33968
+ refuse3();
33969
+ expected.add(control.pluginParent);
33970
+ expectedMarkets.add(parts[0]);
33971
+ }
33972
+ const actual = new Set;
33973
+ for (const file2 of files) {
33974
+ const rel = relative6(cacheRoot, file2), parts = rel.split(sep7);
33975
+ if (parts.length < 3 || !identifier3(parts[0]) || !identifier3(parts[1]))
33976
+ refuse3();
33977
+ actual.add(join19(cacheRoot, parts[0], parts[1]));
33978
+ }
33979
+ const actualMarkets = readdirSync7(cacheRoot);
33980
+ if (actualMarkets.length !== expectedMarkets.size || actualMarkets.some((market) => !expectedMarkets.has(market)))
33981
+ refuse3();
33982
+ for (const market of actualMarkets) {
33983
+ const marketPath = join19(cacheRoot, market), marketStat = lstatSync13(marketPath);
33984
+ if (!identifier3(market) || !marketStat.isDirectory() || marketStat.isSymbolicLink())
33985
+ refuse3();
33986
+ for (const plugin of readdirSync7(marketPath)) {
33987
+ const parent = join19(marketPath, plugin), stat = lstatSync13(parent);
33988
+ if (!identifier3(plugin) || !stat.isDirectory() || stat.isSymbolicLink())
33989
+ refuse3();
33990
+ actual.add(parent);
33991
+ }
33992
+ }
33993
+ if (actual.size !== expected.size || [...actual].some((parent) => !expected.has(parent)))
33994
+ refuse3();
33995
+ for (const member of members2) {
33996
+ const parts = relative6(cacheRoot, member).split(sep7);
33997
+ if (parts.length < 3)
33998
+ continue;
33999
+ const parent = join19(cacheRoot, parts[0], parts[1]);
34000
+ const root = join19(parent, parts[2]);
34001
+ const base = parts[parts.length - 1];
34002
+ if (parts.includes(".codex-plugin") && (parts.length < 4 || parts[3] !== ".codex-plugin" || (parts.length === 4 ? base !== ".codex-plugin" : parts.length !== 5 || base !== "plugin.json")))
34003
+ refuse3();
34004
+ if ([".app.json", ".mcp.json"].includes(base) && (parts.length !== 4 || dirname13(member) !== root))
34005
+ refuse3();
34006
+ if (parts.includes("hooks"))
34007
+ refuse3();
34008
+ }
34009
+ }
34010
+ function assertSkillMaterializations(cacheRoot, controls, files, read) {
34011
+ const expectedByRoot = new Map;
34012
+ const byParent = new Map;
34013
+ for (const control of controls) {
34014
+ const group = byParent.get(control.pluginParent) ?? [];
34015
+ group.push(control);
34016
+ byParent.set(control.pluginParent, group);
34017
+ }
34018
+ for (const [parent, rows] of byParent) {
34019
+ const first = rows[0];
34020
+ const expectedControls = {
34021
+ namespace: first.namespace,
34022
+ manifestSha256: first.manifestSha256,
34023
+ ...first.appSha256 === undefined ? {} : { appSha256: first.appSha256 },
34024
+ ...first.mcpSha256 === undefined ? {} : { mcpSha256: first.mcpSha256 }
34025
+ };
34026
+ if (rows.some((row) => canonical7({
34027
+ namespace: row.namespace,
34028
+ manifestSha256: row.manifestSha256,
34029
+ ...row.appSha256 === undefined ? {} : { appSha256: row.appSha256 },
34030
+ ...row.mcpSha256 === undefined ? {} : { mcpSha256: row.mcpSha256 }
34031
+ }) !== canonical7(expectedControls)))
34032
+ refuse3();
34033
+ const expectedNames = new Set(rows.map((row) => row.name));
34034
+ if (expectedNames.size !== rows.length)
34035
+ refuse3();
34036
+ const entries = readdirSync7(parent);
34037
+ let roots = 0;
34038
+ for (const entry of entries) {
34039
+ if (entry === ".codex-remote-plugin-install.json")
34040
+ continue;
34041
+ if (!/^[A-Za-z0-9][A-Za-z0-9._+-]{0,127}$/.test(entry))
34042
+ refuse3();
34043
+ const root = join19(parent, entry), stat = lstatSync13(root, { throwIfNoEntry: false });
34044
+ if (!stat?.isDirectory() || stat.isSymbolicLink() || realpathSync6(root) !== root)
34045
+ refuse3();
34046
+ const actualControls = readCodexPluginRootControls(root, read);
34047
+ const actualProjection = {
34048
+ namespace: actualControls.namespace,
34049
+ manifestSha256: actualControls.manifestSha256,
34050
+ ...actualControls.appSha256 === undefined ? {} : { appSha256: actualControls.appSha256 },
34051
+ ...actualControls.mcpSha256 === undefined ? {} : { mcpSha256: actualControls.mcpSha256 }
34052
+ };
34053
+ if (canonical7(actualProjection) !== canonical7(expectedControls))
34054
+ refuse3();
34055
+ const key = `${first.pluginId}\x00${root}`;
34056
+ expectedByRoot.set(key, expectedNames);
34057
+ roots++;
34058
+ }
34059
+ if (!roots)
34060
+ refuse3();
34061
+ }
34062
+ for (const file2 of files) {
34063
+ if (!file2.endsWith(`${sep7}SKILL.md`))
34064
+ continue;
34065
+ const rel = relative6(cacheRoot, file2).split(sep7);
34066
+ if (rel.length < 4)
34067
+ refuse3();
34068
+ const parent = join19(cacheRoot, rel[0], rel[1]);
34069
+ if (!byParent.has(parent) || !expectedByRoot.has(`${byParent.get(parent)[0].pluginId}\x00${join19(parent, rel[2])}`))
34070
+ refuse3();
34071
+ }
34072
+ return expectedByRoot;
34073
+ }
34074
+ function effectiveDisabledRules(skill, rules) {
34075
+ if (!Array.isArray(rules))
34076
+ refuse3();
34077
+ const matching = [];
34078
+ for (const candidate of rules) {
34079
+ if (!plainObject(candidate) || typeof candidate.enabled !== "boolean")
34080
+ refuse3();
34081
+ const rule = candidate;
34082
+ const byName = typeof rule.name === "string" && rule.name.trim() === skill.name;
34083
+ let byPath = false;
34084
+ if (typeof rule.path === "string") {
34085
+ if (resolve12(rule.path) !== rule.path)
34086
+ refuse3();
34087
+ let canonicalPath2;
34088
+ try {
34089
+ canonicalPath2 = realpathSync6(rule.path);
34090
+ } catch {
34091
+ canonicalPath2 = resolve12(rule.path);
34092
+ }
34093
+ if (canonicalPath2 === skill.path && rule.path !== canonicalPath2)
34094
+ refuse3();
34095
+ byPath = canonicalPath2 === skill.path;
34096
+ }
34097
+ if ((byName || byPath) && rule.enabled !== false)
34098
+ refuse3();
34099
+ if (byName)
34100
+ matching.push(`name:${skill.name}=disabled`);
34101
+ }
34102
+ if (!isCodexNativeSkillDisabled(skill, rules))
34103
+ refuse3();
34104
+ if (!matching.length)
34105
+ refuse3();
34106
+ return [...new Set(matching)].sort();
34107
+ }
34108
+ function captureCodexSemanticCacheWitness(options) {
34109
+ const tracked = trackedBoundedRead(options.read ?? defaultRead);
34110
+ const read = tracked.read;
34111
+ try {
34112
+ assertCanonicalDirectory(options.cacheRoot);
34113
+ const initialTree = treeSnapshot(options.cacheRoot);
34114
+ const controls = controlProjection(options.controls, read);
34115
+ const appOnlyParents = appOnlyParentProjection(options.cacheRoot, options.appOnlyParents ?? [], read);
34116
+ const skillParents = new Set(controls.map((control) => control.pluginParent));
34117
+ if (appOnlyParents.some((parent) => skillParents.has(parent.pluginParent)))
34118
+ refuse3();
34119
+ if (!reviewedCodexPluginCapabilitiesUnchanged(options.cacheRoot, options.controls, read, options.rules))
34120
+ refuse3();
34121
+ const files = initialTree.files;
34122
+ assertParents(options.cacheRoot, controls, appOnlyParents, files, initialTree.state.members);
34123
+ const expectedNamesByRoot = assertSkillMaterializations(options.cacheRoot, options.controls, files, read);
34124
+ const docs = files.filter((path) => path.endsWith(`${sep7}SKILL.md`));
34125
+ const skillRows = [];
34126
+ const rootNames = new Map;
34127
+ for (const document2 of docs) {
34128
+ const rel = relative6(options.cacheRoot, document2).split(sep7);
34129
+ if (appOnlyParents.some((parent) => parent.pluginParent === join19(options.cacheRoot, rel[0], rel[1])))
34130
+ refuse3();
34131
+ const documentStat = lstatSync13(document2, { throwIfNoEntry: false });
34132
+ if (!documentStat?.isFile() || documentStat.isSymbolicLink() || documentStat.size > MAX_DOCUMENT_BYTES)
34133
+ refuse3();
34134
+ const identity4 = classifyCodexPluginCacheDocument(document2, options.cacheRoot, read);
34135
+ if (identity4 === null)
34136
+ return refuse3();
34137
+ const row = {
34138
+ name: identity4.name,
34139
+ pluginId: identity4.pluginId,
34140
+ namespace: identity4.namespace,
34141
+ pluginParent: identity4.pluginParent,
34142
+ disabledRules: effectiveDisabledRules({ name: identity4.name, path: document2, enabled: true, pluginId: identity4.pluginId }, options.rules)
34143
+ };
34144
+ const root = identity4.root;
34145
+ const rootKey = `${row.pluginId}\x00${root}`;
34146
+ const names = rootNames.get(rootKey) ?? new Set;
34147
+ if (names.has(row.name))
34148
+ refuse3();
34149
+ names.add(row.name);
34150
+ rootNames.set(rootKey, names);
34151
+ skillRows.push(row);
34152
+ }
34153
+ if (!skillRows.length || skillRows.length > 4096)
34154
+ refuse3();
34155
+ const uniqueNames = new Set(skillRows.map((row) => `${row.pluginId}\x00${row.name}`));
34156
+ const reviewedNames = new Set(options.controls.map((control) => `${control.pluginId}\x00${control.name}`));
34157
+ if (reviewedNames.size !== options.controls.length || new Set(options.controls.map((control) => control.name)).size !== options.controls.length)
34158
+ refuse3();
34159
+ if (uniqueNames.size !== reviewedNames.size || [...uniqueNames].some((name) => !reviewedNames.has(name)))
34160
+ refuse3();
34161
+ if (new Set(skillRows.map((row) => row.name)).size !== reviewedNames.size)
34162
+ refuse3();
34163
+ const byPlugin = new Map;
34164
+ for (const row of skillRows) {
34165
+ const names = byPlugin.get(row.pluginId) ?? new Set;
34166
+ names.add(row.name);
34167
+ byPlugin.set(row.pluginId, names);
34168
+ }
34169
+ for (const [key, expected] of expectedNamesByRoot) {
34170
+ const names = rootNames.get(key);
34171
+ if (!names || names.size !== expected.size || [...expected].some((name) => !names.has(name)))
34172
+ refuse3();
34173
+ }
34174
+ if (rootNames.size !== expectedNamesByRoot.size)
34175
+ refuse3();
34176
+ for (const [key, names] of rootNames) {
34177
+ const pluginId = key.slice(0, key.indexOf("\x00")), expected = byPlugin.get(pluginId);
34178
+ if (!expected || names.size !== expected.size || [...expected].some((name) => !names.has(name)))
34179
+ refuse3();
34180
+ }
34181
+ const skillsByName = new Map;
34182
+ for (const row of skillRows) {
34183
+ const key = `${row.pluginId}\x00${row.name}`, prior = skillsByName.get(key);
34184
+ if (prior && canonical7(prior.disabledRules) !== canonical7(row.disabledRules))
34185
+ refuse3();
34186
+ if (!prior)
34187
+ skillsByName.set(key, row);
34188
+ }
34189
+ const uniqueSkills = [...skillsByName.values()];
34190
+ uniqueSkills.sort((a, b) => a.pluginId.localeCompare(b.pluginId) || a.name.localeCompare(b.name));
34191
+ tracked.verify();
34192
+ const finalTree = treeSnapshot(options.cacheRoot);
34193
+ assertSameTree(initialTree.state, finalTree.state, tracked.paths());
34194
+ const completeProjection = { schema: CODEX_SEMANTIC_CACHE_WITNESS_SCHEMA, cacheRoot: options.cacheRoot, controls, appOnlyParents, skills: uniqueSkills };
34195
+ return { ...completeProjection, sha256: hash3(completeProjection) };
34196
+ } catch (error61) {
34197
+ if (error61 instanceof Error && error61.message.startsWith("CODEX_SEMANTIC_CACHE_WITNESS_UNSUPPORTED"))
34198
+ throw error61;
34199
+ return refuse3();
34200
+ }
34201
+ }
34202
+ function assertCodexSemanticCacheWitnessUnchanged(previous, current) {
34203
+ assertWitnessShape(previous);
34204
+ assertWitnessShape(current);
34205
+ const priorProjection = {
34206
+ schema: previous.schema,
34207
+ cacheRoot: previous.cacheRoot,
34208
+ controls: previous.controls,
34209
+ appOnlyParents: previous.appOnlyParents,
34210
+ skills: previous.skills
34211
+ };
34212
+ const currentProjection = {
34213
+ schema: current.schema,
34214
+ cacheRoot: current.cacheRoot,
34215
+ controls: current.controls,
34216
+ appOnlyParents: current.appOnlyParents,
34217
+ skills: current.skills
34218
+ };
34219
+ if (hash3(priorProjection) !== previous.sha256 || hash3(currentProjection) !== current.sha256 || canonical7(priorProjection) !== canonical7(currentProjection))
34220
+ refuse3();
34221
+ }
34222
+ var CODEX_SEMANTIC_CACHE_WITNESS_SCHEMA = "hasna.codex-semantic-cache-witness.v1", identifier3 = (value) => typeof value === "string" && /^[A-Za-z0-9_-]{1,64}$/.test(value), digest = (value) => typeof value === "string" && /^[a-f0-9]{64}$/.test(value), refuse3 = () => {
34223
+ throw new Error("CODEX_SEMANTIC_CACHE_WITNESS_UNSUPPORTED: review Codex plugin cache identity and controls");
34224
+ }, MAX_DOCUMENT_BYTES, MAX_RECEIPT_BYTES;
34225
+ var init_codex_semantic_cache_witness = __esm(() => {
34226
+ init_claude_settings_witness();
34227
+ init_codex_plugin_skill_controls();
34228
+ init_codex_native_skill_catalog();
34229
+ MAX_DOCUMENT_BYTES = 1024 * 1024;
34230
+ MAX_RECEIPT_BYTES = 16 * 1024;
34231
+ });
34232
+
33491
34233
  // src/lib/managed-policy.ts
33492
- import { closeSync as closeSync10, constants as constants7, fstatSync as fstatSync10, lstatSync as lstatSync13, openSync as openSync10, readSync as readSync5 } from "fs";
33493
- import { join as join19 } from "path";
34234
+ import { closeSync as closeSync11, constants as constants8, fstatSync as fstatSync11, lstatSync as lstatSync14, openSync as openSync11, readSync as readSync6 } from "fs";
34235
+ import { join as join20 } from "path";
33494
34236
  function refusal(reason2 = "is unreadable") {
33495
34237
  return new SkillSelectionError("INVALID_AGENT_POLICY", `The Skills agent loading policy ${reason2}; refusing legacy fallback.`);
33496
34238
  }
@@ -33515,17 +34257,17 @@ function parseManagedSkillPolicy(text2) {
33515
34257
  return value;
33516
34258
  }
33517
34259
  function readManagedSkillPolicySnapshot(dataDir2 = getDataDirReadOnly()) {
33518
- const path = join19(dataDir2, "agent-policy.json");
34260
+ const path = join20(dataDir2, "agent-policy.json");
33519
34261
  let descriptor, observed = false;
33520
34262
  try {
33521
- const stat = lstatSync13(path);
34263
+ const stat = lstatSync14(path);
33522
34264
  observed = true;
33523
34265
  if (!stat.isFile() || stat.isSymbolicLink())
33524
34266
  throw refusal();
33525
34267
  if (stat.size > AGENT_POLICY_LIMITS.bytes)
33526
34268
  throw refusal("exceeds its size limit");
33527
- descriptor = openSync10(path, constants7.O_RDONLY | (constants7.O_NOFOLLOW ?? 0) | constants7.O_NONBLOCK);
33528
- const opened = fstatSync10(descriptor);
34269
+ descriptor = openSync11(path, constants8.O_RDONLY | (constants8.O_NOFOLLOW ?? 0) | constants8.O_NONBLOCK);
34270
+ const opened = fstatSync11(descriptor);
33529
34271
  if (!opened.isFile())
33530
34272
  throw refusal();
33531
34273
  if (opened.size > AGENT_POLICY_LIMITS.bytes)
@@ -33533,7 +34275,7 @@ function readManagedSkillPolicySnapshot(dataDir2 = getDataDirReadOnly()) {
33533
34275
  const bytes = Buffer.allocUnsafe(AGENT_POLICY_LIMITS.bytes + 1);
33534
34276
  let length = 0;
33535
34277
  while (length < bytes.length) {
33536
- const count = readSync5(descriptor, bytes, length, bytes.length - length, null);
34278
+ const count = readSync6(descriptor, bytes, length, bytes.length - length, null);
33537
34279
  if (count === 0)
33538
34280
  break;
33539
34281
  length += count;
@@ -33544,7 +34286,7 @@ function readManagedSkillPolicySnapshot(dataDir2 = getDataDirReadOnly()) {
33544
34286
  return { text: text2, value: parseManagedSkillPolicy(text2) };
33545
34287
  } catch (error61) {
33546
34288
  if (error61.code === "ENOENT" && !observed) {
33547
- if (lstatSync13(path, { throwIfNoEntry: false }) === undefined)
34289
+ if (lstatSync14(path, { throwIfNoEntry: false }) === undefined)
33548
34290
  return null;
33549
34291
  }
33550
34292
  if (error61 instanceof SkillSelectionError)
@@ -33552,7 +34294,7 @@ function readManagedSkillPolicySnapshot(dataDir2 = getDataDirReadOnly()) {
33552
34294
  throw refusal();
33553
34295
  } finally {
33554
34296
  if (descriptor !== undefined)
33555
- closeSync10(descriptor);
34297
+ closeSync11(descriptor);
33556
34298
  }
33557
34299
  }
33558
34300
  function readManagedSkillPolicy(dataDir2 = getDataDirReadOnly()) {
@@ -33568,7 +34310,7 @@ var init_managed_policy = __esm(() => {
33568
34310
  });
33569
34311
 
33570
34312
  // src/lib/agent-bridge.ts
33571
- import { createHash as createHash14 } from "crypto";
34313
+ import { createHash as createHash15 } from "crypto";
33572
34314
  var CLI_BRIDGE_VERSION = 1, markdown = `---
33573
34315
  name: skills-cli
33574
34316
  description: Discover, load, author, and run versioned skills through the Skills CLI when a task needs reusable instructions or an executable skill.
@@ -33584,7 +34326,7 @@ Use the Skills CLI as the skill authority for this station.
33584
34326
  This bridge contains no skill payloads. Do not copy skill content into agent-native skill directories or load other native skill copies. If a Skills command refuses authority, selection, integrity, or native drift, report that refusal and use its repair guidance; do not substitute bundled or stale local content. Explicit local draft authoring remains available.
33585
34327
  `, CLI_BRIDGE_DIGEST, CLI_BRIDGE_FILES;
33586
34328
  var init_agent_bridge = __esm(() => {
33587
- CLI_BRIDGE_DIGEST = createHash14("sha256").update(markdown).digest("hex");
34329
+ CLI_BRIDGE_DIGEST = createHash15("sha256").update(markdown).digest("hex");
33588
34330
  CLI_BRIDGE_FILES = Object.freeze({
33589
34331
  "SKILL.md": markdown,
33590
34332
  ".hasna-skills.json": `${JSON.stringify({ managedBy: "@hasna/skills", kind: "cli-bridge", version: CLI_BRIDGE_VERSION, protocol: "selection-v1", contentSha256: CLI_BRIDGE_DIGEST }, null, 2)}
@@ -33595,18 +34337,91 @@ var init_agent_bridge = __esm(() => {
33595
34337
  // src/lib/agent-codex.ts
33596
34338
  var init_agent_codex = () => {};
33597
34339
 
34340
+ // src/lib/hook-diagnostics.ts
34341
+ var CONTEXT_ERROR_CODES, HOOK_REFUSAL_REASON_CODES, OPTIONAL_CONTEXT_FAILURES;
34342
+ var init_hook_diagnostics = __esm(() => {
34343
+ CONTEXT_ERROR_CODES = new Set([
34344
+ "SKILLS_API_CREDENTIAL_UNAVAILABLE",
34345
+ "SKILLS_API_UNAVAILABLE",
34346
+ "SKILLS_API_UNAUTHORIZED",
34347
+ "SKILLS_API_FORBIDDEN",
34348
+ "SKILLS_API_RESOURCE_UNAVAILABLE",
34349
+ "SESSION_WRITE_BUSY",
34350
+ "SKILLS_CONTEXT_FAILED",
34351
+ "SKILLS_STORAGE_FULL",
34352
+ "PROFILE_LOCK_MISMATCH",
34353
+ "PROFILE_IDENTITY_MISMATCH",
34354
+ "PROFILE_APPLIED_REPORT_FAILED",
34355
+ "CACHED_AUTHORITY_REQUIRED",
34356
+ "CACHED_PROFILE_EXPIRED",
34357
+ "CACHED_PROFILE_MISSING",
34358
+ "CACHED_BUNDLE_MISSING",
34359
+ "INVALID_CONTEXT_INPUT",
34360
+ "CONTEXT_INPUT_TOO_LARGE",
34361
+ "INVALID_CONTEXT_BUDGET",
34362
+ "INVALID_SELECTION",
34363
+ "INVALID_SELECTION_ALIASES",
34364
+ "INVALID_RECEIPT",
34365
+ "INVALID_CACHE_FILE",
34366
+ "UNSAFE_CACHE_PATH",
34367
+ "RECEIPT_TOO_LARGE",
34368
+ "BUNDLE_DIGEST_MISMATCH",
34369
+ "BUNDLE_IDENTITY_MISMATCH",
34370
+ "BUNDLE_UNAVAILABLE",
34371
+ "BUNDLE_TOO_LARGE",
34372
+ "SKILL_NOT_SELECTED",
34373
+ "INVALID_SESSION",
34374
+ "SESSION_PARENT_NOT_FOUND",
34375
+ "SESSION_PARENT_MISMATCH",
34376
+ "SESSION_NOT_FOUND",
34377
+ "SESSION_GENERATION_CHANGED",
34378
+ "SESSION_GENERATION_EXHAUSTED",
34379
+ "SESSION_PARENT_CHANGED",
34380
+ "SESSION_RECEIPT_CHANGED",
34381
+ "SESSION_RECONCILIATION_REQUIRED",
34382
+ "SESSION_RENEWAL_TIMEOUT",
34383
+ "SESSION_CONTEXT_CONFLICT",
34384
+ "SESSION_RECONCILIATION_INCOMPLETE",
34385
+ "SESSION_WRITE_LOCKED",
34386
+ "SESSION_WRITE_LOCK_CHANGED",
34387
+ "SESSION_LOCK_RECOVERY_INCOMPLETE"
34388
+ ]);
34389
+ HOOK_REFUSAL_REASON_CODES = Object.freeze([
34390
+ ...CONTEXT_ERROR_CODES,
34391
+ "SKILLS_HOOK_FAILED",
34392
+ "SKILLS_HOOK_TIMEOUT",
34393
+ "SKILLS_HOOK_INVALID_RESPONSE"
34394
+ ]);
34395
+ OPTIONAL_CONTEXT_FAILURES = new Set([
34396
+ "SKILLS_API_CREDENTIAL_UNAVAILABLE",
34397
+ "SKILLS_API_UNAVAILABLE",
34398
+ "SKILLS_API_UNAUTHORIZED",
34399
+ "SKILLS_API_FORBIDDEN",
34400
+ "SKILLS_API_RESOURCE_UNAVAILABLE",
34401
+ "CACHED_PROFILE_EXPIRED",
34402
+ "CACHED_PROFILE_MISSING",
34403
+ "CACHED_BUNDLE_MISSING",
34404
+ "SESSION_RECONCILIATION_REQUIRED",
34405
+ "SESSION_RENEWAL_TIMEOUT",
34406
+ "SESSION_WRITE_BUSY",
34407
+ "SESSION_PARENT_CHANGED",
34408
+ "SESSION_CONTEXT_CONFLICT",
34409
+ "SKILLS_HOOK_TIMEOUT"
34410
+ ]);
34411
+ });
34412
+
33598
34413
  // src/lib/agent-sumi.ts
33599
34414
  import { spawnSync as spawnSync4 } from "child_process";
33600
- import { accessSync, constants as constants8, existsSync as existsSync8, lstatSync as lstatSync14, realpathSync as realpathSync5, statSync as statSync7 } from "fs";
33601
- import { delimiter, isAbsolute as isAbsolute11, join as join20, resolve as resolve12 } from "path";
34415
+ import { accessSync, constants as constants9, existsSync as existsSync8, lstatSync as lstatSync15, realpathSync as realpathSync7, statSync as statSync7 } from "fs";
34416
+ import { delimiter, isAbsolute as isAbsolute12, join as join21, resolve as resolve13 } from "path";
33602
34417
  function recordWithKeys(value, keys) {
33603
34418
  return value !== null && typeof value === "object" && !Array.isArray(value) && Object.keys(value).length === keys.length && keys.every((key) => Object.hasOwn(value, key));
33604
34419
  }
33605
34420
  function absolutePath3(value) {
33606
- return typeof value === "string" && value.length > 0 && value.length <= 32768 && !/[\x00-\x1f\x7f]/.test(value) && isAbsolute11(value) && resolve12(value) === value;
34421
+ return typeof value === "string" && value.length > 0 && value.length <= 32768 && !/[\x00-\x1f\x7f]/.test(value) && isAbsolute12(value) && resolve13(value) === value;
33607
34422
  }
33608
34423
  function absoluteInput(value) {
33609
- return value.length > 0 && value.length <= 32768 && !/[\x00-\x1f\x7f]/.test(value) && isAbsolute11(value);
34424
+ return value.length > 0 && value.length <= 32768 && !/[\x00-\x1f\x7f]/.test(value) && isAbsolute12(value);
33610
34425
  }
33611
34426
  function resolveSumiPathsCommand(pathValue) {
33612
34427
  if (!pathValue)
@@ -33614,9 +34429,9 @@ function resolveSumiPathsCommand(pathValue) {
33614
34429
  for (const directory of pathValue.split(delimiter)) {
33615
34430
  if (!directory || /[\x00-\x1f\x7f]/.test(directory))
33616
34431
  continue;
33617
- const candidate = resolve12(directory, "sumi-paths");
34432
+ const candidate = resolve13(directory, "sumi-paths");
33618
34433
  try {
33619
- accessSync(candidate, constants8.X_OK);
34434
+ accessSync(candidate, constants9.X_OK);
33620
34435
  if (statSync7(candidate).isFile())
33621
34436
  return candidate;
33622
34437
  } catch {}
@@ -33626,7 +34441,7 @@ function resolveSumiPathsCommand(pathValue) {
33626
34441
  function validPathPlan(value, home, cwd) {
33627
34442
  if (!recordWithKeys(value, ["schemaVersion", "kind", "home", "cwd", "roots", "legacyRoots", "configFiles", "skillRoots"]))
33628
34443
  return false;
33629
- if (value.schemaVersion !== 1 || value.kind !== "sumi-paths" || value.home !== resolve12(home) || value.cwd !== resolve12(cwd))
34444
+ if (value.schemaVersion !== 1 || value.kind !== "sumi-paths" || value.home !== resolve13(home) || value.cwd !== resolve13(cwd))
33630
34445
  return false;
33631
34446
  if (!recordWithKeys(value.roots, SUMI_PATH_KEYS) || !recordWithKeys(value.legacyRoots, SUMI_PATH_KEYS))
33632
34447
  return false;
@@ -33648,11 +34463,11 @@ function validPathPlan(value, home, cwd) {
33648
34463
  const legacyConfigRoot = value.legacyRoots.config;
33649
34464
  if (typeof configRoot !== "string" || legacyConfigRoot !== null && typeof legacyConfigRoot !== "string")
33650
34465
  return false;
33651
- if (value.configFiles.canonical !== join20(configRoot, "sumi.json") || value.skillRoots.canonical !== join20(configRoot, "skills"))
34466
+ if (value.configFiles.canonical !== join21(configRoot, "sumi.json") || value.skillRoots.canonical !== join21(configRoot, "skills"))
33652
34467
  return false;
33653
34468
  if (legacyConfigRoot === null)
33654
34469
  return value.configFiles.legacy === null && value.skillRoots.legacy === null;
33655
- return value.configFiles.legacy === join20(legacyConfigRoot, "sumi.json") && value.skillRoots.legacy === join20(legacyConfigRoot, "skills");
34470
+ return value.configFiles.legacy === join21(legacyConfigRoot, "sumi.json") && value.skillRoots.legacy === join21(legacyConfigRoot, "skills");
33656
34471
  }
33657
34472
  function sumiPathPlan(home, cwd = process.cwd(), env = process.env) {
33658
34473
  for (const key of ["SUMI_CONFIG", "SUMI_CONFIG_CONTENT"])
@@ -33662,7 +34477,7 @@ function sumiPathPlan(home, cwd = process.cwd(), env = process.env) {
33662
34477
  throw new SumiPathResolverError("SUMI_PATH_INPUT_REFUSED");
33663
34478
  const runtimePath = process.env.PATH ?? "";
33664
34479
  const executable = resolveSumiPathsCommand(runtimePath);
33665
- if (!executable || !isAbsolute11(executable))
34480
+ if (!executable || !isAbsolute12(executable))
33666
34481
  throw new SumiPathResolverError("SUMI_PATH_RESOLVER_UNAVAILABLE");
33667
34482
  const childEnv = { PATH: runtimePath };
33668
34483
  for (const key of SUMI_PATH_SELECTORS)
@@ -33670,8 +34485,8 @@ function sumiPathPlan(home, cwd = process.cwd(), env = process.env) {
33670
34485
  childEnv[key] = env[key];
33671
34486
  let child2;
33672
34487
  try {
33673
- child2 = spawnSync4(executable, ["--json", "--home", resolve12(home), "--cwd", resolve12(cwd)], {
33674
- cwd: resolve12(cwd),
34488
+ child2 = spawnSync4(executable, ["--json", "--home", resolve13(home), "--cwd", resolve13(cwd)], {
34489
+ cwd: resolve13(cwd),
33675
34490
  env: childEnv,
33676
34491
  encoding: "buffer",
33677
34492
  timeout: 3000,
@@ -33700,17 +34515,17 @@ function sumiPathPlan(home, cwd = process.cwd(), env = process.env) {
33700
34515
  return result;
33701
34516
  }
33702
34517
  function selectedConfigDirectory(plan) {
33703
- const canonical7 = plan.roots.config, legacy = plan.legacyRoots.config;
34518
+ const canonical8 = plan.roots.config, legacy = plan.legacyRoots.config;
33704
34519
  if (legacy === null)
33705
- return existsSync8(canonical7) ? realpathSync5(canonical7) : canonical7;
33706
- const canonicalStat = lstatSync14(canonical7, { throwIfNoEntry: false }), legacyStat = lstatSync14(legacy, { throwIfNoEntry: false });
33707
- if (canonicalStat && legacyStat && realpathSync5(canonical7) !== realpathSync5(legacy))
34520
+ return existsSync8(canonical8) ? realpathSync7(canonical8) : canonical8;
34521
+ const canonicalStat = lstatSync15(canonical8, { throwIfNoEntry: false }), legacyStat = lstatSync15(legacy, { throwIfNoEntry: false });
34522
+ if (canonicalStat && legacyStat && realpathSync7(canonical8) !== realpathSync7(legacy))
33708
34523
  throw new Error("Sumi config roots conflict; complete native home adoption before Skills integration");
33709
- const selected = canonicalStat ? canonical7 : legacyStat ? legacy : canonical7;
34524
+ const selected = canonicalStat ? canonical8 : legacyStat ? legacy : canonical8;
33710
34525
  if (!existsSync8(selected))
33711
34526
  return selected;
33712
- const physical = realpathSync5(selected);
33713
- if ((canonicalStat?.isSymbolicLink() || legacyStat?.isSymbolicLink()) && ![canonical7, legacy].includes(physical))
34527
+ const physical = realpathSync7(selected);
34528
+ if ((canonicalStat?.isSymbolicLink() || legacyStat?.isSymbolicLink()) && ![canonical8, legacy].includes(physical))
33714
34529
  throw new Error("Sumi config alias must resolve to its canonical or legacy root");
33715
34530
  return physical;
33716
34531
  }
@@ -33718,10 +34533,11 @@ function sumiConfigDirectory(home, env = process.env, cwd = process.cwd()) {
33718
34533
  return selectedConfigDirectory(sumiPathPlan(home, cwd, env));
33719
34534
  }
33720
34535
  function sumiConfigPath(home, cwd = process.cwd(), env = process.env) {
33721
- return join20(sumiConfigDirectory(home, env, cwd), "sumi.json");
34536
+ return join21(sumiConfigDirectory(home, env, cwd), "sumi.json");
33722
34537
  }
33723
34538
  var SUMI_PATH_SELECTORS, SUMI_PATH_KEYS, SUMI_PATH_OUTPUT_LIMIT, SumiPathResolverError;
33724
34539
  var init_agent_sumi = __esm(() => {
34540
+ init_hook_diagnostics();
33725
34541
  SUMI_PATH_SELECTORS = ["SUMI_HOME", "SUMI_CONFIG_DIR", "XDG_DATA_HOME", "XDG_CACHE_HOME", "XDG_CONFIG_HOME", "XDG_STATE_HOME"];
33726
34542
  SUMI_PATH_KEYS = ["data", "cache", "config", "state"];
33727
34543
  SUMI_PATH_OUTPUT_LIMIT = 128 * 1024;
@@ -33736,9 +34552,9 @@ var init_agent_sumi = __esm(() => {
33736
34552
  });
33737
34553
 
33738
34554
  // src/lib/codex-hook-trust-files.ts
33739
- import { closeSync as closeSync11, constants as constants9, fstatSync as fstatSync11, fsyncSync as fsyncSync2, lstatSync as lstatSync15, openSync as openSync11, readlinkSync as readlinkSync4, readSync as readSync6, writeFileSync as writeFileSync4 } from "fs";
33740
- import { createHash as createHash15 } from "crypto";
33741
- import { dirname as dirname13, isAbsolute as isAbsolute12, resolve as resolve13 } from "path";
34555
+ import { closeSync as closeSync12, constants as constants10, fstatSync as fstatSync12, fsyncSync as fsyncSync2, lstatSync as lstatSync16, openSync as openSync12, readlinkSync as readlinkSync4, readSync as readSync7, writeFileSync as writeFileSync4 } from "fs";
34556
+ import { createHash as createHash16 } from "crypto";
34557
+ import { dirname as dirname14, isAbsolute as isAbsolute13, resolve as resolve14 } from "path";
33742
34558
  function need6(value, code) {
33743
34559
  if (!value)
33744
34560
  throw new Error(`CODEX_HOOK_TRUST_${code}`);
@@ -33747,37 +34563,37 @@ function trustedAncestorOwner(uid) {
33747
34563
  return BigInt(uid) === 0n || BigInt(uid) === BigInt(process.getuid());
33748
34564
  }
33749
34565
  function safeParents(file2) {
33750
- for (let p = dirname13(file2);; p = dirname13(p)) {
33751
- const s = lstatSync15(p);
34566
+ for (let p = dirname14(file2);; p = dirname14(p)) {
34567
+ const s = lstatSync16(p);
33752
34568
  need6(s.isDirectory() && !s.isSymbolicLink() && trustedAncestorOwner(s.uid), "UNSAFE_PARENT");
33753
34569
  need6((s.mode & 18) === 0 || s.uid === 0 && (s.mode & 512) !== 0, "UNSAFE_PARENT");
33754
- if (dirname13(p) === p)
34570
+ if (dirname14(p) === p)
33755
34571
  break;
33756
34572
  }
33757
34573
  }
33758
34574
  function snapshot(file2, privateFile = false, options = {}) {
33759
34575
  const readOnlyPackage = options.readOnlyPackage === true && !privateFile;
33760
34576
  safeParents(file2);
33761
- const initial = lstatSync15(file2, { bigint: true });
34577
+ const initial = lstatSync16(file2, { bigint: true });
33762
34578
  need6(initial.isFile() && initial.uid === BigInt(process.getuid()) && (initial.nlink === 1n || readOnlyPackage && initial.nlink > 1n) && (initial.mode & 0o022n) === 0n && (!privateFile || (initial.mode & 0o777n) === 0o600n), "UNSAFE_FILE");
33763
34579
  need6(initial.size <= 8n * 1024n * 1024n, "FILE_BOUND");
33764
- const fd = openSync11(file2, constants9.O_RDONLY | constants9.O_NOFOLLOW | constants9.O_NONBLOCK);
34580
+ const fd = openSync12(file2, constants10.O_RDONLY | constants10.O_NOFOLLOW | constants10.O_NONBLOCK);
33765
34581
  try {
33766
- const before = fstatSync11(fd, { bigint: true });
34582
+ const before = fstatSync12(fd, { bigint: true });
33767
34583
  need6(sameStat(initial, before), "INPUT_CHANGED");
33768
34584
  const bytes = Buffer.alloc(Number(before.size) + 1);
33769
34585
  let length = 0;
33770
34586
  while (length < bytes.length) {
33771
- const n2 = readSync6(fd, bytes, length, bytes.length - length, null);
34587
+ const n2 = readSync7(fd, bytes, length, bytes.length - length, null);
33772
34588
  if (!n2)
33773
34589
  break;
33774
34590
  length += n2;
33775
34591
  }
33776
- need6(length === Number(before.size) && sameStat(before, fstatSync11(fd, { bigint: true })) && sameStat(before, lstatSync15(file2, { bigint: true })), "INPUT_CHANGED");
34592
+ need6(length === Number(before.size) && sameStat(before, fstatSync12(fd, { bigint: true })) && sameStat(before, lstatSync16(file2, { bigint: true })), "INPUT_CHANGED");
33777
34593
  const content = bytes.subarray(0, length), text2 = new TextDecoder("utf-8", { fatal: true }).decode(content);
33778
- return { file: file2, privateFile, readOnlyPackage, text: text2, bytes: content, stat: before, sha256: createHash15("sha256").update(content).digest("hex") };
34594
+ return { file: file2, privateFile, readOnlyPackage, text: text2, bytes: content, stat: before, sha256: createHash16("sha256").update(content).digest("hex") };
33779
34595
  } finally {
33780
- closeSync11(fd);
34596
+ closeSync12(fd);
33781
34597
  }
33782
34598
  }
33783
34599
  function unchanged2(before) {
@@ -33839,47 +34655,47 @@ var init_runtime_launcher = __esm(() => {
33839
34655
  });
33840
34656
 
33841
34657
  // src/lib/retained-review-artifacts.ts
33842
- import { createHash as createHash16 } from "crypto";
33843
- import { constants as constants10, closeSync as closeSync12, fstatSync as fstatSync12, fsyncSync as fsyncSync3, lstatSync as lstatSync16, mkdirSync as mkdirSync5, openSync as openSync12, readSync as readSync7, writeSync as writeSync2 } from "fs";
33844
- import { dirname as dirname14, isAbsolute as isAbsolute13, join as join21, resolve as resolve14, sep as sep7 } from "path";
34658
+ import { createHash as createHash17 } from "crypto";
34659
+ import { constants as constants11, closeSync as closeSync13, fstatSync as fstatSync13, fsyncSync as fsyncSync3, lstatSync as lstatSync17, mkdirSync as mkdirSync5, openSync as openSync13, readSync as readSync8, writeSync as writeSync2 } from "fs";
34660
+ import { dirname as dirname15, isAbsolute as isAbsolute14, join as join22, resolve as resolve15, sep as sep8 } from "path";
33845
34661
  function keys(value, names) {
33846
34662
  return Boolean(value && typeof value === "object" && !Array.isArray(value) && Object.keys(value).length === names.length && names.every((name) => Object.hasOwn(value, name)));
33847
34663
  }
33848
34664
  function safe3(path) {
33849
- need7(typeof path === "string" && path.length <= AGENT_POLICY_LIMITS.pathCharacters && isAbsolute13(path) && resolve14(path) === path && !/[\x00-\x1f\x7f]/.test(path));
33850
- for (let cursor = path;; cursor = dirname14(cursor)) {
33851
- const stat = lstatSync16(cursor, { throwIfNoEntry: false });
34665
+ need7(typeof path === "string" && path.length <= AGENT_POLICY_LIMITS.pathCharacters && isAbsolute14(path) && resolve15(path) === path && !/[\x00-\x1f\x7f]/.test(path));
34666
+ for (let cursor = path;; cursor = dirname15(cursor)) {
34667
+ const stat = lstatSync17(cursor, { throwIfNoEntry: false });
33852
34668
  need7(!stat?.isSymbolicLink());
33853
34669
  if (cursor !== path && stat)
33854
34670
  need7(stat.isDirectory());
33855
- if (dirname14(cursor) === cursor)
34671
+ if (dirname15(cursor) === cursor)
33856
34672
  break;
33857
34673
  }
33858
34674
  }
33859
34675
  function readExact(path) {
33860
34676
  safe3(path);
33861
- const before = lstatSync16(path, { throwIfNoEntry: false });
34677
+ const before = lstatSync17(path, { throwIfNoEntry: false });
33862
34678
  need7(before?.isFile() && before.nlink === 1 && before.size <= AGENT_POLICY_LIMITS.discoveryRawSourceBytes && (before.mode & 63) === 0 && (process.getuid === undefined || before.uid === process.getuid()));
33863
- const fd = openSync12(path, constants10.O_RDONLY | constants10.O_NOFOLLOW | constants10.O_NONBLOCK);
34679
+ const fd = openSync13(path, constants11.O_RDONLY | constants11.O_NOFOLLOW | constants11.O_NONBLOCK);
33864
34680
  try {
33865
- const opened = fstatSync12(fd);
34681
+ const opened = fstatSync13(fd);
33866
34682
  need7(opened.dev === before.dev && opened.ino === before.ino && opened.size === before.size && opened.mode === before.mode && opened.uid === before.uid && opened.nlink === 1);
33867
34683
  const bytes = Buffer.alloc(opened.size);
33868
34684
  let offset = 0;
33869
34685
  while (offset < bytes.length) {
33870
- const count = readSync7(fd, bytes, offset, bytes.length - offset, null);
34686
+ const count = readSync8(fd, bytes, offset, bytes.length - offset, null);
33871
34687
  need7(count > 0);
33872
34688
  offset += count;
33873
34689
  }
33874
- need7(readSync7(fd, Buffer.alloc(1), 0, 1, null) === 0);
33875
- const after = fstatSync12(fd), current = lstatSync16(path, { throwIfNoEntry: false });
34690
+ need7(readSync8(fd, Buffer.alloc(1), 0, 1, null) === 0);
34691
+ const after = fstatSync13(fd), current = lstatSync17(path, { throwIfNoEntry: false });
33876
34692
  safe3(path);
33877
34693
  need7(current && opened.dev === current.dev && opened.ino === current.ino && opened.mode === current.mode && opened.uid === current.uid && opened.size === current.size && opened.mtimeMs === current.mtimeMs && opened.ctimeMs === current.ctimeMs && current.nlink === 1 && opened.mode === after.mode && opened.uid === after.uid && after.nlink === 1 && opened.size === after.size && opened.mtimeMs === after.mtimeMs && opened.ctimeMs === after.ctimeMs);
33878
34694
  const text2 = new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(bytes);
33879
34695
  need7(Buffer.from(text2).equals(bytes));
33880
34696
  return text2;
33881
34697
  } finally {
33882
- closeSync12(fd);
34698
+ closeSync13(fd);
33883
34699
  }
33884
34700
  }
33885
34701
  function catalogDigest(text2) {
@@ -33887,7 +34703,7 @@ function catalogDigest(text2) {
33887
34703
  try {
33888
34704
  catalog = JSON.parse(text2);
33889
34705
  } catch {
33890
- return refuse3();
34706
+ return refuse4();
33891
34707
  }
33892
34708
  need7(catalog && typeof catalog === "object" && !Array.isArray(catalog) && Object.keys(catalog).every((key) => ["version", "cwd", "skills", "plugins"].includes(key)) && typeof catalog.version === "string" && supportsCodexNativeCapability(catalog.version, "installed-plugin-review"));
33893
34709
  const skills = projectCodexNativeSkillCatalog({ data: [{ cwd: catalog.cwd, errors: [], skills: catalog.skills }] }, catalog.cwd);
@@ -33895,32 +34711,32 @@ function catalogDigest(text2) {
33895
34711
  return sha3(JSON.stringify({ version: catalog.version, cwd: catalog.cwd, skills, ...plugins === undefined ? {} : { plugins } }));
33896
34712
  }
33897
34713
  function retainedArtifactPath(metadata) {
33898
- return join21(metadata.storeRoot, "agent-discovery", "artifacts", metadata.sha256, "catalog.json");
34714
+ return join22(metadata.storeRoot, "agent-discovery", "artifacts", metadata.sha256, "catalog.json");
33899
34715
  }
33900
34716
  function validRetainedArtifact(value) {
33901
- return keys(value, ["version", "kind", "storeRoot", "originalPath", "sha256", "catalogSha256"]) && value.version === 1 && value.kind === "codex-native-catalog" && hex3(value.sha256) && hex3(value.catalogSha256) && [value.storeRoot, value.originalPath].every((path) => typeof path === "string" && isAbsolute13(path) && resolve14(path) === path && path.length <= AGENT_POLICY_LIMITS.pathCharacters && !/[\x00-\x1f\x7f]/.test(path));
34717
+ return keys(value, ["version", "kind", "storeRoot", "originalPath", "sha256", "catalogSha256"]) && value.version === 1 && value.kind === "codex-native-catalog" && hex3(value.sha256) && hex3(value.catalogSha256) && [value.storeRoot, value.originalPath].every((path) => typeof path === "string" && isAbsolute14(path) && resolve15(path) === path && path.length <= AGENT_POLICY_LIMITS.pathCharacters && !/[\x00-\x1f\x7f]/.test(path));
33902
34718
  }
33903
34719
  function privateStore(storeRoot) {
33904
34720
  safe3(storeRoot);
33905
- const stat = lstatSync16(storeRoot, { throwIfNoEntry: false });
34721
+ const stat = lstatSync17(storeRoot, { throwIfNoEntry: false });
33906
34722
  need7(!stat || stat.isDirectory() && (stat.mode & 18) === 0 && (process.getuid === undefined || stat.uid === process.getuid()));
33907
34723
  }
33908
34724
  function verifyRetainedReviewArtifact(source, storeRoot) {
33909
34725
  const artifact = source.reviewArtifact;
33910
- need7(validRetainedArtifact(artifact) && source.hashMode === "bytes" && source.sha256 === artifact.sha256 && source.format === undefined && source.fields === undefined && source.managedPlugins === undefined && source.path === retainedArtifactPath(artifact) && (storeRoot === undefined || artifact.storeRoot === resolve14(storeRoot)));
34726
+ need7(validRetainedArtifact(artifact) && source.hashMode === "bytes" && source.sha256 === artifact.sha256 && source.format === undefined && source.fields === undefined && source.managedPlugins === undefined && source.path === retainedArtifactPath(artifact) && (storeRoot === undefined || artifact.storeRoot === resolve15(storeRoot)));
33911
34727
  privateStore(artifact.storeRoot);
33912
34728
  const text2 = readExact(source.path);
33913
34729
  need7(sha3(text2) === artifact.sha256 && catalogDigest(text2) === artifact.catalogSha256);
33914
- for (let parent = dirname14(source.path);parent !== artifact.storeRoot; parent = dirname14(parent)) {
33915
- const stat = lstatSync16(parent);
34730
+ for (let parent = dirname15(source.path);parent !== artifact.storeRoot; parent = dirname15(parent)) {
34731
+ const stat = lstatSync17(parent);
33916
34732
  need7(stat.isDirectory() && (stat.mode & 63) === 0 && (process.getuid === undefined || stat.uid === process.getuid()));
33917
34733
  }
33918
34734
  }
33919
- var sha3 = (bytes) => createHash16("sha256").update(bytes).digest("hex"), hex3 = (value) => typeof value === "string" && /^[a-f0-9]{64}$/.test(value), refuse3 = () => {
34735
+ var sha3 = (bytes) => createHash17("sha256").update(bytes).digest("hex"), hex3 = (value) => typeof value === "string" && /^[a-f0-9]{64}$/.test(value), refuse4 = () => {
33920
34736
  throw new Error("REVIEW_ARTIFACT_INVALID");
33921
34737
  }, need7 = (condition) => {
33922
34738
  if (!condition)
33923
- refuse3();
34739
+ refuse4();
33924
34740
  };
33925
34741
  var init_retained_review_artifacts = __esm(() => {
33926
34742
  init_agent_policy_limits();
@@ -33937,6 +34753,8 @@ var init_agent_integration = __esm(() => {
33937
34753
  init_codex_native_skill_catalog();
33938
34754
  init_codex_settings_witness();
33939
34755
  init_claude_settings_witness();
34756
+ init_codex_native_compatibility();
34757
+ init_codex_semantic_cache_witness();
33940
34758
  init_native_discovery_roots();
33941
34759
  init_config();
33942
34760
  init_managed_policy();
@@ -33987,12 +34805,12 @@ var init_skill_aliases = __esm(() => {
33987
34805
 
33988
34806
  // src/lib/project-state.ts
33989
34807
  import { existsSync as existsSync9, mkdirSync as mkdirSync6, readFileSync as readFileSync13, writeFileSync as writeFileSync5 } from "fs";
33990
- import { join as join22 } from "path";
34808
+ import { join as join23 } from "path";
33991
34809
  function getProjectStateDir(targetDir = process.cwd()) {
33992
- return join22(targetDir, SKILLS_PROJECT_DIR);
34810
+ return join23(targetDir, SKILLS_PROJECT_DIR);
33993
34811
  }
33994
34812
  function getProjectConfigPath(targetDir = process.cwd()) {
33995
- return join22(getProjectStateDir(targetDir), PROJECT_CONFIG_FILE);
34813
+ return join23(getProjectStateDir(targetDir), PROJECT_CONFIG_FILE);
33996
34814
  }
33997
34815
  function loadProjectConfig(targetDir = process.cwd()) {
33998
34816
  const path = getProjectConfigPath(targetDir);
@@ -34108,7 +34926,7 @@ var init_project_state = __esm(() => {
34108
34926
 
34109
34927
  // src/lib/installer.ts
34110
34928
  import { existsSync as existsSync10, readFileSync as readFileSync14, rmSync } from "fs";
34111
- import { join as join23 } from "path";
34929
+ import { join as join24 } from "path";
34112
34930
  import { homedir as homedir2 } from "os";
34113
34931
  function getSkillPath(name) {
34114
34932
  const skillName = normalizeSkillName(getCanonicalSkillName(name));
@@ -34118,7 +34936,7 @@ function getSkillPath(name) {
34118
34936
  const extensionPath = findExtensionSkillPath(skillName);
34119
34937
  if (extensionPath)
34120
34938
  return extensionPath;
34121
- return join23(getPortableSkillsRoot(), skillName);
34939
+ return join24(getPortableSkillsRoot(), skillName);
34122
34940
  }
34123
34941
  function getCanonicalSkillName(name) {
34124
34942
  return getSkill(name)?.name ?? resolveSkillAlias(normalizeSkillSlug(name));
@@ -34172,11 +34990,11 @@ function getAgentSkillsDir(agent, scope = "global", projectDir) {
34172
34990
  const base = projectDir || process.cwd();
34173
34991
  switch (agent) {
34174
34992
  case "pi":
34175
- return scope === "project" ? join23(base, ".pi", "skills") : join23(homedir2(), ".pi", "agent", "skills");
34993
+ return scope === "project" ? join24(base, ".pi", "skills") : join24(homedir2(), ".pi", "agent", "skills");
34176
34994
  case "opencode":
34177
- return scope === "project" ? join23(base, ".opencode", "skills") : join23(homedir2(), ".config", "opencode", "skills");
34995
+ return scope === "project" ? join24(base, ".opencode", "skills") : join24(homedir2(), ".config", "opencode", "skills");
34178
34996
  default:
34179
- return scope === "project" ? join23(base, `.${agent}`, "skills") : join23(homedir2(), `.${agent}`, "skills");
34997
+ return scope === "project" ? join24(base, `.${agent}`, "skills") : join24(homedir2(), `.${agent}`, "skills");
34180
34998
  }
34181
34999
  }
34182
35000
  function warnMissingDependencies(name, targetDir) {
@@ -34191,7 +35009,7 @@ function warnMissingDependencies(name, targetDir) {
34191
35009
  }
34192
35010
  }
34193
35011
  function readBundledSkillVersion(name) {
34194
- const pkgPath = join23(getSkillPath(name), "package.json");
35012
+ const pkgPath = join24(getSkillPath(name), "package.json");
34195
35013
  if (!existsSync10(pkgPath))
34196
35014
  return "unknown";
34197
35015
  try {
@@ -34261,11 +35079,11 @@ var init_skill_doc_file = __esm(() => {
34261
35079
 
34262
35080
  // src/lib/skillinfo.ts
34263
35081
  import { existsSync as existsSync11, readFileSync as readFileSync15 } from "fs";
34264
- import { join as join24 } from "path";
35082
+ import { join as join25 } from "path";
34265
35083
  function isInstructionSkillDir(skillPath, meta3) {
34266
35084
  if (meta3?.kind === "instruction")
34267
35085
  return true;
34268
- const skillMdPath = join24(skillPath, "SKILL.md");
35086
+ const skillMdPath = join25(skillPath, "SKILL.md");
34269
35087
  if (!existsSync11(skillMdPath))
34270
35088
  return false;
34271
35089
  try {
@@ -34279,9 +35097,9 @@ function getSkillDocs(name) {
34279
35097
  if (!existsSync11(skillPath))
34280
35098
  return null;
34281
35099
  return {
34282
- skillMd: readIfExists(join24(skillPath, "SKILL.md")),
34283
- readme: readIfExists(join24(skillPath, "README.md")),
34284
- claudeMd: readIfExists(join24(skillPath, "CLAUDE.md"))
35100
+ skillMd: readIfExists(join25(skillPath, "SKILL.md")),
35101
+ readme: readIfExists(join25(skillPath, "README.md")),
35102
+ claudeMd: readIfExists(join25(skillPath, "CLAUDE.md"))
34285
35103
  };
34286
35104
  }
34287
35105
  function getSkillBestDoc(name, file2) {
@@ -34297,14 +35115,14 @@ function getSkillRequirements(name) {
34297
35115
  return null;
34298
35116
  const texts = [];
34299
35117
  for (const file2 of ["SKILL.md", "README.md", "CLAUDE.md", ".env.example", ".env.local.example"]) {
34300
- const content = readIfExists(join24(skillPath, file2));
35118
+ const content = readIfExists(join25(skillPath, file2));
34301
35119
  if (content)
34302
35120
  texts.push(content);
34303
35121
  }
34304
35122
  const meta3 = getSkill(name);
34305
35123
  let dependencies = {};
34306
35124
  try {
34307
- dependencies = JSON.parse(readFileSync15(join24(skillPath, "package.json"), "utf8")).dependencies || {};
35125
+ dependencies = JSON.parse(readFileSync15(join25(skillPath, "package.json"), "utf8")).dependencies || {};
34308
35126
  } catch {}
34309
35127
  return getSkillRequirementsFromContent(name, texts, dependencies, meta3);
34310
35128
  }
@@ -34366,7 +35184,7 @@ async function runSkill(name, args, options = {}) {
34366
35184
  error: `Skill '${name}' is an instruction skill (kind: instruction) and is not runnable. Instruction skills are consumed by coding agents via SKILL.md, not executed with 'skills run'.`
34367
35185
  };
34368
35186
  }
34369
- const pkgPath = join24(skillPath, "package.json");
35187
+ const pkgPath = join25(skillPath, "package.json");
34370
35188
  if (!existsSync11(pkgPath)) {
34371
35189
  return { exitCode: 1, error: `No package.json in skill '${name}'` };
34372
35190
  }
@@ -34386,12 +35204,12 @@ async function runSkill(name, args, options = {}) {
34386
35204
  } catch {
34387
35205
  return { exitCode: 1, error: `Failed to parse package.json for skill '${name}'` };
34388
35206
  }
34389
- const entryPath = join24(skillPath, entryPoint2);
35207
+ const entryPath = join25(skillPath, entryPoint2);
34390
35208
  if (!existsSync11(entryPath)) {
34391
35209
  return { exitCode: 1, error: `Entry point '${entryPoint2}' not found in skill '${name}'` };
34392
35210
  }
34393
35211
  const env = { ...process.env, ...options.env };
34394
- if (!existsSync11(join24(skillPath, "node_modules")) || hasDependencyPreparationMarker(skillPath)) {
35212
+ if (!existsSync11(join25(skillPath, "node_modules")) || hasDependencyPreparationMarker(skillPath)) {
34395
35213
  const failure = await prepareSkillDependencies(skillPath, env, options.preparationTimeoutMs);
34396
35214
  if (failure)
34397
35215
  return failure;
@@ -34417,7 +35235,7 @@ async function runSkill(name, args, options = {}) {
34417
35235
  function detectProjectSkills(cwd = process.cwd()) {
34418
35236
  let pkg;
34419
35237
  try {
34420
- pkg = JSON.parse(readFileSync15(join24(cwd, "package.json"), "utf8"));
35238
+ pkg = JSON.parse(readFileSync15(join25(cwd, "package.json"), "utf8"));
34421
35239
  } catch {
34422
35240
  return { detected: [], recommended: [] };
34423
35241
  }
@@ -34622,7 +35440,7 @@ var init_selection_resolver = __esm(() => {
34622
35440
  });
34623
35441
 
34624
35442
  // src/lib/plugin-projection.ts
34625
- import { createHash as createHash17 } from "crypto";
35443
+ import { createHash as createHash18 } from "crypto";
34626
35444
  function pluginRefusal(message) {
34627
35445
  throw new SkillSelectionError("PLUGIN_ADMISSION_REFUSED", message);
34628
35446
  }
@@ -34700,26 +35518,26 @@ function pluginFileWitnesses(entries) {
34700
35518
  return { path: item.path, mode: item.mode, size: item.bytes.byteLength, sha256: pluginHash(item.bytes) };
34701
35519
  });
34702
35520
  }
34703
- var PLUGIN_PROJECTION_LIMITS, pluginHash = (bytes) => createHash17("sha256").update(bytes).digest("hex");
35521
+ var PLUGIN_PROJECTION_LIMITS, pluginHash = (bytes) => createHash18("sha256").update(bytes).digest("hex");
34704
35522
  var init_plugin_projection = __esm(() => {
34705
35523
  init_selection_cache();
34706
35524
  PLUGIN_PROJECTION_LIMITS = Object.freeze({ files: 1024, bytes: 64 * 1024 * 1024, fileBytes: 16 * 1024 * 1024, metadataBytes: 512 * 1024, registrations: 64, history: 128 });
34707
35525
  });
34708
35526
 
34709
35527
  // src/lib/plugin-projection-store.ts
34710
- import { constants as constants11, closeSync as closeSync13, fchmodSync, fstatSync as fstatSync13, fsyncSync as fsyncSync4, linkSync as linkSync2, lstatSync as lstatSync17, mkdirSync as mkdirSync7, openSync as openSync13, opendirSync as opendirSync2, readSync as readSync8, renameSync as renameSync2, rmdirSync as rmdirSync2, rmSync as rmSync2, unlinkSync as unlinkSync3, writeSync as writeSync3 } from "fs";
34711
- import { dirname as dirname15, isAbsolute as isAbsolute14, join as join25, parse as parse10, resolve as resolve15 } from "path";
35528
+ import { constants as constants12, closeSync as closeSync14, fchmodSync, fstatSync as fstatSync14, fsyncSync as fsyncSync4, linkSync as linkSync2, lstatSync as lstatSync18, mkdirSync as mkdirSync7, openSync as openSync14, opendirSync as opendirSync2, readSync as readSync9, renameSync as renameSync2, rmdirSync as rmdirSync2, rmSync as rmSync2, unlinkSync as unlinkSync3, writeSync as writeSync3 } from "fs";
35529
+ import { dirname as dirname16, isAbsolute as isAbsolute15, join as join26, parse as parse10, resolve as resolve16 } from "path";
34712
35530
  function stat(path) {
34713
35531
  try {
34714
- return lstatSync17(path, { bigint: true });
35532
+ return lstatSync18(path, { bigint: true });
34715
35533
  } catch (error61) {
34716
35534
  if (missing(error61))
34717
35535
  return null;
34718
35536
  return pluginRefusal("Cannot inspect plugin filesystem entry");
34719
35537
  }
34720
35538
  }
34721
- function canonical7(path) {
34722
- pluginNeed(typeof path === "string" && path.length <= 8192 && isAbsolute14(path) && resolve15(path) === path && !/[\x00-\x1f\x7f]/.test(path), "Plugin storage paths must be canonical absolute paths");
35539
+ function canonical8(path) {
35540
+ pluginNeed(typeof path === "string" && path.length <= 8192 && isAbsolute15(path) && resolve16(path) === path && !/[\x00-\x1f\x7f]/.test(path), "Plugin storage paths must be canonical absolute paths");
34723
35541
  }
34724
35542
  function owner(stats, system = false) {
34725
35543
  const current = uid();
@@ -34729,12 +35547,12 @@ function same3(left, right, identityOnly = false) {
34729
35547
  pluginNeed(right && left.dev === right.dev && left.ino === right.ino && left.mode === right.mode && left.uid === right.uid && left.gid === right.gid && (identityOnly || left.size === right.size && left.nlink === right.nlink && left.mtimeNs === right.mtimeNs && left.ctimeNs === right.ctimeNs), "Plugin filesystem entry changed during access");
34730
35548
  }
34731
35549
  function ancestors(path, create = false) {
34732
- canonical7(path);
34733
- const result = [], parent = dirname15(path), filesystemRoot = parse10(parent).root;
35550
+ canonical8(path);
35551
+ const result = [], parent = dirname16(path), filesystemRoot = parse10(parent).root;
34734
35552
  let current = filesystemRoot;
34735
35553
  for (const segment of ["", ...parent.slice(filesystemRoot.length).split("/").filter(Boolean)]) {
34736
35554
  if (segment)
34737
- current = join25(current, segment);
35555
+ current = join26(current, segment);
34738
35556
  let currentStat = stat(current);
34739
35557
  if (!currentStat && create) {
34740
35558
  try {
@@ -34780,19 +35598,19 @@ function readBytes(path, maximum, kind) {
34780
35598
  fileShape(before, maximum, kind);
34781
35599
  let fd;
34782
35600
  try {
34783
- fd = openSync13(path, READ_FLAGS);
34784
- const opened = fstatSync13(fd, { bigint: true });
35601
+ fd = openSync14(path, READ_FLAGS);
35602
+ const opened = fstatSync14(fd, { bigint: true });
34785
35603
  same3(before, opened);
34786
35604
  fileShape(opened, maximum, kind);
34787
35605
  const bytes = new Uint8Array(Number(opened.size));
34788
35606
  let offset = 0;
34789
35607
  while (offset < bytes.byteLength) {
34790
- const count = readSync8(fd, bytes, offset, bytes.byteLength - offset, null);
35608
+ const count = readSync9(fd, bytes, offset, bytes.byteLength - offset, null);
34791
35609
  pluginNeed(count > 0, "Plugin file changed while being read");
34792
35610
  offset += count;
34793
35611
  }
34794
- pluginNeed(readSync8(fd, new Uint8Array(1), 0, 1, null) === 0, "Plugin file grew while being read");
34795
- same3(opened, fstatSync13(fd, { bigint: true }));
35612
+ pluginNeed(readSync9(fd, new Uint8Array(1), 0, 1, null) === 0, "Plugin file grew while being read");
35613
+ same3(opened, fstatSync14(fd, { bigint: true }));
34796
35614
  same3(opened, stat(path));
34797
35615
  verifyAncestors(chain);
34798
35616
  return bytes;
@@ -34802,7 +35620,7 @@ function readBytes(path, maximum, kind) {
34802
35620
  return pluginRefusal("Cannot safely read plugin file");
34803
35621
  } finally {
34804
35622
  if (fd !== undefined)
34805
- closeSync13(fd);
35623
+ closeSync14(fd);
34806
35624
  }
34807
35625
  }
34808
35626
  function exactPaths(entries) {
@@ -34832,7 +35650,7 @@ function directoryNames(path) {
34832
35650
  function snapshotPluginTree(root, options = {}) {
34833
35651
  const chain = ancestors(root), entries = [], files = [], directories = [];
34834
35652
  let bytes = 0, visited = 0;
34835
- const visit3 = (directory, relative6) => {
35653
+ const visit3 = (directory, relative7) => {
34836
35654
  const before = stat(directory);
34837
35655
  pluginNeed(before && before.isDirectory() && !before.isSymbolicLink(), "Plugin tree must contain real directories");
34838
35656
  const names = directoryNames(directory);
@@ -34840,18 +35658,18 @@ function snapshotPluginTree(root, options = {}) {
34840
35658
  directories.push({ path: directory, stat: before, names });
34841
35659
  for (const name of names) {
34842
35660
  pluginNeed(++visited <= PLUGIN_PROJECTION_LIMITS.files * 50, "Plugin tree membership exceeds its limit");
34843
- const path = relative6 ? `${relative6}/${name}` : name;
35661
+ const path = relative7 ? `${relative7}/${name}` : name;
34844
35662
  pluginNeed(new TextEncoder().encode(path).byteLength <= 100 && !/[\\:\x00-\x1f\x7f]/u.test(path), "Plugin entry path exceeds its limit or is unsafe");
34845
- const absolute = join25(directory, name), entryStat = stat(absolute);
35663
+ const absolute = join26(directory, name), entryStat = stat(absolute);
34846
35664
  pluginNeed(entryStat, "Plugin tree member disappeared");
34847
- if (relative6 === "" && name === ".orphaned_at" && (options.nativeRuntime === "claude-2.1.274" || options.nativeRuntime === "claude-2.1.276")) {
35665
+ if (relative7 === "" && name === ".orphaned_at" && (options.nativeRuntime === "claude-2.1.274" || options.nativeRuntime === "claude-2.1.276")) {
34848
35666
  const bytes2 = readBytes(absolute, 32, "native-pin");
34849
35667
  pluginNeed(/^[1-9][0-9]{12}$/.test(new TextDecoder().decode(bytes2)), "Malformed native orphan timestamp");
34850
35668
  same3(entryStat, stat(absolute));
34851
35669
  files.push({ path: absolute, stat: entryStat });
34852
35670
  continue;
34853
35671
  }
34854
- if (relative6 === "" && name === ".in_use" && (options.nativeRuntime === "claude-2.1.274" || options.nativeRuntime === "claude-2.1.276")) {
35672
+ if (relative7 === "" && name === ".in_use" && (options.nativeRuntime === "claude-2.1.274" || options.nativeRuntime === "claude-2.1.276")) {
34855
35673
  pluginNeed(entryStat.isDirectory() && !entryStat.isSymbolicLink(), "Native plugin pins require a real directory");
34856
35674
  owner(entryStat);
34857
35675
  const pins = directoryNames(absolute);
@@ -34859,7 +35677,7 @@ function snapshotPluginTree(root, options = {}) {
34859
35677
  directories.push({ path: absolute, stat: entryStat, names: pins });
34860
35678
  for (const pin of pins) {
34861
35679
  pluginNeed(/^[1-9][0-9]{0,9}$/.test(pin) && Number(pin) <= 2147483647, "Unrecognized native plugin pin name");
34862
- const pinPath = join25(absolute, pin), pinStat = stat(pinPath);
35680
+ const pinPath = join26(absolute, pin), pinStat = stat(pinPath);
34863
35681
  pluginNeed(pinStat, "Native plugin pin disappeared");
34864
35682
  const bytes2 = readBytes(pinPath, 4096, "native-pin");
34865
35683
  let value;
@@ -34925,8 +35743,8 @@ function readPluginJson(path) {
34925
35743
  var READ_FLAGS, WRITE_FLAGS, uid = () => typeof process.getuid === "function" ? BigInt(process.getuid()) : undefined, missing = (error61) => Boolean(error61 && typeof error61 === "object" && "code" in error61 && error61.code === "ENOENT");
34926
35744
  var init_plugin_projection_store = __esm(() => {
34927
35745
  init_plugin_projection();
34928
- READ_FLAGS = constants11.O_RDONLY | constants11.O_NOFOLLOW | constants11.O_NONBLOCK;
34929
- WRITE_FLAGS = constants11.O_WRONLY | constants11.O_CREAT | constants11.O_EXCL | constants11.O_NOFOLLOW | constants11.O_NONBLOCK;
35746
+ READ_FLAGS = constants12.O_RDONLY | constants12.O_NOFOLLOW | constants12.O_NONBLOCK;
35747
+ WRITE_FLAGS = constants12.O_WRONLY | constants12.O_CREAT | constants12.O_EXCL | constants12.O_NOFOLLOW | constants12.O_NONBLOCK;
34930
35748
  });
34931
35749
 
34932
35750
  // src/lib/selected-manifest.ts
@@ -34956,7 +35774,7 @@ var init_selected_manifest = __esm(() => {
34956
35774
  });
34957
35775
 
34958
35776
  // src/lib/plugin-admission.ts
34959
- import { isAbsolute as isAbsolute15, join as join26, resolve as resolve16 } from "path";
35777
+ import { isAbsolute as isAbsolute16, join as join27, resolve as resolve17 } from "path";
34960
35778
  function validatePluginTarget(value) {
34961
35779
  pluginKeys(value, ["schemaVersion", "pluginId", "registrations", "native", "resolver"]);
34962
35780
  pluginNeed(value.schemaVersion === 1, "Invalid plugin admission target");
@@ -34966,7 +35784,7 @@ function validatePluginTarget(value) {
34966
35784
  for (const registration of value.registrations) {
34967
35785
  pluginKeys(registration, ["scope", "projectPath"]);
34968
35786
  pluginNeed(registration.scope === "user" || registration.scope === "project", "Unsupported plugin registration scope");
34969
- pluginNeed(registration.scope === "user" ? registration.projectPath === null : typeof registration.projectPath === "string" && isAbsolute15(registration.projectPath) && resolve16(registration.projectPath) === registration.projectPath, "Plugin scope requires its exact project path");
35787
+ pluginNeed(registration.scope === "user" ? registration.projectPath === null : typeof registration.projectPath === "string" && isAbsolute16(registration.projectPath) && resolve17(registration.projectPath) === registration.projectPath, "Plugin scope requires its exact project path");
34970
35788
  const key = JSON.stringify([registration.scope, registration.projectPath]);
34971
35789
  pluginNeed(!scopes.has(key), "Duplicate plugin registration scope");
34972
35790
  scopes.add(key);
@@ -34974,7 +35792,7 @@ function validatePluginTarget(value) {
34974
35792
  for (const key of ["native", "resolver"]) {
34975
35793
  pluginKeys(value[key], key === "native" ? ["version", "executable", "digest"] : ["executable", "digest"]);
34976
35794
  pluginText(value[key].executable);
34977
- pluginNeed(isAbsolute15(value[key].executable) && resolve16(value[key].executable) === value[key].executable, "Plugin executable must have a canonical absolute path");
35795
+ pluginNeed(isAbsolute16(value[key].executable) && resolve17(value[key].executable) === value[key].executable, "Plugin executable must have a canonical absolute path");
34978
35796
  pluginDigest(value[key].digest);
34979
35797
  }
34980
35798
  pluginNeed(["2.1.274", "2.1.276"].includes(value.native.version), "Plugin admission requires a certified Claude command-source runtime (2.1.274 or 2.1.276)");
@@ -35117,12 +35935,12 @@ function pluginResolverCommand(binding) {
35117
35935
  }
35118
35936
  function pluginBindingPath(storeRoot, id) {
35119
35937
  pluginNeed(/^[a-f0-9]{64}$/.test(id), "Invalid plugin binding identifier");
35120
- return join26(storeRoot, "bindings", `${id}.json`);
35938
+ return join27(storeRoot, "bindings", `${id}.json`);
35121
35939
  }
35122
- function pluginReceiptPath(storeRoot, id, digest) {
35940
+ function pluginReceiptPath(storeRoot, id, digest2) {
35123
35941
  pluginNeed(/^[a-f0-9]{64}$/.test(id), "Invalid plugin binding identifier");
35124
- pluginDigest(digest);
35125
- return join26(storeRoot, "receipts", id, `${digest.slice(7)}.json`);
35942
+ pluginDigest(digest2);
35943
+ return join27(storeRoot, "receipts", id, `${digest2.slice(7)}.json`);
35126
35944
  }
35127
35945
  function readPluginBinding(storeRoot, id) {
35128
35946
  const value = readPluginJson(pluginBindingPath(storeRoot, id));
@@ -35131,18 +35949,18 @@ function readPluginBinding(storeRoot, id) {
35131
35949
  pluginNeed(bindingId(binding) === id, "Plugin admission binding changed");
35132
35950
  return binding;
35133
35951
  }
35134
- function readPluginAdmissionReceipt(storeRoot, id, digest) {
35135
- const value = readPluginJson(pluginReceiptPath(storeRoot, id, digest));
35952
+ function readPluginAdmissionReceipt(storeRoot, id, digest2) {
35953
+ const value = readPluginJson(pluginReceiptPath(storeRoot, id, digest2));
35136
35954
  pluginKeys(value, ["schemaVersion", "plan", "materializedPath", "admittedAt"]);
35137
35955
  pluginNeed(value.schemaVersion === 3, "Unsupported plugin admission receipt; schema version 3 is required");
35138
35956
  validatePlan(value.plan);
35139
35957
  const receipt = value;
35140
35958
  receipt.plan.files = normalizedWitnesses(receipt.plan.files);
35141
35959
  receipt.plan.removed = normalizedWitnesses(receipt.plan.removed);
35142
- pluginNeed(receipt.plan.bindingId === id && receipt.plan.planDigest === digest, "Plugin receipt identity differs from its filename");
35960
+ pluginNeed(receipt.plan.bindingId === id && receipt.plan.planDigest === digest2, "Plugin receipt identity differs from its filename");
35143
35961
  const binding = readPluginBinding(storeRoot, id);
35144
35962
  pluginNeed(canonicalJson(binding) === canonicalJson(receipt.plan.binding) && receipt.plan.sourceCommand === pluginResolverCommand(binding), "Plugin receipt binding changed");
35145
- pluginNeed(receipt.materializedPath === join26(storeRoot, "objects", id, digest.slice(7)), "Plugin receipt points outside its immutable materialization");
35963
+ pluginNeed(receipt.materializedPath === join27(storeRoot, "objects", id, digest2.slice(7)), "Plugin receipt points outside its immutable materialization");
35146
35964
  pluginText(receipt.admittedAt, 64);
35147
35965
  pluginNeed(Number.isFinite(Date.parse(receipt.admittedAt)), "Invalid plugin admission time");
35148
35966
  return receipt;
@@ -35159,8 +35977,8 @@ var init_plugin_admission = __esm(() => {
35159
35977
  });
35160
35978
 
35161
35979
  // src/lib/plugin-discovery.ts
35162
- import { closeSync as closeSync14, constants as constants12, fstatSync as fstatSync14, lstatSync as lstatSync18, openSync as openSync14, opendirSync as opendirSync3, readSync as readSync9 } from "fs";
35163
- import { basename as basename7, dirname as dirname16, isAbsolute as isAbsolute16, join as join27, resolve as resolve17 } from "path";
35980
+ import { closeSync as closeSync15, constants as constants13, fstatSync as fstatSync15, lstatSync as lstatSync19, openSync as openSync15, opendirSync as opendirSync3, readSync as readSync10 } from "fs";
35981
+ import { basename as basename7, dirname as dirname17, isAbsolute as isAbsolute17, join as join28, resolve as resolve18 } from "path";
35164
35982
  function validateManagedPluginWitnesses(value) {
35165
35983
  pluginNeed(Array.isArray(value) && value.length > 0 && value.length <= PLUGIN_PROJECTION_LIMITS.registrations, "Invalid managed plugin witness collection");
35166
35984
  const seen = new Set;
@@ -35169,35 +35987,35 @@ function validateManagedPluginWitnesses(value) {
35169
35987
  pluginNeed(typeof item.bindingId === "string" && /^[a-f0-9]{64}$/.test(item.bindingId) && !seen.has(item.bindingId), "Invalid or duplicate managed plugin witness");
35170
35988
  seen.add(item.bindingId);
35171
35989
  pluginText(item.storeRoot);
35172
- pluginNeed(isAbsolute16(item.storeRoot) && resolve17(item.storeRoot) === item.storeRoot, "Invalid plugin receipt store path");
35990
+ pluginNeed(isAbsolute17(item.storeRoot) && resolve18(item.storeRoot) === item.storeRoot, "Invalid plugin receipt store path");
35173
35991
  }
35174
35992
  }
35175
35993
  function safe4(path) {
35176
35994
  pluginText(path);
35177
- pluginNeed(isAbsolute16(path) && resolve17(path) === path, "Invalid plugin registry path");
35178
- for (let at = path;; at = dirname16(at)) {
35179
- pluginNeed(!lstatSync18(at, { throwIfNoEntry: false })?.isSymbolicLink(), "Plugin registry path traverses a symlink");
35180
- if (at === dirname16(at))
35995
+ pluginNeed(isAbsolute17(path) && resolve18(path) === path, "Invalid plugin registry path");
35996
+ for (let at = path;; at = dirname17(at)) {
35997
+ pluginNeed(!lstatSync19(at, { throwIfNoEntry: false })?.isSymbolicLink(), "Plugin registry path traverses a symlink");
35998
+ if (at === dirname17(at))
35181
35999
  break;
35182
36000
  }
35183
36001
  }
35184
36002
  function readRegistry(path) {
35185
36003
  safe4(path);
35186
- const initial = lstatSync18(path);
36004
+ const initial = lstatSync19(path);
35187
36005
  pluginNeed(initial.isFile() && initial.size <= 1024 * 1024, "Plugin registry is not a bounded regular file");
35188
- const fd = openSync14(path, constants12.O_RDONLY | constants12.O_NOFOLLOW | constants12.O_NONBLOCK);
36006
+ const fd = openSync15(path, constants13.O_RDONLY | constants13.O_NOFOLLOW | constants13.O_NONBLOCK);
35189
36007
  try {
35190
- const opened = fstatSync14(fd);
36008
+ const opened = fstatSync15(fd);
35191
36009
  pluginNeed(opened.isFile() && opened.ino === initial.ino && opened.dev === initial.dev, "Plugin registry changed during open");
35192
36010
  const bytes = Buffer.alloc(1024 * 1024 + 1);
35193
36011
  let length = 0;
35194
36012
  while (length < bytes.length) {
35195
- const count = readSync9(fd, bytes, length, bytes.length - length, null);
36013
+ const count = readSync10(fd, bytes, length, bytes.length - length, null);
35196
36014
  if (!count)
35197
36015
  break;
35198
36016
  length += count;
35199
36017
  }
35200
- const after = fstatSync14(fd), current = lstatSync18(path);
36018
+ const after = fstatSync15(fd), current = lstatSync19(path);
35201
36019
  safe4(path);
35202
36020
  pluginNeed(length <= 1024 * 1024 && length === opened.size && after.size === opened.size && after.mtimeMs === opened.mtimeMs && after.ctimeMs === opened.ctimeMs && current.dev === opened.dev && current.ino === opened.ino && current.mtimeMs === opened.mtimeMs && current.ctimeMs === opened.ctimeMs, "Plugin registry changed during read");
35203
36021
  let value;
@@ -35209,7 +36027,7 @@ function readRegistry(path) {
35209
36027
  pluginNeed(pluginObject(value) && value.version === 2 && pluginObject(value.plugins), "Unsupported native plugin registry schema");
35210
36028
  return { value, rawDigest: pluginHash(bytes.subarray(0, length)) };
35211
36029
  } finally {
35212
- closeSync14(fd);
36030
+ closeSync15(fd);
35213
36031
  }
35214
36032
  }
35215
36033
  function nativeVersionMatches(version2, receipt) {
@@ -35227,7 +36045,7 @@ function hashManagedPluginRegistry(path, managed) {
35227
36045
  seen.add(target.pluginId);
35228
36046
  const rows = plugins[target.pluginId];
35229
36047
  pluginNeed(Array.isArray(rows) && rows.length === target.registrations.length, "Managed plugin registration membership changed");
35230
- const [name, market] = target.pluginId.split("@"), cacheRoot = join27(dirname16(path), "cache", market, name);
36048
+ const [name, market] = target.pluginId.split("@"), cacheRoot = join28(dirname17(path), "cache", market, name);
35231
36049
  const scopes = new Set, approvals = new Map, currentFiles = new Map;
35232
36050
  plugins[target.pluginId] = rows.map((row) => {
35233
36051
  pluginNeed(pluginObject(row), "Invalid managed plugin registration");
@@ -35240,11 +36058,11 @@ function hashManagedPluginRegistry(path, managed) {
35240
36058
  pluginText(row.sourceProducerPath);
35241
36059
  pluginText(row.lastUpdated, 64);
35242
36060
  pluginNeed(Number.isFinite(Date.parse(row.lastUpdated)), "Invalid managed plugin update timestamp");
35243
- pluginNeed(/^(?:[A-Za-z0-9][A-Za-z0-9._+-]*-)?[a-f0-9]{12}$/.test(row.version) && row.installPath === join27(cacheRoot, row.version), "Managed plugin cache path or version is outside its registration");
36061
+ pluginNeed(/^(?:[A-Za-z0-9][A-Za-z0-9._+-]*-)?[a-f0-9]{12}$/.test(row.version) && row.installPath === join28(cacheRoot, row.version), "Managed plugin cache path or version is outside its registration");
35244
36062
  const approval = (producer) => {
35245
36063
  pluginText(producer);
35246
- const digest = `sha256:${basename7(producer)}`;
35247
- const receipt2 = readPluginAdmissionReceipt(witness.storeRoot, witness.bindingId, digest);
36064
+ const digest2 = `sha256:${basename7(producer)}`;
36065
+ const receipt2 = readPluginAdmissionReceipt(witness.storeRoot, witness.bindingId, digest2);
35248
36066
  pluginNeed(receipt2.materializedPath === producer, "Managed producer path is not an approved immutable projection");
35249
36067
  if (!verified.has(producer)) {
35250
36068
  verifiedBytes += receipt2.plan.files.reduce((total, file2) => total + file2.size, 0);
@@ -35270,7 +36088,7 @@ function hashManagedPluginRegistry(path, managed) {
35270
36088
  return Object.fromEntries(Object.entries(row).filter(([key]) => !["version", "installPath", "sourceProducerPath", "previousProducerPaths", "lastUpdated"].includes(key)));
35271
36089
  });
35272
36090
  safe4(cacheRoot);
35273
- const before = lstatSync18(cacheRoot);
36091
+ const before = lstatSync19(cacheRoot);
35274
36092
  pluginNeed(before.isDirectory(), "Invalid managed plugin cache root");
35275
36093
  const directory = opendirSync3(cacheRoot), names = [];
35276
36094
  try {
@@ -35283,17 +36101,17 @@ function hashManagedPluginRegistry(path, managed) {
35283
36101
  directory.closeSync();
35284
36102
  }
35285
36103
  for (const version2 of names.sort()) {
35286
- const files = pluginFileWitnesses(snapshotPluginTree(join27(cacheRoot, version2), { nativeRuntime: `claude-${target.native.version}` }));
36104
+ const files = pluginFileWitnesses(snapshotPluginTree(join28(cacheRoot, version2), { nativeRuntime: `claude-${target.native.version}` }));
35287
36105
  verifiedBytes += files.reduce((total, file2) => total + file2.size, 0);
35288
36106
  pluginNeed(verifiedBytes <= 256 * 1024 * 1024, "Managed plugin verification exceeds its aggregate byte budget");
35289
36107
  const serialized = JSON.stringify(files);
35290
- const expected = currentFiles.get(join27(cacheRoot, version2));
36108
+ const expected = currentFiles.get(join28(cacheRoot, version2));
35291
36109
  pluginNeed(expected === undefined || serialized === expected, "Current native cache differs from its exact registered producer receipt");
35292
36110
  pluginNeed([...approvals.values()].some((receipt) => nativeVersionMatches(version2, receipt) && JSON.stringify(receipt.plan.files) === serialized), "A retained native plugin cache version differs from every approved projection");
35293
36111
  }
35294
36112
  for (const row of rows)
35295
36113
  pluginNeed(names.includes(row.version), "Managed native plugin installation is missing");
35296
- const after = lstatSync18(cacheRoot);
36114
+ const after = lstatSync19(cacheRoot);
35297
36115
  safe4(cacheRoot);
35298
36116
  pluginNeed(before.dev === after.dev && before.ino === after.ino && before.mtimeMs === after.mtimeMs && before.ctimeMs === after.ctimeMs, "Managed cache version membership changed during verification");
35299
36117
  }
@@ -35307,23 +36125,23 @@ var init_plugin_discovery = __esm(() => {
35307
36125
  });
35308
36126
 
35309
36127
  // src/lib/claude-marketplace-registry.ts
35310
- import { createHash as createHash18 } from "crypto";
35311
- import { closeSync as closeSync15, constants as constants13, fstatSync as fstatSync15, lstatSync as lstatSync19, openSync as openSync15, readSync as readSync10 } from "fs";
35312
- import { basename as basename8, dirname as dirname17, isAbsolute as isAbsolute17, resolve as resolve18 } from "path";
36128
+ import { createHash as createHash19 } from "crypto";
36129
+ import { closeSync as closeSync16, constants as constants14, fstatSync as fstatSync16, lstatSync as lstatSync20, openSync as openSync16, readSync as readSync11 } from "fs";
36130
+ import { basename as basename8, dirname as dirname18, isAbsolute as isAbsolute18, resolve as resolve19 } from "path";
35313
36131
  function need8(value, reason2) {
35314
36132
  if (!value)
35315
36133
  throw new Error(`Claude marketplace registry ${reason2}`);
35316
36134
  }
35317
36135
  function absolutePath4(value) {
35318
- need8(typeof value === "string" && value.length > 0 && value.length <= CLAUDE_MARKETPLACE_REGISTRY_LIMITS.pathCharacters && !/[\x00-\x1f\x7f]/.test(value) && isAbsolute17(value) && resolve18(value) === value, "requires a normalized absolute path");
36136
+ need8(typeof value === "string" && value.length > 0 && value.length <= CLAUDE_MARKETPLACE_REGISTRY_LIMITS.pathCharacters && !/[\x00-\x1f\x7f]/.test(value) && isAbsolute18(value) && resolve19(value) === value, "requires a normalized absolute path");
35319
36137
  }
35320
36138
  function parents2(path) {
35321
36139
  const result = [];
35322
- for (let at = dirname17(path);; at = dirname17(at)) {
35323
- const stat2 = lstatSync19(at, { bigint: true });
36140
+ for (let at = dirname18(path);; at = dirname18(at)) {
36141
+ const stat2 = lstatSync20(at, { bigint: true });
35324
36142
  need8(stat2.isDirectory() && !stat2.isSymbolicLink(), "path traverses a symlink or non-directory");
35325
36143
  result.push([at, stat2]);
35326
- if (at === dirname17(at))
36144
+ if (at === dirname18(at))
35327
36145
  return result;
35328
36146
  }
35329
36147
  }
@@ -35331,25 +36149,25 @@ function readRegistry2(path, budget2) {
35331
36149
  absolutePath4(path);
35332
36150
  need8(basename8(path) === "known_marketplaces.json", "requires known_marketplaces.json");
35333
36151
  need8(Number.isSafeInteger(budget2.remaining) && budget2.remaining >= 0, "has an invalid byte budget");
35334
- const ancestors2 = parents2(path), initial = lstatSync19(path, { bigint: true });
36152
+ const ancestors2 = parents2(path), initial = lstatSync20(path, { bigint: true });
35335
36153
  need8(initial.isFile() && !initial.isSymbolicLink() && initial.size <= BigInt(CLAUDE_MARKETPLACE_REGISTRY_LIMITS.bytes), "is not a bounded regular file");
35336
36154
  need8(initial.size <= BigInt(budget2.remaining), "exceeds its aggregate byte limit");
35337
- const fd = openSync15(path, constants13.O_RDONLY | constants13.O_NOFOLLOW | constants13.O_NONBLOCK);
36155
+ const fd = openSync16(path, constants14.O_RDONLY | constants14.O_NOFOLLOW | constants14.O_NONBLOCK);
35338
36156
  try {
35339
- const opened = fstatSync15(fd, { bigint: true });
36157
+ const opened = fstatSync16(fd, { bigint: true });
35340
36158
  need8(opened.isFile() && sameFile2(initial, opened), "changed during open");
35341
36159
  const bytes = Buffer.alloc(Number(opened.size) + 1);
35342
36160
  let length = 0;
35343
36161
  while (length < bytes.length) {
35344
- const count = readSync10(fd, bytes, length, bytes.length - length, null);
36162
+ const count = readSync11(fd, bytes, length, bytes.length - length, null);
35345
36163
  if (!count)
35346
36164
  break;
35347
36165
  length += count;
35348
36166
  }
35349
- const after = fstatSync15(fd, { bigint: true }), current = lstatSync19(path, { bigint: true });
36167
+ const after = fstatSync16(fd, { bigint: true }), current = lstatSync20(path, { bigint: true });
35350
36168
  need8(current.isFile() && sameFile2(opened, after) && sameFile2(after, current) && BigInt(length) === opened.size, "changed during read");
35351
36169
  for (const [ancestor, before] of ancestors2) {
35352
- const now = lstatSync19(ancestor, { bigint: true });
36170
+ const now = lstatSync20(ancestor, { bigint: true });
35353
36171
  need8(now.isDirectory() && before.dev === now.dev && before.ino === now.ino && before.mode === now.mode, "parent changed during read");
35354
36172
  }
35355
36173
  budget2.remaining -= length;
@@ -35359,7 +36177,7 @@ function readRegistry2(path, budget2) {
35359
36177
  throw new Error("Claude marketplace registry is not strict UTF-8");
35360
36178
  }
35361
36179
  } finally {
35362
- closeSync15(fd);
36180
+ closeSync16(fd);
35363
36181
  }
35364
36182
  }
35365
36183
  function parse11(text2) {
@@ -35436,7 +36254,7 @@ function parse11(text2) {
35436
36254
  need8(root.entries.length <= CLAUDE_MARKETPLACE_REGISTRY_LIMITS.rows, "exceeds its marketplace row limit");
35437
36255
  return root;
35438
36256
  }
35439
- function exactKeys(value, keys2) {
36257
+ function exactKeys2(value, keys2) {
35440
36258
  return value?.kind === "object" && value.entries.length === keys2.length && value.entries.every(([key]) => keys2.includes(key));
35441
36259
  }
35442
36260
  function textField(value) {
@@ -35444,8 +36262,8 @@ function textField(value) {
35444
36262
  return value.value;
35445
36263
  }
35446
36264
  function normalizeRow(row, version2 = 1) {
35447
- if (!exactKeys(row, ["source", "installLocation", "lastUpdated"])) {
35448
- if (version2 !== 2 || !exactKeys(row, ["source", "installLocation", "lastUpdated", "autoUpdate"]))
36265
+ if (!exactKeys2(row, ["source", "installLocation", "lastUpdated"])) {
36266
+ if (version2 !== 2 || !exactKeys2(row, ["source", "installLocation", "lastUpdated", "autoUpdate"]))
35449
36267
  return;
35450
36268
  const autoUpdate = field2(row, "autoUpdate");
35451
36269
  need8(autoUpdate?.kind === "literal" && (autoUpdate.value === "true" || autoUpdate.value === "false"), "contains an invalid automatic-update preference");
@@ -35457,7 +36275,7 @@ function normalizeRow(row, version2 = 1) {
35457
36275
  if (type?.kind !== "string" || !["github", "directory"].includes(type.value))
35458
36276
  return;
35459
36277
  const location = type.value === "github" ? "repo" : "path";
35460
- if (!exactKeys(source, ["source", location]))
36278
+ if (!exactKeys2(source, ["source", location]))
35461
36279
  return;
35462
36280
  const sourceLocation = textField(field2(source, location));
35463
36281
  if (type.value === "directory")
@@ -35473,14 +36291,14 @@ function captureClaudeMarketplaceRegistry(path, budget2 = { remaining: 256 * 102
35473
36291
  const value = parse11(readRegistry2(path, budget2));
35474
36292
  for (const [, row] of value.entries)
35475
36293
  normalizeRow(row);
35476
- const sha2562 = createHash18("sha256").update("hasna.skills.claude-marketplace-registry.v1\x00").update(JSON.stringify(value)).digest("hex");
36294
+ const sha2562 = createHash19("sha256").update("hasna.skills.claude-marketplace-registry.v1\x00").update(JSON.stringify(value)).digest("hex");
35477
36295
  return { path, hashMode: "claude-marketplace-registry", sha256: sha2562 };
35478
36296
  }
35479
36297
  function captureClaudeMarketplaceRegistryV2(path, budget2 = { remaining: 256 * 1024 * 1024 }) {
35480
36298
  const value = parse11(readRegistry2(path, budget2));
35481
36299
  for (const [, row] of value.entries)
35482
36300
  normalizeRow(row, 2);
35483
- const sha2562 = createHash18("sha256").update("hasna.skills.claude-marketplace-registry.v2\x00").update(JSON.stringify(value)).digest("hex");
36301
+ const sha2562 = createHash19("sha256").update("hasna.skills.claude-marketplace-registry.v2\x00").update(JSON.stringify(value)).digest("hex");
35484
36302
  return { path, hashMode: "claude-marketplace-registry-v2", sha256: sha2562 };
35485
36303
  }
35486
36304
  var CLAUDE_MARKETPLACE_REGISTRY_LIMITS, sameFile2 = (a, b) => a.dev === b.dev && a.ino === b.ino && a.mode === b.mode && a.uid === b.uid && a.gid === b.gid && a.nlink === b.nlink && a.size === b.size && a.mtimeNs === b.mtimeNs && a.ctimeNs === b.ctimeNs, field2 = (object6, key) => object6.entries.find(([name]) => name === key)?.[1];
@@ -35502,7 +36320,7 @@ var init_codex_hook_additions_review = __esm(() => {
35502
36320
  });
35503
36321
 
35504
36322
  // src/lib/codex-hook-discovery-recovery.ts
35505
- import { createHash as createHash19 } from "crypto";
36323
+ import { createHash as createHash20 } from "crypto";
35506
36324
  function assertCodexHookDiscoveryRecovery(binding, witness) {
35507
36325
  const proof = proofs2.get(witness);
35508
36326
  need6(!!proof && binding.agent === "codex" && witness.discoverySha256 === discoveryDigest(binding), "RECONCILE_DISCOVERY_RECOVERY_CHANGED");
@@ -35517,7 +36335,7 @@ function verifiesCodexHookDiscoverySource(binding, source, currentDigest, witnes
35517
36335
  need6(source.sha256 === witness.beforeSha256 && currentDigest === witness.currentSha256, "RECONCILE_DISCOVERY_RECOVERY_CHANGED");
35518
36336
  return true;
35519
36337
  }
35520
- var sha4 = (text2) => createHash19("sha256").update(text2).digest("hex"), fields, discoveryDigest = (binding) => {
36338
+ var sha4 = (text2) => createHash20("sha256").update(text2).digest("hex"), fields, discoveryDigest = (binding) => {
35521
36339
  const controls = binding.codexDisabledPluginSkills;
35522
36340
  if (!Object.hasOwn(binding, "codexDisabledPluginSkills") || Array.isArray(controls) && controls.length === 0) {
35523
36341
  const { codexDisabledPluginSkills: _controls, ...withoutControls } = binding;
@@ -35535,16 +36353,16 @@ var init_codex_hook_discovery_recovery = __esm(() => {
35535
36353
  });
35536
36354
 
35537
36355
  // src/lib/agent-discovery.ts
35538
- import { createHash as createHash20 } from "crypto";
35539
- import { lstatSync as lstatSync20, readFileSync as readFileSync16, readdirSync as readdirSync7, realpathSync as realpathSync6 } from "fs";
35540
- import { basename as basename9, dirname as dirname18, isAbsolute as isAbsolute18, join as join28, resolve as resolve19, sep as sep8 } from "path";
36356
+ import { createHash as createHash21 } from "crypto";
36357
+ import { lstatSync as lstatSync21, readFileSync as readFileSync16, readdirSync as readdirSync8, realpathSync as realpathSync8 } from "fs";
36358
+ import { basename as basename9, dirname as dirname19, isAbsolute as isAbsolute19, join as join29, relative as relative7, resolve as resolve20, sep as sep9 } from "path";
35541
36359
  import { isDeepStrictEqual as isDeepStrictEqual4 } from "util";
35542
36360
  function discoveryExecutable(agent) {
35543
36361
  const command = DISCOVERY_RUNTIME_COMMANDS[agent];
35544
36362
  const found = command ? Bun.which(command) : null;
35545
36363
  if (!command || !found)
35546
36364
  return null;
35547
- const path = resolve19(found), target = realpathOrNull(path);
36365
+ const path = resolve20(found), target = realpathOrNull(path);
35548
36366
  return target === null ? null : { command, path, target };
35549
36367
  }
35550
36368
  function parseConfig(text2, path, toml = false) {
@@ -35558,12 +36376,12 @@ function parseConfig(text2, path, toml = false) {
35558
36376
  }
35559
36377
  }
35560
36378
  function safe5(path) {
35561
- if (!isAbsolute18(path) || path.includes("\x00"))
36379
+ if (!isAbsolute19(path) || path.includes("\x00"))
35562
36380
  throw new Error("Expected an absolute native discovery path");
35563
- for (let cursor = path;; cursor = dirname18(cursor)) {
35564
- if (lstatSync20(cursor, { throwIfNoEntry: false })?.isSymbolicLink())
36381
+ for (let cursor = path;; cursor = dirname19(cursor)) {
36382
+ if (lstatSync21(cursor, { throwIfNoEntry: false })?.isSymbolicLink())
35565
36383
  throw new Error(`Refusing symlink native discovery input: ${cursor}`);
35566
- if (dirname18(cursor) === cursor)
36384
+ if (dirname19(cursor) === cursor)
35567
36385
  break;
35568
36386
  }
35569
36387
  }
@@ -35571,27 +36389,27 @@ function read(path, changes) {
35571
36389
  safe5(path);
35572
36390
  if (changes?.has(path))
35573
36391
  return changes.get(path);
35574
- const stat2 = lstatSync20(path, { throwIfNoEntry: false });
36392
+ const stat2 = lstatSync21(path, { throwIfNoEntry: false });
35575
36393
  if (!stat2)
35576
36394
  return null;
35577
36395
  if (!stat2.isFile() || stat2.size > 16 * 1024 * 1024)
35578
36396
  throw new Error(`Unsupported or oversized native discovery input: ${path}`);
35579
36397
  return readFileSync16(path, "utf8");
35580
36398
  }
35581
- function assertReviewedClaudeCacheClosures(home, config2, review, canonical8) {
36399
+ function assertReviewedClaudeCacheClosures(home, config2, review, canonical9) {
35582
36400
  const enabledIds = Object.entries(config2.enabledPlugins ?? {}).filter(([, enabled]) => enabled === true).map(([id]) => id);
35583
36401
  if (enabledIds.length === 0)
35584
36402
  return;
35585
- const registryPath = canonical8(join28(home, ".claude/plugins/installed_plugins.json"));
35586
- const cacheAliasRoot = join28(home, ".claude/plugins/cache");
35587
- const cacheRoot = canonical8(cacheAliasRoot);
36403
+ const registryPath = canonical9(join29(home, ".claude/plugins/installed_plugins.json"));
36404
+ const cacheAliasRoot = join29(home, ".claude/plugins/cache");
36405
+ const cacheRoot = canonical9(cacheAliasRoot);
35588
36406
  const registryText = read(registryPath);
35589
36407
  if (registryText === null)
35590
36408
  return;
35591
36409
  const registry2 = parseConfig(registryText, registryPath);
35592
36410
  if (registry2.version !== 2 || !registry2.plugins || typeof registry2.plugins !== "object" || Array.isArray(registry2.plugins))
35593
36411
  throw new Error("Reviewed Claude installed plugin registrations are invalid");
35594
- const cachePath = (path) => typeof path === "string" && isAbsolute18(path) && resolve19(path) === path && [cacheAliasRoot, cacheRoot].some((root) => path === root || path.startsWith(root + sep8));
36412
+ const cachePath = (path) => typeof path === "string" && isAbsolute19(path) && resolve20(path) === path && [cacheAliasRoot, cacheRoot].some((root) => path === root || path.startsWith(root + sep9));
35595
36413
  const activeRoots = new Set;
35596
36414
  for (const id of enabledIds) {
35597
36415
  const rows = registry2.plugins[id];
@@ -35603,13 +36421,13 @@ function assertReviewedClaudeCacheClosures(home, config2, review, canonical8) {
35603
36421
  if (!row || typeof row !== "object" || Array.isArray(row) || typeof row.installPath !== "string") {
35604
36422
  throw new Error("Reviewed Claude enabled plugin registration requires an object with an installPath string");
35605
36423
  }
35606
- if ([cacheAliasRoot, cacheRoot].some((root) => row.installPath === root || row.installPath.startsWith(root + sep8))) {
36424
+ if ([cacheAliasRoot, cacheRoot].some((root) => row.installPath === root || row.installPath.startsWith(root + sep9))) {
35607
36425
  if (!cachePath(row.installPath) || row.installPath.length > AGENT_POLICY_LIMITS.pathCharacters || row.version !== undefined && (typeof row.version !== "string" || basename9(row.installPath) !== row.version)) {
35608
36426
  throw new Error("Reviewed Claude discovery has a malformed active cache registration");
35609
36427
  }
35610
- if (row.scope === "user" && (row.projectPath === undefined || row.projectPath === null)) {} else if (row.scope === "project" && typeof row.projectPath === "string" && isAbsolute18(row.projectPath) && resolve19(row.projectPath) === row.projectPath && row.projectPath.length <= AGENT_POLICY_LIMITS.pathCharacters) {} else
36428
+ if (row.scope === "user" && (row.projectPath === undefined || row.projectPath === null)) {} else if (row.scope === "project" && typeof row.projectPath === "string" && isAbsolute19(row.projectPath) && resolve20(row.projectPath) === row.projectPath && row.projectPath.length <= AGENT_POLICY_LIMITS.pathCharacters) {} else
35611
36429
  throw new Error("Reviewed Claude discovery has an unsupported active cache registration scope");
35612
- activeRoots.add(canonical8(row.installPath));
36430
+ activeRoots.add(canonical9(row.installPath));
35613
36431
  }
35614
36432
  }
35615
36433
  }
@@ -35625,11 +36443,11 @@ function assertReviewedClaudeCacheClosures(home, config2, review, canonical8) {
35625
36443
  };
35626
36444
  for (const root of activeRoots) {
35627
36445
  safe5(root);
35628
- const rootStat = lstatSync20(root, { throwIfNoEntry: false });
35629
- if (!rootStat?.isDirectory() || realpathSync6(root) !== root)
36446
+ const rootStat = lstatSync21(root, { throwIfNoEntry: false });
36447
+ if (!rootStat?.isDirectory() || realpathSync8(root) !== root)
35630
36448
  throw new Error("Reviewed Claude active cache plugin root is missing or unsafe");
35631
- const manifestPath = join28(root, ".claude-plugin/plugin.json");
35632
- const manifestStat = lstatSync20(manifestPath, { throwIfNoEntry: false });
36449
+ const manifestPath = join29(root, ".claude-plugin/plugin.json");
36450
+ const manifestStat = lstatSync21(manifestPath, { throwIfNoEntry: false });
35633
36451
  let manifest;
35634
36452
  if (manifestStat) {
35635
36453
  if (!manifestStat.isFile())
@@ -35644,37 +36462,37 @@ function assertReviewedClaudeCacheClosures(home, config2, review, canonical8) {
35644
36462
  } else if (!review.sources.some((source) => source.path === manifestPath && source.hashMode === "path-bytes" && source.sha256 !== null && source.format === undefined && source.fields === undefined && source.managedPlugins === undefined)) {
35645
36463
  throw new Error("Reviewed Claude active cache plugin manifest absence requires a path-bytes witness");
35646
36464
  }
35647
- const roots = new Set([join28(root, "skills")]);
35648
- if (lstatSync20(join28(root, "SKILL.md"), { throwIfNoEntry: false })?.isFile())
36465
+ const roots = new Set([join29(root, "skills")]);
36466
+ if (lstatSync21(join29(root, "SKILL.md"), { throwIfNoEntry: false })?.isFile())
35649
36467
  roots.add(root);
35650
36468
  const declared = manifest?.skills === undefined ? ["./skills"] : typeof manifest.skills === "string" ? [manifest.skills] : manifest.skills;
35651
36469
  if (!Array.isArray(declared) || declared.some((path) => typeof path !== "string"))
35652
36470
  throw new Error("Reviewed Claude active cache plugin has unsupported skill paths");
35653
36471
  for (const value of declared) {
35654
- const path = resolve19(root, value);
35655
- if (path !== root && !path.startsWith(root + sep8))
36472
+ const path = resolve20(root, value);
36473
+ if (path !== root && !path.startsWith(root + sep9))
35656
36474
  throw new Error("Reviewed Claude active cache plugin skill path escapes its root");
35657
- roots.add(path.endsWith(`${sep8}SKILL.md`) ? dirname18(path) : path);
36475
+ roots.add(path.endsWith(`${sep9}SKILL.md`) ? dirname19(path) : path);
35658
36476
  }
35659
36477
  for (const skillRoot of roots)
35660
36478
  if (!review.roots.includes(skillRoot))
35661
36479
  throw new Error("Reviewed Claude active cache plugin skill root is not covered");
35662
- const hooksPath = join28(root, "hooks/hooks.json");
35663
- const hooksStat = lstatSync20(hooksPath, { throwIfNoEntry: false });
36480
+ const hooksPath = join29(root, "hooks/hooks.json");
36481
+ const hooksStat = lstatSync21(hooksPath, { throwIfNoEntry: false });
35664
36482
  if (hooksStat) {
35665
36483
  if (!hooksStat.isFile())
35666
36484
  throw new Error("Reviewed Claude plugin hook manifest is unsupported");
35667
36485
  requireSource(hooksPath, "hook manifest");
35668
36486
  }
35669
36487
  if (typeof manifest?.hooks === "string")
35670
- requireSource(resolve19(root, manifest.hooks), "manifest-declared hook source");
36488
+ requireSource(resolve20(root, manifest.hooks), "manifest-declared hook source");
35671
36489
  }
35672
36490
  }
35673
36491
  function projectNativeDiscoveryFields(text2, format, fields2, path) {
35674
36492
  const object6 = format === "yaml" ? parseHermesConfig(text2) : parseConfig(text2, path, format === "toml");
35675
36493
  if (!object6 || typeof object6 !== "object" || Array.isArray(object6))
35676
36494
  throw new Error("Expected native discovery configuration object");
35677
- return digest(JSON.stringify(Object.fromEntries(fields2.map((field3) => [field3, object6[field3] ?? null]))));
36495
+ return digest2(JSON.stringify(Object.fromEntries(fields2.map((field3) => [field3, object6[field3] ?? null]))));
35678
36496
  }
35679
36497
  function isSupersededSettingsProjection(agent, configPath, source) {
35680
36498
  if (agent === "sumi")
@@ -35684,7 +36502,7 @@ function isSupersededSettingsProjection(agent, configPath, source) {
35684
36502
  function supersedesSettingsProjection(agent, sources, configPath) {
35685
36503
  if (agent === "sumi")
35686
36504
  return sources.some((source) => source.path === configPath && source.hashMode === "sumi-settings-v1");
35687
- return agent === "codex" && sources.some((source) => source.path === configPath && (source.hashMode === "codex-settings-v2" || (source.hashMode === "codex-settings-v3" || source.hashMode === "codex-settings-v4")));
36505
+ return agent === "codex" && sources.some((source) => source.path === configPath && (source.hashMode === "codex-settings-v2" || (source.hashMode === "codex-settings-v3" || source.hashMode === "codex-settings-v4" || source.hashMode === "codex-settings-v5")));
35688
36506
  }
35689
36507
  function projected(source, changes, budget2 = discoveryByteBudget()) {
35690
36508
  if (source.reviewArtifact !== undefined)
@@ -35697,13 +36515,13 @@ function projected(source, changes, budget2 = discoveryByteBudget()) {
35697
36515
  throw new Error(`Native discovery input changed; run skills hook install with a fresh discovery review: ${source.path}`);
35698
36516
  return changes?.has(source.path) ? hashSumiSettingsReplacement(changes.get(source.path), budget2) : current;
35699
36517
  }
35700
- if (source.hashMode === "codex-settings-v1" || source.hashMode === "codex-settings-v2" || (source.hashMode === "codex-settings-v3" || source.hashMode === "codex-settings-v4")) {
36518
+ if (source.hashMode === "codex-settings-v1" || source.hashMode === "codex-settings-v2" || (source.hashMode === "codex-settings-v3" || source.hashMode === "codex-settings-v4" || source.hashMode === "codex-settings-v5")) {
35701
36519
  if (source.format !== undefined || source.fields !== undefined || source.managedPlugins !== undefined || typeof source.sha256 !== "string" || !/^[a-f0-9]{64}$/.test(source.sha256))
35702
36520
  throw new Error("Codex settings witnesses require exact typed metadata");
35703
- const current = (source.hashMode === "codex-settings-v4" ? captureCodexSettingsV4 : source.hashMode === "codex-settings-v3" ? captureCodexSettingsV3 : source.hashMode === "codex-settings-v2" ? captureCodexSettingsV2 : captureCodexSettings)(source.path, budget2).sha256;
36521
+ const current = (source.hashMode === "codex-settings-v5" ? captureCodexSettingsV5 : source.hashMode === "codex-settings-v4" ? captureCodexSettingsV4 : source.hashMode === "codex-settings-v3" ? captureCodexSettingsV3 : source.hashMode === "codex-settings-v2" ? captureCodexSettingsV2 : captureCodexSettings)(source.path, budget2).sha256;
35704
36522
  if (current !== source.sha256)
35705
36523
  throw new Error(`Native discovery input changed; run skills hook install with a fresh discovery review: ${source.path}`);
35706
- return changes?.has(source.path) ? (source.hashMode === "codex-settings-v4" ? hashCodexSettingsReplacementV4 : source.hashMode === "codex-settings-v3" ? hashCodexSettingsReplacementV3 : source.hashMode === "codex-settings-v2" ? hashCodexSettingsReplacementV2 : hashCodexSettingsReplacement)(changes.get(source.path), budget2) : current;
36524
+ return changes?.has(source.path) ? (source.hashMode === "codex-settings-v5" ? hashCodexSettingsReplacementV5 : source.hashMode === "codex-settings-v4" ? hashCodexSettingsReplacementV4 : source.hashMode === "codex-settings-v3" ? hashCodexSettingsReplacementV3 : source.hashMode === "codex-settings-v2" ? hashCodexSettingsReplacementV2 : hashCodexSettingsReplacement)(changes.get(source.path), budget2) : current;
35707
36525
  }
35708
36526
  if (source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || (source.hashMode === "claude-settings-v3" || source.hashMode === "claude-settings-v4")) {
35709
36527
  if (source.format !== undefined || source.fields !== undefined || source.managedPlugins !== undefined || typeof source.sha256 !== "string" || !/^[a-f0-9]{64}$/.test(source.sha256))
@@ -35755,7 +36573,7 @@ function projected(source, changes, budget2 = discoveryByteBudget()) {
35755
36573
  if (text2 === null)
35756
36574
  return null;
35757
36575
  if (!source.format)
35758
- return digest(text2);
36576
+ return digest2(text2);
35759
36577
  return projectNativeDiscoveryFields(text2, source.format, source.fields ?? [], source.path);
35760
36578
  }
35761
36579
  function absentCodexSkillRoots(binding) {
@@ -35764,18 +36582,18 @@ function absentCodexSkillRoots(binding) {
35764
36582
  return [];
35765
36583
  if (binding.agent !== "codex" || !Array.isArray(controls) || controls.length > 4096)
35766
36584
  throw new Error("Invalid disabled Codex discovery proof");
35767
- if (binding.method !== "reviewed" || controls.every((control) => lstatSync20(control.pluginParent, { throwIfNoEntry: false })))
36585
+ if (binding.method !== "reviewed" || controls.every((control) => lstatSync21(control.pluginParent, { throwIfNoEntry: false })))
35768
36586
  return [];
35769
- const cache = dirname18(dirname18(controls[0].pluginParent)), config2 = join28(dirname18(dirname18(cache)), "config.toml");
36587
+ const cache = dirname19(dirname19(controls[0].pluginParent)), config2 = join29(dirname19(dirname19(cache)), "config.toml");
35770
36588
  const source = binding.sources.find((source2) => source2.path === config2 && source2.sha256 !== null && source2.format === undefined && source2.fields === undefined);
35771
36589
  if (!source || projected(source) !== source.sha256)
35772
36590
  throw new Error("Missing current disabled Codex configuration witness");
35773
36591
  const rules = Bun.TOML.parse(read(config2)).skills?.config ?? [];
35774
36592
  return [...new Set(controls.map((control) => control.pluginParent))].filter((parent) => !codexDirectHookSelects(cache, parent) && absentDisabledCodexPluginParent(cache, parent, controls, rules));
35775
36593
  }
35776
- function codexDirectHookSelects(cache, root) {
35777
- const codex = dirname18(dirname18(cache)), config2 = Bun.TOML.parse(read(join28(codex, "config.toml")) ?? "");
35778
- const hooks = read(join28(codex, "hooks.json"));
36594
+ function codexDirectHookSelects(cache, root, configPath = join29(dirname19(dirname19(cache)), "config.toml")) {
36595
+ const codex = dirname19(configPath), config2 = Bun.TOML.parse(read(configPath) ?? "");
36596
+ const hooks = read(join29(codex, "hooks.json"));
35779
36597
  if (hooks !== null)
35780
36598
  hashNativeJsonControls(hooks);
35781
36599
  return JSON.stringify(config2.hooks ?? {}).includes(root) || hooks !== null && JSON.stringify(JSON.parse(hooks)).includes(root);
@@ -35787,7 +36605,7 @@ function retiredCodexRoots(binding) {
35787
36605
  const controls = binding.codexDisabledPluginSkills;
35788
36606
  if (binding.agent !== "codex" || binding.method !== "reviewed" || !Array.isArray(controls) || !controls.length || !Array.isArray(proof.roots) || proof.roots.length > AGENT_POLICY_LIMITS.discoveryRoots || new Set(proof.roots).size !== proof.roots.length || !Array.isArray(proof.directories) || proof.parents !== undefined && (!Array.isArray(proof.parents) || proof.parents.length > AGENT_POLICY_LIMITS.discoveryRoots || new Set(proof.parents).size !== proof.parents.length) || !proof.roots.length && !proof.parents?.length)
35789
36607
  throw new Error("Invalid retired Codex materialization proof");
35790
- const cache = dirname18(dirname18(controls[0].pluginParent)), config2 = join28(dirname18(dirname18(cache)), "config.toml");
36608
+ const cache = dirname19(dirname19(controls[0].pluginParent)), config2 = join29(dirname19(dirname19(cache)), "config.toml");
35791
36609
  const source = binding.sources.find((source2) => source2.path === config2 && source2.sha256 !== null && source2.format === undefined && source2.fields === undefined);
35792
36610
  if (!source || projected(source) !== source.sha256)
35793
36611
  throw new Error("Missing current retired Codex configuration witness");
@@ -35795,7 +36613,7 @@ function retiredCodexRoots(binding) {
35795
36613
  if ((proof.parents ?? []).some((parent) => codexDirectHookSelects(cache, parent) || !reviewedDisabledCodexPluginParent(cache, parent, controls, rules)) || !reviewedCodexPluginCapabilitiesUnchanged(cache, controls, (path) => read(path), rules))
35796
36614
  throw new Error("Retired Codex parent capabilities changed");
35797
36615
  for (const root of proof.roots) {
35798
- const manifest = binding.sources.find((source2) => source2.path === join28(root, ".codex-plugin/plugin.json") && source2.sha256 !== null && source2.format === undefined && source2.fields === undefined && [undefined, "bytes"].includes(source2.hashMode));
36616
+ const manifest = binding.sources.find((source2) => source2.path === join29(root, ".codex-plugin/plugin.json") && source2.sha256 !== null && source2.format === undefined && source2.fields === undefined && [undefined, "bytes"].includes(source2.hashMode));
35799
36617
  if (!manifest || codexDirectHookSelects(cache, root) || !reviewedRetiredCodexRoot(cache, root, controls, rules, (path) => read(path), true))
35800
36618
  throw new Error("Retired Codex materialization changed");
35801
36619
  }
@@ -35804,7 +36622,7 @@ function retiredCodexRoots(binding) {
35804
36622
  function retainableAbsentSource(source) {
35805
36623
  if (source.format !== undefined || source.fields !== undefined || source.managedPlugins !== undefined)
35806
36624
  return false;
35807
- return [undefined, "bytes"].includes(source.hashMode) || source.hashMode === "claude-plugin-manifest-v1" && source.sha256 !== null && source.path.endsWith(join28(sep8, ".claude-plugin", "plugin.json"));
36625
+ return [undefined, "bytes"].includes(source.hashMode) || source.hashMode === "claude-plugin-manifest-v1" && source.sha256 !== null && source.path.endsWith(join29(sep9, ".claude-plugin", "plugin.json"));
35808
36626
  }
35809
36627
  function absentRetiredClaudeRoots(binding) {
35810
36628
  if (binding.agent !== "claude" || binding.method !== "reviewed")
@@ -35813,17 +36631,17 @@ function absentRetiredClaudeRoots(binding) {
35813
36631
  for (const source of binding.sources) {
35814
36632
  if (!retainableAbsentSource(source) || source.sha256 === null)
35815
36633
  continue;
35816
- const marker = sep8 + ".claude" + sep8 + "plugins" + sep8 + "cache" + sep8, at = source.path.indexOf(marker);
36634
+ const marker = sep9 + ".claude" + sep9 + "plugins" + sep9 + "cache" + sep9, at = source.path.indexOf(marker);
35817
36635
  if (at < 0 || source.path.indexOf(marker, at + 1) >= 0)
35818
36636
  continue;
35819
- const cache = source.path.slice(0, at + marker.length - 1), parts = source.path.slice(at + marker.length).split(sep8);
36637
+ const cache = source.path.slice(0, at + marker.length - 1), parts = source.path.slice(at + marker.length).split(sep9);
35820
36638
  if (parts.length < 4 || parts.slice(0, 3).some((part) => !part || part === "." || part === ".."))
35821
36639
  continue;
35822
- const root = join28(cache, ...parts.slice(0, 3));
36640
+ const root = join29(cache, ...parts.slice(0, 3));
35823
36641
  safe5(root);
35824
- if (lstatSync20(root, { throwIfNoEntry: false }))
36642
+ if (lstatSync21(root, { throwIfNoEntry: false }))
35825
36643
  continue;
35826
- const claude = dirname18(dirname18(cache)), settings = join28(claude, "settings.json"), registry2 = join28(claude, "plugins/installed_plugins.json");
36644
+ const claude = dirname19(dirname19(cache)), settings = join29(claude, "settings.json"), registry2 = join29(claude, "plugins/installed_plugins.json");
35827
36645
  const full = (path) => binding.sources.find((item) => item.path === path && item.sha256 !== null && item.format === undefined && item.fields === undefined);
35828
36646
  const configSource = full(settings), registrySource = full(registry2);
35829
36647
  if (!configSource || !registrySource || projected(configSource) !== configSource.sha256 || projected(registrySource) !== registrySource.sha256)
@@ -35840,15 +36658,15 @@ function absentRetiredClaudeRoots(binding) {
35840
36658
  if (!row || typeof row !== "object" || Array.isArray(row))
35841
36659
  return null;
35842
36660
  const value = row;
35843
- if (typeof value.installPath !== "string" || /[\x00-\x1f\x7f]/.test(value.installPath) || !isAbsolute18(value.installPath) || resolve19(value.installPath) !== value.installPath || value.installPath.length > AGENT_POLICY_LIMITS.pathCharacters)
36661
+ if (typeof value.installPath !== "string" || /[\x00-\x1f\x7f]/.test(value.installPath) || !isAbsolute19(value.installPath) || resolve20(value.installPath) !== value.installPath || value.installPath.length > AGENT_POLICY_LIMITS.pathCharacters)
35844
36662
  return null;
35845
36663
  if (value.scope === "user")
35846
36664
  return value.projectPath === undefined || value.projectPath === null ? "user\x00" : null;
35847
36665
  if (value.scope === "project")
35848
- return typeof value.projectPath === "string" && !/[\x00-\x1f\x7f]/.test(value.projectPath) && value.projectPath.length <= AGENT_POLICY_LIMITS.pathCharacters && isAbsolute18(value.projectPath) && resolve19(value.projectPath) === value.projectPath ? `project\x00${value.projectPath}` : null;
36666
+ return typeof value.projectPath === "string" && !/[\x00-\x1f\x7f]/.test(value.projectPath) && value.projectPath.length <= AGENT_POLICY_LIMITS.pathCharacters && isAbsolute19(value.projectPath) && resolve20(value.projectPath) === value.projectPath ? `project\x00${value.projectPath}` : null;
35849
36667
  return null;
35850
36668
  };
35851
- if (Object.values(installed.plugins).some((value) => !Array.isArray(value) || value.some((row) => !row || typeof row.installPath !== "string" || row.installPath === root || row.installPath.startsWith(root + sep8) || root.startsWith(row.installPath + sep8))))
36669
+ if (Object.values(installed.plugins).some((value) => !Array.isArray(value) || value.some((row) => !row || typeof row.installPath !== "string" || row.installPath === root || row.installPath.startsWith(root + sep9) || root.startsWith(row.installPath + sep9))))
35852
36670
  continue;
35853
36671
  const rows = installed.plugins[id];
35854
36672
  if (!Array.isArray(rows) || rows.length < 1)
@@ -35866,36 +36684,94 @@ function absentRetiredClaudeRoots(binding) {
35866
36684
  if (!targetValid || !targetScopes.has("user\x00"))
35867
36685
  continue;
35868
36686
  const active = rows[0]?.installPath;
35869
- if (typeof active !== "string" || rows[0]?.version !== basename9(active) || dirname18(active) !== dirname18(root) || active === root || !lstatSync20(active, { throwIfNoEntry: false })?.isDirectory() || realpathSync6(active) !== active)
36687
+ if (typeof active !== "string" || rows[0]?.version !== basename9(active) || dirname19(active) !== dirname19(root) || active === root || !lstatSync21(active, { throwIfNoEntry: false })?.isDirectory() || realpathSync8(active) !== active)
35870
36688
  continue;
35871
- const activeManifest = full(join28(active, ".claude-plugin/plugin.json"));
36689
+ const activeManifest = full(join29(active, ".claude-plugin/plugin.json"));
35872
36690
  if (!activeManifest || projected(activeManifest) !== activeManifest.sha256)
35873
36691
  continue;
35874
36692
  result.add(root);
35875
36693
  }
35876
36694
  return [...result];
35877
36695
  }
35878
- function verifyAgentDiscovery(binding, codexRecovery) {
36696
+ function codexSemanticCacheSourceRole(source, cacheRoot, parents3) {
36697
+ if (!isAbsolute19(source.path) || resolve20(source.path) !== source.path || /[\x00-\x1f\x7f]/.test(source.path) || source.format !== undefined || source.fields !== undefined || source.managedPlugins !== undefined || source.reviewArtifact !== undefined || source.hashMode !== undefined && source.hashMode !== "bytes")
36698
+ return false;
36699
+ const parts = relative7(cacheRoot, source.path).split(sep9);
36700
+ if (parts.length < 3 || !parents3.includes(join29(cacheRoot, parts[0], parts[1])))
36701
+ return false;
36702
+ const tail = parts.slice(3).join("/");
36703
+ return parts.length === 5 && tail === ".codex-plugin/plugin.json" && source.sha256 !== null || parts.length === 4 && [".app.json", ".mcp.json"].includes(tail) && source.sha256 !== null || source.sha256 === null && (parts.length === 4 && tail === "SKILL.md" || parts.length === 5 && tail === "hooks/hooks.json");
36704
+ }
36705
+ function codexSemanticCacheDirectoryRole(path, cacheRoot) {
36706
+ return isAbsolute19(path) && resolve20(path) === path && !/[\x00-\x1f\x7f]/.test(path) && (path === cacheRoot || path.startsWith(cacheRoot + sep9));
36707
+ }
36708
+ function assertCodexSemanticCacheHookSafety(cacheRoot, parents3, configPath, hookRootAlias = null) {
36709
+ const selectionRoots = [cacheRoot, ...parents3];
36710
+ if (hookRootAlias !== null) {
36711
+ if (!hookRootAlias || Object.keys(hookRootAlias).length !== 2 || [hookRootAlias.alias, hookRootAlias.target].some((path) => typeof path !== "string" || !isAbsolute19(path) || resolve20(path) !== path || /[\x00-\x1f\x7f]/.test(path)) || hookRootAlias.target !== dirname19(configPath) || cacheRoot !== join29(hookRootAlias.target, "plugins/cache") || !lstatSync21(hookRootAlias.alias, { throwIfNoEntry: false })?.isSymbolicLink() || realpathSync8(hookRootAlias.alias) !== hookRootAlias.target || realpathSync8(hookRootAlias.target) !== hookRootAlias.target)
36712
+ throw new Error("Reviewed semantic cache hook alias changed");
36713
+ selectionRoots.push(...selectionRoots.map((root) => join29(hookRootAlias.alias, relative7(hookRootAlias.target, root))));
36714
+ }
36715
+ selectionRoots.push("plugins/cache");
36716
+ if (selectionRoots.some((parent) => codexDirectHookSelects(cacheRoot, parent, configPath)))
36717
+ throw new Error("Direct native hooks select a projected Codex cache input");
36718
+ }
36719
+ function verifyCodexSemanticCacheDiscovery(binding, reviewedRootAliases) {
36720
+ const proof = binding.codexSemanticCache;
36721
+ if (!proof)
36722
+ return;
36723
+ if (reviewedRootAliases !== undefined) {
36724
+ const alias = reviewedRootAliases.find((alias2) => alias2.agent === "codex");
36725
+ const expected = alias ? { alias: alias.alias, target: alias.target } : null;
36726
+ if (!isDeepStrictEqual4(proof.hookRootAlias, expected))
36727
+ throw new Error("Semantic cache hook alias differs from reviewed root binding");
36728
+ }
36729
+ const controls = binding.codexDisabledPluginSkills;
36730
+ if (binding.agent !== "codex" || binding.method !== "reviewed" || !controls?.length || proof.schema !== "hasna.codex-semantic-cache-discovery.v1" || !/^[a-f0-9]{64}$/.test(proof.previousPolicySha256) || !Array.isArray(proof.appOnlyParents) || !Array.isArray(proof.supersededSources) || !Array.isArray(proof.supersededDirectories))
36731
+ throw new Error("Invalid Codex semantic cache discovery proof");
36732
+ const cacheRoot = proof.witness.cacheRoot;
36733
+ if (controls.some((control) => dirname19(dirname19(control.pluginParent)) !== cacheRoot))
36734
+ throw new Error("Codex semantic cache names another enrolled cache");
36735
+ const parents3 = [...new Set([...controls.map((control) => control.pluginParent), ...proof.appOnlyParents.map((parent) => parent.pluginParent)])];
36736
+ const sources = binding.sources.filter((source) => codexSemanticCacheSourceRole(source, cacheRoot, parents3));
36737
+ const directories = (binding.directories ?? []).filter((directory) => codexSemanticCacheDirectoryRole(directory.path, cacheRoot));
36738
+ if (!directories.length || !isDeepStrictEqual4(sources, proof.supersededSources) || !isDeepStrictEqual4(directories, proof.supersededDirectories))
36739
+ throw new Error("Codex semantic cache provenance changed");
36740
+ const configPath = proof.configPath;
36741
+ if (!isAbsolute19(configPath) || resolve20(configPath) !== configPath || basename9(configPath) !== "config.toml" || /[\x00-\x1f\x7f]/.test(configPath))
36742
+ throw new Error("Invalid semantic cache configuration source");
36743
+ const configSource = binding.sources.find((source) => source.path === configPath && source.sha256 !== null && source.format === undefined && source.fields === undefined);
36744
+ if (!configSource || projected(configSource) !== configSource.sha256)
36745
+ throw new Error("Codex semantic cache requires unchanged reviewed configuration");
36746
+ assertCodexSemanticCacheHookSafety(cacheRoot, parents3, configPath, proof.hookRootAlias);
36747
+ const rules = parseConfig(read(configPath), configPath, true).skills?.config ?? [];
36748
+ const current = captureCodexSemanticCacheWitness({ cacheRoot, controls, appOnlyParents: proof.appOnlyParents, rules });
36749
+ assertCodexSemanticCacheWitnessUnchanged(proof.witness, current);
36750
+ return proof;
36751
+ }
36752
+ function verifyAgentDiscovery(binding, codexRecovery, reviewedRootAliases) {
35879
36753
  if (codexRecovery)
35880
36754
  assertCodexHookDiscoveryRecovery(binding, codexRecovery);
35881
36755
  if (!binding || !Array.isArray(binding.sources) || !Array.isArray(binding.roots) || binding.sources.length > AGENT_POLICY_LIMITS.discoverySources || binding.roots.length > AGENT_POLICY_LIMITS.discoveryRoots)
35882
36756
  throw new Error("Invalid native discovery binding");
35883
36757
  if (binding.agent === "hermes" && !binding.directories?.length)
35884
36758
  throw new Error("Hermes discovery requires directory membership coverage; run skills hook install with a fresh discovery review");
36759
+ const semanticCache = verifyCodexSemanticCacheDiscovery(binding, reviewedRootAliases);
36760
+ const semanticDirectory = (path) => Boolean(semanticCache && codexSemanticCacheDirectoryRole(path, semanticCache.witness.cacheRoot));
35885
36761
  const installationRoots = codexInstallationRoots(binding);
35886
36762
  const retiredRoots = retiredCodexRoots(binding);
35887
- const installationInput = (path) => installationRoots.some((root) => path === root || path.startsWith(root + sep8));
36763
+ const installationInput = (path) => installationRoots.some((root) => path === root || path.startsWith(root + sep9));
35888
36764
  if (binding.directories !== undefined) {
35889
36765
  const projected2 = binding.codexInstallationInputs?.directories ?? [];
35890
- const ancestors2 = binding.directories.filter((directory) => installationRoots.some((root) => root.startsWith(directory.path + sep8)));
36766
+ const ancestors2 = binding.directories.filter((directory) => installationRoots.some((root) => root.startsWith(directory.path + sep9)));
35891
36767
  if (projected2.length !== ancestors2.length || projected2.some((directory) => !ancestors2.some((original) => original.path === directory.path)))
35892
36768
  throw new Error("Missing installation input directory projection");
35893
- const ordinary = binding.directories.filter((directory) => !installationInput(directory.path) && !ancestors2.includes(directory));
36769
+ const ordinary = binding.directories.filter((directory) => !installationInput(directory.path) && !ancestors2.includes(directory) && !semanticDirectory(directory.path));
35894
36770
  if (binding.codexRetiredMaterializations) {
35895
- const projection = binding.codexRetiredMaterializations.directories;
36771
+ const projection = binding.codexRetiredMaterializations.directories.filter((directory) => !semanticDirectory(directory.path));
35896
36772
  if (projection.length !== ordinary.length || projection.some((item, index) => item.path !== ordinary[index]?.path))
35897
36773
  throw new Error("Missing retired Codex directory projection");
35898
- const omitted = [...retiredRoots, ...(binding.codexRetiredMaterializations.parents ?? []).filter((parent) => !lstatSync20(parent, { throwIfNoEntry: false }))];
36774
+ const omitted = [...retiredRoots, ...(binding.codexRetiredMaterializations.parents ?? []).filter((parent) => !lstatSync21(parent, { throwIfNoEntry: false }))];
35899
36775
  if (projection.every((item) => Array.isArray(item.entries)))
35900
36776
  verifyDiscoveryDirectoryProjection(projection, omitted);
35901
36777
  else {
@@ -35909,7 +36785,7 @@ function verifyAgentDiscovery(binding, codexRecovery) {
35909
36785
  verifyDiscoveryDirectories(ordinary);
35910
36786
  verifyDiscoveryDirectories(projected2, installationRoots);
35911
36787
  }
35912
- const absentRoots = [...absentCodexSkillRoots(binding), ...absentRetiredClaudeRoots(binding), ...retiredRoots.filter((root) => !lstatSync20(root, { throwIfNoEntry: false }))];
36788
+ const absentRoots = [...absentCodexSkillRoots(binding), ...absentRetiredClaudeRoots(binding), ...retiredRoots.filter((root) => !lstatSync21(root, { throwIfNoEntry: false }))];
35913
36789
  const budget2 = discoveryByteBudget();
35914
36790
  for (const source of binding.sources) {
35915
36791
  assertMarketplaceBinding(binding, source);
@@ -35919,11 +36795,15 @@ function verifyAgentDiscovery(binding, codexRecovery) {
35919
36795
  throw new Error("Invalid native discovery projection");
35920
36796
  if (source.sha256 !== null && !/^[a-f0-9]{64}$/.test(source.sha256))
35921
36797
  throw new Error("Invalid native discovery digest");
36798
+ if (semanticCache?.supersededSources.some((previous) => isDeepStrictEqual4(previous, source))) {
36799
+ safe5(source.path);
36800
+ continue;
36801
+ }
35922
36802
  if (installationInput(source.path)) {
35923
36803
  safe5(source.path);
35924
36804
  continue;
35925
36805
  }
35926
- if (absentRoots.some((root) => source.path.startsWith(root + sep8)) && retainableAbsentSource(source)) {
36806
+ if (absentRoots.some((root) => source.path.startsWith(root + sep9)) && retainableAbsentSource(source)) {
35927
36807
  safe5(source.path);
35928
36808
  continue;
35929
36809
  }
@@ -35935,7 +36815,7 @@ function verifyAgentDiscovery(binding, codexRecovery) {
35935
36815
  safe5(root);
35936
36816
  for (const root of absentRoots) {
35937
36817
  safe5(root);
35938
- if (lstatSync20(root, { throwIfNoEntry: false }))
36818
+ if (lstatSync21(root, { throwIfNoEntry: false }))
35939
36819
  throw new Error("Retired native materialization changed during discovery verification");
35940
36820
  }
35941
36821
  }
@@ -35945,13 +36825,13 @@ function codexInstallationRoots(binding) {
35945
36825
  return [];
35946
36826
  if (binding.agent !== "codex" || binding.method !== "reviewed" || !supportsCodexNativeCapability(proof.version, "installed-plugin-review") || !/^[a-f0-9]{64}$/.test(proof.catalogSha256) || !Array.isArray(proof.plugins) || !proof.plugins.length)
35947
36827
  throw new Error("Invalid native installation input proof");
35948
- const cache = dirname18(dirname18(proof.plugins[0].pluginParent));
35949
- const config2 = join28(dirname18(dirname18(cache)), "config.toml"), home = dirname18(dirname18(dirname18(cache)));
36828
+ const cache = dirname19(dirname19(proof.plugins[0].pluginParent));
36829
+ const config2 = join29(dirname19(dirname19(cache)), "config.toml"), home = dirname19(dirname19(dirname19(cache)));
35950
36830
  const configSource = binding.sources.find((source) => source.path === config2 && source.sha256 !== null && (!source.format || source.format === "toml" && source.fields?.includes("plugins")));
35951
- const nativeRoots = NATIVE_SKILL_ROOTS.filter(([agent]) => agent === "codex").map(([, path]) => join28(home, path));
35952
- if (!configSource || proof.plugins.some((input2) => nativeRoots.some((root) => root === input2.sourceRoot || root.startsWith(input2.sourceRoot + sep8) || input2.sourceRoot.startsWith(root + sep8)) || binding.sources.some((source) => basename9(source.path) === "config.toml" && (source.path === input2.sourceRoot || source.path.startsWith(input2.sourceRoot + sep8)))))
36831
+ const nativeRoots = NATIVE_SKILL_ROOTS.filter(([agent]) => agent === "codex").map(([, path]) => join29(home, path));
36832
+ if (!configSource || proof.plugins.some((input2) => nativeRoots.some((root) => root === input2.sourceRoot || root.startsWith(input2.sourceRoot + sep9) || input2.sourceRoot.startsWith(root + sep9)) || binding.sources.some((source) => basename9(source.path) === "config.toml" && (source.path === input2.sourceRoot || source.path.startsWith(input2.sourceRoot + sep9)))))
35953
36833
  throw new Error("Native installation input overlaps configuration or loading roots");
35954
- if (proof.plugins.some((input2) => dirname18(dirname18(input2.pluginParent)) !== cache || !binding.sources.some((source) => source.path === join28(input2.sourceRoot, ".codex-plugin/plugin.json") && source.sha256 !== null && source.format === undefined && source.fields === undefined)))
36834
+ if (proof.plugins.some((input2) => dirname19(dirname19(input2.pluginParent)) !== cache || !binding.sources.some((source) => source.path === join29(input2.sourceRoot, ".codex-plugin/plugin.json") && source.sha256 !== null && source.format === undefined && source.fields === undefined)))
35955
36835
  throw new Error("Missing native installation input source witness");
35956
36836
  return reviewedCodexPluginSourceRoots(cache, proof.plugins, (path) => {
35957
36837
  const text2 = read(path);
@@ -35961,11 +36841,11 @@ function codexInstallationRoots(binding) {
35961
36841
  });
35962
36842
  }
35963
36843
  function assertMarketplaceBinding(binding, source) {
35964
- if (source.hashMode === "claude-plugin-manifest-v1" && (binding.agent !== "claude" || basename9(source.path) !== "plugin.json" || !source.path.endsWith(join28(sep8, ".claude-plugin", "plugin.json"))))
36844
+ if (source.hashMode === "claude-plugin-manifest-v1" && (binding.agent !== "claude" || basename9(source.path) !== "plugin.json" || !source.path.endsWith(join29(sep9, ".claude-plugin", "plugin.json"))))
35965
36845
  throw new Error("Claude plugin manifest witnesses require Claude plugin discovery");
35966
36846
  if (source.hashMode === "sumi-settings-v1" && (binding.agent !== "sumi" || binding.method !== "reviewed" || basename9(source.path) !== "sumi.json"))
35967
36847
  throw new Error("Sumi settings witnesses require explicit reviewed Sumi configuration");
35968
- if ((source.hashMode === "codex-settings-v1" || source.hashMode === "codex-settings-v2" || (source.hashMode === "codex-settings-v3" || source.hashMode === "codex-settings-v4")) && (binding.agent !== "codex" || binding.method !== "reviewed" || basename9(source.path) !== "config.toml"))
36848
+ if ((source.hashMode === "codex-settings-v1" || source.hashMode === "codex-settings-v2" || (source.hashMode === "codex-settings-v3" || source.hashMode === "codex-settings-v4" || source.hashMode === "codex-settings-v5")) && (binding.agent !== "codex" || binding.method !== "reviewed" || basename9(source.path) !== "config.toml"))
35969
36849
  throw new Error("Codex settings witnesses require explicit reviewed Codex configuration");
35970
36850
  if ((source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || (source.hashMode === "claude-settings-v3" || source.hashMode === "claude-settings-v4")) && (binding.agent !== "claude" || binding.method !== "reviewed" || basename9(source.path) !== "settings.json"))
35971
36851
  throw new Error("Claude settings witnesses require explicit reviewed Claude configuration");
@@ -35977,13 +36857,13 @@ function assertMarketplaceBinding(binding, source) {
35977
36857
  function agentDiscoveryConfigPath(home, agent) {
35978
36858
  if (agent === "sumi")
35979
36859
  return sumiConfigPath(home);
35980
- return join28(home, agent === "hermes" ? ".hermes/config.yaml" : agent === "opencode" ? ".config/opencode/opencode.json" : `.${agent}/${agent === "codex" ? "config.toml" : agent === "cursor" ? "hooks.json" : "settings.json"}`);
36860
+ return join29(home, agent === "hermes" ? ".hermes/config.yaml" : agent === "opencode" ? ".config/opencode/opencode.json" : `.${agent}/${agent === "codex" ? "config.toml" : agent === "cursor" ? "hooks.json" : "settings.json"}`);
35981
36861
  }
35982
36862
  function resolveAgentDiscovery(options) {
35983
- const canonical8 = options.canonical ?? resolve19, home = resolve19(options.home), agent = options.agent;
36863
+ const canonical9 = options.canonical ?? resolve20, home = resolve20(options.home), agent = options.agent;
35984
36864
  const sources = [], roots = new Set, builtinNames = [];
35985
36865
  const witness = (path, format, fields2, hashMode) => {
35986
- const source = { path: canonical8(path), sha256: null, ...format ? { format, fields: fields2 } : {}, ...hashMode ? { hashMode } : {} };
36866
+ const source = { path: canonical9(path), sha256: null, ...format ? { format, fields: fields2 } : {}, ...hashMode ? { hashMode } : {} };
35987
36867
  source.sha256 = projected(source);
35988
36868
  sources.push(source);
35989
36869
  return read(source.path);
@@ -36001,42 +36881,42 @@ function resolveAgentDiscovery(options) {
36001
36881
  const review = options.reviewed?.agents.find((item) => item.agent === agent);
36002
36882
  if (agent === "sumi") {
36003
36883
  const directory = sumiConfigDirectory(home);
36004
- if (witness(join28(directory, "sumi.jsonc")) !== null)
36884
+ if (witness(join29(directory, "sumi.jsonc")) !== null)
36005
36885
  unresolved("JSONC configuration requires a supported format adapter");
36006
- for (const root of [directory, join28(home, ".claude"), join28(home, ".agents")])
36886
+ for (const root of [directory, join29(home, ".claude"), join29(home, ".agents")])
36007
36887
  for (const name of ["skill", "skills"])
36008
- roots.add(canonical8(join28(root, name)));
36888
+ roots.add(canonical9(join29(root, name)));
36009
36889
  if (config2.skills !== undefined && (!Array.isArray(config2.skills) || config2.skills.some((path) => typeof path !== "string")))
36010
36890
  unresolved("skills must be a string array");
36011
36891
  for (const value of config2.skills ?? []) {
36012
- if (typeof value !== "string" || /[\0$]/.test(value) || !value || !(isAbsolute18(value) || value.startsWith("~/")))
36892
+ if (typeof value !== "string" || /[\0$]/.test(value) || !value || !(isAbsolute19(value) || value.startsWith("~/")))
36013
36893
  unresolved("remote or relative skill sources need a dedicated discovery adapter");
36014
- roots.add(canonical8(value.startsWith("~/") ? join28(home, value.slice(2)) : value));
36894
+ roots.add(canonical9(value.startsWith("~/") ? join29(home, value.slice(2)) : value));
36015
36895
  }
36016
36896
  for (const key of ["plugin", "plugins"])
36017
36897
  if (config2[key] !== undefined && !Array.isArray(config2[key]))
36018
36898
  unresolved(`${key} must be an array`);
36019
- const plugins = [join28(directory, "plugin"), join28(directory, "plugins")];
36899
+ const plugins = [join29(directory, "plugin"), join29(directory, "plugins")];
36020
36900
  for (const path of plugins) {
36021
36901
  safe5(path);
36022
- if (lstatSync20(path, { throwIfNoEntry: false })?.isDirectory())
36023
- for (const name of readdirSync7(path).sort()) {
36902
+ if (lstatSync21(path, { throwIfNoEntry: false })?.isDirectory())
36903
+ for (const name of readdirSync8(path).sort()) {
36024
36904
  if (name === "skills-cli.js" && path === plugins[1])
36025
36905
  continue;
36026
- const target = join28(path, name);
36027
- if (!lstatSync20(target).isFile())
36906
+ const target = join29(path, name);
36907
+ if (!lstatSync21(target).isFile())
36028
36908
  unresolved("local plugin packages need a dedicated discovery adapter");
36029
36909
  witness(target);
36030
36910
  }
36031
36911
  }
36032
36912
  for (const root of roots) {
36033
36913
  safe5(root);
36034
- if (lstatSync20(root, { throwIfNoEntry: false })?.isDirectory() && readdirSync7(root).some((name) => name.endsWith(".md")))
36914
+ if (lstatSync21(root, { throwIfNoEntry: false })?.isDirectory() && readdirSync8(root).some((name) => name.endsWith(".md")))
36035
36915
  unresolved("flat markdown skills require a dedicated native migration adapter");
36036
36916
  }
36037
36917
  }
36038
36918
  if (agent === "hermes") {
36039
- const profile = witness(join28(home, ".hermes/active_profile"));
36919
+ const profile = witness(join29(home, ".hermes/active_profile"));
36040
36920
  if (profile?.trim() && profile.trim() !== "default")
36041
36921
  unresolved("a non-default profile is active");
36042
36922
  const declared = config2.skills?.external_dirs ?? [], paths = typeof declared === "string" ? [declared] : declared;
@@ -36050,7 +36930,7 @@ function resolveAgentDiscovery(options) {
36050
36930
  continue;
36051
36931
  if (normalized.startsWith("~") && normalized !== "~" && !normalized.startsWith("~/"))
36052
36932
  unresolved("user-specific tilde expansion requires a separate discovery adapter");
36053
- const path = normalized === "~" ? home : normalized.startsWith("~/") ? join28(home, normalized.slice(2)) : resolve19(home, ".hermes", normalized);
36933
+ const path = normalized === "~" ? home : normalized.startsWith("~/") ? join29(home, normalized.slice(2)) : resolve20(home, ".hermes", normalized);
36054
36934
  safe5(path);
36055
36935
  roots.add(path);
36056
36936
  }
@@ -36059,24 +36939,24 @@ function resolveAgentDiscovery(options) {
36059
36939
  const executable = options.executable === undefined ? discoveryExecutable(agent) : options.executable;
36060
36940
  if (executable) {
36061
36941
  let packageRoot;
36062
- for (let directory = dirname18(executable.target), depth = 0;depth < 8; directory = dirname18(directory), depth++) {
36063
- const path = join28(directory, "package.json"), raw = read(path);
36942
+ for (let directory = dirname19(executable.target), depth = 0;depth < 8; directory = dirname19(directory), depth++) {
36943
+ const path = join29(directory, "package.json"), raw = read(path);
36064
36944
  if (raw !== null && parseConfig(raw, path).name === "@google/gemini-cli") {
36065
36945
  packageRoot = directory;
36066
36946
  witness(path);
36067
36947
  break;
36068
36948
  }
36069
- if (dirname18(directory) === directory)
36949
+ if (dirname19(directory) === directory)
36070
36950
  break;
36071
36951
  }
36072
36952
  if (!packageRoot)
36073
36953
  unresolved("installed Gemini package layout is not recognized");
36074
- const builtinRoot = join28(packageRoot, "bundle/builtin");
36954
+ const builtinRoot = join29(packageRoot, "bundle/builtin");
36075
36955
  safe5(builtinRoot);
36076
- if (!lstatSync20(builtinRoot, { throwIfNoEntry: false })?.isDirectory())
36956
+ if (!lstatSync21(builtinRoot, { throwIfNoEntry: false })?.isDirectory())
36077
36957
  unresolved("installed Gemini builtin root is missing");
36078
- for (const name of readdirSync7(builtinRoot).sort()) {
36079
- const text2 = witness(join28(builtinRoot, name, "SKILL.md"));
36958
+ for (const name of readdirSync8(builtinRoot).sort()) {
36959
+ const text2 = witness(join29(builtinRoot, name, "SKILL.md"));
36080
36960
  const match = text2?.match(/^---\r?\n[\s\S]*?^name:\s*([a-z0-9][a-z0-9-]*)\s*$/m);
36081
36961
  if (!match?.[1] || builtinNames.includes(match[1]))
36082
36962
  unresolved("installed Gemini builtin name is missing or ambiguous");
@@ -36089,11 +36969,16 @@ function resolveAgentDiscovery(options) {
36089
36969
  if (retained.agent !== agent || retained.method !== "reviewed")
36090
36970
  unresolved("invalid retained review");
36091
36971
  verifyAgentDiscovery(retained);
36092
- if (!retained.sources.some((source) => source.path === canonical8(configPath) && source.format === undefined && source.fields === undefined))
36972
+ if (!retained.sources.some((source) => source.path === canonical9(configPath) && source.format === undefined && source.fields === undefined))
36093
36973
  unresolved("retained review is missing the full agent configuration source");
36094
- if (retained.sources.some((source) => (source.hashMode === "sumi-settings-v1" || source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || (source.hashMode === "claude-settings-v3" || source.hashMode === "claude-settings-v4" || (source.hashMode === "codex-settings-v1" || source.hashMode === "codex-settings-v2" || (source.hashMode === "codex-settings-v3" || source.hashMode === "codex-settings-v4")))) && source.path !== canonical8(configPath)))
36974
+ if (retained.sources.some((source) => (source.hashMode === "sumi-settings-v1" || source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || (source.hashMode === "claude-settings-v3" || source.hashMode === "claude-settings-v4" || (source.hashMode === "codex-settings-v1" || source.hashMode === "codex-settings-v2" || (source.hashMode === "codex-settings-v3" || source.hashMode === "codex-settings-v4" || source.hashMode === "codex-settings-v5")))) && source.path !== canonical9(configPath)))
36095
36975
  unresolved("retained settings witness names another configuration source");
36096
- const covered = supersedesSettingsProjection(agent, retained.sources, canonical8(configPath)) ? sources.filter((source) => !isSupersededSettingsProjection(agent, canonical8(configPath), source)) : sources;
36976
+ let covered = supersedesSettingsProjection(agent, retained.sources, canonical9(configPath)) ? sources.filter((source) => !isSupersededSettingsProjection(agent, canonical9(configPath), source)) : sources;
36977
+ if (retained.codexSemanticCache) {
36978
+ const proof = retained.codexSemanticCache;
36979
+ const parents3 = [...new Set([...(retained.codexDisabledPluginSkills ?? []).map((control) => control.pluginParent), ...proof.appOnlyParents.map((parent) => parent.pluginParent)])];
36980
+ covered = covered.filter((source) => !codexSemanticCacheSourceRole(source, proof.witness.cacheRoot, parents3));
36981
+ }
36097
36982
  if (covered.some((source) => !retained.sources.some((saved) => isDeepStrictEqual4(saved, source))) || [...roots].some((root) => !retained.roots.includes(root)) || agent === "gemini" && JSON.stringify(retained.builtinNames) !== JSON.stringify(builtinNames))
36098
36983
  unresolved("retained review is missing current runtime discovery coverage");
36099
36984
  return retained;
@@ -36105,16 +36990,16 @@ function resolveAgentDiscovery(options) {
36105
36990
  if (review.sources.some((source) => source.format !== undefined || source.fields !== undefined))
36106
36991
  throw new Error("Explicit discovery reviews require full source-file hashes");
36107
36992
  verifyAgentDiscovery(supplied);
36108
- if (review.sources.some((source) => (source.hashMode === "sumi-settings-v1" || source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || (source.hashMode === "claude-settings-v3" || source.hashMode === "claude-settings-v4" || (source.hashMode === "codex-settings-v1" || source.hashMode === "codex-settings-v2" || (source.hashMode === "codex-settings-v3" || source.hashMode === "codex-settings-v4")))) && source.path !== canonical8(configPath)))
36993
+ if (review.sources.some((source) => (source.hashMode === "sumi-settings-v1" || source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || (source.hashMode === "claude-settings-v3" || source.hashMode === "claude-settings-v4" || (source.hashMode === "codex-settings-v1" || source.hashMode === "codex-settings-v2" || (source.hashMode === "codex-settings-v3" || source.hashMode === "codex-settings-v4" || source.hashMode === "codex-settings-v5")))) && source.path !== canonical9(configPath)))
36109
36994
  throw new Error("Semantic settings witnesses must name the configured agent configuration source");
36110
- if (!review.sources.some((source) => source.path === canonical8(configPath)))
36995
+ if (!review.sources.some((source) => source.path === canonical9(configPath)))
36111
36996
  throw new Error("Discovery review must include the agent configuration source");
36112
- const reviewedSources = supersedesSettingsProjection(agent, review.sources, canonical8(configPath)) ? sources.filter((source) => !isSupersededSettingsProjection(agent, canonical8(configPath), source)) : sources;
36997
+ const reviewedSources = supersedesSettingsProjection(agent, review.sources, canonical9(configPath)) ? sources.filter((source) => !isSupersededSettingsProjection(agent, canonical9(configPath), source)) : sources;
36113
36998
  const reviewedSourcesWithManifestProjection = review.sources.map((source) => {
36114
- if (agent !== "claude" || source.sha256 === null || source.format !== undefined || source.fields !== undefined || source.managedPlugins !== undefined || source.hashMode !== undefined && source.hashMode !== "bytes" || basename9(source.path) !== "plugin.json" || !source.path.endsWith(join28(sep8, ".claude-plugin", "plugin.json")))
36999
+ if (agent !== "claude" || source.sha256 === null || source.format !== undefined || source.fields !== undefined || source.managedPlugins !== undefined || source.hashMode !== undefined && source.hashMode !== "bytes" || basename9(source.path) !== "plugin.json" || !source.path.endsWith(join29(sep9, ".claude-plugin", "plugin.json")))
36115
37000
  return source;
36116
- const pluginRoot = dirname18(dirname18(source.path)), hooksPath = join28(pluginRoot, "hooks/hooks.json");
36117
- const hookStat = lstatSync20(hooksPath, { throwIfNoEntry: false });
37001
+ const pluginRoot = dirname19(dirname19(source.path)), hooksPath = join29(pluginRoot, "hooks/hooks.json");
37002
+ const hookStat = lstatSync21(hooksPath, { throwIfNoEntry: false });
36118
37003
  const text2 = read(source.path);
36119
37004
  if (text2 === null)
36120
37005
  throw new Error("Reviewed Claude plugin manifest is missing");
@@ -36128,58 +37013,58 @@ function resolveAgentDiscovery(options) {
36128
37013
  if (manifest.hooks !== undefined) {
36129
37014
  if (typeof manifest.hooks !== "string")
36130
37015
  throw new Error("Reviewed Claude plugin manifest has an unsupported hooks target");
36131
- const declaredHookPath = resolve19(pluginRoot, manifest.hooks);
36132
- if (!declaredHookPath.startsWith(pluginRoot + sep8))
37016
+ const declaredHookPath = resolve20(pluginRoot, manifest.hooks);
37017
+ if (!declaredHookPath.startsWith(pluginRoot + sep9))
36133
37018
  throw new Error("Reviewed Claude plugin hooks target escapes its root");
36134
37019
  reviewedHookPaths.add(declaredHookPath);
36135
37020
  }
36136
37021
  for (const hooksFile of reviewedHookPaths)
36137
- if (!review.sources.some((hook) => hook.path === canonical8(hooksFile) && hook.sha256 !== null && hook.format === undefined && hook.fields === undefined && hook.managedPlugins === undefined && (hook.hashMode === undefined || hook.hashMode === "bytes")))
37022
+ if (!review.sources.some((hook) => hook.path === canonical9(hooksFile) && hook.sha256 !== null && hook.format === undefined && hook.fields === undefined && hook.managedPlugins === undefined && (hook.hashMode === undefined || hook.hashMode === "bytes")))
36138
37023
  throw new Error("Reviewed Claude plugin manifest requires separately reviewed exact hook file sources");
36139
37024
  return { path: source.path, sha256: manifestSha256, hashMode: "claude-plugin-manifest-v1" };
36140
37025
  });
36141
37026
  if (agent === "claude")
36142
- assertReviewedClaudeCacheClosures(home, config2, review, canonical8);
37027
+ assertReviewedClaudeCacheClosures(home, config2, review, canonical9);
36143
37028
  const combined = [...reviewedSources, ...reviewedSourcesWithManifestProjection];
36144
37029
  const unique = combined.filter((source, index) => combined.findIndex((candidate) => isDeepStrictEqual4(candidate, source)) === index);
36145
37030
  return { ...supplied, roots: [...new Set([...roots, ...supplied.roots])].sort(), sources: unique, ...agent === "gemini" ? { builtinNames } : {} };
36146
37031
  }
36147
37032
  function plugin(root) {
36148
- root = canonical8(root);
37033
+ root = canonical9(root);
36149
37034
  safe5(root);
36150
- const manifestPath = join28(root, agent === "claude" ? ".claude-plugin/plugin.json" : ".codex-plugin/plugin.json");
37035
+ const manifestPath = join29(root, agent === "claude" ? ".claude-plugin/plugin.json" : ".codex-plugin/plugin.json");
36151
37036
  const raw = witness(manifestPath, undefined, undefined, agent === "claude" ? "claude-plugin-manifest-v1" : undefined);
36152
37037
  if (raw === null)
36153
37038
  unresolved("plugin manifest missing");
36154
37039
  const manifest = parseConfig(raw, manifestPath);
36155
- const hooks = witness(join28(root, "hooks/hooks.json"));
37040
+ const hooks = witness(join29(root, "hooks/hooks.json"));
36156
37041
  if (manifest.hooks !== undefined || hooks !== null)
36157
37042
  unresolved("plugin hooks require a separate no-skill-injection review");
36158
- const commands = join28(root, "commands");
37043
+ const commands = join29(root, "commands");
36159
37044
  safe5(commands);
36160
- if (agent === "claude" && (manifest.commands !== undefined || lstatSync20(commands, { throwIfNoEntry: false })?.isDirectory() && readdirSync7(commands).length))
37045
+ if (agent === "claude" && (manifest.commands !== undefined || lstatSync21(commands, { throwIfNoEntry: false })?.isDirectory() && readdirSync8(commands).length))
36161
37046
  unresolved("legacy command discovery requires retirement or a dedicated format adapter");
36162
- const rootSkill = witness(join28(root, "SKILL.md"));
37047
+ const rootSkill = witness(join29(root, "SKILL.md"));
36163
37048
  if (rootSkill !== null)
36164
37049
  roots.add(root);
36165
37050
  const declared = manifest.skills === undefined ? ["./skills"] : typeof manifest.skills === "string" ? [manifest.skills] : manifest.skills;
36166
37051
  if (!Array.isArray(declared) || declared.some((path) => typeof path !== "string"))
36167
37052
  unresolved("unsupported plugin skill paths");
36168
37053
  if (agent === "claude")
36169
- roots.add(join28(root, "skills"));
37054
+ roots.add(join29(root, "skills"));
36170
37055
  for (const value of declared) {
36171
- const path = resolve19(root, value);
36172
- if (path !== root && !path.startsWith(root + sep8))
37056
+ const path = resolve20(root, value);
37057
+ if (path !== root && !path.startsWith(root + sep9))
36173
37058
  unresolved("plugin skill path escapes its root");
36174
- roots.add(path.endsWith(`${sep8}SKILL.md`) ? dirname18(path) : path);
37059
+ roots.add(path.endsWith(`${sep9}SKILL.md`) ? dirname19(path) : path);
36175
37060
  }
36176
37061
  }
36177
37062
  if (agent === "claude") {
36178
- const registrations = witness(join28(home, ".claude/plugins/installed_plugins.json"));
36179
- const installed = registrations === null ? {} : parseConfig(registrations, join28(home, ".claude/plugins/installed_plugins.json")).plugins;
36180
- const commands = canonical8(join28(home, ".claude/commands"));
37063
+ const registrations = witness(join29(home, ".claude/plugins/installed_plugins.json"));
37064
+ const installed = registrations === null ? {} : parseConfig(registrations, join29(home, ".claude/plugins/installed_plugins.json")).plugins;
37065
+ const commands = canonical9(join29(home, ".claude/commands"));
36181
37066
  safe5(commands);
36182
- if (lstatSync20(commands, { throwIfNoEntry: false })?.isDirectory() && readdirSync7(commands).length)
37067
+ if (lstatSync21(commands, { throwIfNoEntry: false })?.isDirectory() && readdirSync8(commands).length)
36183
37068
  unresolved("legacy home command discovery requires a dedicated format adapter");
36184
37069
  for (const [id, enabled] of Object.entries(config2.enabledPlugins ?? {})) {
36185
37070
  if (enabled === false)
@@ -36199,37 +37084,37 @@ function resolveAgentDiscovery(options) {
36199
37084
  unresolved("unsupported plugin enablement");
36200
37085
  const split = id.lastIndexOf("@"), name = id.slice(0, split), marketplace = id.slice(split + 1);
36201
37086
  const market = config2.marketplaces?.[marketplace] ?? (marketplace === "personal" ? { source_type: "local", source: home } : undefined);
36202
- if (split < 1 || market?.source_type !== "local" || typeof market.source !== "string" || !isAbsolute18(market.source))
37087
+ if (split < 1 || market?.source_type !== "local" || typeof market.source !== "string" || !isAbsolute19(market.source))
36203
37088
  unresolved("enabled plugin marketplace is not an explicit local source");
36204
- const catalogText = witness(join28(market.source, ".agents/plugins/marketplace.json"));
37089
+ const catalogText = witness(join29(market.source, ".agents/plugins/marketplace.json"));
36205
37090
  if (catalogText === null)
36206
37091
  unresolved("marketplace catalog missing");
36207
- const catalog = parseConfig(catalogText, join28(market.source, ".agents/plugins/marketplace.json")), matches = Array.isArray(catalog.plugins) ? catalog.plugins.filter((item) => item.name === name) : [];
37092
+ const catalog = parseConfig(catalogText, join29(market.source, ".agents/plugins/marketplace.json")), matches = Array.isArray(catalog.plugins) ? catalog.plugins.filter((item) => item.name === name) : [];
36208
37093
  if (matches.length !== 1 || matches[0]?.source?.source !== "local" || typeof matches[0]?.source?.path !== "string")
36209
37094
  unresolved("plugin catalog source is missing or ambiguous");
36210
- plugin(resolve19(market.source, matches[0].source.path));
37095
+ plugin(resolve20(market.source, matches[0].source.path));
36211
37096
  }
36212
37097
  } else if (agent === "opencode") {
36213
- if (witness(join28(home, ".config/opencode/opencode.jsonc")) !== null || witness(join28(home, ".config/opencode/config.json")) !== null)
37098
+ if (witness(join29(home, ".config/opencode/opencode.jsonc")) !== null || witness(join29(home, ".config/opencode/config.json")) !== null)
36214
37099
  unresolved("additional config layers require review");
36215
37100
  if ((config2.plugin?.length ?? 0) > 0 || config2.skills?.urls?.length)
36216
37101
  unresolved("external plugin or remote skill source");
36217
37102
  for (const path of config2.skills?.paths ?? []) {
36218
- if (typeof path !== "string" || !isAbsolute18(path))
37103
+ if (typeof path !== "string" || !isAbsolute19(path))
36219
37104
  unresolved("relative or malformed added skill root");
36220
37105
  roots.add(path);
36221
37106
  }
36222
- const localPlugins = join28(home, ".config/opencode/plugins");
37107
+ const localPlugins = join29(home, ".config/opencode/plugins");
36223
37108
  safe5(localPlugins);
36224
- if (lstatSync20(localPlugins, { throwIfNoEntry: false }) && readdirSync7(localPlugins).some((name) => name !== "skills-cli.js"))
37109
+ if (lstatSync21(localPlugins, { throwIfNoEntry: false }) && readdirSync8(localPlugins).some((name) => name !== "skills-cli.js"))
36225
37110
  unresolved("additional local plugin hooks require review");
36226
37111
  } else if (agent === "sumi") {
36227
- if ((config2.plugin?.length ?? 0) > 0 || (config2.plugins?.length ?? 0) > 0 || sources.some((source) => source.path !== canonical8(configPath) && source.path !== canonical8(join28(sumiConfigDirectory(home), "sumi.jsonc")) && source.sha256 !== null))
37112
+ if ((config2.plugin?.length ?? 0) > 0 || (config2.plugins?.length ?? 0) > 0 || sources.some((source) => source.path !== canonical9(configPath) && source.path !== canonical9(join29(sumiConfigDirectory(home), "sumi.jsonc")) && source.sha256 !== null))
36228
37113
  unresolved("external or foreign local plugins require review");
36229
37114
  } else if (agent === "hermes") {
36230
- for (const directory of [join28(home, ".hermes/plugins"), join28(home, ".hermes/hermes-agent")]) {
37115
+ for (const directory of [join29(home, ".hermes/plugins"), join29(home, ".hermes/hermes-agent")]) {
36231
37116
  safe5(directory);
36232
- if (lstatSync20(directory, { throwIfNoEntry: false }))
37117
+ if (lstatSync21(directory, { throwIfNoEntry: false }))
36233
37118
  unresolved("installed runtime/plugin discovery requires reviewed source bindings");
36234
37119
  }
36235
37120
  if (Bun.which("hermes") || Object.keys(config2.plugins ?? {}).length)
@@ -36237,32 +37122,32 @@ function resolveAgentDiscovery(options) {
36237
37122
  } else if (agent === "gemini") {
36238
37123
  if (Object.keys(config2.extensions ?? {}).length || config2.skills?.paths?.length)
36239
37124
  unresolved("custom extension or skill paths");
36240
- const directory = join28(home, ".gemini/extensions");
37125
+ const directory = join29(home, ".gemini/extensions");
36241
37126
  safe5(directory);
36242
- if (lstatSync20(directory, { throwIfNoEntry: false }))
36243
- for (const name of readdirSync7(directory)) {
36244
- const root = join28(directory, name);
37127
+ if (lstatSync21(directory, { throwIfNoEntry: false }))
37128
+ for (const name of readdirSync8(directory)) {
37129
+ const root = join29(directory, name);
36245
37130
  safe5(root);
36246
- if (!lstatSync20(root)?.isDirectory())
37131
+ if (!lstatSync21(root)?.isDirectory())
36247
37132
  continue;
36248
- const raw = witness(join28(root, "gemini-extension.json"));
37133
+ const raw = witness(join29(root, "gemini-extension.json"));
36249
37134
  if (raw === null)
36250
37135
  unresolved("extension registration missing");
36251
- const manifest = parseConfig(raw, join28(root, "gemini-extension.json"));
36252
- if (manifest.hooks !== undefined || witness(join28(root, "hooks/hooks.json")) !== null || witness(join28(root, ".gemini-extension-install.json")) !== null)
37136
+ const manifest = parseConfig(raw, join29(root, "gemini-extension.json"));
37137
+ if (manifest.hooks !== undefined || witness(join29(root, "hooks/hooks.json")) !== null || witness(join29(root, ".gemini-extension-install.json")) !== null)
36253
37138
  unresolved("extension hooks or linked registration require review");
36254
- roots.add(join28(root, "skills"));
37139
+ roots.add(join29(root, "skills"));
36255
37140
  }
36256
37141
  }
36257
- 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) => canonical8(path))) } : {} };
37142
+ return { agent, roots: [...roots].sort(), sources, method: "automatic", ...agent === "gemini" ? { builtinNames } : {}, ...agent === "hermes" ? { directories: captureDiscoveryDirectories([join29(home, ".hermes/plugins"), join29(home, ".hermes/hermes-agent")].map((path) => canonical9(path))) } : {} };
36258
37143
  }
36259
37144
  var DISCOVERY_RUNTIME_COMMANDS, realpathOrNull = (path) => {
36260
37145
  try {
36261
- return realpathSync6(path);
37146
+ return realpathSync8(path);
36262
37147
  } catch {
36263
37148
  return null;
36264
37149
  }
36265
- }, digest = (text2) => createHash20("sha256").update(text2).digest("hex");
37150
+ }, digest2 = (text2) => createHash21("sha256").update(text2).digest("hex");
36266
37151
  var init_agent_discovery = __esm(() => {
36267
37152
  init_sumi_settings_witness();
36268
37153
  init_agent_policy_limits();
@@ -36283,16 +37168,17 @@ var init_agent_discovery = __esm(() => {
36283
37168
  init_native_discovery_roots();
36284
37169
  init_codex_native_compatibility();
36285
37170
  init_retained_review_artifacts();
37171
+ init_codex_semantic_cache_witness();
36286
37172
  init_agent_discovery_directories();
36287
37173
  DISCOVERY_RUNTIME_COMMANDS = Object.freeze({ gemini: "gemini" });
36288
37174
  });
36289
37175
 
36290
37176
  // src/lib/authoring-path.ts
36291
- import { lstatSync as lstatSync21, realpathSync as realpathSync7 } from "fs";
37177
+ import { lstatSync as lstatSync22, realpathSync as realpathSync9 } from "fs";
36292
37178
  import { homedir as homedir3 } from "os";
36293
- import { basename as basename10, dirname as dirname19, join as join29, resolve as resolve20, sep as sep9 } from "path";
37179
+ import { basename as basename10, dirname as dirname20, join as join30, resolve as resolve21, sep as sep10 } from "path";
36294
37180
  function pathParts(path) {
36295
- return resolve20(path).split(sep9).filter(Boolean);
37181
+ return resolve21(path).split(sep10).filter(Boolean);
36296
37182
  }
36297
37183
  function nativeRootMatch(path) {
36298
37184
  const parts = pathParts(path);
@@ -36306,24 +37192,24 @@ function nativeRootMatch(path) {
36306
37192
  return;
36307
37193
  }
36308
37194
  function physicalPath(path) {
36309
- let cursor = resolve20(path);
37195
+ let cursor = resolve21(path);
36310
37196
  const suffix = [];
36311
- while (!lstatSync21(cursor, { throwIfNoEntry: false })) {
37197
+ while (!lstatSync22(cursor, { throwIfNoEntry: false })) {
36312
37198
  suffix.unshift(basename10(cursor));
36313
- const parent = dirname19(cursor);
37199
+ const parent = dirname20(cursor);
36314
37200
  if (parent === cursor)
36315
- return resolve20(path);
37201
+ return resolve21(path);
36316
37202
  cursor = parent;
36317
37203
  }
36318
- return resolve20(realpathSync7(cursor), ...suffix);
37204
+ return resolve21(realpathSync9(cursor), ...suffix);
36319
37205
  }
36320
37206
  function contains(root, path) {
36321
- return path === root || path.startsWith(root + sep9);
37207
+ return path === root || path.startsWith(root + sep10);
36322
37208
  }
36323
37209
  function configuredRoots(home, explicitHome) {
36324
- const homeData = join29(home, ".hasna", "skills");
37210
+ const homeData = join30(home, ".hasna", "skills");
36325
37211
  const homePolicy = readManagedSkillPolicySnapshot(homeData);
36326
- const configuredPolicy = !explicitHome && resolve20(getDataDirReadOnly()) !== resolve20(homeData) ? readManagedSkillPolicySnapshot(getDataDirReadOnly()) : null;
37212
+ const configuredPolicy = !explicitHome && resolve21(getDataDirReadOnly()) !== resolve21(homeData) ? readManagedSkillPolicySnapshot(getDataDirReadOnly()) : null;
36327
37213
  const policy = homePolicy ?? configuredPolicy;
36328
37214
  const bridge = policy?.value.bridge;
36329
37215
  if (bridge && (typeof bridge.home !== "string" || physicalPath(bridge.home) !== physicalPath(home))) {
@@ -36352,8 +37238,8 @@ function configuredRoots(home, explicitHome) {
36352
37238
  admitBinding(binding);
36353
37239
  continue;
36354
37240
  }
36355
- const nativeHome = join29(home, agent === "opencode" ? ".config/opencode" : `.${agent}`);
36356
- if (!lstatSync21(nativeHome, { throwIfNoEntry: false }))
37241
+ const nativeHome = join30(home, agent === "opencode" ? ".config/opencode" : `.${agent}`);
37242
+ if (!lstatSync22(nativeHome, { throwIfNoEntry: false }))
36357
37243
  continue;
36358
37244
  roots.push(...resolveAgentDiscovery({ home, agent, canonical: physicalPath }).roots);
36359
37245
  }
@@ -36362,22 +37248,22 @@ function configuredRoots(home, explicitHome) {
36362
37248
  function assertPortableAuthoringPath(path, options = {}) {
36363
37249
  if (typeof path !== "string" || !path || path.includes("\x00"))
36364
37250
  throw new Error("Invalid portable authoring path");
36365
- const lexical = resolve20(path);
37251
+ const lexical = resolve21(path);
36366
37252
  const physical = physicalPath(lexical);
36367
37253
  const candidates = [lexical, physical];
36368
37254
  let native = candidates.map(nativeRootMatch).find(Boolean);
36369
- const home = resolve20(options.homeDir ?? homedir3());
36370
- const defaults = NATIVE_DISCOVERY_ROOTS.map((parts) => join29(home, ...parts));
36371
- defaults.push(join29(home, ".codex/plugins/cache"), join29(home, ".claude/plugins/cache"), join29(home, ".claude/plugins/synced"), join29(home, ".gemini/extensions"));
37255
+ const home = resolve21(options.homeDir ?? homedir3());
37256
+ const defaults = NATIVE_DISCOVERY_ROOTS.map((parts) => join30(home, ...parts));
37257
+ defaults.push(join30(home, ".codex/plugins/cache"), join30(home, ".claude/plugins/cache"), join30(home, ".claude/plugins/synced"), join30(home, ".gemini/extensions"));
36372
37258
  for (const root of defaults) {
36373
- if (candidates.some((candidate) => contains(resolve20(root), candidate) || contains(physicalPath(root), candidate)))
37259
+ if (candidates.some((candidate) => contains(resolve21(root), candidate) || contains(physicalPath(root), candidate)))
36374
37260
  native ??= root;
36375
37261
  }
36376
37262
  if (native) {
36377
37263
  throw new Error(`Refusing portable Skills authoring below native discovery root '${native}': ${lexical}. Set HASNA_SKILLS_DIR to a private authoring corpus outside native roots.`);
36378
37264
  }
36379
37265
  for (const root of configuredRoots(home, options.homeDir !== undefined)) {
36380
- if (candidates.some((candidate) => contains(resolve20(root), candidate) || contains(physicalPath(root), candidate))) {
37266
+ if (candidates.some((candidate) => contains(resolve21(root), candidate) || contains(physicalPath(root), candidate))) {
36381
37267
  throw new Error(`Refusing portable Skills authoring below configured native discovery root: ${lexical}`);
36382
37268
  }
36383
37269
  }
@@ -36397,29 +37283,29 @@ import {
36397
37283
  existsSync as existsSync12,
36398
37284
  mkdirSync as mkdirSync8,
36399
37285
  mkdtempSync,
36400
- readdirSync as readdirSync8,
36401
- realpathSync as realpathSync8,
37286
+ readdirSync as readdirSync9,
37287
+ realpathSync as realpathSync10,
36402
37288
  renameSync as renameSync3,
36403
37289
  rmSync as rmSync3,
36404
37290
  statSync as statSync8,
36405
37291
  writeFileSync as writeFileSync6
36406
37292
  } from "fs";
36407
- import { basename as basename11, dirname as dirname20, isAbsolute as isAbsolute19, join as join30, normalize as normalize4, relative as relative6, resolve as resolve21, sep as sep10 } from "path";
37293
+ import { basename as basename11, dirname as dirname21, isAbsolute as isAbsolute20, join as join31, normalize as normalize4, relative as relative8, resolve as resolve22, sep as sep11 } from "path";
36408
37294
  function getPortableSkillsRoot(options = {}) {
36409
37295
  return resolvePortableSkillsRoot(options, true);
36410
37296
  }
36411
37297
  function resolvePortableSkillsRoot(options, migrate) {
36412
37298
  if (options.rootDir)
36413
37299
  return options.rootDir;
36414
- const appDir = options.homeDir ? join30(options.homeDir, ".hasna", "skills") : migrate ? getDataDir() : getDataDirReadOnly();
36415
- const cache = join30(appDir, SKILLS_CACHE_DIRNAME);
37300
+ const appDir = options.homeDir ? join31(options.homeDir, ".hasna", "skills") : migrate ? getDataDir() : getDataDirReadOnly();
37301
+ const cache = join31(appDir, SKILLS_CACHE_DIRNAME);
36416
37302
  if (isOwnerLayoutMigrated(appDir) && safeIsDirectory(cache))
36417
37303
  return cache;
36418
- const installed = join30(appDir, INSTALLED_SKILLS_DIRNAME);
37304
+ const installed = join31(appDir, INSTALLED_SKILLS_DIRNAME);
36419
37305
  return installed;
36420
37306
  }
36421
37307
  function getPortableSkillPath(name, options = {}) {
36422
- return join30(getPortableSkillsRoot(options), normalizePortableSkillName(name));
37308
+ return join31(getPortableSkillsRoot(options), normalizePortableSkillName(name));
36423
37309
  }
36424
37310
  function findPortableSkill(name, options = {}) {
36425
37311
  let normalized;
@@ -36442,10 +37328,10 @@ function listPortableSkills(options = {}) {
36442
37328
  if (!safeIsDirectory(root))
36443
37329
  return [];
36444
37330
  const skills = [];
36445
- for (const entry of readdirSync8(root).sort()) {
37331
+ for (const entry of readdirSync9(root).sort()) {
36446
37332
  if (entry.startsWith("."))
36447
37333
  continue;
36448
- const path = join30(root, entry);
37334
+ const path = join31(root, entry);
36449
37335
  if (!safeIsDirectory(path))
36450
37336
  continue;
36451
37337
  try {
@@ -36478,9 +37364,9 @@ function isOfficialSkillName(name) {
36478
37364
  function scaffoldPortableSkill(name, options = {}) {
36479
37365
  const skillName = normalizeNewPortableSkillName(name);
36480
37366
  const readOnlyRoot = resolvePortableSkillsRoot(options, false);
36481
- assertPortableAuthoringPath(join30(readOnlyRoot, skillName), options);
37367
+ assertPortableAuthoringPath(join31(readOnlyRoot, skillName), options);
36482
37368
  const root = getPortableSkillsRoot(options);
36483
- const skillPath = join30(root, skillName);
37369
+ const skillPath = join31(root, skillName);
36484
37370
  assertPortableAuthoringPath(skillPath, options);
36485
37371
  if (existsSync12(skillPath)) {
36486
37372
  if (!options.overwrite)
@@ -36499,20 +37385,20 @@ function scaffoldPortableSkill(name, options = {}) {
36499
37385
  return { name: skillName, path: skillPath, manifest, created: true };
36500
37386
  }
36501
37387
  function physicalImportPath(path) {
36502
- let ancestor = resolve21(path);
37388
+ let ancestor = resolve22(path);
36503
37389
  const suffix = [];
36504
37390
  while (!existsSync12(ancestor)) {
36505
37391
  suffix.unshift(basename11(ancestor));
36506
- ancestor = dirname20(ancestor);
37392
+ ancestor = dirname21(ancestor);
36507
37393
  }
36508
- return join30(realpathSync8(ancestor), ...suffix);
37394
+ return join31(realpathSync10(ancestor), ...suffix);
36509
37395
  }
36510
37396
  function assertDisjointImportPaths(source, destination) {
36511
- const sourcePath = realpathSync8(source);
37397
+ const sourcePath = realpathSync10(source);
36512
37398
  const destinationPath = physicalImportPath(destination);
36513
37399
  const contains2 = (parent, child2) => {
36514
- const path = relative6(parent, child2);
36515
- return path === "" || !isAbsolute19(path) && path !== ".." && !path.startsWith(`..${sep10}`);
37400
+ const path = relative8(parent, child2);
37401
+ return path === "" || !isAbsolute20(path) && path !== ".." && !path.startsWith(`..${sep11}`);
36516
37402
  };
36517
37403
  if (contains2(sourcePath, destinationPath) || contains2(destinationPath, sourcePath)) {
36518
37404
  throw new Error("Source and destination skill directories must not overlap");
@@ -36531,11 +37417,11 @@ function portPortableSkill(sourcePath, options = {}) {
36531
37417
  const via = explicitName ? `Name '${skillName}' matches a bundled official skill.` : `Inferred name '${skillName}'${sourceSlug && sourceSlug !== skillName ? ` (from source folder '${basename11(absoluteSource)}')` : ""} matches a bundled official skill.`;
36532
37418
  throw new Error(`${via} Importing it would shadow the official '${skillName}'. ` + `Pass --name to choose a different name, or --allow-shadow to override deliberately.`);
36533
37419
  }
36534
- const readOnlyDestination = join30(resolvePortableSkillsRoot(options, false), skillName);
37420
+ const readOnlyDestination = join31(resolvePortableSkillsRoot(options, false), skillName);
36535
37421
  assertPortableAuthoringPath(readOnlyDestination, options);
36536
37422
  assertDisjointImportPaths(absoluteSource, readOnlyDestination);
36537
37423
  const root = getPortableSkillsRoot(options);
36538
- const destination = join30(root, skillName);
37424
+ const destination = join31(root, skillName);
36539
37425
  assertPortableAuthoringPath(destination, options);
36540
37426
  assertDisjointImportPaths(absoluteSource, destination);
36541
37427
  if (existsSync12(destination)) {
@@ -36543,7 +37429,7 @@ function portPortableSkill(sourcePath, options = {}) {
36543
37429
  throw new Error(`Skill '${skillName}' already exists at ${destination}`);
36544
37430
  rmSync3(destination, { recursive: true, force: true });
36545
37431
  }
36546
- mkdirSync8(dirname20(destination), { recursive: true });
37432
+ mkdirSync8(dirname21(destination), { recursive: true });
36547
37433
  copySkillDirectory(absoluteSource, destination);
36548
37434
  const base = {
36549
37435
  ...inferred,
@@ -36567,8 +37453,8 @@ function validatePortableSkillDirectory(name, skillPath) {
36567
37453
  const warnings = [...base.warnings];
36568
37454
  let manifest;
36569
37455
  if (existsSync12(skillPath)) {
36570
- const skillJsonPath = join30(skillPath, "skill.json");
36571
- const skillMdPath = join30(skillPath, "SKILL.md");
37456
+ const skillJsonPath = join31(skillPath, "skill.json");
37457
+ const skillMdPath = join31(skillPath, "SKILL.md");
36572
37458
  if (!existsSync12(skillJsonPath) && !existsSync12(skillMdPath)) {
36573
37459
  add3(issues, "portable.manifest_missing", "Missing portable manifest: expected SKILL.md frontmatter and/or skill.json");
36574
37460
  }
@@ -36588,7 +37474,7 @@ function validatePortableSkillDirectory(name, skillPath) {
36588
37474
  add3(issues, "portable.version_missing", "Portable manifest missing version");
36589
37475
  }
36590
37476
  const contractIssues = validatePortableManifestContract(manifest, {
36591
- strict: existsSync12(join30(skillPath, "skill.json")),
37477
+ strict: existsSync12(join31(skillPath, "skill.json")),
36592
37478
  skillPath
36593
37479
  });
36594
37480
  for (const issue2 of contractIssues)
@@ -36628,7 +37514,7 @@ function validatePortableSkillDirectory(name, skillPath) {
36628
37514
  add3(issues, "portable.command_entry_unsafe", `Command '${command.name}' entry '${command.entry}' must stay inside the skill directory`);
36629
37515
  continue;
36630
37516
  }
36631
- const entryPath = join30(skillPath, command.entry);
37517
+ const entryPath = join31(skillPath, command.entry);
36632
37518
  if (!existsSync12(entryPath))
36633
37519
  add3(issues, "portable.command_entry_missing", `Command '${command.name}' entry '${command.entry}' is missing`);
36634
37520
  else if (statSync8(entryPath).isDirectory())
@@ -36639,7 +37525,7 @@ function validatePortableSkillDirectory(name, skillPath) {
36639
37525
  } catch (error61) {
36640
37526
  add3(issues, "portable.manifest_invalid", error61.message);
36641
37527
  }
36642
- if (manifest?.kind !== "instruction" && !existsSync12(join30(skillPath, "AGENTS.md"))) {
37528
+ if (manifest?.kind !== "instruction" && !existsSync12(join31(skillPath, "AGENTS.md"))) {
36643
37529
  add3(issues, "portable.agents_missing", "Missing AGENTS.md with build-out instructions for coding agents");
36644
37530
  }
36645
37531
  }
@@ -36677,7 +37563,7 @@ function safeIsDirectory(path) {
36677
37563
  }
36678
37564
  }
36679
37565
  function isSafeRelativePath2(value) {
36680
- if (!value.trim() || isAbsolute19(value))
37566
+ if (!value.trim() || isAbsolute20(value))
36681
37567
  return false;
36682
37568
  const normalized = normalize4(value).replace(/\\/g, "/");
36683
37569
  return normalized !== ".." && !normalized.startsWith("../") && !normalized.includes("/../");
@@ -36866,8 +37752,8 @@ var init_search = __esm(() => {
36866
37752
  });
36867
37753
 
36868
37754
  // src/lib/registry.ts
36869
- import { existsSync as existsSync13, readFileSync as readFileSync17, readdirSync as readdirSync9 } from "fs";
36870
- import { join as join31 } from "path";
37755
+ import { existsSync as existsSync13, readFileSync as readFileSync17, readdirSync as readdirSync10 } from "fs";
37756
+ import { join as join32 } from "path";
36871
37757
  function parseSkillMdFrontmatter(content) {
36872
37758
  const match = content.match(/^---\n([\s\S]*?)\n---/);
36873
37759
  if (!match)
@@ -36904,11 +37790,11 @@ function discoverSkillsInDir(dir, source = "custom") {
36904
37790
  return [];
36905
37791
  const result = [];
36906
37792
  try {
36907
- const entries = readdirSync9(dir, { withFileTypes: true });
37793
+ const entries = readdirSync10(dir, { withFileTypes: true });
36908
37794
  for (const entry of entries) {
36909
37795
  if (!entry.isDirectory())
36910
37796
  continue;
36911
- const skillMdPath = join31(dir, entry.name, "SKILL.md");
37797
+ const skillMdPath = join32(dir, entry.name, "SKILL.md");
36912
37798
  if (!existsSync13(skillMdPath))
36913
37799
  continue;
36914
37800
  let content;
@@ -36928,7 +37814,7 @@ function discoverSkillsInDir(dir, source = "custom") {
36928
37814
  category: fm.category || "Development Tools",
36929
37815
  tags: fm.tags || [],
36930
37816
  ...fm.kind ? { kind: fm.kind } : {},
36931
- ...isHostedMetadataSkillDir(join31(dir, entry.name)) ? { serverOwned: true } : {},
37817
+ ...isHostedMetadataSkillDir(join32(dir, entry.name)) ? { serverOwned: true } : {},
36932
37818
  source
36933
37819
  });
36934
37820
  }
@@ -36940,12 +37826,12 @@ function findExtensionSkillPath(name) {
36940
37826
  if (!config2.extensionsDir || !existsSync13(config2.extensionsDir))
36941
37827
  return null;
36942
37828
  try {
36943
- const entries = readdirSync9(config2.extensionsDir, { withFileTypes: true });
37829
+ const entries = readdirSync10(config2.extensionsDir, { withFileTypes: true });
36944
37830
  for (const entry of entries) {
36945
37831
  if (!entry.isDirectory())
36946
37832
  continue;
36947
- const skillDir = join31(config2.extensionsDir, entry.name);
36948
- const skillMdPath = join31(skillDir, "SKILL.md");
37833
+ const skillDir = join32(config2.extensionsDir, entry.name);
37834
+ const skillMdPath = join32(skillDir, "SKILL.md");
36949
37835
  if (!existsSync13(skillMdPath))
36950
37836
  continue;
36951
37837
  let content;
@@ -37362,7 +38248,7 @@ var init_v4 = __esm(() => {
37362
38248
  });
37363
38249
 
37364
38250
  // src/lib/canonical-json.ts
37365
- import { createHash as createHash21 } from "crypto";
38251
+ import { createHash as createHash22 } from "crypto";
37366
38252
  function canonicalJson2(value, maximumBytes = 2 * 1024 * 1024) {
37367
38253
  return canonicalJsonAtDepth(value, maximumBytes, 64);
37368
38254
  }
@@ -37406,7 +38292,7 @@ function canonicalJsonAtDepth(value, maximumBytes, maximumDepth) {
37406
38292
  return visit3(value, 0);
37407
38293
  }
37408
38294
  function canonicalJsonSha256(value, maximumBytes) {
37409
- return createHash21("sha256").update(canonicalJson2(value, maximumBytes)).digest("hex");
38295
+ return createHash22("sha256").update(canonicalJson2(value, maximumBytes)).digest("hex");
37410
38296
  }
37411
38297
  var init_canonical_json = () => {};
37412
38298
 
@@ -37516,14 +38402,14 @@ function requireResult(value) {
37516
38402
  if (!value)
37517
38403
  throw new RemoteRecurringReadError;
37518
38404
  }
37519
- function termsIntegrity(terms, hash3, identity3, own2) {
37520
- requireResult(terms.organizationId === identity3.organization.id && (!own2 || terms.approvedByUserId === identity3.user.id && terms.approvedMembershipId === identity3.user.membershipId));
37521
- requireResult(canonicalJsonSha256(terms) === hash3);
38405
+ function termsIntegrity(terms, hash4, identity4, own2) {
38406
+ requireResult(terms.organizationId === identity4.organization.id && (!own2 || terms.approvedByUserId === identity4.user.id && terms.approvedMembershipId === identity4.user.membershipId));
38407
+ requireResult(canonicalJsonSha256(terms) === hash4);
37522
38408
  requireResult(canonicalJsonSha256({ skill: terms.skill, input: terms.input, args: terms.args, runtime: terms.runtime }) === terms.payloadSha256);
37523
38409
  requireResult(Date.parse(terms.expiresAt) > Date.parse(terms.startsAt));
37524
38410
  }
37525
- function previewIntegrity(value, identity3) {
37526
- termsIntegrity(value.terms, value.termsSha256, identity3, true);
38411
+ function previewIntegrity(value, identity4) {
38412
+ termsIntegrity(value.terms, value.termsSha256, identity4, true);
37527
38413
  requireResult(Date.parse(value.approvalDeadline) > Date.parse(value.quote.quotedAt));
37528
38414
  const anchor2 = Date.parse(value.terms.startsAt), end = Date.parse(value.terms.expiresAt), cadence = value.terms.everyMinutes * 60000;
37529
38415
  requireResult(value.firstDueInstants.every((at, i) => Date.parse(at) === anchor2 + i * cadence && Date.parse(at) < end));
@@ -37531,7 +38417,7 @@ function previewIntegrity(value, identity3) {
37531
38417
  const day = Date.parse(value.firstPeriod.startsAt);
37532
38418
  requireResult(day % 86400000 === 0 && day <= anchor2 && anchor2 < Date.parse(value.firstPeriod.endsAt) && Date.parse(value.firstPeriod.endsAt) === day + 86400000);
37533
38419
  }
37534
- function parseRecurringResult(action, value, input2, identity3) {
38420
+ function parseRecurringResult(action, value, input2, identity4) {
37535
38421
  const wrappers = { preview: 1, draft: 1, activate: 2, list: 3, get: 1, occurrences: 0, revoke: 0 };
37536
38422
  canonicalJsonAtDepth(value, 64 * 1024 * 1024, 64 + wrappers[action]);
37537
38423
  const result = results[action].parse(value);
@@ -37540,7 +38426,7 @@ function parseRecurringResult(action, value, input2, identity3) {
37540
38426
  const row = input2;
37541
38427
  if (action === "preview" || action === "draft") {
37542
38428
  const p = result;
37543
- previewIntegrity(p, identity3);
38429
+ previewIntegrity(p, identity4);
37544
38430
  if (action === "draft")
37545
38431
  requireResult(p.draftId === row.draftId);
37546
38432
  else {
@@ -37559,7 +38445,7 @@ function parseRecurringResult(action, value, input2, identity3) {
37559
38445
  }
37560
38446
  const views = action === "list" ? result.items : action === "get" ? [result] : action === "activate" ? [result.consent] : [];
37561
38447
  for (const view of views) {
37562
- termsIntegrity(view.terms, view.termsSha256, identity3, action === "activate");
38448
+ termsIntegrity(view.terms, view.termsSha256, identity4, action === "activate");
37563
38449
  requireResult(view.state === "revoked" === (view.revokedAt !== null));
37564
38450
  if (action === "get")
37565
38451
  requireResult(view.consentId === row.consentId);
@@ -37585,7 +38471,7 @@ function parseRecurringResult(action, value, input2, identity3) {
37585
38471
  }
37586
38472
  return result;
37587
38473
  }
37588
- var RecurringInputError, RemoteRecurringUnavailableError, RemoteRecurringReadError, RemoteRecurringUnconfirmedError, failures, RemoteRecurringError, uuid3, instant2, integer2, digest2, list, inputs, capabilityNames, budget2, period, preview, consent, refusal2, occurrence, revocation, page = (item) => exports_external.object({ contractVersion: exports_external.literal(1), items: exports_external.array(item).max(100), nextCursor: exports_external.string().min(1).max(2048).nullable() }), results;
38474
+ var RecurringInputError, RemoteRecurringUnavailableError, RemoteRecurringReadError, RemoteRecurringUnconfirmedError, failures, RemoteRecurringError, uuid3, instant2, integer2, digest3, list, inputs, capabilityNames, budget2, period, preview, consent, refusal2, occurrence, revocation, page = (item) => exports_external.object({ contractVersion: exports_external.literal(1), items: exports_external.array(item).max(100), nextCursor: exports_external.string().min(1).max(2048).nullable() }), results;
37589
38475
  var init_remote_recurring = __esm(() => {
37590
38476
  init_v4();
37591
38477
  init_canonical_json();
@@ -37651,7 +38537,7 @@ var init_remote_recurring = __esm(() => {
37651
38537
  uuid3 = exports_external.string().regex(/^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/);
37652
38538
  instant2 = exports_external.string().max(32).datetime();
37653
38539
  integer2 = exports_external.number().int().min(0).max(MAX_RECURRING_CREDITS);
37654
- digest2 = exports_external.string().regex(/^[a-f0-9]{64}$/);
38540
+ digest3 = exports_external.string().regex(/^[a-f0-9]{64}$/);
37655
38541
  list = exports_external.object({ limit: exports_external.number().int().min(1).max(100).optional(), cursor: exports_external.string().min(1).max(2048).optional() }).strict();
37656
38542
  inputs = {
37657
38543
  preview: recurringRequestSchema,
@@ -37677,7 +38563,7 @@ var init_remote_recurring = __esm(() => {
37677
38563
  contractVersion: exports_external.literal(1),
37678
38564
  draftId: uuid3,
37679
38565
  terms: recurringTermsSchema,
37680
- termsSha256: digest2,
38566
+ termsSha256: digest3,
37681
38567
  quote: exports_external.object({ costCredits: integer2, quotedAt: instant2, admissionReprices: exports_external.literal(true) }),
37682
38568
  approvalDeadline: instant2,
37683
38569
  firstDueInstants: exports_external.array(instant2).min(1).max(5),
@@ -37689,7 +38575,7 @@ var init_remote_recurring = __esm(() => {
37689
38575
  consentId: uuid3,
37690
38576
  scheduleId: uuid3,
37691
38577
  terms: recurringTermsSchema,
37692
- termsSha256: digest2,
38578
+ termsSha256: digest3,
37693
38579
  state: exports_external.enum(["active", "revoked", "expired"]),
37694
38580
  activatedAt: instant2,
37695
38581
  revokedAt: instant2.nullable(),
@@ -37943,10 +38829,10 @@ function sessionToken(value) {
37943
38829
  return value;
37944
38830
  }
37945
38831
  function parseWorkspaceSession(value, expected) {
37946
- const identity3 = parseWorkspaceIdentity(value, expected.userId);
37947
- if (identity3.user.membershipId !== expected.membershipId)
38832
+ const identity4 = parseWorkspaceIdentity(value, expected.userId);
38833
+ if (identity4.user.membershipId !== expected.membershipId)
37948
38834
  throw new WorkspaceIdentityMismatchError;
37949
- return { token: sessionToken(value.token), ...identity3 };
38835
+ return { token: sessionToken(value.token), ...identity4 };
37950
38836
  }
37951
38837
  function parseWorkspaceLogin(value, expectedUserId) {
37952
38838
  const user = record5(value) && value.user;
@@ -38157,13 +39043,13 @@ var init_remote_workspace_leave = __esm(() => {
38157
39043
 
38158
39044
  // src/lib/auth-store.ts
38159
39045
  import { chmodSync, existsSync as existsSync14, mkdirSync as mkdirSync9, readFileSync as readFileSync18, renameSync as renameSync4, statSync as statSync9, unlinkSync as unlinkSync4, writeFileSync as writeFileSync7 } from "fs";
38160
- import { basename as basename12, dirname as dirname21, join as join32 } from "path";
39046
+ import { basename as basename12, dirname as dirname22, join as join33 } from "path";
38161
39047
  function getAuthFilePath(env = process.env) {
38162
39048
  return skillsCredentialFilePath(env);
38163
39049
  }
38164
39050
  function getIdentityFilePath(env = process.env) {
38165
39051
  const file2 = skillsCredentialFilePath(env);
38166
- return join32(dirname21(file2), basename12(file2).replace(/^credentials/, "identity") + ".json");
39052
+ return join33(dirname22(file2), basename12(file2).replace(/^credentials/, "identity") + ".json");
38167
39053
  }
38168
39054
  function getApiUrl(action, env = process.env, options = {}) {
38169
39055
  return requireSkillsApiOrigin(action, env, options);
@@ -38391,10 +39277,10 @@ async function readQuoteUnavailableCode(response) {
38391
39277
  let timer;
38392
39278
  let deadlineExceeded = false;
38393
39279
  const expired = Symbol("quote body deadline");
38394
- const deadline = new Promise((resolve22) => {
39280
+ const deadline = new Promise((resolve23) => {
38395
39281
  timer = setTimeout(() => {
38396
39282
  deadlineExceeded = true;
38397
- resolve22(expired);
39283
+ resolve23(expired);
38398
39284
  reader.cancel().catch(() => {});
38399
39285
  }, 1500);
38400
39286
  });
@@ -38697,16 +39583,16 @@ class RemoteSkillsClient {
38697
39583
  async listAccountWorkspaces(expectedUserId) {
38698
39584
  const expected = expectedUserId === undefined ? undefined : workspaceExpectedUserId(expectedUserId);
38699
39585
  const connection = new RemoteSkillsClient(this.apiKey, this.apiUrl);
38700
- let identity3;
39586
+ let identity4;
38701
39587
  if (expected !== undefined) {
38702
39588
  const value = await connection.requestWorkspaceSelection("/api/auth/whoami");
38703
39589
  if (!value || typeof value !== "object" || value.authMethod !== "jwt")
38704
39590
  throw new RemoteWorkspaceSelectionError("/api/v1/account/workspaces", "INTERACTIVE_SESSION_REQUIRED");
38705
- identity3 = parseWorkspaceIdentity(value, expected);
39591
+ identity4 = parseWorkspaceIdentity(value, expected);
38706
39592
  }
38707
39593
  const result = parseAccountWorkspaces(await connection.requestWorkspaceSelection("/api/v1/account/workspaces"));
38708
39594
  const current = result.workspaces.find((workspace) => workspace.current);
38709
- if (identity3 && (current.membershipId !== identity3.user.membershipId || current.organization.id !== identity3.organization.id))
39595
+ if (identity4 && (current.membershipId !== identity4.user.membershipId || current.organization.id !== identity4.organization.id))
38710
39596
  throw new WorkspaceIdentityMismatchError;
38711
39597
  return result;
38712
39598
  }
@@ -38724,10 +39610,10 @@ class RemoteSkillsClient {
38724
39610
  const verified = await new RemoteSkillsClient(selected.token, connection.apiUrl).requestWorkspaceSelection("/api/auth/whoami");
38725
39611
  if (!verified || typeof verified !== "object" || verified.authMethod !== "jwt")
38726
39612
  throw new RemoteWorkspaceSelectionError("/api/v1/account/workspaces/switch", "INTERACTIVE_SESSION_REQUIRED");
38727
- const identity3 = parseWorkspaceIdentity(verified, target.userId);
38728
- if (identity3.user.membershipId !== target.membershipId || identity3.organization.id !== selected.organization.id)
39613
+ const identity4 = parseWorkspaceIdentity(verified, target.userId);
39614
+ if (identity4.user.membershipId !== target.membershipId || identity4.organization.id !== selected.organization.id)
38729
39615
  throw new WorkspaceIdentityMismatchError;
38730
- return { token: selected.token, ...identity3 };
39616
+ return { token: selected.token, ...identity4 };
38731
39617
  }
38732
39618
  async requestWorkspaceSelection(path, options) {
38733
39619
  let response;
@@ -38811,8 +39697,8 @@ class RemoteSkillsClient {
38811
39697
  const value = await connection.requestWorkspaceSelection("/api/auth/whoami");
38812
39698
  if (!value || typeof value !== "object" || value.authMethod !== "jwt")
38813
39699
  throw new RemoteWorkspaceLeaveError("INTERACTIVE_SESSION_REQUIRED");
38814
- const identity3 = parseWorkspaceIdentity(value, captured.context.userId);
38815
- if (identity3.user.membershipId !== captured.context.membershipId)
39700
+ const identity4 = parseWorkspaceIdentity(value, captured.context.userId);
39701
+ if (identity4.user.membershipId !== captured.context.membershipId)
38816
39702
  throw new WorkspaceIdentityMismatchError;
38817
39703
  let response, body;
38818
39704
  try {
@@ -38827,7 +39713,7 @@ class RemoteSkillsClient {
38827
39713
  throw new RemoteWorkspaceLeaveError(code);
38828
39714
  throw new RemoteWorkspaceLeaveUnconfirmedError;
38829
39715
  }
38830
- return parseWorkspaceLeaveResult(body, captured.context.membershipId, identity3.organization.id);
39716
+ return parseWorkspaceLeaveResult(body, captured.context.membershipId, identity4.organization.id);
38831
39717
  }
38832
39718
  listWorkspaceInvitations(context, options = {}) {
38833
39719
  return this.requestWorkspaceInvitation(context, "list", options);
@@ -38853,8 +39739,8 @@ class RemoteSkillsClient {
38853
39739
  const identityValue = await connection.requestWorkspaceSelection("/api/auth/whoami");
38854
39740
  if (!identityValue || typeof identityValue !== "object" || identityValue.authMethod !== "jwt")
38855
39741
  throw new RemoteWorkspaceInvitationError("INTERACTIVE_SESSION_REQUIRED");
38856
- const identity3 = parseWorkspaceIdentity(identityValue, target.userId);
38857
- if (identity3.user.membershipId !== target.membershipId)
39742
+ const identity4 = parseWorkspaceIdentity(identityValue, target.userId);
39743
+ if (identity4.user.membershipId !== target.membershipId)
38858
39744
  throw new WorkspaceIdentityMismatchError;
38859
39745
  const request = invitationRequest(action, captured), read2 = action === "list" || action === "get";
38860
39746
  let response, value;
@@ -38871,7 +39757,7 @@ class RemoteSkillsClient {
38871
39757
  throw read2 ? new RemoteWorkspaceInvitationReadError : new RemoteWorkspaceInvitationUnconfirmedError;
38872
39758
  }
38873
39759
  try {
38874
- return parseInvitationResult(action, value, captured, identity3.organization.id);
39760
+ return parseInvitationResult(action, value, captured, identity4.organization.id);
38875
39761
  } catch {
38876
39762
  throw read2 ? new RemoteWorkspaceInvitationReadError : new RemoteWorkspaceInvitationUnconfirmedError;
38877
39763
  }
@@ -38912,7 +39798,7 @@ class RemoteSkillsClient {
38912
39798
  } catch {
38913
39799
  throw new RemoteRecurringUnavailableError;
38914
39800
  }
38915
- let identity3, identityValue;
39801
+ let identity4, identityValue;
38916
39802
  try {
38917
39803
  const response = await connection.request("/api/auth/whoami");
38918
39804
  if (!response.ok) {
@@ -38921,8 +39807,8 @@ class RemoteSkillsClient {
38921
39807
  }
38922
39808
  identityValue = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(await readBoundedResponse(response, 64 * 1024)));
38923
39809
  const observedUser = identityValue.user?.id;
38924
- identity3 = parseWorkspaceIdentity(identityValue, target?.userId ?? workspaceExpectedUserId(observedUser));
38925
- if (target && identity3.user.membershipId !== target.membershipId)
39810
+ identity4 = parseWorkspaceIdentity(identityValue, target?.userId ?? workspaceExpectedUserId(observedUser));
39811
+ if (target && identity4.user.membershipId !== target.membershipId)
38926
39812
  throw new WorkspaceIdentityMismatchError;
38927
39813
  } catch {
38928
39814
  throw new RemoteRecurringReadError;
@@ -38932,16 +39818,16 @@ class RemoteSkillsClient {
38932
39818
  throw new RemoteRecurringError("RECURRING_HUMAN_APPROVAL_REQUIRED");
38933
39819
  assertRecurringCapability(capability, "draft");
38934
39820
  const selected = captured;
38935
- const draft = await connection.dispatchRecurring("draft", { draftId: selected.draftId }, identity3);
39821
+ const draft = await connection.dispatchRecurring("draft", { draftId: selected.draftId }, identity4);
38936
39822
  if (!draft || draft.termsSha256 !== selected.approval.acceptedTermsSha256)
38937
39823
  throw new RemoteRecurringError("RECURRING_TERMS_UNAVAILABLE");
38938
39824
  }
38939
39825
  let selectedConsent;
38940
39826
  if (action === "occurrences") {
38941
39827
  assertRecurringCapability(capability, "get");
38942
- selectedConsent = await connection.dispatchRecurring("get", { consentId: captured.consentId }, identity3);
39828
+ selectedConsent = await connection.dispatchRecurring("get", { consentId: captured.consentId }, identity4);
38943
39829
  }
38944
- const result = await connection.dispatchRecurring(action, captured, identity3);
39830
+ const result = await connection.dispatchRecurring(action, captured, identity4);
38945
39831
  if (action === "occurrences") {
38946
39832
  const items = result.items;
38947
39833
  if (items.length && (!selectedConsent || items.some((item) => item.scheduleId !== selectedConsent.scheduleId)))
@@ -38949,7 +39835,7 @@ class RemoteSkillsClient {
38949
39835
  }
38950
39836
  return result;
38951
39837
  }
38952
- async dispatchRecurring(action, input2, identity3) {
39838
+ async dispatchRecurring(action, input2, identity4) {
38953
39839
  const request = recurringRequest(action, input2);
38954
39840
  let response, value;
38955
39841
  try {
@@ -38969,7 +39855,7 @@ class RemoteSkillsClient {
38969
39855
  try {
38970
39856
  if (response.status !== 200 || value === null)
38971
39857
  throw new RemoteRecurringReadError;
38972
- return parseRecurringResult(action, value, input2, identity3);
39858
+ return parseRecurringResult(action, value, input2, identity4);
38973
39859
  } catch {
38974
39860
  throw request.read ? new RemoteRecurringReadError : new RemoteRecurringUnconfirmedError;
38975
39861
  }
@@ -39632,13 +40518,13 @@ var init_remote_invitation_recovery = __esm(() => {
39632
40518
  });
39633
40519
 
39634
40520
  // src/lib/remote-private-publications.ts
39635
- import { createHash as createHash22 } from "crypto";
40521
+ import { createHash as createHash23 } from "crypto";
39636
40522
  function checkedPublicationDeclaration(value) {
39637
- 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)
40523
+ if (!exact(value, ["idempotencyKey", "version", "expectedCurrentVersionId", "manifestText", "archiveSha256", "archiveByteSize"]) || !publicationUuid(value.idempotencyKey) || !(value.expectedCurrentVersionId === null || publicationUuid(value.expectedCurrentVersionId)) || typeof value.version !== "string" || !value.version || value.version.length > 128 || /[\p{Cc}\p{Cs}]/u.test(value.version) || typeof value.manifestText !== "string" || Buffer.byteLength(value.manifestText) > 16384 || !hash4(value.archiveSha256) || !Number.isSafeInteger(value.archiveByteSize) || Number(value.archiveByteSize) < 1 || Number(value.archiveByteSize) > PRIVATE_PUBLICATION_MAX_BYTES)
39638
40524
  return bad();
39639
40525
  try {
39640
40526
  const manifest = JSON.parse(value.manifestText);
39641
- if (!record9(manifest) || manifest.version !== value.version || validatePortableManifestContract(manifest, { strict: true }).length || !hash3(manifest.provenance?.content_hash))
40527
+ if (!record9(manifest) || manifest.version !== value.version || validatePortableManifestContract(manifest, { strict: true }).length || !hash4(manifest.provenance?.content_hash))
39642
40528
  return bad();
39643
40529
  } catch {
39644
40530
  return bad();
@@ -39646,7 +40532,7 @@ function checkedPublicationDeclaration(value) {
39646
40532
  return Object.freeze({ ...value });
39647
40533
  }
39648
40534
  function checkedPublicationView(value, skillId, intentId, declaration) {
39649
- if (!exact(value, ["id", "skillId", "version", "expectedCurrentVersionId", "archiveSha256", "archiveByteSize", "state", "expiresAt", "createdAt", "versionId"]) || !publicationUuid(value.id) || value.skillId !== skillId || intentId !== undefined && value.id !== intentId || typeof value.version !== "string" || !value.version || value.version.length > 128 || /[\p{Cc}\p{Cs}]/u.test(value.version) || !(value.expectedCurrentVersionId === null || publicationUuid(value.expectedCurrentVersionId)) || !hash3(value.archiveSha256) || !Number.isSafeInteger(value.archiveByteSize) || Number(value.archiveByteSize) < 1 || Number(value.archiveByteSize) > PRIVATE_PUBLICATION_MAX_BYTES || typeof value.state !== "string" || !["awaiting_upload", "queued", "verifying", "needs_attention", "committed", "rejected", "cancelled", "expired"].includes(value.state) || !date5(value.expiresAt) || !date5(value.createdAt) || !(value.versionId === null || publicationUuid(value.versionId)) || value.state === "committed" && value.versionId === null)
40535
+ if (!exact(value, ["id", "skillId", "version", "expectedCurrentVersionId", "archiveSha256", "archiveByteSize", "state", "expiresAt", "createdAt", "versionId"]) || !publicationUuid(value.id) || value.skillId !== skillId || intentId !== undefined && value.id !== intentId || typeof value.version !== "string" || !value.version || value.version.length > 128 || /[\p{Cc}\p{Cs}]/u.test(value.version) || !(value.expectedCurrentVersionId === null || publicationUuid(value.expectedCurrentVersionId)) || !hash4(value.archiveSha256) || !Number.isSafeInteger(value.archiveByteSize) || Number(value.archiveByteSize) < 1 || Number(value.archiveByteSize) > PRIVATE_PUBLICATION_MAX_BYTES || typeof value.state !== "string" || !["awaiting_upload", "queued", "verifying", "needs_attention", "committed", "rejected", "cancelled", "expired"].includes(value.state) || !date5(value.expiresAt) || !date5(value.createdAt) || !(value.versionId === null || publicationUuid(value.versionId)) || value.state === "committed" && value.versionId === null)
39650
40536
  return invalid4();
39651
40537
  if (declaration && ["version", "expectedCurrentVersionId", "archiveSha256", "archiveByteSize"].some((k) => value[k] !== declaration[k]))
39652
40538
  return invalid4();
@@ -39877,12 +40763,12 @@ class RemotePrivatePublicationsClient {
39877
40763
  previous = view;
39878
40764
  if (!["queued", "verifying"].includes(view.state) || Date.now() >= until)
39879
40765
  return view;
39880
- await new Promise((resolve22) => {
40766
+ await new Promise((resolve23) => {
39881
40767
  const timer = setTimeout(done, Math.min(1000, until - Date.now()));
39882
40768
  function done() {
39883
40769
  clearTimeout(timer);
39884
40770
  options.signal?.removeEventListener("abort", done);
39885
- resolve22();
40771
+ resolve23();
39886
40772
  }
39887
40773
  options.signal?.addEventListener("abort", done, { once: true });
39888
40774
  });
@@ -39893,7 +40779,7 @@ var PRIVATE_PUBLICATION_MAX_BYTES, failures2, PrivatePublicationError, bad = ()
39893
40779
  throw new PrivatePublicationError("INVALID_PUBLICATION_INPUT", "Invalid publication input or recovery data.");
39894
40780
  }, invalid4 = () => {
39895
40781
  throw new PrivatePublicationError("INVALID_PUBLICATION_RESPONSE", "The server returned an invalid publication result.");
39896
- }, 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), record9 = (v) => !!v && typeof v === "object" && !Array.isArray(v), exact = (v, keys2) => record9(v) && Object.keys(v).sort().join(",") === keys2.sort().join(","), date5 = (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) => createHash22("sha256").update(bytes).digest("hex");
40782
+ }, publicationUuid = (v) => typeof v === "string" && /^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/.test(v), hash4 = (v) => typeof v === "string" && /^[a-f0-9]{64}$/.test(v), record9 = (v) => !!v && typeof v === "object" && !Array.isArray(v), exact = (v, keys2) => record9(v) && Object.keys(v).sort().join(",") === keys2.sort().join(","), date5 = (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");
39897
40783
  var init_remote_private_publications = __esm(() => {
39898
40784
  init_fleet_credentials();
39899
40785
  init_remote_workspace_selection();
@@ -40170,10 +41056,10 @@ var init_remote_auth = __esm(() => {
40170
41056
  });
40171
41057
 
40172
41058
  // src/lib/workspace-profile.ts
40173
- import { constants as constants14, closeSync as closeSync16, fstatSync as fstatSync16, lstatSync as lstatSync22, mkdirSync as mkdirSync10, mkdtempSync as mkdtempSync2, openSync as openSync16, readFileSync as readFileSync19, renameSync as renameSync5, rmSync as rmSync4, writeFileSync as writeFileSync8 } from "fs";
41059
+ import { constants as constants15, closeSync as closeSync17, fstatSync as fstatSync17, lstatSync as lstatSync23, mkdirSync as mkdirSync10, mkdtempSync as mkdtempSync2, openSync as openSync17, readFileSync as readFileSync19, renameSync as renameSync5, rmSync as rmSync4, writeFileSync as writeFileSync8 } from "fs";
40174
41060
  function stat2(path) {
40175
41061
  try {
40176
- return lstatSync22(path);
41062
+ return lstatSync23(path);
40177
41063
  } catch (error61) {
40178
41064
  if (error61.code === "ENOENT")
40179
41065
  return null;
@@ -40183,17 +41069,17 @@ function stat2(path) {
40183
41069
  function safeText(file2) {
40184
41070
  if (stat2(file2) === null)
40185
41071
  return null;
40186
- const fd = openSync16(file2, constants14.O_RDONLY | constants14.O_NOFOLLOW | constants14.O_NONBLOCK);
41072
+ const fd = openSync17(file2, constants15.O_RDONLY | constants15.O_NOFOLLOW | constants15.O_NONBLOCK);
40187
41073
  try {
40188
- const s = fstatSync16(fd);
41074
+ const s = fstatSync17(fd);
40189
41075
  if (!s.isFile() || s.size > 65536 || ![256, 384].includes(s.mode & 4095) || process.getuid && s.uid !== process.getuid())
40190
41076
  return fail("The selected profile must use bounded owner-only regular files.");
40191
41077
  return readFileSync19(fd, "utf8");
40192
41078
  } finally {
40193
- closeSync16(fd);
41079
+ closeSync17(fd);
40194
41080
  }
40195
41081
  }
40196
- function checkIdentityMetadata(file2, identity3) {
41082
+ function checkIdentityMetadata(file2, identity4) {
40197
41083
  const text3 = safeText(file2);
40198
41084
  if (text3 === null)
40199
41085
  return;
@@ -40205,7 +41091,7 @@ function checkIdentityMetadata(file2, identity3) {
40205
41091
  }
40206
41092
  if (!value || typeof value !== "object" || Array.isArray(value))
40207
41093
  return fail("The profile identity metadata is invalid.");
40208
- for (const [key, expected] of Object.entries({ userId: identity3.user.id, orgId: identity3.organization.id })) {
41094
+ for (const [key, expected] of Object.entries({ userId: identity4.user.id, orgId: identity4.organization.id })) {
40209
41095
  if (value[key] !== undefined && value[key] !== expected)
40210
41096
  return fail("The profile identity metadata does not match its authenticated key. Sign in again before managing this workspace.");
40211
41097
  }
@@ -40227,10 +41113,10 @@ function prepareProfileWorkspace(action, source = process.env) {
40227
41113
  const connection = await resolveSkillsConnection(env);
40228
41114
  if (!connection || connection.apiOrigin !== origin)
40229
41115
  return fail("The selected profile has no usable credential for this server.");
40230
- const identity3 = await keyIdentity(connection.apiKey, origin);
40231
- checkIdentityMetadata(getIdentityFilePath(env), identity3);
41116
+ const identity4 = await keyIdentity(connection.apiKey, origin);
41117
+ checkIdentityMetadata(getIdentityFilePath(env), identity4);
40232
41118
  unchanged3();
40233
- const context = { userId: identity3.user.id, membershipId: identity3.user.membershipId };
41119
+ const context = { userId: identity4.user.id, membershipId: identity4.user.membershipId };
40234
41120
  return { origin, context, unchanged: unchanged3 };
40235
41121
  } };
40236
41122
  }
@@ -40311,15 +41197,15 @@ async function prepareRecurringCustomer(requested, source = process.env) {
40311
41197
  await assertCurrent();
40312
41198
  const value = await new RemoteSkillsClient(connection.apiKey, connection.apiOrigin).getIdentity();
40313
41199
  const user = value.user;
40314
- const identity3 = parseWorkspaceIdentity(value, context?.userId ?? workspaceExpectedUserId(user?.id));
41200
+ const identity4 = parseWorkspaceIdentity(value, context?.userId ?? workspaceExpectedUserId(user?.id));
40315
41201
  await assertCurrent();
40316
- if (value.authMethod !== "api_key" || context && identity3.user.membershipId !== context.membershipId)
41202
+ if (value.authMethod !== "api_key" || context && identity4.user.membershipId !== context.membershipId)
40317
41203
  changed();
40318
- const binding = JSON.stringify([identity3.user.id, identity3.user.membershipId, identity3.organization.id]);
41204
+ const binding = JSON.stringify([identity4.user.id, identity4.user.membershipId, identity4.organization.id]);
40319
41205
  if (originalIdentity !== undefined && originalIdentity !== binding)
40320
41206
  changed();
40321
41207
  originalIdentity = binding;
40322
- if (verification(identity3.user.email) !== normalized)
41208
+ if (verification(identity4.user.email) !== normalized)
40323
41209
  throw new RecurringCustomerError("RECURRING_ACCOUNT_EMAIL_MISMATCH", "Use the selected account's current email. No verification request or recurring activation was submitted.");
40324
41210
  return normalized;
40325
41211
  }
@@ -40402,8 +41288,8 @@ var init_recurring_customer = __esm(() => {
40402
41288
  });
40403
41289
 
40404
41290
  // src/lib/recurring-recovery.ts
40405
- import { constants as constants15, closeSync as closeSync17, fsyncSync as fsyncSync5, fstatSync as fstatSync17, lstatSync as lstatSync23, mkdirSync as mkdirSync11, openSync as openSync17, readSync as readSync11, realpathSync as realpathSync9, renameSync as renameSync6, unlinkSync as unlinkSync5, writeFileSync as writeFileSync9 } from "fs";
40406
- import { dirname as dirname22, isAbsolute as isAbsolute20, join as join33, resolve as resolve22 } from "path";
41291
+ import { constants as constants16, closeSync as closeSync18, fsyncSync as fsyncSync5, fstatSync as fstatSync18, lstatSync as lstatSync24, mkdirSync as mkdirSync11, openSync as openSync18, readSync as readSync12, realpathSync as realpathSync11, renameSync as renameSync6, unlinkSync as unlinkSync5, writeFileSync as writeFileSync9 } from "fs";
41292
+ import { dirname as dirname23, isAbsolute as isAbsolute21, join as join34, resolve as resolve23 } from "path";
40407
41293
  import { randomUUID as randomUUID2 } from "crypto";
40408
41294
 
40409
41295
  class RecoveryOwner {
@@ -40411,75 +41297,75 @@ class RecoveryOwner {
40411
41297
  parents = [];
40412
41298
  constructor(directory) {
40413
41299
  this.directory = directory;
40414
- if (!isAbsolute20(directory) || resolve22(directory) !== directory || realpathSync9(directory) !== directory)
41300
+ if (!isAbsolute21(directory) || resolve23(directory) !== directory || realpathSync11(directory) !== directory)
40415
41301
  invalid5();
40416
- for (let path = directory;; path = dirname22(path)) {
40417
- const stat3 = lstatSync23(path);
41302
+ for (let path = directory;; path = dirname23(path)) {
41303
+ const stat3 = lstatSync24(path);
40418
41304
  if (!stat3.isDirectory() || stat3.isSymbolicLink())
40419
41305
  invalid5();
40420
41306
  this.parents.push({ path, dev: stat3.dev, ino: stat3.ino });
40421
- if (path === dirname22(path))
41307
+ if (path === dirname23(path))
40422
41308
  break;
40423
41309
  }
40424
41310
  this.assert();
40425
41311
  }
40426
41312
  assert() {
40427
- if (realpathSync9(this.directory) !== this.directory)
41313
+ if (realpathSync11(this.directory) !== this.directory)
40428
41314
  invalid5();
40429
41315
  for (const prior of this.parents) {
40430
- const now = lstatSync23(prior.path);
41316
+ const now = lstatSync24(prior.path);
40431
41317
  if (!now.isDirectory() || now.isSymbolicLink() || now.dev !== prior.dev || now.ino !== prior.ino)
40432
41318
  invalid5();
40433
41319
  }
40434
- const own2 = lstatSync23(this.directory);
41320
+ const own2 = lstatSync24(this.directory);
40435
41321
  if ((own2.mode & 511) !== 448 || (own2.mode & 3584) !== 0 || process.getuid && own2.uid !== process.getuid())
40436
41322
  invalid5();
40437
41323
  }
40438
41324
  read(name) {
40439
41325
  this.assert();
40440
- const fd = openSync17(join33(this.directory, name), constants15.O_RDONLY | constants15.O_NOFOLLOW | constants15.O_NONBLOCK);
41326
+ const fd = openSync18(join34(this.directory, name), constants16.O_RDONLY | constants16.O_NOFOLLOW | constants16.O_NONBLOCK);
40441
41327
  try {
40442
- const before = fstatSync17(fd);
41328
+ const before = fstatSync18(fd);
40443
41329
  if (!before.isFile() || before.nlink !== 1 || (before.mode & 4095) !== 384 || before.size < 1 || before.size > 8192 || process.getuid && before.uid !== process.getuid())
40444
41330
  invalid5();
40445
41331
  const bytes = Buffer.alloc(before.size + 1);
40446
41332
  let size = 0;
40447
41333
  while (size < bytes.length) {
40448
- const n2 = readSync11(fd, bytes, size, bytes.length - size, size);
41334
+ const n2 = readSync12(fd, bytes, size, bytes.length - size, size);
40449
41335
  if (!n2)
40450
41336
  break;
40451
41337
  size += n2;
40452
41338
  }
40453
- const after = fstatSync17(fd), path = lstatSync23(join33(this.directory, name));
41339
+ const after = fstatSync18(fd), path = lstatSync24(join34(this.directory, name));
40454
41340
  if (size !== before.size || after.size !== before.size || before.mtimeMs !== after.mtimeMs || before.ctimeMs !== after.ctimeMs || path.dev !== before.dev || path.ino !== before.ino || !path.isFile() || path.isSymbolicLink())
40455
41341
  invalid5();
40456
41342
  this.assert();
40457
41343
  return new TextDecoder("utf-8", { fatal: true }).decode(bytes.subarray(0, size));
40458
41344
  } finally {
40459
- closeSync17(fd);
41345
+ closeSync18(fd);
40460
41346
  }
40461
41347
  }
40462
41348
  write(name, value) {
40463
41349
  this.assert();
40464
41350
  const bytes = canonicalJson2(value, 8192) + `
40465
41351
  `;
40466
- const fd = openSync17(join33(this.directory, name), constants15.O_WRONLY | constants15.O_CREAT | constants15.O_EXCL | constants15.O_NOFOLLOW, 384);
41352
+ const fd = openSync18(join34(this.directory, name), constants16.O_WRONLY | constants16.O_CREAT | constants16.O_EXCL | constants16.O_NOFOLLOW, 384);
40467
41353
  try {
40468
41354
  writeFileSync9(fd, bytes);
40469
41355
  fsyncSync5(fd);
40470
41356
  } finally {
40471
- closeSync17(fd);
41357
+ closeSync18(fd);
40472
41358
  }
40473
41359
  this.assert();
40474
41360
  this.sync();
40475
41361
  }
40476
41362
  sync() {
40477
41363
  this.assert();
40478
- const fd = openSync17(this.directory, constants15.O_RDONLY | constants15.O_NOFOLLOW);
41364
+ const fd = openSync18(this.directory, constants16.O_RDONLY | constants16.O_NOFOLLOW);
40479
41365
  try {
40480
41366
  fsyncSync5(fd);
40481
41367
  } finally {
40482
- closeSync17(fd);
41368
+ closeSync18(fd);
40483
41369
  }
40484
41370
  }
40485
41371
  saveState(state, expected) {
@@ -40490,30 +41376,30 @@ class RecoveryOwner {
40490
41376
  if (this.read("state.json") !== expected)
40491
41377
  invalid5();
40492
41378
  this.assert();
40493
- renameSync6(join33(this.directory, name), join33(this.directory, "state.json"));
41379
+ renameSync6(join34(this.directory, name), join34(this.directory, "state.json"));
40494
41380
  this.sync();
40495
41381
  }
40496
41382
  async locked(action) {
40497
41383
  this.assert();
40498
41384
  let fd;
40499
41385
  try {
40500
- fd = openSync17(join33(this.directory, "operation.lock"), constants15.O_WRONLY | constants15.O_CREAT | constants15.O_EXCL | constants15.O_NOFOLLOW, 384);
41386
+ fd = openSync18(join34(this.directory, "operation.lock"), constants16.O_WRONLY | constants16.O_CREAT | constants16.O_EXCL | constants16.O_NOFOLLOW, 384);
40501
41387
  } catch {
40502
41388
  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.");
40503
41389
  }
40504
- const owner2 = fstatSync17(fd);
41390
+ const owner2 = fstatSync18(fd);
40505
41391
  try {
40506
41392
  writeFileSync9(fd, JSON.stringify({ pid: process.pid }));
40507
41393
  fsyncSync5(fd);
40508
41394
  this.sync();
40509
41395
  return await action();
40510
41396
  } finally {
40511
- closeSync17(fd);
41397
+ closeSync18(fd);
40512
41398
  this.assert();
40513
- const now = lstatSync23(join33(this.directory, "operation.lock"));
41399
+ const now = lstatSync24(join34(this.directory, "operation.lock"));
40514
41400
  if (owner2.dev !== now.dev || owner2.ino !== now.ino || !now.isFile() || now.isSymbolicLink())
40515
41401
  invalid5();
40516
- unlinkSync5(join33(this.directory, "operation.lock"));
41402
+ unlinkSync5(join34(this.directory, "operation.lock"));
40517
41403
  this.sync();
40518
41404
  }
40519
41405
  }
@@ -40546,7 +41432,7 @@ function base(customer, organizationId) {
40546
41432
  };
40547
41433
  }
40548
41434
  function create(directory, intent) {
40549
- if (!isAbsolute20(directory) || resolve22(directory) !== directory || realpathSync9(dirname22(directory)) !== dirname22(directory))
41435
+ if (!isAbsolute21(directory) || resolve23(directory) !== directory || realpathSync11(dirname23(directory)) !== dirname23(directory))
40550
41436
  invalid5();
40551
41437
  mkdirSync11(directory, { mode: 448 });
40552
41438
  const owner2 = new RecoveryOwner(directory), checked = intentSchema.parse(intent), intentSha256 = canonicalJsonSha256(checked);
@@ -40709,12 +41595,12 @@ var init_recurring_recovery = __esm(() => {
40709
41595
  });
40710
41596
 
40711
41597
  // src/lib/recurring-surface.ts
40712
- import { isAbsolute as isAbsolute21 } from "path";
41598
+ import { isAbsolute as isAbsolute22 } from "path";
40713
41599
  function recurringMcpSchema(action) {
40714
41600
  return action === "activate" ? recurringSurfaceSchemas.activate.extend({ code, confirm: exports_external.literal(true) }) : recurringSurfaceSchemas[action];
40715
41601
  }
40716
- function expectedDraft(draft, hash4) {
40717
- if (!draft || draft.termsSha256 !== hash4)
41602
+ function expectedDraft(draft, hash5) {
41603
+ if (!draft || draft.termsSha256 !== hash5)
40718
41604
  throw new RemoteRecurringError("RECURRING_TERMS_UNAVAILABLE");
40719
41605
  return draft;
40720
41606
  }
@@ -40814,7 +41700,7 @@ var init_recurring_surface = __esm(() => {
40814
41700
  uuid13 = exports_external.string().regex(/^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/);
40815
41701
  context = { userId: uuid13.optional(), membershipId: uuid13.optional() };
40816
41702
  page2 = { limit: exports_external.number().int().min(1).max(100).optional(), cursor: exports_external.string().min(1).max(2048).optional() };
40817
- directory = exports_external.string().max(4096).refine(isAbsolute21, "Use an absolute recovery directory");
41703
+ directory = exports_external.string().max(4096).refine(isAbsolute22, "Use an absolute recovery directory");
40818
41704
  email4 = exports_external.string().trim().toLowerCase().email().max(254);
40819
41705
  code = exports_external.string().regex(/^\d{6}$/);
40820
41706
  recurringSurfaceSchemas = {
@@ -42643,21 +43529,21 @@ var init_credential_state = __esm(() => {
42643
43529
  });
42644
43530
 
42645
43531
  // src/lib/run-state.ts
42646
- import { createHash as createHash23, randomBytes } from "crypto";
42647
- import { existsSync as existsSync15, mkdirSync as mkdirSync12, readFileSync as readFileSync20, readdirSync as readdirSync10, statSync as statSync10, writeFileSync as writeFileSync10 } from "fs";
42648
- import { extname, join as join34, relative as relative7 } from "path";
43532
+ import { createHash as createHash24, randomBytes } from "crypto";
43533
+ import { existsSync as existsSync15, mkdirSync as mkdirSync12, readFileSync as readFileSync20, readdirSync as readdirSync11, statSync as statSync10, writeFileSync as writeFileSync10 } from "fs";
43534
+ import { extname, join as join35, relative as relative9 } from "path";
42649
43535
  function createSkillRun(params, targetDir = process.cwd()) {
42650
43536
  const now = new Date;
42651
43537
  const id = createRunId(now);
42652
43538
  const day = now.toISOString().slice(0, 10);
42653
43539
  const skillName = normalizeSkillName(params.skill);
42654
43540
  const root = getProjectStateDir(targetDir);
42655
- const runDir = join34(root, "runs", day, id);
42656
- const logsDir = join34(runDir, "logs");
42657
- const exportDir = join34(root, "exports", skillName, id);
43541
+ const runDir = join35(root, "runs", day, id);
43542
+ const logsDir = join35(runDir, "logs");
43543
+ const exportDir = join35(root, "exports", skillName, id);
42658
43544
  mkdirSync12(logsDir, { recursive: true });
42659
43545
  mkdirSync12(exportDir, { recursive: true });
42660
- mkdirSync12(join34(root, "tmp"), { recursive: true });
43546
+ mkdirSync12(join35(root, "tmp"), { recursive: true });
42661
43547
  const record10 = {
42662
43548
  id,
42663
43549
  skill: skillName,
@@ -42709,22 +43595,22 @@ function updateSkillRun(context2, patch) {
42709
43595
  return context2.record;
42710
43596
  }
42711
43597
  function writeRunLogs(context2, stdout = "", stderr = "") {
42712
- writeFileSync10(join34(context2.logsDir, "stdout.log"), stdout);
42713
- writeFileSync10(join34(context2.logsDir, "stderr.log"), stderr);
43598
+ writeFileSync10(join35(context2.logsDir, "stdout.log"), stdout);
43599
+ writeFileSync10(join35(context2.logsDir, "stderr.log"), stderr);
42714
43600
  }
42715
43601
  function appendRunEvent(context2, event, data = {}) {
42716
43602
  const line = JSON.stringify({ ts: new Date().toISOString(), event, ...data }) + `
42717
43603
  `;
42718
- const path = join34(context2.runDir, "events.ndjson");
43604
+ const path = join35(context2.runDir, "events.ndjson");
42719
43605
  const previous = existsSync15(path) ? readFileSync20(path, "utf-8") : "";
42720
43606
  writeFileSync10(path, previous + line);
42721
43607
  }
42722
43608
  function findSkillRun(runId, targetDir = process.cwd()) {
42723
- const runsRoot = join34(getProjectStateDir(targetDir), "runs");
43609
+ const runsRoot = join35(getProjectStateDir(targetDir), "runs");
42724
43610
  if (!existsSync15(runsRoot))
42725
43611
  return null;
42726
- for (const day of readdirSync10(runsRoot)) {
42727
- const record10 = readRunRecord(join34(runsRoot, day, runId));
43612
+ for (const day of readdirSync11(runsRoot)) {
43613
+ const record10 = readRunRecord(join35(runsRoot, day, runId));
42728
43614
  if (record10)
42729
43615
  return record10;
42730
43616
  }
@@ -42741,11 +43627,11 @@ function skillRunEnv(context2) {
42741
43627
  };
42742
43628
  }
42743
43629
  function writeRunRecord(context2) {
42744
- writeFileSync10(join34(context2.runDir, "run.json"), JSON.stringify(context2.record, null, 2) + `
43630
+ writeFileSync10(join35(context2.runDir, "run.json"), JSON.stringify(context2.record, null, 2) + `
42745
43631
  `);
42746
43632
  }
42747
43633
  function writeArtifactsManifest(context2, artifacts) {
42748
- writeFileSync10(join34(context2.runDir, "artifacts.json"), JSON.stringify({ runId: context2.record.id, artifacts }, null, 2) + `
43634
+ writeFileSync10(join35(context2.runDir, "artifacts.json"), JSON.stringify({ runId: context2.record.id, artifacts }, null, 2) + `
42749
43635
  `);
42750
43636
  }
42751
43637
  function collectRunArtifacts(context2) {
@@ -42758,14 +43644,14 @@ function collectRunArtifacts(context2) {
42758
43644
  artifacts.push({
42759
43645
  path: toProjectRelative(context2.targetDir, path),
42760
43646
  mime: mimeForPath(path),
42761
- sha256: createHash23("sha256").update(bytes).digest("hex"),
43647
+ sha256: createHash24("sha256").update(bytes).digest("hex"),
42762
43648
  sizeBytes: stat3.size
42763
43649
  });
42764
43650
  }
42765
43651
  return artifacts.sort((a, b) => a.path.localeCompare(b.path));
42766
43652
  }
42767
43653
  function readRunRecord(runDir) {
42768
- const path = join34(runDir, "run.json");
43654
+ const path = join35(runDir, "run.json");
42769
43655
  if (!existsSync15(path))
42770
43656
  return null;
42771
43657
  try {
@@ -42776,8 +43662,8 @@ function readRunRecord(runDir) {
42776
43662
  }
42777
43663
  function walkFiles(dir) {
42778
43664
  const files = [];
42779
- for (const entry of readdirSync10(dir)) {
42780
- const full = join34(dir, entry);
43665
+ for (const entry of readdirSync11(dir)) {
43666
+ const full = join35(dir, entry);
42781
43667
  if (statSync10(full).isDirectory())
42782
43668
  files.push(...walkFiles(full));
42783
43669
  else
@@ -42789,7 +43675,7 @@ function createRunId(now) {
42789
43675
  return `run_${now.getTime().toString(36)}_${randomBytes(4).toString("hex")}`;
42790
43676
  }
42791
43677
  function toProjectRelative(targetDir, path) {
42792
- const rel = relative7(targetDir, path).split(/[\\/]/).join("/");
43678
+ const rel = relative9(targetDir, path).split(/[\\/]/).join("/");
42793
43679
  return rel.startsWith(".") ? rel : `./${rel}`;
42794
43680
  }
42795
43681
  function mimeForPath(path) {
@@ -43030,11 +43916,11 @@ var init_cloud_executions = __esm(() => {
43030
43916
  // node_modules/@hasna/secrets/dist/sdk.js
43031
43917
  import { isIP as isIP2 } from "net";
43032
43918
  import { spawnSync as spawnSync5 } from "child_process";
43033
- import { closeSync as closeSync18, fstatSync as fstatSync18, openSync as openSync18, readFileSync as readFileSync21 } from "fs";
43919
+ import { closeSync as closeSync19, fstatSync as fstatSync19, openSync as openSync19, readFileSync as readFileSync21 } from "fs";
43034
43920
  import { O_NOFOLLOW as O_NOFOLLOW3, O_NONBLOCK as O_NONBLOCK3, O_RDONLY as O_RDONLY3 } from "constants";
43035
43921
  import { createRequire as createRequire2 } from "module";
43036
43922
  import { hostname as osHostname2 } from "os";
43037
- import { isAbsolute as isAbsolute22, join as join35 } from "path";
43923
+ import { isAbsolute as isAbsolute23, join as join36 } from "path";
43038
43924
  import { createRequire as createRequire22 } from "module";
43039
43925
  function envToken2(name) {
43040
43926
  return name.toUpperCase().replace(/-/g, "_");
@@ -43058,21 +43944,21 @@ function homeDir2(env) {
43058
43944
  }
43059
43945
  function absoluteOverride2(env, key) {
43060
43946
  const value = env[key]?.trim();
43061
- return value && isAbsolute22(value) ? value : null;
43947
+ return value && isAbsolute23(value) ? value : null;
43062
43948
  }
43063
43949
  function hasnaHomeDir2(env) {
43064
43950
  const override = absoluteOverride2(env, HASNA_HOME_ENV_KEY2);
43065
43951
  if (override)
43066
43952
  return override;
43067
43953
  const home = homeDir2(env);
43068
- return home ? join35(home, HASNA_HOME_DIR2) : null;
43954
+ return home ? join36(home, HASNA_HOME_DIR2) : null;
43069
43955
  }
43070
43956
  function appConfigDir2(name, env) {
43071
43957
  const configRoot = absoluteOverride2(env, HASNA_CONFIG_HOME_ENV_KEY2);
43072
43958
  if (configRoot)
43073
- return join35(configRoot, name);
43959
+ return join36(configRoot, name);
43074
43960
  const root = hasnaHomeDir2(env);
43075
- return root ? join35(root, name, CONFIG_SUBDIR2) : null;
43961
+ return root ? join36(root, name, CONFIG_SUBDIR2) : null;
43076
43962
  }
43077
43963
  function credentialDiskSourceList2(name, env, profile = null) {
43078
43964
  if (!SAFE_APP_SLUG2.test(name))
@@ -43081,7 +43967,7 @@ function credentialDiskSourceList2(name, env, profile = null) {
43081
43967
  if (!directory2)
43082
43968
  return [];
43083
43969
  const file2 = profile ? `${CREDENTIALS_FILE2}-${profile}` : CREDENTIALS_FILE2;
43084
- return [{ path: join35(directory2, file2), tier: "disk" }];
43970
+ return [{ path: join36(directory2, file2), tier: "disk" }];
43085
43971
  }
43086
43972
  function credentialDiskSources2(name, env) {
43087
43973
  return credentialDiskSourceList2(name, env, null).map((s) => s.path);
@@ -43135,7 +44021,7 @@ function readAppConfigFile2(path) {
43135
44021
  };
43136
44022
  let fd = -1;
43137
44023
  try {
43138
- fd = openSync18(path, O_RDONLY3 | O_NOFOLLOW3 | O_NONBLOCK3);
44024
+ fd = openSync19(path, O_RDONLY3 | O_NOFOLLOW3 | O_NONBLOCK3);
43139
44025
  } catch (error61) {
43140
44026
  const code2 = error61.code;
43141
44027
  if (code2 === "ENOENT" || code2 === "ENOTDIR")
@@ -43145,7 +44031,7 @@ function readAppConfigFile2(path) {
43145
44031
  unsafe(`the path could not be opened (${code2 ?? "unknown error"})`);
43146
44032
  }
43147
44033
  try {
43148
- const before = fstatSync18(fd);
44034
+ const before = fstatSync19(fd);
43149
44035
  if (!before.isFile())
43150
44036
  unsafe("the path is not a regular file");
43151
44037
  if (!configFileModeAllowed2(before.mode)) {
@@ -43157,14 +44043,14 @@ function readAppConfigFile2(path) {
43157
44043
  if (before.size > MAX_CREDENTIAL_FILE_BYTES2)
43158
44044
  unsafe("the file exceeds the size limit");
43159
44045
  const bytes = readFileSync21(fd);
43160
- const after = fstatSync18(fd);
44046
+ const after = fstatSync19(fd);
43161
44047
  if (!configFileReadsCoherent2(before, after)) {
43162
44048
  unsafe("the file changed while being read");
43163
44049
  }
43164
44050
  return parseEnvFile2(bytes.toString("utf8"));
43165
44051
  } finally {
43166
44052
  if (fd !== -1)
43167
- closeSync18(fd);
44053
+ closeSync19(fd);
43168
44054
  }
43169
44055
  }
43170
44056
  function readCredentialFile2(path, apiKeyKeys) {
@@ -44195,7 +45081,7 @@ function createSecretsClientFromEnv(env = process.env, overrides = {}) {
44195
45081
  });
44196
45082
  return new SecretsClient({ ...clientOverrides, baseUrl, apiKey });
44197
45083
  }
44198
- var __esm2 = (fn, res) => () => (fn && (res = fn(fn = 0)), res), CREDENTIAL_PROFILE_ENV_KEY2 = "HASNA_PROFILE", CredentialResolutionError2, CredentialFileUnsafeError2, HASNA_HOME_ENV_KEY2 = "HASNA_HOME", HASNA_CONFIG_HOME_ENV_KEY2 = "HASNA_CONFIG_HOME", KEYCHAIN_STATION_ENV_KEY2 = "HASNA_STATION", HASNA_HOME_DIR2 = ".hasna", CONFIG_SUBDIR2 = "config", CREDENTIALS_FILE2 = "credentials", KEYCHAIN_SECURITY_BIN2 = "/usr/bin/security", KEYCHAIN_SERVICE_PREFIX2 = "hasna.credentials", KEYCHAIN_ITEM_NOT_FOUND_STATUS2 = 44, KEYCHAIN_SPAWN_TIMEOUT_MS2 = 1e4, MAX_CREDENTIAL_FILE_BYTES2, SAFE_APP_SLUG2, SAFE_PROFILE2, ILLEGAL_IN_HEADER_VALUE2, VAULT_POINTER_SHAPE2, CREDENTIAL_SHAPED_KEY2, INSPECT_CUSTOM2, CREDENTIAL_SEAL2, CALLER_SUPPLIED_CREDENTIAL_PROVIDER_SOURCE = "caller-supplied CredentialProvider", AMBIENT_ENVIRONMENT2, SECRETS_PACKAGE_SPECIFIER, requireSecretsSdk2, DEFAULT_FLEET_GATEWAY_ORIGIN2 = "https://api.hasna.com", DEFAULT_AUTHORITY_SOURCE = "default", ASCII_CONTROL_PATTERN2, DNS_LABEL_PATTERN2, ClientTransportConfigurationError2, HasnaHttpError, DEFAULT_RETRY_STATUSES, IDEMPOTENT_METHODS2, AUTHORITY_OVERRIDE_HEADERS2, defaultSleep = (ms) => new Promise((resolve23) => setTimeout(resolve23, ms)), init_transport2, MAX_CREDENTIAL_FILE_BYTES22, INSPECT_CUSTOM22, CREDENTIAL_SEAL22, AMBIENT_ENVIRONMENT22, SECRETS_PACKAGE_SPECIFIER2, requireSecretsSdk22, IDEMPOTENT_METHODS22, AUTHORITY_OVERRIDE_HEADERS22, init_storage, PATHS_RESOLVER_APP_SLUG_RE2, SQLITE_SIDECAR_FILES, LEGACY_SERVICE_FILES, init_data_dir, SecretsTestIsolationError, TEST_ENTRYPOINT_RE, init_test_isolation, init_client, ApiError;
45084
+ var __esm2 = (fn, res) => () => (fn && (res = fn(fn = 0)), res), CREDENTIAL_PROFILE_ENV_KEY2 = "HASNA_PROFILE", CredentialResolutionError2, CredentialFileUnsafeError2, HASNA_HOME_ENV_KEY2 = "HASNA_HOME", HASNA_CONFIG_HOME_ENV_KEY2 = "HASNA_CONFIG_HOME", KEYCHAIN_STATION_ENV_KEY2 = "HASNA_STATION", HASNA_HOME_DIR2 = ".hasna", CONFIG_SUBDIR2 = "config", CREDENTIALS_FILE2 = "credentials", KEYCHAIN_SECURITY_BIN2 = "/usr/bin/security", KEYCHAIN_SERVICE_PREFIX2 = "hasna.credentials", KEYCHAIN_ITEM_NOT_FOUND_STATUS2 = 44, KEYCHAIN_SPAWN_TIMEOUT_MS2 = 1e4, MAX_CREDENTIAL_FILE_BYTES2, SAFE_APP_SLUG2, SAFE_PROFILE2, ILLEGAL_IN_HEADER_VALUE2, VAULT_POINTER_SHAPE2, CREDENTIAL_SHAPED_KEY2, INSPECT_CUSTOM2, CREDENTIAL_SEAL2, CALLER_SUPPLIED_CREDENTIAL_PROVIDER_SOURCE = "caller-supplied CredentialProvider", AMBIENT_ENVIRONMENT2, SECRETS_PACKAGE_SPECIFIER, requireSecretsSdk2, DEFAULT_FLEET_GATEWAY_ORIGIN2 = "https://api.hasna.com", DEFAULT_AUTHORITY_SOURCE = "default", ASCII_CONTROL_PATTERN2, DNS_LABEL_PATTERN2, ClientTransportConfigurationError2, HasnaHttpError, DEFAULT_RETRY_STATUSES, IDEMPOTENT_METHODS2, AUTHORITY_OVERRIDE_HEADERS2, defaultSleep = (ms) => new Promise((resolve24) => setTimeout(resolve24, ms)), init_transport2, MAX_CREDENTIAL_FILE_BYTES22, INSPECT_CUSTOM22, CREDENTIAL_SEAL22, AMBIENT_ENVIRONMENT22, SECRETS_PACKAGE_SPECIFIER2, requireSecretsSdk22, IDEMPOTENT_METHODS22, AUTHORITY_OVERRIDE_HEADERS22, init_storage, PATHS_RESOLVER_APP_SLUG_RE2, SQLITE_SIDECAR_FILES, LEGACY_SERVICE_FILES, init_data_dir, SecretsTestIsolationError, TEST_ENTRYPOINT_RE, init_test_isolation, init_client, ApiError;
44199
45085
  var init_sdk = __esm(() => {
44200
45086
  init_transport2 = __esm2(() => {
44201
45087
  CredentialResolutionError2 = class CredentialResolutionError3 extends Error {
@@ -44330,75 +45216,75 @@ var init_sdk = __esm(() => {
44330
45216
  });
44331
45217
 
44332
45218
  // src/lib/execution-secrets.ts
44333
- import { constants as constants16, closeSync as closeSync19, fstatSync as fstatSync19, openSync as openSync19, readSync as readSync12, realpathSync as realpathSync10 } from "fs";
45219
+ import { constants as constants17, closeSync as closeSync20, fstatSync as fstatSync20, openSync as openSync20, readSync as readSync13, realpathSync as realpathSync12 } from "fs";
44334
45220
  import { hostname as stationHostname } from "os";
44335
45221
  function selectedSecretBindingsTemplate(scope, names, createClient = createSecretsClientFromEnv) {
44336
45222
  let secretsAuthority;
44337
45223
  try {
44338
45224
  secretsAuthority = createClient().baseUrl;
44339
45225
  } catch {
44340
- return refuse4("LOCAL_SECRET_UNAVAILABLE", "Configure the Secrets CLI authority and authentication before preparing execution bindings.");
45226
+ return refuse5("LOCAL_SECRET_UNAVAILABLE", "Configure the Secrets CLI authority and authentication before preparing execution bindings.");
44341
45227
  }
44342
45228
  const { authority, workspaceId, profileRevision, slug: slug2, version: version2, bundleDigest } = scope.selection;
44343
45229
  return {
44344
45230
  schema: "hasna.skills-secret-bindings.v1",
44345
45231
  selection: { authority, workspaceId, profileId: scope.profileId, profileRevision, slug: slug2, version: version2, bundleDigest },
44346
- consumer: { stationId: process.env.HASNA_STATION || stationHostname(), workspaceDirectory: realpathSync10(scope.cwd) },
45232
+ consumer: { stationId: process.env.HASNA_STATION || stationHostname(), workspaceDirectory: realpathSync12(scope.cwd) },
44347
45233
  secretsAuthority,
44348
45234
  bindings: Object.fromEntries(names.map((name) => [name, ""]))
44349
45235
  };
44350
45236
  }
44351
- function refuse4(code2, message) {
45237
+ function refuse5(code2, message) {
44352
45238
  throw new SkillSelectionError(code2, message);
44353
45239
  }
44354
45240
  function record10(value) {
44355
45241
  return !!value && typeof value === "object" && !Array.isArray(value);
44356
45242
  }
44357
- function exactKeys2(value, keys2) {
45243
+ function exactKeys3(value, keys2) {
44358
45244
  return Object.keys(value).length === keys2.length && keys2.every((key) => Object.hasOwn(value, key));
44359
45245
  }
44360
- function identifier3(value) {
45246
+ function identifier4(value) {
44361
45247
  return typeof value === "string" && value.length > 0 && value.length <= 2048 && !/[\x00-\x20\x7f]/.test(value);
44362
45248
  }
44363
45249
  function declaredSecretNames(value) {
44364
45250
  if (value === undefined)
44365
45251
  return [];
44366
45252
  if (!Array.isArray(value) || value.length > 32 || value.some((name) => typeof name !== "string" || !/^[A-Z][A-Z0-9_]{0,127}$/.test(name)) || new Set(value).size !== value.length) {
44367
- return refuse4("INVALID_SKILL_MANIFEST", "Runtime environment references must be unique uppercase identifiers (at most 32).");
45253
+ return refuse5("INVALID_SKILL_MANIFEST", "Runtime environment references must be unique uppercase identifiers (at most 32).");
44368
45254
  }
44369
45255
  if (value.some((name) => /^(?:PATH|HOME|TMPDIR|TEMP|TMP|LANG|LC_ALL|TERM|SHELL|ENV|BASH_ENV|IFS|NODE_OPTIONS|NODE_PATH)$/.test(name) || /^(?:SKILLS_|BUN_|PYTHON|LD_|DYLD_)/.test(name))) {
44370
- return refuse4("INVALID_SKILL_MANIFEST", "Runtime environment references cannot override execution controls.");
45256
+ return refuse5("INVALID_SKILL_MANIFEST", "Runtime environment references cannot override execution controls.");
44371
45257
  }
44372
45258
  return value;
44373
45259
  }
44374
45260
  function validateSelectedSecretBindings(value, scope, names) {
44375
- if (!record10(value) || !exactKeys2(value, ["schema", "selection", "consumer", "secretsAuthority", "bindings"]) || value.schema !== "hasna.skills-secret-bindings.v1" || !record10(value.selection) || !exactKeys2(value.selection, ["authority", "workspaceId", "profileId", "profileRevision", "slug", "version", "bundleDigest"]) || !record10(value.consumer) || !exactKeys2(value.consumer, ["stationId", "workspaceDirectory"]) || !record10(value.bindings)) {
44376
- return refuse4("INVALID_SECRET_BINDINGS", "Secret bindings do not match the hasna.skills-secret-bindings.v1 contract.");
45261
+ if (!record10(value) || !exactKeys3(value, ["schema", "selection", "consumer", "secretsAuthority", "bindings"]) || value.schema !== "hasna.skills-secret-bindings.v1" || !record10(value.selection) || !exactKeys3(value.selection, ["authority", "workspaceId", "profileId", "profileRevision", "slug", "version", "bundleDigest"]) || !record10(value.consumer) || !exactKeys3(value.consumer, ["stationId", "workspaceDirectory"]) || !record10(value.bindings)) {
45262
+ return refuse5("INVALID_SECRET_BINDINGS", "Secret bindings do not match the hasna.skills-secret-bindings.v1 contract.");
44377
45263
  }
44378
45264
  for (const [key, expected] of Object.entries({ authority: scope.selection.authority, workspaceId: scope.selection.workspaceId, profileId: scope.profileId, profileRevision: scope.selection.profileRevision, slug: scope.selection.slug, version: scope.selection.version, bundleDigest: scope.selection.bundleDigest })) {
44379
45265
  if (value.selection[key] !== expected)
44380
- return refuse4("SECRET_BINDING_SCOPE_MISMATCH", "Secret bindings do not match the exact selected authority, workspace, profile, revision, version and digest.");
45266
+ return refuse5("SECRET_BINDING_SCOPE_MISMATCH", "Secret bindings do not match the exact selected authority, workspace, profile, revision, version and digest.");
44381
45267
  }
44382
45268
  let workspaceDirectory;
44383
45269
  try {
44384
- workspaceDirectory = realpathSync10(scope.cwd);
45270
+ workspaceDirectory = realpathSync12(scope.cwd);
44385
45271
  } catch {
44386
- return refuse4("SECRET_BINDING_CONSUMER_MISMATCH", "The execution workspace cannot be resolved.");
45272
+ return refuse5("SECRET_BINDING_CONSUMER_MISMATCH", "The execution workspace cannot be resolved.");
44387
45273
  }
44388
45274
  if (value.consumer.stationId !== (process.env.HASNA_STATION || stationHostname()) || value.consumer.workspaceDirectory !== workspaceDirectory) {
44389
- return refuse4("SECRET_BINDING_CONSUMER_MISMATCH", "Secret bindings do not match this station and canonical workspace directory.");
45275
+ return refuse5("SECRET_BINDING_CONSUMER_MISMATCH", "Secret bindings do not match this station and canonical workspace directory.");
44390
45276
  }
44391
45277
  try {
44392
- if (!identifier3(value.secretsAuthority))
45278
+ if (!identifier4(value.secretsAuthority))
44393
45279
  throw new Error;
44394
45280
  const url2 = new URL(value.secretsAuthority);
44395
45281
  if (url2.protocol !== "https:" && !(url2.protocol === "http:" && ["127.0.0.1", "[::1]", "localhost"].includes(url2.hostname)) || url2.username || url2.password || url2.search || url2.hash || !url2.pathname.endsWith("/v1") || url2.href !== value.secretsAuthority)
44396
45282
  throw new Error;
44397
45283
  } catch {
44398
- return refuse4("INVALID_SECRET_BINDINGS", "Secret bindings require a canonical HTTPS Secrets /v1 authority (loopback HTTP is allowed).");
45284
+ return refuse5("INVALID_SECRET_BINDINGS", "Secret bindings require a canonical HTTPS Secrets /v1 authority (loopback HTTP is allowed).");
44399
45285
  }
44400
- if (!exactKeys2(value.bindings, names) || Object.values(value.bindings).some((key) => !identifier3(key) || !/^[A-Za-z0-9][A-Za-z0-9._/-]*$/.test(key) || key.split("/").some((part) => !part || part === "." || part === ".."))) {
44401
- return refuse4("INVALID_SECRET_BINDINGS", "Bind every declared environment name exactly once to a vault key; undeclared bindings and values are refused.");
45286
+ if (!exactKeys3(value.bindings, names) || Object.values(value.bindings).some((key) => !identifier4(key) || !/^[A-Za-z0-9][A-Za-z0-9._/-]*$/.test(key) || key.split("/").some((part) => !part || part === "." || part === ".."))) {
45287
+ return refuse5("INVALID_SECRET_BINDINGS", "Bind every declared environment name exactly once to a vault key; undeclared bindings and values are refused.");
44402
45288
  }
44403
45289
  return structuredClone(value);
44404
45290
  }
@@ -44409,10 +45295,10 @@ async function resolveSelectedSecrets(bindings, createClient = createSecretsClie
44409
45295
  try {
44410
45296
  client = createClient();
44411
45297
  } catch {
44412
- return refuse4("LOCAL_SECRET_UNAVAILABLE", "The configured Secrets client could not authenticate. No ambient credential fallback was attempted.");
45298
+ return refuse5("LOCAL_SECRET_UNAVAILABLE", "The configured Secrets client could not authenticate. No ambient credential fallback was attempted.");
44413
45299
  }
44414
45300
  if (client.baseUrl !== bindings.secretsAuthority)
44415
- return refuse4("SECRET_BINDING_AUTHORITY_MISMATCH", "The configured Secrets authority differs from the reviewed binding. No secret was requested.");
45301
+ return refuse5("SECRET_BINDING_AUTHORITY_MISMATCH", "The configured Secrets authority differs from the reviewed binding. No secret was requested.");
44416
45302
  const env = {};
44417
45303
  const signal = AbortSignal.timeout(15000);
44418
45304
  try {
@@ -44424,7 +45310,7 @@ async function resolveSelectedSecrets(bindings, createClient = createSecretsClie
44424
45310
  }
44425
45311
  return env;
44426
45312
  } catch {
44427
- return refuse4("LOCAL_SECRET_UNAVAILABLE", "A declared secret could not be resolved, was invalid, or has expired. The skill was not started; no fallback was attempted.");
45313
+ return refuse5("LOCAL_SECRET_UNAVAILABLE", "A declared secret could not be resolved, was invalid, or has expired. The skill was not started; no fallback was attempted.");
44428
45314
  }
44429
45315
  }
44430
45316
  function redactExecutionSecrets(text3, env) {
@@ -44572,10 +45458,10 @@ __export(exports_selected_run, {
44572
45458
  prepareSelectedSecretBindings: () => prepareSelectedSecretBindings,
44573
45459
  executeSelectedLocal: () => executeSelectedLocal
44574
45460
  });
44575
- import { createHash as createHash24 } from "crypto";
45461
+ import { createHash as createHash25 } from "crypto";
44576
45462
  import { spawn as spawn2 } from "child_process";
44577
- import { mkdirSync as mkdirSync13, mkdtempSync as mkdtempSync3, writeFileSync as writeFileSync11, realpathSync as realpathSync11 } from "fs";
44578
- import { dirname as dirname23, join as join36, resolve as resolve23 } from "path";
45463
+ import { mkdirSync as mkdirSync13, mkdtempSync as mkdtempSync3, writeFileSync as writeFileSync11, realpathSync as realpathSync13 } from "fs";
45464
+ import { dirname as dirname24, join as join37, resolve as resolve24 } from "path";
44579
45465
  import { tmpdir, hostname as stationHostname2 } from "os";
44580
45466
  async function resolveSelectedRun(spec, profileId, options = {}) {
44581
45467
  const context2 = await resolveSelectionContext(profileId, options);
@@ -44655,7 +45541,7 @@ async function executeSelectedLocal(selected, options = {}) {
44655
45541
  throw new SkillSelectionError("INVALID_SECRET_BINDINGS", "Explicit environment values must be bounded strings without NUL bytes.");
44656
45542
  secretEnv[name] = value;
44657
45543
  }
44658
- const runDirectory = mkdtempSync3(join36(tmpdir(), "skills-execution-"));
45544
+ const runDirectory = mkdtempSync3(join37(tmpdir(), "skills-execution-"));
44659
45545
  const paths = new SkillEntryPaths;
44660
45546
  for (const entry of entries) {
44661
45547
  paths.add(entry.path, 100, () => {
@@ -44663,12 +45549,12 @@ async function executeSelectedLocal(selected, options = {}) {
44663
45549
  }, () => {
44664
45550
  throw new SkillSelectionError("INVALID_BUNDLE_PATH", "The execution bundle path exceeds its limit.");
44665
45551
  });
44666
- const destination = join36(runDirectory, entry.path);
44667
- mkdirSync13(dirname23(destination), { recursive: true, mode: 448 });
45552
+ const destination = join37(runDirectory, entry.path);
45553
+ mkdirSync13(dirname24(destination), { recursive: true, mode: 448 });
44668
45554
  writeFileSync11(destination, entry.bytes, { flag: "wx", mode: entry.mode & 511 });
44669
45555
  }
44670
45556
  env.SKILLS_INPUT_JSON = input2;
44671
- env.SKILLS_WORKSPACE_DIR = resolve23(options.cwd ?? process.cwd());
45557
+ env.SKILLS_WORKSPACE_DIR = resolve24(options.cwd ?? process.cwd());
44672
45558
  env.SKILLS_RUN_DIR = runDirectory;
44673
45559
  if (runtime.version) {
44674
45560
  const version2 = await subprocess([executable, ...runtimeName === "bun" ? ["--no-env-file"] : [], "--version"], runDirectory, env, "", Math.min(timeoutMs, 5000));
@@ -44681,7 +45567,7 @@ async function executeSelectedLocal(selected, options = {}) {
44681
45567
  const { authority: authority2, workspaceId, profileRevision, slug: slug2, version: version2, bundleDigest } = selection2;
44682
45568
  const request2 = {
44683
45569
  selection: { authority: authority2, workspaceId, profileId, profileRevision, slug: slug2, version: version2, bundleDigest },
44684
- consumer: { stationId: process.env.HASNA_STATION || stationHostname2(), workspaceDirectory: realpathSync11(options.cwd ?? process.cwd()) }
45570
+ consumer: { stationId: process.env.HASNA_STATION || stationHostname2(), workspaceDirectory: realpathSync13(options.cwd ?? process.cwd()) }
44685
45571
  };
44686
45572
  const grant = await (options.resolveExecutionGrant ?? resolveExecutionGrant)(request2);
44687
45573
  if (!grant || !grantIdentifier(grant.policyRevision) || !grantIdentifier(grant.grantId))
@@ -44691,20 +45577,20 @@ async function executeSelectedLocal(selected, options = {}) {
44691
45577
  }
44692
45578
  if (bindings)
44693
45579
  secretEnv = await resolveSelectedSecrets(bindings, options.createSecretsClient);
44694
- const result = await subprocess([executable, ...runtimeName === "bun" ? ["--no-env-file"] : [], join36(runDirectory, declaredEntry), ...args], runDirectory, { ...env, ...secretEnv }, input2, timeoutMs);
45580
+ const result = await subprocess([executable, ...runtimeName === "bun" ? ["--no-env-file"] : [], join37(runDirectory, declaredEntry), ...args], runDirectory, { ...env, ...secretEnv }, input2, timeoutMs);
44695
45581
  result.stdout = redactExecutionSecrets(result.stdout, secretEnv);
44696
45582
  result.stderr = redactExecutionSecrets(result.stderr, secretEnv);
44697
45583
  const receipt = {
44698
45584
  selection: selection2,
44699
45585
  target: "local",
44700
45586
  runtime: runtimeName,
44701
- inputDigest: `sha256:${createHash24("sha256").update(input2).digest("hex")}`,
45587
+ inputDigest: `sha256:${createHash25("sha256").update(input2).digest("hex")}`,
44702
45588
  runDirectory,
44703
45589
  ...executionGrant ? { executionGrant } : {},
44704
45590
  ...bindings ? { secretBinding: { schema: bindings.schema, selection: bindings.selection, consumer: bindings.consumer, secretsAuthority: bindings.secretsAuthority, bindings: bindings.bindings } } : {},
44705
45591
  ...result
44706
45592
  };
44707
- writeFileSync11(join36(runDirectory, ".execution-receipt.json"), JSON.stringify({ ...receipt, stdout: undefined, stderr: undefined }), { mode: 384 });
45593
+ writeFileSync11(join37(runDirectory, ".execution-receipt.json"), JSON.stringify({ ...receipt, stdout: undefined, stderr: undefined }), { mode: 384 });
44708
45594
  return receipt;
44709
45595
  }
44710
45596
  async function subprocess(command, cwd, env, input2, timeoutMs) {
@@ -44893,8 +45779,8 @@ var init_blog_article = __esm(() => {
44893
45779
  });
44894
45780
 
44895
45781
  // src/mcp/operation-tools.ts
44896
- import { existsSync as existsSync16, readdirSync as readdirSync11, statSync as statSync11 } from "fs";
44897
- import { join as join37 } from "path";
45782
+ import { existsSync as existsSync16, readdirSync as readdirSync12, statSync as statSync11 } from "fs";
45783
+ import { join as join38 } from "path";
44898
45784
  function registerOperationTools(server) {
44899
45785
  server.registerTool("cloud_skill_eligibility", {
44900
45786
  title: "Cloud Skill Eligibility",
@@ -45370,8 +46256,8 @@ function registerOperationTools(server) {
45370
46256
  let skillCount = 0;
45371
46257
  if (exists) {
45372
46258
  try {
45373
- skillCount = readdirSync11(agentSkillsPath).filter((f) => {
45374
- const full = join37(agentSkillsPath, f);
46259
+ skillCount = readdirSync12(agentSkillsPath).filter((f) => {
46260
+ const full = join38(agentSkillsPath, f);
45375
46261
  return !f.startsWith(".") && statSync11(full).isDirectory();
45376
46262
  }).length;
45377
46263
  } catch {}
@@ -45439,14 +46325,14 @@ var init_operation_tools = __esm(() => {
45439
46325
 
45440
46326
  // src/lib/feedback.ts
45441
46327
  import { appendFileSync, existsSync as existsSync17, mkdirSync as mkdirSync14 } from "fs";
45442
- import { dirname as dirname24, join as join38 } from "path";
46328
+ import { dirname as dirname25, join as join39 } from "path";
45443
46329
  import { Database } from "bun:sqlite";
45444
46330
  function getFeedbackDbPath() {
45445
- return join38(getDataDir(), "skills.db");
46331
+ return join39(getDataDir(), "skills.db");
45446
46332
  }
45447
46333
  function getFeedbackDb() {
45448
46334
  const dbPath = getFeedbackDbPath();
45449
- const dir = dirname24(dbPath);
46335
+ const dir = dirname25(dbPath);
45450
46336
  if (!existsSync17(dir))
45451
46337
  mkdirSync14(dir, { recursive: true });
45452
46338
  const db = new Database(dbPath);
@@ -45474,8 +46360,8 @@ function saveFeedback(input2) {
45474
46360
  throw new Error("Feedback message is required");
45475
46361
  const category = input2.category ?? "general";
45476
46362
  if (isApiMode()) {
45477
- const path = join38(getDataDir(), "feedback.jsonl");
45478
- const dir = dirname24(path);
46363
+ const path = join39(getDataDir(), "feedback.jsonl");
46364
+ const dir = dirname25(path);
45479
46365
  if (!existsSync17(dir))
45480
46366
  mkdirSync14(dir, { recursive: true });
45481
46367
  appendFileSync(path, JSON.stringify({ message, category, email: input2.email ?? null, agent: input2.agent ?? null, version: input2.version ?? null, createdAt: new Date().toISOString() }) + `
@@ -45639,9 +46525,9 @@ var init_resource_meta_tools = __esm(() => {
45639
46525
 
45640
46526
  // src/lib/scheduler.ts
45641
46527
  import { existsSync as existsSync18, readFileSync as readFileSync22, writeFileSync as writeFileSync12, mkdirSync as mkdirSync15 } from "fs";
45642
- import { join as join39 } from "path";
46528
+ import { join as join40 } from "path";
45643
46529
  function getSchedulesPath(targetDir = process.cwd()) {
45644
- return join39(targetDir, ".skills", "schedules.json");
46530
+ return join40(targetDir, ".skills", "schedules.json");
45645
46531
  }
45646
46532
  function loadSchedules(targetDir = process.cwd()) {
45647
46533
  const path = getSchedulesPath(targetDir);
@@ -45654,7 +46540,7 @@ function loadSchedules(targetDir = process.cwd()) {
45654
46540
  }
45655
46541
  function saveSchedules(data, targetDir = process.cwd()) {
45656
46542
  const path = getSchedulesPath(targetDir);
45657
- const dir = join39(targetDir, ".skills");
46543
+ const dir = join40(targetDir, ".skills");
45658
46544
  if (!existsSync18(dir))
45659
46545
  mkdirSync15(dir, { recursive: true });
45660
46546
  writeFileSync12(path, JSON.stringify(data, null, 2));
@@ -45926,16 +46812,16 @@ var init_schedule_tools = __esm(() => {
45926
46812
  });
45927
46813
 
45928
46814
  // src/lib/native-storage.ts
45929
- import { createHash as createHash25, createHmac } from "crypto";
46815
+ import { createHash as createHash26, createHmac } from "crypto";
45930
46816
  import {
45931
46817
  existsSync as existsSync19,
45932
46818
  mkdirSync as mkdirSync16,
45933
46819
  readFileSync as readFileSync23,
45934
- readdirSync as readdirSync12,
46820
+ readdirSync as readdirSync13,
45935
46821
  statSync as statSync12,
45936
46822
  writeFileSync as writeFileSync13
45937
46823
  } from "fs";
45938
- import { dirname as dirname25, join as join40, normalize as normalize5, relative as relative8, sep as sep11 } from "path";
46824
+ import { dirname as dirname26, join as join41, normalize as normalize5, relative as relative10, sep as sep12 } from "path";
45939
46825
  function resolveSkillsNativeStorageConfig(env = process.env) {
45940
46826
  assertNoRetiredModeEnvVars(env, {
45941
46827
  app: SKILLS_ENV_NAMESPACE,
@@ -45976,7 +46862,7 @@ function getSkillsNativeStorageStatus(options = {}) {
45976
46862
  local: {
45977
46863
  dataDir: getDataDir(),
45978
46864
  projectStateDir: getProjectStateDir(targetDir),
45979
- feedbackDbPath: join40(getDataDir(), "skills.db")
46865
+ feedbackDbPath: join41(getDataDir(), "skills.db")
45980
46866
  },
45981
46867
  remote: {
45982
46868
  databaseConfigured: Boolean(config2.databaseUrl),
@@ -45999,11 +46885,11 @@ function exportSkillsLocalSnapshot(targetDir = process.cwd(), options = {}) {
45999
46885
  if (existsSync19(projectStateDir)) {
46000
46886
  for (const filePath of walkFiles2(projectStateDir)) {
46001
46887
  const bytes = readFileSync23(filePath);
46002
- const relativePath = toPosix(relative8(targetDir, filePath));
46888
+ const relativePath = toPosix(relative10(targetDir, filePath));
46003
46889
  files.push({
46004
46890
  path: relativePath,
46005
46891
  sizeBytes: bytes.byteLength,
46006
- sha256: createHash25("sha256").update(bytes).digest("hex"),
46892
+ sha256: createHash26("sha256").update(bytes).digest("hex"),
46007
46893
  ...options.includeFileContents ? { contentBase64: Buffer.from(bytes).toString("base64") } : {}
46008
46894
  });
46009
46895
  }
@@ -46056,8 +46942,8 @@ function parsePositiveInteger(value) {
46056
46942
  }
46057
46943
  function walkFiles2(dir) {
46058
46944
  const files = [];
46059
- for (const entry of readdirSync12(dir)) {
46060
- const full = join40(dir, entry);
46945
+ for (const entry of readdirSync13(dir)) {
46946
+ const full = join41(dir, entry);
46061
46947
  const stats = statSync12(full);
46062
46948
  if (stats.isDirectory())
46063
46949
  files.push(...walkFiles2(full));
@@ -46295,73 +47181,73 @@ var init_private_publication_customer = __esm(() => {
46295
47181
  });
46296
47182
 
46297
47183
  // src/lib/private-publication-recovery.ts
46298
- import { constants as constants17, closeSync as closeSync20, fsyncSync as fsyncSync6, fstatSync as fstatSync20, lstatSync as lstatSync24, mkdirSync as mkdirSync17, openSync as openSync20, readSync as readSync13, realpathSync as realpathSync12, renameSync as renameSync7, unlinkSync as unlinkSync6, writeFileSync as writeFileSync14 } from "fs";
46299
- import { dirname as dirname26, isAbsolute as isAbsolute23, join as join41, resolve as resolve24 } from "path";
47184
+ import { constants as constants18, closeSync as closeSync21, fsyncSync as fsyncSync6, fstatSync as fstatSync21, lstatSync as lstatSync25, mkdirSync as mkdirSync17, openSync as openSync21, readSync as readSync14, realpathSync as realpathSync14, renameSync as renameSync7, unlinkSync as unlinkSync6, writeFileSync as writeFileSync14 } from "fs";
47185
+ import { dirname as dirname27, isAbsolute as isAbsolute24, join as join42, resolve as resolve25 } from "path";
46300
47186
  import { randomUUID as randomUUID3 } from "crypto";
46301
47187
  function safeDirectory(directory2) {
46302
- if (!isAbsolute23(directory2) || directory2 !== resolve24(directory2) || realpathSync12(directory2) !== directory2)
47188
+ if (!isAbsolute24(directory2) || directory2 !== resolve25(directory2) || realpathSync14(directory2) !== directory2)
46303
47189
  return fail2();
46304
- for (let path = directory2;; path = dirname26(path)) {
46305
- const stat3 = lstatSync24(path);
47190
+ for (let path = directory2;; path = dirname27(path)) {
47191
+ const stat3 = lstatSync25(path);
46306
47192
  if (!stat3.isDirectory() || stat3.isSymbolicLink())
46307
47193
  return fail2();
46308
- if (path === dirname26(path))
47194
+ if (path === dirname27(path))
46309
47195
  break;
46310
47196
  }
46311
- const own2 = lstatSync24(directory2);
47197
+ const own2 = lstatSync25(directory2);
46312
47198
  if ((own2.mode & 63) !== 0 || process.getuid && own2.uid !== process.getuid())
46313
47199
  return fail2();
46314
47200
  return { dev: own2.dev, ino: own2.ino };
46315
47201
  }
46316
- function unchangedDirectory(directory2, identity3) {
47202
+ function unchangedDirectory(directory2, identity4) {
46317
47203
  const now = safeDirectory(directory2);
46318
- if (now.dev !== identity3.dev || now.ino !== identity3.ino)
47204
+ if (now.dev !== identity4.dev || now.ino !== identity4.ino)
46319
47205
  return fail2();
46320
47206
  }
46321
47207
  function readOwned(directory2, name, max) {
46322
- const identity3 = safeDirectory(directory2), file2 = join41(directory2, name);
46323
- const fd = openSync20(file2, constants17.O_RDONLY | constants17.O_NOFOLLOW);
47208
+ const identity4 = safeDirectory(directory2), file2 = join42(directory2, name);
47209
+ const fd = openSync21(file2, constants18.O_RDONLY | constants18.O_NOFOLLOW);
46324
47210
  try {
46325
- const stat3 = fstatSync20(fd);
47211
+ const stat3 = fstatSync21(fd);
46326
47212
  if (!stat3.isFile() || stat3.nlink !== 1 || stat3.size > max || stat3.size < 1 || (stat3.mode & 63) !== 0 || process.getuid && stat3.uid !== process.getuid())
46327
47213
  return fail2();
46328
47214
  const buffer = Buffer.alloc(Math.min(max, stat3.size) + 1);
46329
47215
  let length = 0;
46330
47216
  while (length < buffer.length) {
46331
- const count = readSync13(fd, buffer, length, buffer.length - length, length);
47217
+ const count = readSync14(fd, buffer, length, buffer.length - length, length);
46332
47218
  if (count === 0)
46333
47219
  break;
46334
47220
  length += count;
46335
47221
  }
46336
- const bytes = buffer.subarray(0, length), after = fstatSync20(fd);
46337
- unchangedDirectory(directory2, identity3);
47222
+ const bytes = buffer.subarray(0, length), after = fstatSync21(fd);
47223
+ unchangedDirectory(directory2, identity4);
46338
47224
  if (bytes.length !== stat3.size || stat3.size !== after.size || stat3.mtimeMs !== after.mtimeMs || stat3.ctimeMs !== after.ctimeMs)
46339
47225
  return fail2();
46340
47226
  return bytes;
46341
47227
  } finally {
46342
- closeSync20(fd);
47228
+ closeSync21(fd);
46343
47229
  }
46344
47230
  }
46345
47231
  function writeOwned(directory2, name, bytes) {
46346
- const fd = openSync20(join41(directory2, name), constants17.O_WRONLY | constants17.O_CREAT | constants17.O_EXCL | constants17.O_NOFOLLOW, 384);
47232
+ const fd = openSync21(join42(directory2, name), constants18.O_WRONLY | constants18.O_CREAT | constants18.O_EXCL | constants18.O_NOFOLLOW, 384);
46347
47233
  try {
46348
47234
  writeFileSync14(fd, bytes);
46349
47235
  fsyncSync6(fd);
46350
47236
  } finally {
46351
- closeSync20(fd);
47237
+ closeSync21(fd);
46352
47238
  }
46353
47239
  }
46354
47240
  function save(directory2, value) {
46355
- const identity3 = safeDirectory(directory2), temporary = `.receipt-${randomUUID3()}.json`;
47241
+ const identity4 = safeDirectory(directory2), temporary = `.receipt-${randomUUID3()}.json`;
46356
47242
  writeOwned(directory2, temporary, JSON.stringify(value) + `
46357
47243
  `);
46358
- unchangedDirectory(directory2, identity3);
46359
- renameSync7(join41(directory2, temporary), join41(directory2, "receipt.json"));
46360
- const fd = openSync20(directory2, constants17.O_RDONLY | constants17.O_NOFOLLOW);
47244
+ unchangedDirectory(directory2, identity4);
47245
+ renameSync7(join42(directory2, temporary), join42(directory2, "receipt.json"));
47246
+ const fd = openSync21(directory2, constants18.O_RDONLY | constants18.O_NOFOLLOW);
46361
47247
  try {
46362
47248
  fsyncSync6(fd);
46363
47249
  } finally {
46364
- closeSync20(fd);
47250
+ closeSync21(fd);
46365
47251
  }
46366
47252
  }
46367
47253
  function bind(client, receipt) {
@@ -46369,23 +47255,23 @@ function bind(client, receipt) {
46369
47255
  throw new PrivatePublicationError("PUBLICATION_IDENTITY_CHANGED", "The fresh session does not match the recovery directory's server, account and membership.");
46370
47256
  }
46371
47257
  async function locked(directory2, action) {
46372
- const identity3 = safeDirectory(directory2), file2 = join41(directory2, "operation.lock");
47258
+ const identity4 = safeDirectory(directory2), file2 = join42(directory2, "operation.lock");
46373
47259
  let fd;
46374
47260
  try {
46375
- fd = openSync20(file2, constants17.O_WRONLY | constants17.O_CREAT | constants17.O_EXCL | constants17.O_NOFOLLOW, 384);
47261
+ fd = openSync21(file2, constants18.O_WRONLY | constants18.O_CREAT | constants18.O_EXCL | constants18.O_NOFOLLOW, 384);
46376
47262
  } catch {
46377
47263
  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.");
46378
47264
  }
46379
- const lock = fstatSync20(fd);
47265
+ const lock = fstatSync21(fd);
46380
47266
  try {
46381
47267
  writeFileSync14(fd, JSON.stringify({ pid: process.pid }) + `
46382
47268
  `);
46383
47269
  fsyncSync6(fd);
46384
47270
  return await action();
46385
47271
  } finally {
46386
- closeSync20(fd);
46387
- unchangedDirectory(directory2, identity3);
46388
- const now = lstatSync24(file2);
47272
+ closeSync21(fd);
47273
+ unchangedDirectory(directory2, identity4);
47274
+ const now = lstatSync25(file2);
46389
47275
  if (now.dev !== lock.dev || now.ino !== lock.ino || !now.isFile() || now.isSymbolicLink())
46390
47276
  fail2();
46391
47277
  unlinkSync6(file2);
@@ -46437,15 +47323,15 @@ async function preparePrivatePublication(client, sourceDirectory, recoveryDirect
46437
47323
  phase: "prepared",
46438
47324
  intent: null
46439
47325
  };
46440
- if (!isAbsolute23(recoveryDirectory) || resolve24(recoveryDirectory) !== recoveryDirectory || realpathSync12(dirname26(recoveryDirectory)) !== dirname26(recoveryDirectory))
47326
+ if (!isAbsolute24(recoveryDirectory) || resolve25(recoveryDirectory) !== recoveryDirectory || realpathSync14(dirname27(recoveryDirectory)) !== dirname27(recoveryDirectory))
46441
47327
  return fail2();
46442
47328
  mkdirSync17(recoveryDirectory, { mode: 448 });
46443
47329
  safeDirectory(recoveryDirectory);
46444
- const parent = openSync20(dirname26(recoveryDirectory), constants17.O_RDONLY | constants17.O_NOFOLLOW);
47330
+ const parent = openSync21(dirname27(recoveryDirectory), constants18.O_RDONLY | constants18.O_NOFOLLOW);
46445
47331
  try {
46446
47332
  fsyncSync6(parent);
46447
47333
  } finally {
46448
- closeSync20(parent);
47334
+ closeSync21(parent);
46449
47335
  }
46450
47336
  writeOwned(recoveryDirectory, "bundle.tgz", packed.bytes);
46451
47337
  save(recoveryDirectory, receipt);
@@ -46538,10 +47424,10 @@ var init_private_publication_recovery = __esm(() => {
46538
47424
  });
46539
47425
 
46540
47426
  // src/mcp/private-publication-tools.ts
46541
- import { isAbsolute as isAbsolute24 } from "path";
47427
+ import { isAbsolute as isAbsolute25 } from "path";
46542
47428
  function registerPrivatePublicationTools(server) {
46543
47429
  const uuid9 = exports_external.string().regex(/^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/);
46544
- const directory2 = exports_external.string().max(4096).refine(isAbsolute24, "Use an absolute local directory");
47430
+ const directory2 = exports_external.string().max(4096).refine(isAbsolute25, "Use an absolute local directory");
46545
47431
  const verification2 = { email: exports_external.string().email().max(254), code: exports_external.string().regex(/^\d{6}$/), userId: uuid9, membershipId: uuid9, recoveryDirectory: directory2 };
46546
47432
  const description = "Manage a private source publication using fresh workspace-bound verification and a host-local recovery directory. Publishing requires explicit UUID current-version comparison and upload consent. Resume reuses immutable saved bytes and intent; an uncertain PUT is finalized for server verification, never uploaded twice. Sessions and signed URLs are not returned or persisted. Private execution is unavailable. Host request history may contain the supplied verification code.";
46547
47433
  const handler = (action) => async (value) => {
@@ -46974,19 +47860,19 @@ async function connectMcpForNode() {
46974
47860
  return { server: server2, transport };
46975
47861
  }
46976
47862
  function readBody(req) {
46977
- return new Promise((resolve25, reject) => {
47863
+ return new Promise((resolve26, reject) => {
46978
47864
  const chunks = [];
46979
47865
  req.on("data", (chunk) => chunks.push(Buffer.from(chunk)));
46980
47866
  req.on("end", () => {
46981
47867
  const raw = Buffer.concat(chunks).toString("utf-8");
46982
47868
  if (!raw.trim()) {
46983
- resolve25(undefined);
47869
+ resolve26(undefined);
46984
47870
  return;
46985
47871
  }
46986
47872
  try {
46987
- resolve25(JSON.parse(raw));
47873
+ resolve26(JSON.parse(raw));
46988
47874
  } catch {
46989
- resolve25(undefined);
47875
+ resolve26(undefined);
46990
47876
  }
46991
47877
  });
46992
47878
  req.on("error", reject);
@@ -47028,9 +47914,9 @@ async function startSkillsMcpHttpServer(options = {}) {
47028
47914
  }
47029
47915
  }
47030
47916
  });
47031
- await new Promise((resolve25, reject) => {
47917
+ await new Promise((resolve26, reject) => {
47032
47918
  httpServer.once("error", reject);
47033
- httpServer.listen(port, hostname4, () => resolve25());
47919
+ httpServer.listen(port, hostname4, () => resolve26());
47034
47920
  });
47035
47921
  const address = httpServer.address();
47036
47922
  const listenPort = typeof address === "object" && address ? address.port : port;