@hasna/skills 0.10.63 → 0.10.64

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.64",
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)}
@@ -33597,16 +34339,16 @@ var init_agent_codex = () => {};
33597
34339
 
33598
34340
  // src/lib/agent-sumi.ts
33599
34341
  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";
34342
+ import { accessSync, constants as constants9, existsSync as existsSync8, lstatSync as lstatSync15, realpathSync as realpathSync7, statSync as statSync7 } from "fs";
34343
+ import { delimiter, isAbsolute as isAbsolute12, join as join21, resolve as resolve13 } from "path";
33602
34344
  function recordWithKeys(value, keys) {
33603
34345
  return value !== null && typeof value === "object" && !Array.isArray(value) && Object.keys(value).length === keys.length && keys.every((key) => Object.hasOwn(value, key));
33604
34346
  }
33605
34347
  function absolutePath3(value) {
33606
- return typeof value === "string" && value.length > 0 && value.length <= 32768 && !/[\x00-\x1f\x7f]/.test(value) && isAbsolute11(value) && resolve12(value) === value;
34348
+ return typeof value === "string" && value.length > 0 && value.length <= 32768 && !/[\x00-\x1f\x7f]/.test(value) && isAbsolute12(value) && resolve13(value) === value;
33607
34349
  }
33608
34350
  function absoluteInput(value) {
33609
- return value.length > 0 && value.length <= 32768 && !/[\x00-\x1f\x7f]/.test(value) && isAbsolute11(value);
34351
+ return value.length > 0 && value.length <= 32768 && !/[\x00-\x1f\x7f]/.test(value) && isAbsolute12(value);
33610
34352
  }
33611
34353
  function resolveSumiPathsCommand(pathValue) {
33612
34354
  if (!pathValue)
@@ -33614,9 +34356,9 @@ function resolveSumiPathsCommand(pathValue) {
33614
34356
  for (const directory of pathValue.split(delimiter)) {
33615
34357
  if (!directory || /[\x00-\x1f\x7f]/.test(directory))
33616
34358
  continue;
33617
- const candidate = resolve12(directory, "sumi-paths");
34359
+ const candidate = resolve13(directory, "sumi-paths");
33618
34360
  try {
33619
- accessSync(candidate, constants8.X_OK);
34361
+ accessSync(candidate, constants9.X_OK);
33620
34362
  if (statSync7(candidate).isFile())
33621
34363
  return candidate;
33622
34364
  } catch {}
@@ -33626,7 +34368,7 @@ function resolveSumiPathsCommand(pathValue) {
33626
34368
  function validPathPlan(value, home, cwd) {
33627
34369
  if (!recordWithKeys(value, ["schemaVersion", "kind", "home", "cwd", "roots", "legacyRoots", "configFiles", "skillRoots"]))
33628
34370
  return false;
33629
- if (value.schemaVersion !== 1 || value.kind !== "sumi-paths" || value.home !== resolve12(home) || value.cwd !== resolve12(cwd))
34371
+ if (value.schemaVersion !== 1 || value.kind !== "sumi-paths" || value.home !== resolve13(home) || value.cwd !== resolve13(cwd))
33630
34372
  return false;
33631
34373
  if (!recordWithKeys(value.roots, SUMI_PATH_KEYS) || !recordWithKeys(value.legacyRoots, SUMI_PATH_KEYS))
33632
34374
  return false;
@@ -33648,11 +34390,11 @@ function validPathPlan(value, home, cwd) {
33648
34390
  const legacyConfigRoot = value.legacyRoots.config;
33649
34391
  if (typeof configRoot !== "string" || legacyConfigRoot !== null && typeof legacyConfigRoot !== "string")
33650
34392
  return false;
33651
- if (value.configFiles.canonical !== join20(configRoot, "sumi.json") || value.skillRoots.canonical !== join20(configRoot, "skills"))
34393
+ if (value.configFiles.canonical !== join21(configRoot, "sumi.json") || value.skillRoots.canonical !== join21(configRoot, "skills"))
33652
34394
  return false;
33653
34395
  if (legacyConfigRoot === null)
33654
34396
  return value.configFiles.legacy === null && value.skillRoots.legacy === null;
33655
- return value.configFiles.legacy === join20(legacyConfigRoot, "sumi.json") && value.skillRoots.legacy === join20(legacyConfigRoot, "skills");
34397
+ return value.configFiles.legacy === join21(legacyConfigRoot, "sumi.json") && value.skillRoots.legacy === join21(legacyConfigRoot, "skills");
33656
34398
  }
33657
34399
  function sumiPathPlan(home, cwd = process.cwd(), env = process.env) {
33658
34400
  for (const key of ["SUMI_CONFIG", "SUMI_CONFIG_CONTENT"])
@@ -33662,7 +34404,7 @@ function sumiPathPlan(home, cwd = process.cwd(), env = process.env) {
33662
34404
  throw new SumiPathResolverError("SUMI_PATH_INPUT_REFUSED");
33663
34405
  const runtimePath = process.env.PATH ?? "";
33664
34406
  const executable = resolveSumiPathsCommand(runtimePath);
33665
- if (!executable || !isAbsolute11(executable))
34407
+ if (!executable || !isAbsolute12(executable))
33666
34408
  throw new SumiPathResolverError("SUMI_PATH_RESOLVER_UNAVAILABLE");
33667
34409
  const childEnv = { PATH: runtimePath };
33668
34410
  for (const key of SUMI_PATH_SELECTORS)
@@ -33670,8 +34412,8 @@ function sumiPathPlan(home, cwd = process.cwd(), env = process.env) {
33670
34412
  childEnv[key] = env[key];
33671
34413
  let child2;
33672
34414
  try {
33673
- child2 = spawnSync4(executable, ["--json", "--home", resolve12(home), "--cwd", resolve12(cwd)], {
33674
- cwd: resolve12(cwd),
34415
+ child2 = spawnSync4(executable, ["--json", "--home", resolve13(home), "--cwd", resolve13(cwd)], {
34416
+ cwd: resolve13(cwd),
33675
34417
  env: childEnv,
33676
34418
  encoding: "buffer",
33677
34419
  timeout: 3000,
@@ -33700,17 +34442,17 @@ function sumiPathPlan(home, cwd = process.cwd(), env = process.env) {
33700
34442
  return result;
33701
34443
  }
33702
34444
  function selectedConfigDirectory(plan) {
33703
- const canonical7 = plan.roots.config, legacy = plan.legacyRoots.config;
34445
+ const canonical8 = plan.roots.config, legacy = plan.legacyRoots.config;
33704
34446
  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))
34447
+ return existsSync8(canonical8) ? realpathSync7(canonical8) : canonical8;
34448
+ const canonicalStat = lstatSync15(canonical8, { throwIfNoEntry: false }), legacyStat = lstatSync15(legacy, { throwIfNoEntry: false });
34449
+ if (canonicalStat && legacyStat && realpathSync7(canonical8) !== realpathSync7(legacy))
33708
34450
  throw new Error("Sumi config roots conflict; complete native home adoption before Skills integration");
33709
- const selected = canonicalStat ? canonical7 : legacyStat ? legacy : canonical7;
34451
+ const selected = canonicalStat ? canonical8 : legacyStat ? legacy : canonical8;
33710
34452
  if (!existsSync8(selected))
33711
34453
  return selected;
33712
- const physical = realpathSync5(selected);
33713
- if ((canonicalStat?.isSymbolicLink() || legacyStat?.isSymbolicLink()) && ![canonical7, legacy].includes(physical))
34454
+ const physical = realpathSync7(selected);
34455
+ if ((canonicalStat?.isSymbolicLink() || legacyStat?.isSymbolicLink()) && ![canonical8, legacy].includes(physical))
33714
34456
  throw new Error("Sumi config alias must resolve to its canonical or legacy root");
33715
34457
  return physical;
33716
34458
  }
@@ -33718,7 +34460,7 @@ function sumiConfigDirectory(home, env = process.env, cwd = process.cwd()) {
33718
34460
  return selectedConfigDirectory(sumiPathPlan(home, cwd, env));
33719
34461
  }
33720
34462
  function sumiConfigPath(home, cwd = process.cwd(), env = process.env) {
33721
- return join20(sumiConfigDirectory(home, env, cwd), "sumi.json");
34463
+ return join21(sumiConfigDirectory(home, env, cwd), "sumi.json");
33722
34464
  }
33723
34465
  var SUMI_PATH_SELECTORS, SUMI_PATH_KEYS, SUMI_PATH_OUTPUT_LIMIT, SumiPathResolverError;
33724
34466
  var init_agent_sumi = __esm(() => {
@@ -33736,9 +34478,9 @@ var init_agent_sumi = __esm(() => {
33736
34478
  });
33737
34479
 
33738
34480
  // 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";
34481
+ 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";
34482
+ import { createHash as createHash16 } from "crypto";
34483
+ import { dirname as dirname14, isAbsolute as isAbsolute13, resolve as resolve14 } from "path";
33742
34484
  function need6(value, code) {
33743
34485
  if (!value)
33744
34486
  throw new Error(`CODEX_HOOK_TRUST_${code}`);
@@ -33747,37 +34489,37 @@ function trustedAncestorOwner(uid) {
33747
34489
  return BigInt(uid) === 0n || BigInt(uid) === BigInt(process.getuid());
33748
34490
  }
33749
34491
  function safeParents(file2) {
33750
- for (let p = dirname13(file2);; p = dirname13(p)) {
33751
- const s = lstatSync15(p);
34492
+ for (let p = dirname14(file2);; p = dirname14(p)) {
34493
+ const s = lstatSync16(p);
33752
34494
  need6(s.isDirectory() && !s.isSymbolicLink() && trustedAncestorOwner(s.uid), "UNSAFE_PARENT");
33753
34495
  need6((s.mode & 18) === 0 || s.uid === 0 && (s.mode & 512) !== 0, "UNSAFE_PARENT");
33754
- if (dirname13(p) === p)
34496
+ if (dirname14(p) === p)
33755
34497
  break;
33756
34498
  }
33757
34499
  }
33758
34500
  function snapshot(file2, privateFile = false, options = {}) {
33759
34501
  const readOnlyPackage = options.readOnlyPackage === true && !privateFile;
33760
34502
  safeParents(file2);
33761
- const initial = lstatSync15(file2, { bigint: true });
34503
+ const initial = lstatSync16(file2, { bigint: true });
33762
34504
  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
34505
  need6(initial.size <= 8n * 1024n * 1024n, "FILE_BOUND");
33764
- const fd = openSync11(file2, constants9.O_RDONLY | constants9.O_NOFOLLOW | constants9.O_NONBLOCK);
34506
+ const fd = openSync12(file2, constants10.O_RDONLY | constants10.O_NOFOLLOW | constants10.O_NONBLOCK);
33765
34507
  try {
33766
- const before = fstatSync11(fd, { bigint: true });
34508
+ const before = fstatSync12(fd, { bigint: true });
33767
34509
  need6(sameStat(initial, before), "INPUT_CHANGED");
33768
34510
  const bytes = Buffer.alloc(Number(before.size) + 1);
33769
34511
  let length = 0;
33770
34512
  while (length < bytes.length) {
33771
- const n2 = readSync6(fd, bytes, length, bytes.length - length, null);
34513
+ const n2 = readSync7(fd, bytes, length, bytes.length - length, null);
33772
34514
  if (!n2)
33773
34515
  break;
33774
34516
  length += n2;
33775
34517
  }
33776
- need6(length === Number(before.size) && sameStat(before, fstatSync11(fd, { bigint: true })) && sameStat(before, lstatSync15(file2, { bigint: true })), "INPUT_CHANGED");
34518
+ need6(length === Number(before.size) && sameStat(before, fstatSync12(fd, { bigint: true })) && sameStat(before, lstatSync16(file2, { bigint: true })), "INPUT_CHANGED");
33777
34519
  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") };
34520
+ return { file: file2, privateFile, readOnlyPackage, text: text2, bytes: content, stat: before, sha256: createHash16("sha256").update(content).digest("hex") };
33779
34521
  } finally {
33780
- closeSync11(fd);
34522
+ closeSync12(fd);
33781
34523
  }
33782
34524
  }
33783
34525
  function unchanged2(before) {
@@ -33839,47 +34581,47 @@ var init_runtime_launcher = __esm(() => {
33839
34581
  });
33840
34582
 
33841
34583
  // 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";
34584
+ import { createHash as createHash17 } from "crypto";
34585
+ 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";
34586
+ import { dirname as dirname15, isAbsolute as isAbsolute14, join as join22, resolve as resolve15, sep as sep8 } from "path";
33845
34587
  function keys(value, names) {
33846
34588
  return Boolean(value && typeof value === "object" && !Array.isArray(value) && Object.keys(value).length === names.length && names.every((name) => Object.hasOwn(value, name)));
33847
34589
  }
33848
34590
  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 });
34591
+ need7(typeof path === "string" && path.length <= AGENT_POLICY_LIMITS.pathCharacters && isAbsolute14(path) && resolve15(path) === path && !/[\x00-\x1f\x7f]/.test(path));
34592
+ for (let cursor = path;; cursor = dirname15(cursor)) {
34593
+ const stat = lstatSync17(cursor, { throwIfNoEntry: false });
33852
34594
  need7(!stat?.isSymbolicLink());
33853
34595
  if (cursor !== path && stat)
33854
34596
  need7(stat.isDirectory());
33855
- if (dirname14(cursor) === cursor)
34597
+ if (dirname15(cursor) === cursor)
33856
34598
  break;
33857
34599
  }
33858
34600
  }
33859
34601
  function readExact(path) {
33860
34602
  safe3(path);
33861
- const before = lstatSync16(path, { throwIfNoEntry: false });
34603
+ const before = lstatSync17(path, { throwIfNoEntry: false });
33862
34604
  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);
34605
+ const fd = openSync13(path, constants11.O_RDONLY | constants11.O_NOFOLLOW | constants11.O_NONBLOCK);
33864
34606
  try {
33865
- const opened = fstatSync12(fd);
34607
+ const opened = fstatSync13(fd);
33866
34608
  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
34609
  const bytes = Buffer.alloc(opened.size);
33868
34610
  let offset = 0;
33869
34611
  while (offset < bytes.length) {
33870
- const count = readSync7(fd, bytes, offset, bytes.length - offset, null);
34612
+ const count = readSync8(fd, bytes, offset, bytes.length - offset, null);
33871
34613
  need7(count > 0);
33872
34614
  offset += count;
33873
34615
  }
33874
- need7(readSync7(fd, Buffer.alloc(1), 0, 1, null) === 0);
33875
- const after = fstatSync12(fd), current = lstatSync16(path, { throwIfNoEntry: false });
34616
+ need7(readSync8(fd, Buffer.alloc(1), 0, 1, null) === 0);
34617
+ const after = fstatSync13(fd), current = lstatSync17(path, { throwIfNoEntry: false });
33876
34618
  safe3(path);
33877
34619
  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
34620
  const text2 = new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(bytes);
33879
34621
  need7(Buffer.from(text2).equals(bytes));
33880
34622
  return text2;
33881
34623
  } finally {
33882
- closeSync12(fd);
34624
+ closeSync13(fd);
33883
34625
  }
33884
34626
  }
33885
34627
  function catalogDigest(text2) {
@@ -33887,7 +34629,7 @@ function catalogDigest(text2) {
33887
34629
  try {
33888
34630
  catalog = JSON.parse(text2);
33889
34631
  } catch {
33890
- return refuse3();
34632
+ return refuse4();
33891
34633
  }
33892
34634
  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
34635
  const skills = projectCodexNativeSkillCatalog({ data: [{ cwd: catalog.cwd, errors: [], skills: catalog.skills }] }, catalog.cwd);
@@ -33895,32 +34637,32 @@ function catalogDigest(text2) {
33895
34637
  return sha3(JSON.stringify({ version: catalog.version, cwd: catalog.cwd, skills, ...plugins === undefined ? {} : { plugins } }));
33896
34638
  }
33897
34639
  function retainedArtifactPath(metadata) {
33898
- return join21(metadata.storeRoot, "agent-discovery", "artifacts", metadata.sha256, "catalog.json");
34640
+ return join22(metadata.storeRoot, "agent-discovery", "artifacts", metadata.sha256, "catalog.json");
33899
34641
  }
33900
34642
  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));
34643
+ 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
34644
  }
33903
34645
  function privateStore(storeRoot) {
33904
34646
  safe3(storeRoot);
33905
- const stat = lstatSync16(storeRoot, { throwIfNoEntry: false });
34647
+ const stat = lstatSync17(storeRoot, { throwIfNoEntry: false });
33906
34648
  need7(!stat || stat.isDirectory() && (stat.mode & 18) === 0 && (process.getuid === undefined || stat.uid === process.getuid()));
33907
34649
  }
33908
34650
  function verifyRetainedReviewArtifact(source, storeRoot) {
33909
34651
  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)));
34652
+ 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
34653
  privateStore(artifact.storeRoot);
33912
34654
  const text2 = readExact(source.path);
33913
34655
  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);
34656
+ for (let parent = dirname15(source.path);parent !== artifact.storeRoot; parent = dirname15(parent)) {
34657
+ const stat = lstatSync17(parent);
33916
34658
  need7(stat.isDirectory() && (stat.mode & 63) === 0 && (process.getuid === undefined || stat.uid === process.getuid()));
33917
34659
  }
33918
34660
  }
33919
- var sha3 = (bytes) => createHash16("sha256").update(bytes).digest("hex"), hex3 = (value) => typeof value === "string" && /^[a-f0-9]{64}$/.test(value), refuse3 = () => {
34661
+ var sha3 = (bytes) => createHash17("sha256").update(bytes).digest("hex"), hex3 = (value) => typeof value === "string" && /^[a-f0-9]{64}$/.test(value), refuse4 = () => {
33920
34662
  throw new Error("REVIEW_ARTIFACT_INVALID");
33921
34663
  }, need7 = (condition) => {
33922
34664
  if (!condition)
33923
- refuse3();
34665
+ refuse4();
33924
34666
  };
33925
34667
  var init_retained_review_artifacts = __esm(() => {
33926
34668
  init_agent_policy_limits();
@@ -33937,6 +34679,8 @@ var init_agent_integration = __esm(() => {
33937
34679
  init_codex_native_skill_catalog();
33938
34680
  init_codex_settings_witness();
33939
34681
  init_claude_settings_witness();
34682
+ init_codex_native_compatibility();
34683
+ init_codex_semantic_cache_witness();
33940
34684
  init_native_discovery_roots();
33941
34685
  init_config();
33942
34686
  init_managed_policy();
@@ -33987,12 +34731,12 @@ var init_skill_aliases = __esm(() => {
33987
34731
 
33988
34732
  // src/lib/project-state.ts
33989
34733
  import { existsSync as existsSync9, mkdirSync as mkdirSync6, readFileSync as readFileSync13, writeFileSync as writeFileSync5 } from "fs";
33990
- import { join as join22 } from "path";
34734
+ import { join as join23 } from "path";
33991
34735
  function getProjectStateDir(targetDir = process.cwd()) {
33992
- return join22(targetDir, SKILLS_PROJECT_DIR);
34736
+ return join23(targetDir, SKILLS_PROJECT_DIR);
33993
34737
  }
33994
34738
  function getProjectConfigPath(targetDir = process.cwd()) {
33995
- return join22(getProjectStateDir(targetDir), PROJECT_CONFIG_FILE);
34739
+ return join23(getProjectStateDir(targetDir), PROJECT_CONFIG_FILE);
33996
34740
  }
33997
34741
  function loadProjectConfig(targetDir = process.cwd()) {
33998
34742
  const path = getProjectConfigPath(targetDir);
@@ -34108,7 +34852,7 @@ var init_project_state = __esm(() => {
34108
34852
 
34109
34853
  // src/lib/installer.ts
34110
34854
  import { existsSync as existsSync10, readFileSync as readFileSync14, rmSync } from "fs";
34111
- import { join as join23 } from "path";
34855
+ import { join as join24 } from "path";
34112
34856
  import { homedir as homedir2 } from "os";
34113
34857
  function getSkillPath(name) {
34114
34858
  const skillName = normalizeSkillName(getCanonicalSkillName(name));
@@ -34118,7 +34862,7 @@ function getSkillPath(name) {
34118
34862
  const extensionPath = findExtensionSkillPath(skillName);
34119
34863
  if (extensionPath)
34120
34864
  return extensionPath;
34121
- return join23(getPortableSkillsRoot(), skillName);
34865
+ return join24(getPortableSkillsRoot(), skillName);
34122
34866
  }
34123
34867
  function getCanonicalSkillName(name) {
34124
34868
  return getSkill(name)?.name ?? resolveSkillAlias(normalizeSkillSlug(name));
@@ -34172,11 +34916,11 @@ function getAgentSkillsDir(agent, scope = "global", projectDir) {
34172
34916
  const base = projectDir || process.cwd();
34173
34917
  switch (agent) {
34174
34918
  case "pi":
34175
- return scope === "project" ? join23(base, ".pi", "skills") : join23(homedir2(), ".pi", "agent", "skills");
34919
+ return scope === "project" ? join24(base, ".pi", "skills") : join24(homedir2(), ".pi", "agent", "skills");
34176
34920
  case "opencode":
34177
- return scope === "project" ? join23(base, ".opencode", "skills") : join23(homedir2(), ".config", "opencode", "skills");
34921
+ return scope === "project" ? join24(base, ".opencode", "skills") : join24(homedir2(), ".config", "opencode", "skills");
34178
34922
  default:
34179
- return scope === "project" ? join23(base, `.${agent}`, "skills") : join23(homedir2(), `.${agent}`, "skills");
34923
+ return scope === "project" ? join24(base, `.${agent}`, "skills") : join24(homedir2(), `.${agent}`, "skills");
34180
34924
  }
34181
34925
  }
34182
34926
  function warnMissingDependencies(name, targetDir) {
@@ -34191,7 +34935,7 @@ function warnMissingDependencies(name, targetDir) {
34191
34935
  }
34192
34936
  }
34193
34937
  function readBundledSkillVersion(name) {
34194
- const pkgPath = join23(getSkillPath(name), "package.json");
34938
+ const pkgPath = join24(getSkillPath(name), "package.json");
34195
34939
  if (!existsSync10(pkgPath))
34196
34940
  return "unknown";
34197
34941
  try {
@@ -34261,11 +35005,11 @@ var init_skill_doc_file = __esm(() => {
34261
35005
 
34262
35006
  // src/lib/skillinfo.ts
34263
35007
  import { existsSync as existsSync11, readFileSync as readFileSync15 } from "fs";
34264
- import { join as join24 } from "path";
35008
+ import { join as join25 } from "path";
34265
35009
  function isInstructionSkillDir(skillPath, meta3) {
34266
35010
  if (meta3?.kind === "instruction")
34267
35011
  return true;
34268
- const skillMdPath = join24(skillPath, "SKILL.md");
35012
+ const skillMdPath = join25(skillPath, "SKILL.md");
34269
35013
  if (!existsSync11(skillMdPath))
34270
35014
  return false;
34271
35015
  try {
@@ -34279,9 +35023,9 @@ function getSkillDocs(name) {
34279
35023
  if (!existsSync11(skillPath))
34280
35024
  return null;
34281
35025
  return {
34282
- skillMd: readIfExists(join24(skillPath, "SKILL.md")),
34283
- readme: readIfExists(join24(skillPath, "README.md")),
34284
- claudeMd: readIfExists(join24(skillPath, "CLAUDE.md"))
35026
+ skillMd: readIfExists(join25(skillPath, "SKILL.md")),
35027
+ readme: readIfExists(join25(skillPath, "README.md")),
35028
+ claudeMd: readIfExists(join25(skillPath, "CLAUDE.md"))
34285
35029
  };
34286
35030
  }
34287
35031
  function getSkillBestDoc(name, file2) {
@@ -34297,14 +35041,14 @@ function getSkillRequirements(name) {
34297
35041
  return null;
34298
35042
  const texts = [];
34299
35043
  for (const file2 of ["SKILL.md", "README.md", "CLAUDE.md", ".env.example", ".env.local.example"]) {
34300
- const content = readIfExists(join24(skillPath, file2));
35044
+ const content = readIfExists(join25(skillPath, file2));
34301
35045
  if (content)
34302
35046
  texts.push(content);
34303
35047
  }
34304
35048
  const meta3 = getSkill(name);
34305
35049
  let dependencies = {};
34306
35050
  try {
34307
- dependencies = JSON.parse(readFileSync15(join24(skillPath, "package.json"), "utf8")).dependencies || {};
35051
+ dependencies = JSON.parse(readFileSync15(join25(skillPath, "package.json"), "utf8")).dependencies || {};
34308
35052
  } catch {}
34309
35053
  return getSkillRequirementsFromContent(name, texts, dependencies, meta3);
34310
35054
  }
@@ -34366,7 +35110,7 @@ async function runSkill(name, args, options = {}) {
34366
35110
  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
35111
  };
34368
35112
  }
34369
- const pkgPath = join24(skillPath, "package.json");
35113
+ const pkgPath = join25(skillPath, "package.json");
34370
35114
  if (!existsSync11(pkgPath)) {
34371
35115
  return { exitCode: 1, error: `No package.json in skill '${name}'` };
34372
35116
  }
@@ -34386,12 +35130,12 @@ async function runSkill(name, args, options = {}) {
34386
35130
  } catch {
34387
35131
  return { exitCode: 1, error: `Failed to parse package.json for skill '${name}'` };
34388
35132
  }
34389
- const entryPath = join24(skillPath, entryPoint2);
35133
+ const entryPath = join25(skillPath, entryPoint2);
34390
35134
  if (!existsSync11(entryPath)) {
34391
35135
  return { exitCode: 1, error: `Entry point '${entryPoint2}' not found in skill '${name}'` };
34392
35136
  }
34393
35137
  const env = { ...process.env, ...options.env };
34394
- if (!existsSync11(join24(skillPath, "node_modules")) || hasDependencyPreparationMarker(skillPath)) {
35138
+ if (!existsSync11(join25(skillPath, "node_modules")) || hasDependencyPreparationMarker(skillPath)) {
34395
35139
  const failure = await prepareSkillDependencies(skillPath, env, options.preparationTimeoutMs);
34396
35140
  if (failure)
34397
35141
  return failure;
@@ -34417,7 +35161,7 @@ async function runSkill(name, args, options = {}) {
34417
35161
  function detectProjectSkills(cwd = process.cwd()) {
34418
35162
  let pkg;
34419
35163
  try {
34420
- pkg = JSON.parse(readFileSync15(join24(cwd, "package.json"), "utf8"));
35164
+ pkg = JSON.parse(readFileSync15(join25(cwd, "package.json"), "utf8"));
34421
35165
  } catch {
34422
35166
  return { detected: [], recommended: [] };
34423
35167
  }
@@ -34622,7 +35366,7 @@ var init_selection_resolver = __esm(() => {
34622
35366
  });
34623
35367
 
34624
35368
  // src/lib/plugin-projection.ts
34625
- import { createHash as createHash17 } from "crypto";
35369
+ import { createHash as createHash18 } from "crypto";
34626
35370
  function pluginRefusal(message) {
34627
35371
  throw new SkillSelectionError("PLUGIN_ADMISSION_REFUSED", message);
34628
35372
  }
@@ -34700,26 +35444,26 @@ function pluginFileWitnesses(entries) {
34700
35444
  return { path: item.path, mode: item.mode, size: item.bytes.byteLength, sha256: pluginHash(item.bytes) };
34701
35445
  });
34702
35446
  }
34703
- var PLUGIN_PROJECTION_LIMITS, pluginHash = (bytes) => createHash17("sha256").update(bytes).digest("hex");
35447
+ var PLUGIN_PROJECTION_LIMITS, pluginHash = (bytes) => createHash18("sha256").update(bytes).digest("hex");
34704
35448
  var init_plugin_projection = __esm(() => {
34705
35449
  init_selection_cache();
34706
35450
  PLUGIN_PROJECTION_LIMITS = Object.freeze({ files: 1024, bytes: 64 * 1024 * 1024, fileBytes: 16 * 1024 * 1024, metadataBytes: 512 * 1024, registrations: 64, history: 128 });
34707
35451
  });
34708
35452
 
34709
35453
  // 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";
35454
+ 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";
35455
+ import { dirname as dirname16, isAbsolute as isAbsolute15, join as join26, parse as parse10, resolve as resolve16 } from "path";
34712
35456
  function stat(path) {
34713
35457
  try {
34714
- return lstatSync17(path, { bigint: true });
35458
+ return lstatSync18(path, { bigint: true });
34715
35459
  } catch (error61) {
34716
35460
  if (missing(error61))
34717
35461
  return null;
34718
35462
  return pluginRefusal("Cannot inspect plugin filesystem entry");
34719
35463
  }
34720
35464
  }
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");
35465
+ function canonical8(path) {
35466
+ 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
35467
  }
34724
35468
  function owner(stats, system = false) {
34725
35469
  const current = uid();
@@ -34729,12 +35473,12 @@ function same3(left, right, identityOnly = false) {
34729
35473
  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
35474
  }
34731
35475
  function ancestors(path, create = false) {
34732
- canonical7(path);
34733
- const result = [], parent = dirname15(path), filesystemRoot = parse10(parent).root;
35476
+ canonical8(path);
35477
+ const result = [], parent = dirname16(path), filesystemRoot = parse10(parent).root;
34734
35478
  let current = filesystemRoot;
34735
35479
  for (const segment of ["", ...parent.slice(filesystemRoot.length).split("/").filter(Boolean)]) {
34736
35480
  if (segment)
34737
- current = join25(current, segment);
35481
+ current = join26(current, segment);
34738
35482
  let currentStat = stat(current);
34739
35483
  if (!currentStat && create) {
34740
35484
  try {
@@ -34780,19 +35524,19 @@ function readBytes(path, maximum, kind) {
34780
35524
  fileShape(before, maximum, kind);
34781
35525
  let fd;
34782
35526
  try {
34783
- fd = openSync13(path, READ_FLAGS);
34784
- const opened = fstatSync13(fd, { bigint: true });
35527
+ fd = openSync14(path, READ_FLAGS);
35528
+ const opened = fstatSync14(fd, { bigint: true });
34785
35529
  same3(before, opened);
34786
35530
  fileShape(opened, maximum, kind);
34787
35531
  const bytes = new Uint8Array(Number(opened.size));
34788
35532
  let offset = 0;
34789
35533
  while (offset < bytes.byteLength) {
34790
- const count = readSync8(fd, bytes, offset, bytes.byteLength - offset, null);
35534
+ const count = readSync9(fd, bytes, offset, bytes.byteLength - offset, null);
34791
35535
  pluginNeed(count > 0, "Plugin file changed while being read");
34792
35536
  offset += count;
34793
35537
  }
34794
- pluginNeed(readSync8(fd, new Uint8Array(1), 0, 1, null) === 0, "Plugin file grew while being read");
34795
- same3(opened, fstatSync13(fd, { bigint: true }));
35538
+ pluginNeed(readSync9(fd, new Uint8Array(1), 0, 1, null) === 0, "Plugin file grew while being read");
35539
+ same3(opened, fstatSync14(fd, { bigint: true }));
34796
35540
  same3(opened, stat(path));
34797
35541
  verifyAncestors(chain);
34798
35542
  return bytes;
@@ -34802,7 +35546,7 @@ function readBytes(path, maximum, kind) {
34802
35546
  return pluginRefusal("Cannot safely read plugin file");
34803
35547
  } finally {
34804
35548
  if (fd !== undefined)
34805
- closeSync13(fd);
35549
+ closeSync14(fd);
34806
35550
  }
34807
35551
  }
34808
35552
  function exactPaths(entries) {
@@ -34832,7 +35576,7 @@ function directoryNames(path) {
34832
35576
  function snapshotPluginTree(root, options = {}) {
34833
35577
  const chain = ancestors(root), entries = [], files = [], directories = [];
34834
35578
  let bytes = 0, visited = 0;
34835
- const visit3 = (directory, relative6) => {
35579
+ const visit3 = (directory, relative7) => {
34836
35580
  const before = stat(directory);
34837
35581
  pluginNeed(before && before.isDirectory() && !before.isSymbolicLink(), "Plugin tree must contain real directories");
34838
35582
  const names = directoryNames(directory);
@@ -34840,18 +35584,18 @@ function snapshotPluginTree(root, options = {}) {
34840
35584
  directories.push({ path: directory, stat: before, names });
34841
35585
  for (const name of names) {
34842
35586
  pluginNeed(++visited <= PLUGIN_PROJECTION_LIMITS.files * 50, "Plugin tree membership exceeds its limit");
34843
- const path = relative6 ? `${relative6}/${name}` : name;
35587
+ const path = relative7 ? `${relative7}/${name}` : name;
34844
35588
  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);
35589
+ const absolute = join26(directory, name), entryStat = stat(absolute);
34846
35590
  pluginNeed(entryStat, "Plugin tree member disappeared");
34847
- if (relative6 === "" && name === ".orphaned_at" && (options.nativeRuntime === "claude-2.1.274" || options.nativeRuntime === "claude-2.1.276")) {
35591
+ if (relative7 === "" && name === ".orphaned_at" && (options.nativeRuntime === "claude-2.1.274" || options.nativeRuntime === "claude-2.1.276")) {
34848
35592
  const bytes2 = readBytes(absolute, 32, "native-pin");
34849
35593
  pluginNeed(/^[1-9][0-9]{12}$/.test(new TextDecoder().decode(bytes2)), "Malformed native orphan timestamp");
34850
35594
  same3(entryStat, stat(absolute));
34851
35595
  files.push({ path: absolute, stat: entryStat });
34852
35596
  continue;
34853
35597
  }
34854
- if (relative6 === "" && name === ".in_use" && (options.nativeRuntime === "claude-2.1.274" || options.nativeRuntime === "claude-2.1.276")) {
35598
+ if (relative7 === "" && name === ".in_use" && (options.nativeRuntime === "claude-2.1.274" || options.nativeRuntime === "claude-2.1.276")) {
34855
35599
  pluginNeed(entryStat.isDirectory() && !entryStat.isSymbolicLink(), "Native plugin pins require a real directory");
34856
35600
  owner(entryStat);
34857
35601
  const pins = directoryNames(absolute);
@@ -34859,7 +35603,7 @@ function snapshotPluginTree(root, options = {}) {
34859
35603
  directories.push({ path: absolute, stat: entryStat, names: pins });
34860
35604
  for (const pin of pins) {
34861
35605
  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);
35606
+ const pinPath = join26(absolute, pin), pinStat = stat(pinPath);
34863
35607
  pluginNeed(pinStat, "Native plugin pin disappeared");
34864
35608
  const bytes2 = readBytes(pinPath, 4096, "native-pin");
34865
35609
  let value;
@@ -34925,8 +35669,8 @@ function readPluginJson(path) {
34925
35669
  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
35670
  var init_plugin_projection_store = __esm(() => {
34927
35671
  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;
35672
+ READ_FLAGS = constants12.O_RDONLY | constants12.O_NOFOLLOW | constants12.O_NONBLOCK;
35673
+ WRITE_FLAGS = constants12.O_WRONLY | constants12.O_CREAT | constants12.O_EXCL | constants12.O_NOFOLLOW | constants12.O_NONBLOCK;
34930
35674
  });
34931
35675
 
34932
35676
  // src/lib/selected-manifest.ts
@@ -34956,7 +35700,7 @@ var init_selected_manifest = __esm(() => {
34956
35700
  });
34957
35701
 
34958
35702
  // src/lib/plugin-admission.ts
34959
- import { isAbsolute as isAbsolute15, join as join26, resolve as resolve16 } from "path";
35703
+ import { isAbsolute as isAbsolute16, join as join27, resolve as resolve17 } from "path";
34960
35704
  function validatePluginTarget(value) {
34961
35705
  pluginKeys(value, ["schemaVersion", "pluginId", "registrations", "native", "resolver"]);
34962
35706
  pluginNeed(value.schemaVersion === 1, "Invalid plugin admission target");
@@ -34966,7 +35710,7 @@ function validatePluginTarget(value) {
34966
35710
  for (const registration of value.registrations) {
34967
35711
  pluginKeys(registration, ["scope", "projectPath"]);
34968
35712
  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");
35713
+ 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
35714
  const key = JSON.stringify([registration.scope, registration.projectPath]);
34971
35715
  pluginNeed(!scopes.has(key), "Duplicate plugin registration scope");
34972
35716
  scopes.add(key);
@@ -34974,7 +35718,7 @@ function validatePluginTarget(value) {
34974
35718
  for (const key of ["native", "resolver"]) {
34975
35719
  pluginKeys(value[key], key === "native" ? ["version", "executable", "digest"] : ["executable", "digest"]);
34976
35720
  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");
35721
+ pluginNeed(isAbsolute16(value[key].executable) && resolve17(value[key].executable) === value[key].executable, "Plugin executable must have a canonical absolute path");
34978
35722
  pluginDigest(value[key].digest);
34979
35723
  }
34980
35724
  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 +35861,12 @@ function pluginResolverCommand(binding) {
35117
35861
  }
35118
35862
  function pluginBindingPath(storeRoot, id) {
35119
35863
  pluginNeed(/^[a-f0-9]{64}$/.test(id), "Invalid plugin binding identifier");
35120
- return join26(storeRoot, "bindings", `${id}.json`);
35864
+ return join27(storeRoot, "bindings", `${id}.json`);
35121
35865
  }
35122
- function pluginReceiptPath(storeRoot, id, digest) {
35866
+ function pluginReceiptPath(storeRoot, id, digest2) {
35123
35867
  pluginNeed(/^[a-f0-9]{64}$/.test(id), "Invalid plugin binding identifier");
35124
- pluginDigest(digest);
35125
- return join26(storeRoot, "receipts", id, `${digest.slice(7)}.json`);
35868
+ pluginDigest(digest2);
35869
+ return join27(storeRoot, "receipts", id, `${digest2.slice(7)}.json`);
35126
35870
  }
35127
35871
  function readPluginBinding(storeRoot, id) {
35128
35872
  const value = readPluginJson(pluginBindingPath(storeRoot, id));
@@ -35131,18 +35875,18 @@ function readPluginBinding(storeRoot, id) {
35131
35875
  pluginNeed(bindingId(binding) === id, "Plugin admission binding changed");
35132
35876
  return binding;
35133
35877
  }
35134
- function readPluginAdmissionReceipt(storeRoot, id, digest) {
35135
- const value = readPluginJson(pluginReceiptPath(storeRoot, id, digest));
35878
+ function readPluginAdmissionReceipt(storeRoot, id, digest2) {
35879
+ const value = readPluginJson(pluginReceiptPath(storeRoot, id, digest2));
35136
35880
  pluginKeys(value, ["schemaVersion", "plan", "materializedPath", "admittedAt"]);
35137
35881
  pluginNeed(value.schemaVersion === 3, "Unsupported plugin admission receipt; schema version 3 is required");
35138
35882
  validatePlan(value.plan);
35139
35883
  const receipt = value;
35140
35884
  receipt.plan.files = normalizedWitnesses(receipt.plan.files);
35141
35885
  receipt.plan.removed = normalizedWitnesses(receipt.plan.removed);
35142
- pluginNeed(receipt.plan.bindingId === id && receipt.plan.planDigest === digest, "Plugin receipt identity differs from its filename");
35886
+ pluginNeed(receipt.plan.bindingId === id && receipt.plan.planDigest === digest2, "Plugin receipt identity differs from its filename");
35143
35887
  const binding = readPluginBinding(storeRoot, id);
35144
35888
  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");
35889
+ pluginNeed(receipt.materializedPath === join27(storeRoot, "objects", id, digest2.slice(7)), "Plugin receipt points outside its immutable materialization");
35146
35890
  pluginText(receipt.admittedAt, 64);
35147
35891
  pluginNeed(Number.isFinite(Date.parse(receipt.admittedAt)), "Invalid plugin admission time");
35148
35892
  return receipt;
@@ -35159,8 +35903,8 @@ var init_plugin_admission = __esm(() => {
35159
35903
  });
35160
35904
 
35161
35905
  // 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";
35906
+ import { closeSync as closeSync15, constants as constants13, fstatSync as fstatSync15, lstatSync as lstatSync19, openSync as openSync15, opendirSync as opendirSync3, readSync as readSync10 } from "fs";
35907
+ import { basename as basename7, dirname as dirname17, isAbsolute as isAbsolute17, join as join28, resolve as resolve18 } from "path";
35164
35908
  function validateManagedPluginWitnesses(value) {
35165
35909
  pluginNeed(Array.isArray(value) && value.length > 0 && value.length <= PLUGIN_PROJECTION_LIMITS.registrations, "Invalid managed plugin witness collection");
35166
35910
  const seen = new Set;
@@ -35169,35 +35913,35 @@ function validateManagedPluginWitnesses(value) {
35169
35913
  pluginNeed(typeof item.bindingId === "string" && /^[a-f0-9]{64}$/.test(item.bindingId) && !seen.has(item.bindingId), "Invalid or duplicate managed plugin witness");
35170
35914
  seen.add(item.bindingId);
35171
35915
  pluginText(item.storeRoot);
35172
- pluginNeed(isAbsolute16(item.storeRoot) && resolve17(item.storeRoot) === item.storeRoot, "Invalid plugin receipt store path");
35916
+ pluginNeed(isAbsolute17(item.storeRoot) && resolve18(item.storeRoot) === item.storeRoot, "Invalid plugin receipt store path");
35173
35917
  }
35174
35918
  }
35175
35919
  function safe4(path) {
35176
35920
  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))
35921
+ pluginNeed(isAbsolute17(path) && resolve18(path) === path, "Invalid plugin registry path");
35922
+ for (let at = path;; at = dirname17(at)) {
35923
+ pluginNeed(!lstatSync19(at, { throwIfNoEntry: false })?.isSymbolicLink(), "Plugin registry path traverses a symlink");
35924
+ if (at === dirname17(at))
35181
35925
  break;
35182
35926
  }
35183
35927
  }
35184
35928
  function readRegistry(path) {
35185
35929
  safe4(path);
35186
- const initial = lstatSync18(path);
35930
+ const initial = lstatSync19(path);
35187
35931
  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);
35932
+ const fd = openSync15(path, constants13.O_RDONLY | constants13.O_NOFOLLOW | constants13.O_NONBLOCK);
35189
35933
  try {
35190
- const opened = fstatSync14(fd);
35934
+ const opened = fstatSync15(fd);
35191
35935
  pluginNeed(opened.isFile() && opened.ino === initial.ino && opened.dev === initial.dev, "Plugin registry changed during open");
35192
35936
  const bytes = Buffer.alloc(1024 * 1024 + 1);
35193
35937
  let length = 0;
35194
35938
  while (length < bytes.length) {
35195
- const count = readSync9(fd, bytes, length, bytes.length - length, null);
35939
+ const count = readSync10(fd, bytes, length, bytes.length - length, null);
35196
35940
  if (!count)
35197
35941
  break;
35198
35942
  length += count;
35199
35943
  }
35200
- const after = fstatSync14(fd), current = lstatSync18(path);
35944
+ const after = fstatSync15(fd), current = lstatSync19(path);
35201
35945
  safe4(path);
35202
35946
  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
35947
  let value;
@@ -35209,7 +35953,7 @@ function readRegistry(path) {
35209
35953
  pluginNeed(pluginObject(value) && value.version === 2 && pluginObject(value.plugins), "Unsupported native plugin registry schema");
35210
35954
  return { value, rawDigest: pluginHash(bytes.subarray(0, length)) };
35211
35955
  } finally {
35212
- closeSync14(fd);
35956
+ closeSync15(fd);
35213
35957
  }
35214
35958
  }
35215
35959
  function nativeVersionMatches(version2, receipt) {
@@ -35227,7 +35971,7 @@ function hashManagedPluginRegistry(path, managed) {
35227
35971
  seen.add(target.pluginId);
35228
35972
  const rows = plugins[target.pluginId];
35229
35973
  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);
35974
+ const [name, market] = target.pluginId.split("@"), cacheRoot = join28(dirname17(path), "cache", market, name);
35231
35975
  const scopes = new Set, approvals = new Map, currentFiles = new Map;
35232
35976
  plugins[target.pluginId] = rows.map((row) => {
35233
35977
  pluginNeed(pluginObject(row), "Invalid managed plugin registration");
@@ -35240,11 +35984,11 @@ function hashManagedPluginRegistry(path, managed) {
35240
35984
  pluginText(row.sourceProducerPath);
35241
35985
  pluginText(row.lastUpdated, 64);
35242
35986
  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");
35987
+ 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
35988
  const approval = (producer) => {
35245
35989
  pluginText(producer);
35246
- const digest = `sha256:${basename7(producer)}`;
35247
- const receipt2 = readPluginAdmissionReceipt(witness.storeRoot, witness.bindingId, digest);
35990
+ const digest2 = `sha256:${basename7(producer)}`;
35991
+ const receipt2 = readPluginAdmissionReceipt(witness.storeRoot, witness.bindingId, digest2);
35248
35992
  pluginNeed(receipt2.materializedPath === producer, "Managed producer path is not an approved immutable projection");
35249
35993
  if (!verified.has(producer)) {
35250
35994
  verifiedBytes += receipt2.plan.files.reduce((total, file2) => total + file2.size, 0);
@@ -35270,7 +36014,7 @@ function hashManagedPluginRegistry(path, managed) {
35270
36014
  return Object.fromEntries(Object.entries(row).filter(([key]) => !["version", "installPath", "sourceProducerPath", "previousProducerPaths", "lastUpdated"].includes(key)));
35271
36015
  });
35272
36016
  safe4(cacheRoot);
35273
- const before = lstatSync18(cacheRoot);
36017
+ const before = lstatSync19(cacheRoot);
35274
36018
  pluginNeed(before.isDirectory(), "Invalid managed plugin cache root");
35275
36019
  const directory = opendirSync3(cacheRoot), names = [];
35276
36020
  try {
@@ -35283,17 +36027,17 @@ function hashManagedPluginRegistry(path, managed) {
35283
36027
  directory.closeSync();
35284
36028
  }
35285
36029
  for (const version2 of names.sort()) {
35286
- const files = pluginFileWitnesses(snapshotPluginTree(join27(cacheRoot, version2), { nativeRuntime: `claude-${target.native.version}` }));
36030
+ const files = pluginFileWitnesses(snapshotPluginTree(join28(cacheRoot, version2), { nativeRuntime: `claude-${target.native.version}` }));
35287
36031
  verifiedBytes += files.reduce((total, file2) => total + file2.size, 0);
35288
36032
  pluginNeed(verifiedBytes <= 256 * 1024 * 1024, "Managed plugin verification exceeds its aggregate byte budget");
35289
36033
  const serialized = JSON.stringify(files);
35290
- const expected = currentFiles.get(join27(cacheRoot, version2));
36034
+ const expected = currentFiles.get(join28(cacheRoot, version2));
35291
36035
  pluginNeed(expected === undefined || serialized === expected, "Current native cache differs from its exact registered producer receipt");
35292
36036
  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
36037
  }
35294
36038
  for (const row of rows)
35295
36039
  pluginNeed(names.includes(row.version), "Managed native plugin installation is missing");
35296
- const after = lstatSync18(cacheRoot);
36040
+ const after = lstatSync19(cacheRoot);
35297
36041
  safe4(cacheRoot);
35298
36042
  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
36043
  }
@@ -35307,23 +36051,23 @@ var init_plugin_discovery = __esm(() => {
35307
36051
  });
35308
36052
 
35309
36053
  // 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";
36054
+ import { createHash as createHash19 } from "crypto";
36055
+ import { closeSync as closeSync16, constants as constants14, fstatSync as fstatSync16, lstatSync as lstatSync20, openSync as openSync16, readSync as readSync11 } from "fs";
36056
+ import { basename as basename8, dirname as dirname18, isAbsolute as isAbsolute18, resolve as resolve19 } from "path";
35313
36057
  function need8(value, reason2) {
35314
36058
  if (!value)
35315
36059
  throw new Error(`Claude marketplace registry ${reason2}`);
35316
36060
  }
35317
36061
  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");
36062
+ 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
36063
  }
35320
36064
  function parents2(path) {
35321
36065
  const result = [];
35322
- for (let at = dirname17(path);; at = dirname17(at)) {
35323
- const stat2 = lstatSync19(at, { bigint: true });
36066
+ for (let at = dirname18(path);; at = dirname18(at)) {
36067
+ const stat2 = lstatSync20(at, { bigint: true });
35324
36068
  need8(stat2.isDirectory() && !stat2.isSymbolicLink(), "path traverses a symlink or non-directory");
35325
36069
  result.push([at, stat2]);
35326
- if (at === dirname17(at))
36070
+ if (at === dirname18(at))
35327
36071
  return result;
35328
36072
  }
35329
36073
  }
@@ -35331,25 +36075,25 @@ function readRegistry2(path, budget2) {
35331
36075
  absolutePath4(path);
35332
36076
  need8(basename8(path) === "known_marketplaces.json", "requires known_marketplaces.json");
35333
36077
  need8(Number.isSafeInteger(budget2.remaining) && budget2.remaining >= 0, "has an invalid byte budget");
35334
- const ancestors2 = parents2(path), initial = lstatSync19(path, { bigint: true });
36078
+ const ancestors2 = parents2(path), initial = lstatSync20(path, { bigint: true });
35335
36079
  need8(initial.isFile() && !initial.isSymbolicLink() && initial.size <= BigInt(CLAUDE_MARKETPLACE_REGISTRY_LIMITS.bytes), "is not a bounded regular file");
35336
36080
  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);
36081
+ const fd = openSync16(path, constants14.O_RDONLY | constants14.O_NOFOLLOW | constants14.O_NONBLOCK);
35338
36082
  try {
35339
- const opened = fstatSync15(fd, { bigint: true });
36083
+ const opened = fstatSync16(fd, { bigint: true });
35340
36084
  need8(opened.isFile() && sameFile2(initial, opened), "changed during open");
35341
36085
  const bytes = Buffer.alloc(Number(opened.size) + 1);
35342
36086
  let length = 0;
35343
36087
  while (length < bytes.length) {
35344
- const count = readSync10(fd, bytes, length, bytes.length - length, null);
36088
+ const count = readSync11(fd, bytes, length, bytes.length - length, null);
35345
36089
  if (!count)
35346
36090
  break;
35347
36091
  length += count;
35348
36092
  }
35349
- const after = fstatSync15(fd, { bigint: true }), current = lstatSync19(path, { bigint: true });
36093
+ const after = fstatSync16(fd, { bigint: true }), current = lstatSync20(path, { bigint: true });
35350
36094
  need8(current.isFile() && sameFile2(opened, after) && sameFile2(after, current) && BigInt(length) === opened.size, "changed during read");
35351
36095
  for (const [ancestor, before] of ancestors2) {
35352
- const now = lstatSync19(ancestor, { bigint: true });
36096
+ const now = lstatSync20(ancestor, { bigint: true });
35353
36097
  need8(now.isDirectory() && before.dev === now.dev && before.ino === now.ino && before.mode === now.mode, "parent changed during read");
35354
36098
  }
35355
36099
  budget2.remaining -= length;
@@ -35359,7 +36103,7 @@ function readRegistry2(path, budget2) {
35359
36103
  throw new Error("Claude marketplace registry is not strict UTF-8");
35360
36104
  }
35361
36105
  } finally {
35362
- closeSync15(fd);
36106
+ closeSync16(fd);
35363
36107
  }
35364
36108
  }
35365
36109
  function parse11(text2) {
@@ -35436,7 +36180,7 @@ function parse11(text2) {
35436
36180
  need8(root.entries.length <= CLAUDE_MARKETPLACE_REGISTRY_LIMITS.rows, "exceeds its marketplace row limit");
35437
36181
  return root;
35438
36182
  }
35439
- function exactKeys(value, keys2) {
36183
+ function exactKeys2(value, keys2) {
35440
36184
  return value?.kind === "object" && value.entries.length === keys2.length && value.entries.every(([key]) => keys2.includes(key));
35441
36185
  }
35442
36186
  function textField(value) {
@@ -35444,8 +36188,8 @@ function textField(value) {
35444
36188
  return value.value;
35445
36189
  }
35446
36190
  function normalizeRow(row, version2 = 1) {
35447
- if (!exactKeys(row, ["source", "installLocation", "lastUpdated"])) {
35448
- if (version2 !== 2 || !exactKeys(row, ["source", "installLocation", "lastUpdated", "autoUpdate"]))
36191
+ if (!exactKeys2(row, ["source", "installLocation", "lastUpdated"])) {
36192
+ if (version2 !== 2 || !exactKeys2(row, ["source", "installLocation", "lastUpdated", "autoUpdate"]))
35449
36193
  return;
35450
36194
  const autoUpdate = field2(row, "autoUpdate");
35451
36195
  need8(autoUpdate?.kind === "literal" && (autoUpdate.value === "true" || autoUpdate.value === "false"), "contains an invalid automatic-update preference");
@@ -35457,7 +36201,7 @@ function normalizeRow(row, version2 = 1) {
35457
36201
  if (type?.kind !== "string" || !["github", "directory"].includes(type.value))
35458
36202
  return;
35459
36203
  const location = type.value === "github" ? "repo" : "path";
35460
- if (!exactKeys(source, ["source", location]))
36204
+ if (!exactKeys2(source, ["source", location]))
35461
36205
  return;
35462
36206
  const sourceLocation = textField(field2(source, location));
35463
36207
  if (type.value === "directory")
@@ -35473,14 +36217,14 @@ function captureClaudeMarketplaceRegistry(path, budget2 = { remaining: 256 * 102
35473
36217
  const value = parse11(readRegistry2(path, budget2));
35474
36218
  for (const [, row] of value.entries)
35475
36219
  normalizeRow(row);
35476
- const sha2562 = createHash18("sha256").update("hasna.skills.claude-marketplace-registry.v1\x00").update(JSON.stringify(value)).digest("hex");
36220
+ const sha2562 = createHash19("sha256").update("hasna.skills.claude-marketplace-registry.v1\x00").update(JSON.stringify(value)).digest("hex");
35477
36221
  return { path, hashMode: "claude-marketplace-registry", sha256: sha2562 };
35478
36222
  }
35479
36223
  function captureClaudeMarketplaceRegistryV2(path, budget2 = { remaining: 256 * 1024 * 1024 }) {
35480
36224
  const value = parse11(readRegistry2(path, budget2));
35481
36225
  for (const [, row] of value.entries)
35482
36226
  normalizeRow(row, 2);
35483
- const sha2562 = createHash18("sha256").update("hasna.skills.claude-marketplace-registry.v2\x00").update(JSON.stringify(value)).digest("hex");
36227
+ const sha2562 = createHash19("sha256").update("hasna.skills.claude-marketplace-registry.v2\x00").update(JSON.stringify(value)).digest("hex");
35484
36228
  return { path, hashMode: "claude-marketplace-registry-v2", sha256: sha2562 };
35485
36229
  }
35486
36230
  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 +36246,7 @@ var init_codex_hook_additions_review = __esm(() => {
35502
36246
  });
35503
36247
 
35504
36248
  // src/lib/codex-hook-discovery-recovery.ts
35505
- import { createHash as createHash19 } from "crypto";
36249
+ import { createHash as createHash20 } from "crypto";
35506
36250
  function assertCodexHookDiscoveryRecovery(binding, witness) {
35507
36251
  const proof = proofs2.get(witness);
35508
36252
  need6(!!proof && binding.agent === "codex" && witness.discoverySha256 === discoveryDigest(binding), "RECONCILE_DISCOVERY_RECOVERY_CHANGED");
@@ -35517,7 +36261,7 @@ function verifiesCodexHookDiscoverySource(binding, source, currentDigest, witnes
35517
36261
  need6(source.sha256 === witness.beforeSha256 && currentDigest === witness.currentSha256, "RECONCILE_DISCOVERY_RECOVERY_CHANGED");
35518
36262
  return true;
35519
36263
  }
35520
- var sha4 = (text2) => createHash19("sha256").update(text2).digest("hex"), fields, discoveryDigest = (binding) => {
36264
+ var sha4 = (text2) => createHash20("sha256").update(text2).digest("hex"), fields, discoveryDigest = (binding) => {
35521
36265
  const controls = binding.codexDisabledPluginSkills;
35522
36266
  if (!Object.hasOwn(binding, "codexDisabledPluginSkills") || Array.isArray(controls) && controls.length === 0) {
35523
36267
  const { codexDisabledPluginSkills: _controls, ...withoutControls } = binding;
@@ -35535,16 +36279,16 @@ var init_codex_hook_discovery_recovery = __esm(() => {
35535
36279
  });
35536
36280
 
35537
36281
  // 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";
36282
+ import { createHash as createHash21 } from "crypto";
36283
+ import { lstatSync as lstatSync21, readFileSync as readFileSync16, readdirSync as readdirSync8, realpathSync as realpathSync8 } from "fs";
36284
+ 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
36285
  import { isDeepStrictEqual as isDeepStrictEqual4 } from "util";
35542
36286
  function discoveryExecutable(agent) {
35543
36287
  const command = DISCOVERY_RUNTIME_COMMANDS[agent];
35544
36288
  const found = command ? Bun.which(command) : null;
35545
36289
  if (!command || !found)
35546
36290
  return null;
35547
- const path = resolve19(found), target = realpathOrNull(path);
36291
+ const path = resolve20(found), target = realpathOrNull(path);
35548
36292
  return target === null ? null : { command, path, target };
35549
36293
  }
35550
36294
  function parseConfig(text2, path, toml = false) {
@@ -35558,12 +36302,12 @@ function parseConfig(text2, path, toml = false) {
35558
36302
  }
35559
36303
  }
35560
36304
  function safe5(path) {
35561
- if (!isAbsolute18(path) || path.includes("\x00"))
36305
+ if (!isAbsolute19(path) || path.includes("\x00"))
35562
36306
  throw new Error("Expected an absolute native discovery path");
35563
- for (let cursor = path;; cursor = dirname18(cursor)) {
35564
- if (lstatSync20(cursor, { throwIfNoEntry: false })?.isSymbolicLink())
36307
+ for (let cursor = path;; cursor = dirname19(cursor)) {
36308
+ if (lstatSync21(cursor, { throwIfNoEntry: false })?.isSymbolicLink())
35565
36309
  throw new Error(`Refusing symlink native discovery input: ${cursor}`);
35566
- if (dirname18(cursor) === cursor)
36310
+ if (dirname19(cursor) === cursor)
35567
36311
  break;
35568
36312
  }
35569
36313
  }
@@ -35571,27 +36315,27 @@ function read(path, changes) {
35571
36315
  safe5(path);
35572
36316
  if (changes?.has(path))
35573
36317
  return changes.get(path);
35574
- const stat2 = lstatSync20(path, { throwIfNoEntry: false });
36318
+ const stat2 = lstatSync21(path, { throwIfNoEntry: false });
35575
36319
  if (!stat2)
35576
36320
  return null;
35577
36321
  if (!stat2.isFile() || stat2.size > 16 * 1024 * 1024)
35578
36322
  throw new Error(`Unsupported or oversized native discovery input: ${path}`);
35579
36323
  return readFileSync16(path, "utf8");
35580
36324
  }
35581
- function assertReviewedClaudeCacheClosures(home, config2, review, canonical8) {
36325
+ function assertReviewedClaudeCacheClosures(home, config2, review, canonical9) {
35582
36326
  const enabledIds = Object.entries(config2.enabledPlugins ?? {}).filter(([, enabled]) => enabled === true).map(([id]) => id);
35583
36327
  if (enabledIds.length === 0)
35584
36328
  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);
36329
+ const registryPath = canonical9(join29(home, ".claude/plugins/installed_plugins.json"));
36330
+ const cacheAliasRoot = join29(home, ".claude/plugins/cache");
36331
+ const cacheRoot = canonical9(cacheAliasRoot);
35588
36332
  const registryText = read(registryPath);
35589
36333
  if (registryText === null)
35590
36334
  return;
35591
36335
  const registry2 = parseConfig(registryText, registryPath);
35592
36336
  if (registry2.version !== 2 || !registry2.plugins || typeof registry2.plugins !== "object" || Array.isArray(registry2.plugins))
35593
36337
  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));
36338
+ const cachePath = (path) => typeof path === "string" && isAbsolute19(path) && resolve20(path) === path && [cacheAliasRoot, cacheRoot].some((root) => path === root || path.startsWith(root + sep9));
35595
36339
  const activeRoots = new Set;
35596
36340
  for (const id of enabledIds) {
35597
36341
  const rows = registry2.plugins[id];
@@ -35603,13 +36347,13 @@ function assertReviewedClaudeCacheClosures(home, config2, review, canonical8) {
35603
36347
  if (!row || typeof row !== "object" || Array.isArray(row) || typeof row.installPath !== "string") {
35604
36348
  throw new Error("Reviewed Claude enabled plugin registration requires an object with an installPath string");
35605
36349
  }
35606
- if ([cacheAliasRoot, cacheRoot].some((root) => row.installPath === root || row.installPath.startsWith(root + sep8))) {
36350
+ if ([cacheAliasRoot, cacheRoot].some((root) => row.installPath === root || row.installPath.startsWith(root + sep9))) {
35607
36351
  if (!cachePath(row.installPath) || row.installPath.length > AGENT_POLICY_LIMITS.pathCharacters || row.version !== undefined && (typeof row.version !== "string" || basename9(row.installPath) !== row.version)) {
35608
36352
  throw new Error("Reviewed Claude discovery has a malformed active cache registration");
35609
36353
  }
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
36354
+ 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
36355
  throw new Error("Reviewed Claude discovery has an unsupported active cache registration scope");
35612
- activeRoots.add(canonical8(row.installPath));
36356
+ activeRoots.add(canonical9(row.installPath));
35613
36357
  }
35614
36358
  }
35615
36359
  }
@@ -35625,11 +36369,11 @@ function assertReviewedClaudeCacheClosures(home, config2, review, canonical8) {
35625
36369
  };
35626
36370
  for (const root of activeRoots) {
35627
36371
  safe5(root);
35628
- const rootStat = lstatSync20(root, { throwIfNoEntry: false });
35629
- if (!rootStat?.isDirectory() || realpathSync6(root) !== root)
36372
+ const rootStat = lstatSync21(root, { throwIfNoEntry: false });
36373
+ if (!rootStat?.isDirectory() || realpathSync8(root) !== root)
35630
36374
  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 });
36375
+ const manifestPath = join29(root, ".claude-plugin/plugin.json");
36376
+ const manifestStat = lstatSync21(manifestPath, { throwIfNoEntry: false });
35633
36377
  let manifest;
35634
36378
  if (manifestStat) {
35635
36379
  if (!manifestStat.isFile())
@@ -35644,37 +36388,37 @@ function assertReviewedClaudeCacheClosures(home, config2, review, canonical8) {
35644
36388
  } 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
36389
  throw new Error("Reviewed Claude active cache plugin manifest absence requires a path-bytes witness");
35646
36390
  }
35647
- const roots = new Set([join28(root, "skills")]);
35648
- if (lstatSync20(join28(root, "SKILL.md"), { throwIfNoEntry: false })?.isFile())
36391
+ const roots = new Set([join29(root, "skills")]);
36392
+ if (lstatSync21(join29(root, "SKILL.md"), { throwIfNoEntry: false })?.isFile())
35649
36393
  roots.add(root);
35650
36394
  const declared = manifest?.skills === undefined ? ["./skills"] : typeof manifest.skills === "string" ? [manifest.skills] : manifest.skills;
35651
36395
  if (!Array.isArray(declared) || declared.some((path) => typeof path !== "string"))
35652
36396
  throw new Error("Reviewed Claude active cache plugin has unsupported skill paths");
35653
36397
  for (const value of declared) {
35654
- const path = resolve19(root, value);
35655
- if (path !== root && !path.startsWith(root + sep8))
36398
+ const path = resolve20(root, value);
36399
+ if (path !== root && !path.startsWith(root + sep9))
35656
36400
  throw new Error("Reviewed Claude active cache plugin skill path escapes its root");
35657
- roots.add(path.endsWith(`${sep8}SKILL.md`) ? dirname18(path) : path);
36401
+ roots.add(path.endsWith(`${sep9}SKILL.md`) ? dirname19(path) : path);
35658
36402
  }
35659
36403
  for (const skillRoot of roots)
35660
36404
  if (!review.roots.includes(skillRoot))
35661
36405
  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 });
36406
+ const hooksPath = join29(root, "hooks/hooks.json");
36407
+ const hooksStat = lstatSync21(hooksPath, { throwIfNoEntry: false });
35664
36408
  if (hooksStat) {
35665
36409
  if (!hooksStat.isFile())
35666
36410
  throw new Error("Reviewed Claude plugin hook manifest is unsupported");
35667
36411
  requireSource(hooksPath, "hook manifest");
35668
36412
  }
35669
36413
  if (typeof manifest?.hooks === "string")
35670
- requireSource(resolve19(root, manifest.hooks), "manifest-declared hook source");
36414
+ requireSource(resolve20(root, manifest.hooks), "manifest-declared hook source");
35671
36415
  }
35672
36416
  }
35673
36417
  function projectNativeDiscoveryFields(text2, format, fields2, path) {
35674
36418
  const object6 = format === "yaml" ? parseHermesConfig(text2) : parseConfig(text2, path, format === "toml");
35675
36419
  if (!object6 || typeof object6 !== "object" || Array.isArray(object6))
35676
36420
  throw new Error("Expected native discovery configuration object");
35677
- return digest(JSON.stringify(Object.fromEntries(fields2.map((field3) => [field3, object6[field3] ?? null]))));
36421
+ return digest2(JSON.stringify(Object.fromEntries(fields2.map((field3) => [field3, object6[field3] ?? null]))));
35678
36422
  }
35679
36423
  function isSupersededSettingsProjection(agent, configPath, source) {
35680
36424
  if (agent === "sumi")
@@ -35684,7 +36428,7 @@ function isSupersededSettingsProjection(agent, configPath, source) {
35684
36428
  function supersedesSettingsProjection(agent, sources, configPath) {
35685
36429
  if (agent === "sumi")
35686
36430
  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")));
36431
+ 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
36432
  }
35689
36433
  function projected(source, changes, budget2 = discoveryByteBudget()) {
35690
36434
  if (source.reviewArtifact !== undefined)
@@ -35697,13 +36441,13 @@ function projected(source, changes, budget2 = discoveryByteBudget()) {
35697
36441
  throw new Error(`Native discovery input changed; run skills hook install with a fresh discovery review: ${source.path}`);
35698
36442
  return changes?.has(source.path) ? hashSumiSettingsReplacement(changes.get(source.path), budget2) : current;
35699
36443
  }
35700
- if (source.hashMode === "codex-settings-v1" || source.hashMode === "codex-settings-v2" || (source.hashMode === "codex-settings-v3" || source.hashMode === "codex-settings-v4")) {
36444
+ 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
36445
  if (source.format !== undefined || source.fields !== undefined || source.managedPlugins !== undefined || typeof source.sha256 !== "string" || !/^[a-f0-9]{64}$/.test(source.sha256))
35702
36446
  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;
36447
+ 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
36448
  if (current !== source.sha256)
35705
36449
  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;
36450
+ 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
36451
  }
35708
36452
  if (source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || (source.hashMode === "claude-settings-v3" || source.hashMode === "claude-settings-v4")) {
35709
36453
  if (source.format !== undefined || source.fields !== undefined || source.managedPlugins !== undefined || typeof source.sha256 !== "string" || !/^[a-f0-9]{64}$/.test(source.sha256))
@@ -35755,7 +36499,7 @@ function projected(source, changes, budget2 = discoveryByteBudget()) {
35755
36499
  if (text2 === null)
35756
36500
  return null;
35757
36501
  if (!source.format)
35758
- return digest(text2);
36502
+ return digest2(text2);
35759
36503
  return projectNativeDiscoveryFields(text2, source.format, source.fields ?? [], source.path);
35760
36504
  }
35761
36505
  function absentCodexSkillRoots(binding) {
@@ -35764,18 +36508,18 @@ function absentCodexSkillRoots(binding) {
35764
36508
  return [];
35765
36509
  if (binding.agent !== "codex" || !Array.isArray(controls) || controls.length > 4096)
35766
36510
  throw new Error("Invalid disabled Codex discovery proof");
35767
- if (binding.method !== "reviewed" || controls.every((control) => lstatSync20(control.pluginParent, { throwIfNoEntry: false })))
36511
+ if (binding.method !== "reviewed" || controls.every((control) => lstatSync21(control.pluginParent, { throwIfNoEntry: false })))
35768
36512
  return [];
35769
- const cache = dirname18(dirname18(controls[0].pluginParent)), config2 = join28(dirname18(dirname18(cache)), "config.toml");
36513
+ const cache = dirname19(dirname19(controls[0].pluginParent)), config2 = join29(dirname19(dirname19(cache)), "config.toml");
35770
36514
  const source = binding.sources.find((source2) => source2.path === config2 && source2.sha256 !== null && source2.format === undefined && source2.fields === undefined);
35771
36515
  if (!source || projected(source) !== source.sha256)
35772
36516
  throw new Error("Missing current disabled Codex configuration witness");
35773
36517
  const rules = Bun.TOML.parse(read(config2)).skills?.config ?? [];
35774
36518
  return [...new Set(controls.map((control) => control.pluginParent))].filter((parent) => !codexDirectHookSelects(cache, parent) && absentDisabledCodexPluginParent(cache, parent, controls, rules));
35775
36519
  }
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"));
36520
+ function codexDirectHookSelects(cache, root, configPath = join29(dirname19(dirname19(cache)), "config.toml")) {
36521
+ const codex = dirname19(configPath), config2 = Bun.TOML.parse(read(configPath) ?? "");
36522
+ const hooks = read(join29(codex, "hooks.json"));
35779
36523
  if (hooks !== null)
35780
36524
  hashNativeJsonControls(hooks);
35781
36525
  return JSON.stringify(config2.hooks ?? {}).includes(root) || hooks !== null && JSON.stringify(JSON.parse(hooks)).includes(root);
@@ -35787,7 +36531,7 @@ function retiredCodexRoots(binding) {
35787
36531
  const controls = binding.codexDisabledPluginSkills;
35788
36532
  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
36533
  throw new Error("Invalid retired Codex materialization proof");
35790
- const cache = dirname18(dirname18(controls[0].pluginParent)), config2 = join28(dirname18(dirname18(cache)), "config.toml");
36534
+ const cache = dirname19(dirname19(controls[0].pluginParent)), config2 = join29(dirname19(dirname19(cache)), "config.toml");
35791
36535
  const source = binding.sources.find((source2) => source2.path === config2 && source2.sha256 !== null && source2.format === undefined && source2.fields === undefined);
35792
36536
  if (!source || projected(source) !== source.sha256)
35793
36537
  throw new Error("Missing current retired Codex configuration witness");
@@ -35795,7 +36539,7 @@ function retiredCodexRoots(binding) {
35795
36539
  if ((proof.parents ?? []).some((parent) => codexDirectHookSelects(cache, parent) || !reviewedDisabledCodexPluginParent(cache, parent, controls, rules)) || !reviewedCodexPluginCapabilitiesUnchanged(cache, controls, (path) => read(path), rules))
35796
36540
  throw new Error("Retired Codex parent capabilities changed");
35797
36541
  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));
36542
+ 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
36543
  if (!manifest || codexDirectHookSelects(cache, root) || !reviewedRetiredCodexRoot(cache, root, controls, rules, (path) => read(path), true))
35800
36544
  throw new Error("Retired Codex materialization changed");
35801
36545
  }
@@ -35804,7 +36548,7 @@ function retiredCodexRoots(binding) {
35804
36548
  function retainableAbsentSource(source) {
35805
36549
  if (source.format !== undefined || source.fields !== undefined || source.managedPlugins !== undefined)
35806
36550
  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"));
36551
+ 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
36552
  }
35809
36553
  function absentRetiredClaudeRoots(binding) {
35810
36554
  if (binding.agent !== "claude" || binding.method !== "reviewed")
@@ -35813,17 +36557,17 @@ function absentRetiredClaudeRoots(binding) {
35813
36557
  for (const source of binding.sources) {
35814
36558
  if (!retainableAbsentSource(source) || source.sha256 === null)
35815
36559
  continue;
35816
- const marker = sep8 + ".claude" + sep8 + "plugins" + sep8 + "cache" + sep8, at = source.path.indexOf(marker);
36560
+ const marker = sep9 + ".claude" + sep9 + "plugins" + sep9 + "cache" + sep9, at = source.path.indexOf(marker);
35817
36561
  if (at < 0 || source.path.indexOf(marker, at + 1) >= 0)
35818
36562
  continue;
35819
- const cache = source.path.slice(0, at + marker.length - 1), parts = source.path.slice(at + marker.length).split(sep8);
36563
+ const cache = source.path.slice(0, at + marker.length - 1), parts = source.path.slice(at + marker.length).split(sep9);
35820
36564
  if (parts.length < 4 || parts.slice(0, 3).some((part) => !part || part === "." || part === ".."))
35821
36565
  continue;
35822
- const root = join28(cache, ...parts.slice(0, 3));
36566
+ const root = join29(cache, ...parts.slice(0, 3));
35823
36567
  safe5(root);
35824
- if (lstatSync20(root, { throwIfNoEntry: false }))
36568
+ if (lstatSync21(root, { throwIfNoEntry: false }))
35825
36569
  continue;
35826
- const claude = dirname18(dirname18(cache)), settings = join28(claude, "settings.json"), registry2 = join28(claude, "plugins/installed_plugins.json");
36570
+ const claude = dirname19(dirname19(cache)), settings = join29(claude, "settings.json"), registry2 = join29(claude, "plugins/installed_plugins.json");
35827
36571
  const full = (path) => binding.sources.find((item) => item.path === path && item.sha256 !== null && item.format === undefined && item.fields === undefined);
35828
36572
  const configSource = full(settings), registrySource = full(registry2);
35829
36573
  if (!configSource || !registrySource || projected(configSource) !== configSource.sha256 || projected(registrySource) !== registrySource.sha256)
@@ -35840,15 +36584,15 @@ function absentRetiredClaudeRoots(binding) {
35840
36584
  if (!row || typeof row !== "object" || Array.isArray(row))
35841
36585
  return null;
35842
36586
  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)
36587
+ 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
36588
  return null;
35845
36589
  if (value.scope === "user")
35846
36590
  return value.projectPath === undefined || value.projectPath === null ? "user\x00" : null;
35847
36591
  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;
36592
+ 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
36593
  return null;
35850
36594
  };
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))))
36595
+ 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
36596
  continue;
35853
36597
  const rows = installed.plugins[id];
35854
36598
  if (!Array.isArray(rows) || rows.length < 1)
@@ -35866,36 +36610,94 @@ function absentRetiredClaudeRoots(binding) {
35866
36610
  if (!targetValid || !targetScopes.has("user\x00"))
35867
36611
  continue;
35868
36612
  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)
36613
+ if (typeof active !== "string" || rows[0]?.version !== basename9(active) || dirname19(active) !== dirname19(root) || active === root || !lstatSync21(active, { throwIfNoEntry: false })?.isDirectory() || realpathSync8(active) !== active)
35870
36614
  continue;
35871
- const activeManifest = full(join28(active, ".claude-plugin/plugin.json"));
36615
+ const activeManifest = full(join29(active, ".claude-plugin/plugin.json"));
35872
36616
  if (!activeManifest || projected(activeManifest) !== activeManifest.sha256)
35873
36617
  continue;
35874
36618
  result.add(root);
35875
36619
  }
35876
36620
  return [...result];
35877
36621
  }
35878
- function verifyAgentDiscovery(binding, codexRecovery) {
36622
+ function codexSemanticCacheSourceRole(source, cacheRoot, parents3) {
36623
+ 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")
36624
+ return false;
36625
+ const parts = relative7(cacheRoot, source.path).split(sep9);
36626
+ if (parts.length < 3 || !parents3.includes(join29(cacheRoot, parts[0], parts[1])))
36627
+ return false;
36628
+ const tail = parts.slice(3).join("/");
36629
+ 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");
36630
+ }
36631
+ function codexSemanticCacheDirectoryRole(path, cacheRoot) {
36632
+ return isAbsolute19(path) && resolve20(path) === path && !/[\x00-\x1f\x7f]/.test(path) && (path === cacheRoot || path.startsWith(cacheRoot + sep9));
36633
+ }
36634
+ function assertCodexSemanticCacheHookSafety(cacheRoot, parents3, configPath, hookRootAlias = null) {
36635
+ const selectionRoots = [cacheRoot, ...parents3];
36636
+ if (hookRootAlias !== null) {
36637
+ 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)
36638
+ throw new Error("Reviewed semantic cache hook alias changed");
36639
+ selectionRoots.push(...selectionRoots.map((root) => join29(hookRootAlias.alias, relative7(hookRootAlias.target, root))));
36640
+ }
36641
+ selectionRoots.push("plugins/cache");
36642
+ if (selectionRoots.some((parent) => codexDirectHookSelects(cacheRoot, parent, configPath)))
36643
+ throw new Error("Direct native hooks select a projected Codex cache input");
36644
+ }
36645
+ function verifyCodexSemanticCacheDiscovery(binding, reviewedRootAliases) {
36646
+ const proof = binding.codexSemanticCache;
36647
+ if (!proof)
36648
+ return;
36649
+ if (reviewedRootAliases !== undefined) {
36650
+ const alias = reviewedRootAliases.find((alias2) => alias2.agent === "codex");
36651
+ const expected = alias ? { alias: alias.alias, target: alias.target } : null;
36652
+ if (!isDeepStrictEqual4(proof.hookRootAlias, expected))
36653
+ throw new Error("Semantic cache hook alias differs from reviewed root binding");
36654
+ }
36655
+ const controls = binding.codexDisabledPluginSkills;
36656
+ 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))
36657
+ throw new Error("Invalid Codex semantic cache discovery proof");
36658
+ const cacheRoot = proof.witness.cacheRoot;
36659
+ if (controls.some((control) => dirname19(dirname19(control.pluginParent)) !== cacheRoot))
36660
+ throw new Error("Codex semantic cache names another enrolled cache");
36661
+ const parents3 = [...new Set([...controls.map((control) => control.pluginParent), ...proof.appOnlyParents.map((parent) => parent.pluginParent)])];
36662
+ const sources = binding.sources.filter((source) => codexSemanticCacheSourceRole(source, cacheRoot, parents3));
36663
+ const directories = (binding.directories ?? []).filter((directory) => codexSemanticCacheDirectoryRole(directory.path, cacheRoot));
36664
+ if (!directories.length || !isDeepStrictEqual4(sources, proof.supersededSources) || !isDeepStrictEqual4(directories, proof.supersededDirectories))
36665
+ throw new Error("Codex semantic cache provenance changed");
36666
+ const configPath = proof.configPath;
36667
+ if (!isAbsolute19(configPath) || resolve20(configPath) !== configPath || basename9(configPath) !== "config.toml" || /[\x00-\x1f\x7f]/.test(configPath))
36668
+ throw new Error("Invalid semantic cache configuration source");
36669
+ const configSource = binding.sources.find((source) => source.path === configPath && source.sha256 !== null && source.format === undefined && source.fields === undefined);
36670
+ if (!configSource || projected(configSource) !== configSource.sha256)
36671
+ throw new Error("Codex semantic cache requires unchanged reviewed configuration");
36672
+ assertCodexSemanticCacheHookSafety(cacheRoot, parents3, configPath, proof.hookRootAlias);
36673
+ const rules = parseConfig(read(configPath), configPath, true).skills?.config ?? [];
36674
+ const current = captureCodexSemanticCacheWitness({ cacheRoot, controls, appOnlyParents: proof.appOnlyParents, rules });
36675
+ assertCodexSemanticCacheWitnessUnchanged(proof.witness, current);
36676
+ return proof;
36677
+ }
36678
+ function verifyAgentDiscovery(binding, codexRecovery, reviewedRootAliases) {
35879
36679
  if (codexRecovery)
35880
36680
  assertCodexHookDiscoveryRecovery(binding, codexRecovery);
35881
36681
  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
36682
  throw new Error("Invalid native discovery binding");
35883
36683
  if (binding.agent === "hermes" && !binding.directories?.length)
35884
36684
  throw new Error("Hermes discovery requires directory membership coverage; run skills hook install with a fresh discovery review");
36685
+ const semanticCache = verifyCodexSemanticCacheDiscovery(binding, reviewedRootAliases);
36686
+ const semanticDirectory = (path) => Boolean(semanticCache && codexSemanticCacheDirectoryRole(path, semanticCache.witness.cacheRoot));
35885
36687
  const installationRoots = codexInstallationRoots(binding);
35886
36688
  const retiredRoots = retiredCodexRoots(binding);
35887
- const installationInput = (path) => installationRoots.some((root) => path === root || path.startsWith(root + sep8));
36689
+ const installationInput = (path) => installationRoots.some((root) => path === root || path.startsWith(root + sep9));
35888
36690
  if (binding.directories !== undefined) {
35889
36691
  const projected2 = binding.codexInstallationInputs?.directories ?? [];
35890
- const ancestors2 = binding.directories.filter((directory) => installationRoots.some((root) => root.startsWith(directory.path + sep8)));
36692
+ const ancestors2 = binding.directories.filter((directory) => installationRoots.some((root) => root.startsWith(directory.path + sep9)));
35891
36693
  if (projected2.length !== ancestors2.length || projected2.some((directory) => !ancestors2.some((original) => original.path === directory.path)))
35892
36694
  throw new Error("Missing installation input directory projection");
35893
- const ordinary = binding.directories.filter((directory) => !installationInput(directory.path) && !ancestors2.includes(directory));
36695
+ const ordinary = binding.directories.filter((directory) => !installationInput(directory.path) && !ancestors2.includes(directory) && !semanticDirectory(directory.path));
35894
36696
  if (binding.codexRetiredMaterializations) {
35895
- const projection = binding.codexRetiredMaterializations.directories;
36697
+ const projection = binding.codexRetiredMaterializations.directories.filter((directory) => !semanticDirectory(directory.path));
35896
36698
  if (projection.length !== ordinary.length || projection.some((item, index) => item.path !== ordinary[index]?.path))
35897
36699
  throw new Error("Missing retired Codex directory projection");
35898
- const omitted = [...retiredRoots, ...(binding.codexRetiredMaterializations.parents ?? []).filter((parent) => !lstatSync20(parent, { throwIfNoEntry: false }))];
36700
+ const omitted = [...retiredRoots, ...(binding.codexRetiredMaterializations.parents ?? []).filter((parent) => !lstatSync21(parent, { throwIfNoEntry: false }))];
35899
36701
  if (projection.every((item) => Array.isArray(item.entries)))
35900
36702
  verifyDiscoveryDirectoryProjection(projection, omitted);
35901
36703
  else {
@@ -35909,7 +36711,7 @@ function verifyAgentDiscovery(binding, codexRecovery) {
35909
36711
  verifyDiscoveryDirectories(ordinary);
35910
36712
  verifyDiscoveryDirectories(projected2, installationRoots);
35911
36713
  }
35912
- const absentRoots = [...absentCodexSkillRoots(binding), ...absentRetiredClaudeRoots(binding), ...retiredRoots.filter((root) => !lstatSync20(root, { throwIfNoEntry: false }))];
36714
+ const absentRoots = [...absentCodexSkillRoots(binding), ...absentRetiredClaudeRoots(binding), ...retiredRoots.filter((root) => !lstatSync21(root, { throwIfNoEntry: false }))];
35913
36715
  const budget2 = discoveryByteBudget();
35914
36716
  for (const source of binding.sources) {
35915
36717
  assertMarketplaceBinding(binding, source);
@@ -35919,11 +36721,15 @@ function verifyAgentDiscovery(binding, codexRecovery) {
35919
36721
  throw new Error("Invalid native discovery projection");
35920
36722
  if (source.sha256 !== null && !/^[a-f0-9]{64}$/.test(source.sha256))
35921
36723
  throw new Error("Invalid native discovery digest");
36724
+ if (semanticCache?.supersededSources.some((previous) => isDeepStrictEqual4(previous, source))) {
36725
+ safe5(source.path);
36726
+ continue;
36727
+ }
35922
36728
  if (installationInput(source.path)) {
35923
36729
  safe5(source.path);
35924
36730
  continue;
35925
36731
  }
35926
- if (absentRoots.some((root) => source.path.startsWith(root + sep8)) && retainableAbsentSource(source)) {
36732
+ if (absentRoots.some((root) => source.path.startsWith(root + sep9)) && retainableAbsentSource(source)) {
35927
36733
  safe5(source.path);
35928
36734
  continue;
35929
36735
  }
@@ -35935,7 +36741,7 @@ function verifyAgentDiscovery(binding, codexRecovery) {
35935
36741
  safe5(root);
35936
36742
  for (const root of absentRoots) {
35937
36743
  safe5(root);
35938
- if (lstatSync20(root, { throwIfNoEntry: false }))
36744
+ if (lstatSync21(root, { throwIfNoEntry: false }))
35939
36745
  throw new Error("Retired native materialization changed during discovery verification");
35940
36746
  }
35941
36747
  }
@@ -35945,13 +36751,13 @@ function codexInstallationRoots(binding) {
35945
36751
  return [];
35946
36752
  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
36753
  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)));
36754
+ const cache = dirname19(dirname19(proof.plugins[0].pluginParent));
36755
+ const config2 = join29(dirname19(dirname19(cache)), "config.toml"), home = dirname19(dirname19(dirname19(cache)));
35950
36756
  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)))))
36757
+ const nativeRoots = NATIVE_SKILL_ROOTS.filter(([agent]) => agent === "codex").map(([, path]) => join29(home, path));
36758
+ 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
36759
  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)))
36760
+ 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
36761
  throw new Error("Missing native installation input source witness");
35956
36762
  return reviewedCodexPluginSourceRoots(cache, proof.plugins, (path) => {
35957
36763
  const text2 = read(path);
@@ -35961,11 +36767,11 @@ function codexInstallationRoots(binding) {
35961
36767
  });
35962
36768
  }
35963
36769
  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"))))
36770
+ 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
36771
  throw new Error("Claude plugin manifest witnesses require Claude plugin discovery");
35966
36772
  if (source.hashMode === "sumi-settings-v1" && (binding.agent !== "sumi" || binding.method !== "reviewed" || basename9(source.path) !== "sumi.json"))
35967
36773
  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"))
36774
+ 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
36775
  throw new Error("Codex settings witnesses require explicit reviewed Codex configuration");
35970
36776
  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
36777
  throw new Error("Claude settings witnesses require explicit reviewed Claude configuration");
@@ -35977,13 +36783,13 @@ function assertMarketplaceBinding(binding, source) {
35977
36783
  function agentDiscoveryConfigPath(home, agent) {
35978
36784
  if (agent === "sumi")
35979
36785
  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"}`);
36786
+ 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
36787
  }
35982
36788
  function resolveAgentDiscovery(options) {
35983
- const canonical8 = options.canonical ?? resolve19, home = resolve19(options.home), agent = options.agent;
36789
+ const canonical9 = options.canonical ?? resolve20, home = resolve20(options.home), agent = options.agent;
35984
36790
  const sources = [], roots = new Set, builtinNames = [];
35985
36791
  const witness = (path, format, fields2, hashMode) => {
35986
- const source = { path: canonical8(path), sha256: null, ...format ? { format, fields: fields2 } : {}, ...hashMode ? { hashMode } : {} };
36792
+ const source = { path: canonical9(path), sha256: null, ...format ? { format, fields: fields2 } : {}, ...hashMode ? { hashMode } : {} };
35987
36793
  source.sha256 = projected(source);
35988
36794
  sources.push(source);
35989
36795
  return read(source.path);
@@ -36001,42 +36807,42 @@ function resolveAgentDiscovery(options) {
36001
36807
  const review = options.reviewed?.agents.find((item) => item.agent === agent);
36002
36808
  if (agent === "sumi") {
36003
36809
  const directory = sumiConfigDirectory(home);
36004
- if (witness(join28(directory, "sumi.jsonc")) !== null)
36810
+ if (witness(join29(directory, "sumi.jsonc")) !== null)
36005
36811
  unresolved("JSONC configuration requires a supported format adapter");
36006
- for (const root of [directory, join28(home, ".claude"), join28(home, ".agents")])
36812
+ for (const root of [directory, join29(home, ".claude"), join29(home, ".agents")])
36007
36813
  for (const name of ["skill", "skills"])
36008
- roots.add(canonical8(join28(root, name)));
36814
+ roots.add(canonical9(join29(root, name)));
36009
36815
  if (config2.skills !== undefined && (!Array.isArray(config2.skills) || config2.skills.some((path) => typeof path !== "string")))
36010
36816
  unresolved("skills must be a string array");
36011
36817
  for (const value of config2.skills ?? []) {
36012
- if (typeof value !== "string" || /[\0$]/.test(value) || !value || !(isAbsolute18(value) || value.startsWith("~/")))
36818
+ if (typeof value !== "string" || /[\0$]/.test(value) || !value || !(isAbsolute19(value) || value.startsWith("~/")))
36013
36819
  unresolved("remote or relative skill sources need a dedicated discovery adapter");
36014
- roots.add(canonical8(value.startsWith("~/") ? join28(home, value.slice(2)) : value));
36820
+ roots.add(canonical9(value.startsWith("~/") ? join29(home, value.slice(2)) : value));
36015
36821
  }
36016
36822
  for (const key of ["plugin", "plugins"])
36017
36823
  if (config2[key] !== undefined && !Array.isArray(config2[key]))
36018
36824
  unresolved(`${key} must be an array`);
36019
- const plugins = [join28(directory, "plugin"), join28(directory, "plugins")];
36825
+ const plugins = [join29(directory, "plugin"), join29(directory, "plugins")];
36020
36826
  for (const path of plugins) {
36021
36827
  safe5(path);
36022
- if (lstatSync20(path, { throwIfNoEntry: false })?.isDirectory())
36023
- for (const name of readdirSync7(path).sort()) {
36828
+ if (lstatSync21(path, { throwIfNoEntry: false })?.isDirectory())
36829
+ for (const name of readdirSync8(path).sort()) {
36024
36830
  if (name === "skills-cli.js" && path === plugins[1])
36025
36831
  continue;
36026
- const target = join28(path, name);
36027
- if (!lstatSync20(target).isFile())
36832
+ const target = join29(path, name);
36833
+ if (!lstatSync21(target).isFile())
36028
36834
  unresolved("local plugin packages need a dedicated discovery adapter");
36029
36835
  witness(target);
36030
36836
  }
36031
36837
  }
36032
36838
  for (const root of roots) {
36033
36839
  safe5(root);
36034
- if (lstatSync20(root, { throwIfNoEntry: false })?.isDirectory() && readdirSync7(root).some((name) => name.endsWith(".md")))
36840
+ if (lstatSync21(root, { throwIfNoEntry: false })?.isDirectory() && readdirSync8(root).some((name) => name.endsWith(".md")))
36035
36841
  unresolved("flat markdown skills require a dedicated native migration adapter");
36036
36842
  }
36037
36843
  }
36038
36844
  if (agent === "hermes") {
36039
- const profile = witness(join28(home, ".hermes/active_profile"));
36845
+ const profile = witness(join29(home, ".hermes/active_profile"));
36040
36846
  if (profile?.trim() && profile.trim() !== "default")
36041
36847
  unresolved("a non-default profile is active");
36042
36848
  const declared = config2.skills?.external_dirs ?? [], paths = typeof declared === "string" ? [declared] : declared;
@@ -36050,7 +36856,7 @@ function resolveAgentDiscovery(options) {
36050
36856
  continue;
36051
36857
  if (normalized.startsWith("~") && normalized !== "~" && !normalized.startsWith("~/"))
36052
36858
  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);
36859
+ const path = normalized === "~" ? home : normalized.startsWith("~/") ? join29(home, normalized.slice(2)) : resolve20(home, ".hermes", normalized);
36054
36860
  safe5(path);
36055
36861
  roots.add(path);
36056
36862
  }
@@ -36059,24 +36865,24 @@ function resolveAgentDiscovery(options) {
36059
36865
  const executable = options.executable === undefined ? discoveryExecutable(agent) : options.executable;
36060
36866
  if (executable) {
36061
36867
  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);
36868
+ for (let directory = dirname19(executable.target), depth = 0;depth < 8; directory = dirname19(directory), depth++) {
36869
+ const path = join29(directory, "package.json"), raw = read(path);
36064
36870
  if (raw !== null && parseConfig(raw, path).name === "@google/gemini-cli") {
36065
36871
  packageRoot = directory;
36066
36872
  witness(path);
36067
36873
  break;
36068
36874
  }
36069
- if (dirname18(directory) === directory)
36875
+ if (dirname19(directory) === directory)
36070
36876
  break;
36071
36877
  }
36072
36878
  if (!packageRoot)
36073
36879
  unresolved("installed Gemini package layout is not recognized");
36074
- const builtinRoot = join28(packageRoot, "bundle/builtin");
36880
+ const builtinRoot = join29(packageRoot, "bundle/builtin");
36075
36881
  safe5(builtinRoot);
36076
- if (!lstatSync20(builtinRoot, { throwIfNoEntry: false })?.isDirectory())
36882
+ if (!lstatSync21(builtinRoot, { throwIfNoEntry: false })?.isDirectory())
36077
36883
  unresolved("installed Gemini builtin root is missing");
36078
- for (const name of readdirSync7(builtinRoot).sort()) {
36079
- const text2 = witness(join28(builtinRoot, name, "SKILL.md"));
36884
+ for (const name of readdirSync8(builtinRoot).sort()) {
36885
+ const text2 = witness(join29(builtinRoot, name, "SKILL.md"));
36080
36886
  const match = text2?.match(/^---\r?\n[\s\S]*?^name:\s*([a-z0-9][a-z0-9-]*)\s*$/m);
36081
36887
  if (!match?.[1] || builtinNames.includes(match[1]))
36082
36888
  unresolved("installed Gemini builtin name is missing or ambiguous");
@@ -36089,11 +36895,16 @@ function resolveAgentDiscovery(options) {
36089
36895
  if (retained.agent !== agent || retained.method !== "reviewed")
36090
36896
  unresolved("invalid retained review");
36091
36897
  verifyAgentDiscovery(retained);
36092
- if (!retained.sources.some((source) => source.path === canonical8(configPath) && source.format === undefined && source.fields === undefined))
36898
+ if (!retained.sources.some((source) => source.path === canonical9(configPath) && source.format === undefined && source.fields === undefined))
36093
36899
  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)))
36900
+ 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
36901
  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;
36902
+ let covered = supersedesSettingsProjection(agent, retained.sources, canonical9(configPath)) ? sources.filter((source) => !isSupersededSettingsProjection(agent, canonical9(configPath), source)) : sources;
36903
+ if (retained.codexSemanticCache) {
36904
+ const proof = retained.codexSemanticCache;
36905
+ const parents3 = [...new Set([...(retained.codexDisabledPluginSkills ?? []).map((control) => control.pluginParent), ...proof.appOnlyParents.map((parent) => parent.pluginParent)])];
36906
+ covered = covered.filter((source) => !codexSemanticCacheSourceRole(source, proof.witness.cacheRoot, parents3));
36907
+ }
36097
36908
  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
36909
  unresolved("retained review is missing current runtime discovery coverage");
36099
36910
  return retained;
@@ -36105,16 +36916,16 @@ function resolveAgentDiscovery(options) {
36105
36916
  if (review.sources.some((source) => source.format !== undefined || source.fields !== undefined))
36106
36917
  throw new Error("Explicit discovery reviews require full source-file hashes");
36107
36918
  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)))
36919
+ 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
36920
  throw new Error("Semantic settings witnesses must name the configured agent configuration source");
36110
- if (!review.sources.some((source) => source.path === canonical8(configPath)))
36921
+ if (!review.sources.some((source) => source.path === canonical9(configPath)))
36111
36922
  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;
36923
+ const reviewedSources = supersedesSettingsProjection(agent, review.sources, canonical9(configPath)) ? sources.filter((source) => !isSupersededSettingsProjection(agent, canonical9(configPath), source)) : sources;
36113
36924
  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")))
36925
+ 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
36926
  return source;
36116
- const pluginRoot = dirname18(dirname18(source.path)), hooksPath = join28(pluginRoot, "hooks/hooks.json");
36117
- const hookStat = lstatSync20(hooksPath, { throwIfNoEntry: false });
36927
+ const pluginRoot = dirname19(dirname19(source.path)), hooksPath = join29(pluginRoot, "hooks/hooks.json");
36928
+ const hookStat = lstatSync21(hooksPath, { throwIfNoEntry: false });
36118
36929
  const text2 = read(source.path);
36119
36930
  if (text2 === null)
36120
36931
  throw new Error("Reviewed Claude plugin manifest is missing");
@@ -36128,58 +36939,58 @@ function resolveAgentDiscovery(options) {
36128
36939
  if (manifest.hooks !== undefined) {
36129
36940
  if (typeof manifest.hooks !== "string")
36130
36941
  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))
36942
+ const declaredHookPath = resolve20(pluginRoot, manifest.hooks);
36943
+ if (!declaredHookPath.startsWith(pluginRoot + sep9))
36133
36944
  throw new Error("Reviewed Claude plugin hooks target escapes its root");
36134
36945
  reviewedHookPaths.add(declaredHookPath);
36135
36946
  }
36136
36947
  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")))
36948
+ 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
36949
  throw new Error("Reviewed Claude plugin manifest requires separately reviewed exact hook file sources");
36139
36950
  return { path: source.path, sha256: manifestSha256, hashMode: "claude-plugin-manifest-v1" };
36140
36951
  });
36141
36952
  if (agent === "claude")
36142
- assertReviewedClaudeCacheClosures(home, config2, review, canonical8);
36953
+ assertReviewedClaudeCacheClosures(home, config2, review, canonical9);
36143
36954
  const combined = [...reviewedSources, ...reviewedSourcesWithManifestProjection];
36144
36955
  const unique = combined.filter((source, index) => combined.findIndex((candidate) => isDeepStrictEqual4(candidate, source)) === index);
36145
36956
  return { ...supplied, roots: [...new Set([...roots, ...supplied.roots])].sort(), sources: unique, ...agent === "gemini" ? { builtinNames } : {} };
36146
36957
  }
36147
36958
  function plugin(root) {
36148
- root = canonical8(root);
36959
+ root = canonical9(root);
36149
36960
  safe5(root);
36150
- const manifestPath = join28(root, agent === "claude" ? ".claude-plugin/plugin.json" : ".codex-plugin/plugin.json");
36961
+ const manifestPath = join29(root, agent === "claude" ? ".claude-plugin/plugin.json" : ".codex-plugin/plugin.json");
36151
36962
  const raw = witness(manifestPath, undefined, undefined, agent === "claude" ? "claude-plugin-manifest-v1" : undefined);
36152
36963
  if (raw === null)
36153
36964
  unresolved("plugin manifest missing");
36154
36965
  const manifest = parseConfig(raw, manifestPath);
36155
- const hooks = witness(join28(root, "hooks/hooks.json"));
36966
+ const hooks = witness(join29(root, "hooks/hooks.json"));
36156
36967
  if (manifest.hooks !== undefined || hooks !== null)
36157
36968
  unresolved("plugin hooks require a separate no-skill-injection review");
36158
- const commands = join28(root, "commands");
36969
+ const commands = join29(root, "commands");
36159
36970
  safe5(commands);
36160
- if (agent === "claude" && (manifest.commands !== undefined || lstatSync20(commands, { throwIfNoEntry: false })?.isDirectory() && readdirSync7(commands).length))
36971
+ if (agent === "claude" && (manifest.commands !== undefined || lstatSync21(commands, { throwIfNoEntry: false })?.isDirectory() && readdirSync8(commands).length))
36161
36972
  unresolved("legacy command discovery requires retirement or a dedicated format adapter");
36162
- const rootSkill = witness(join28(root, "SKILL.md"));
36973
+ const rootSkill = witness(join29(root, "SKILL.md"));
36163
36974
  if (rootSkill !== null)
36164
36975
  roots.add(root);
36165
36976
  const declared = manifest.skills === undefined ? ["./skills"] : typeof manifest.skills === "string" ? [manifest.skills] : manifest.skills;
36166
36977
  if (!Array.isArray(declared) || declared.some((path) => typeof path !== "string"))
36167
36978
  unresolved("unsupported plugin skill paths");
36168
36979
  if (agent === "claude")
36169
- roots.add(join28(root, "skills"));
36980
+ roots.add(join29(root, "skills"));
36170
36981
  for (const value of declared) {
36171
- const path = resolve19(root, value);
36172
- if (path !== root && !path.startsWith(root + sep8))
36982
+ const path = resolve20(root, value);
36983
+ if (path !== root && !path.startsWith(root + sep9))
36173
36984
  unresolved("plugin skill path escapes its root");
36174
- roots.add(path.endsWith(`${sep8}SKILL.md`) ? dirname18(path) : path);
36985
+ roots.add(path.endsWith(`${sep9}SKILL.md`) ? dirname19(path) : path);
36175
36986
  }
36176
36987
  }
36177
36988
  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"));
36989
+ const registrations = witness(join29(home, ".claude/plugins/installed_plugins.json"));
36990
+ const installed = registrations === null ? {} : parseConfig(registrations, join29(home, ".claude/plugins/installed_plugins.json")).plugins;
36991
+ const commands = canonical9(join29(home, ".claude/commands"));
36181
36992
  safe5(commands);
36182
- if (lstatSync20(commands, { throwIfNoEntry: false })?.isDirectory() && readdirSync7(commands).length)
36993
+ if (lstatSync21(commands, { throwIfNoEntry: false })?.isDirectory() && readdirSync8(commands).length)
36183
36994
  unresolved("legacy home command discovery requires a dedicated format adapter");
36184
36995
  for (const [id, enabled] of Object.entries(config2.enabledPlugins ?? {})) {
36185
36996
  if (enabled === false)
@@ -36199,37 +37010,37 @@ function resolveAgentDiscovery(options) {
36199
37010
  unresolved("unsupported plugin enablement");
36200
37011
  const split = id.lastIndexOf("@"), name = id.slice(0, split), marketplace = id.slice(split + 1);
36201
37012
  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))
37013
+ if (split < 1 || market?.source_type !== "local" || typeof market.source !== "string" || !isAbsolute19(market.source))
36203
37014
  unresolved("enabled plugin marketplace is not an explicit local source");
36204
- const catalogText = witness(join28(market.source, ".agents/plugins/marketplace.json"));
37015
+ const catalogText = witness(join29(market.source, ".agents/plugins/marketplace.json"));
36205
37016
  if (catalogText === null)
36206
37017
  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) : [];
37018
+ const catalog = parseConfig(catalogText, join29(market.source, ".agents/plugins/marketplace.json")), matches = Array.isArray(catalog.plugins) ? catalog.plugins.filter((item) => item.name === name) : [];
36208
37019
  if (matches.length !== 1 || matches[0]?.source?.source !== "local" || typeof matches[0]?.source?.path !== "string")
36209
37020
  unresolved("plugin catalog source is missing or ambiguous");
36210
- plugin(resolve19(market.source, matches[0].source.path));
37021
+ plugin(resolve20(market.source, matches[0].source.path));
36211
37022
  }
36212
37023
  } else if (agent === "opencode") {
36213
- if (witness(join28(home, ".config/opencode/opencode.jsonc")) !== null || witness(join28(home, ".config/opencode/config.json")) !== null)
37024
+ if (witness(join29(home, ".config/opencode/opencode.jsonc")) !== null || witness(join29(home, ".config/opencode/config.json")) !== null)
36214
37025
  unresolved("additional config layers require review");
36215
37026
  if ((config2.plugin?.length ?? 0) > 0 || config2.skills?.urls?.length)
36216
37027
  unresolved("external plugin or remote skill source");
36217
37028
  for (const path of config2.skills?.paths ?? []) {
36218
- if (typeof path !== "string" || !isAbsolute18(path))
37029
+ if (typeof path !== "string" || !isAbsolute19(path))
36219
37030
  unresolved("relative or malformed added skill root");
36220
37031
  roots.add(path);
36221
37032
  }
36222
- const localPlugins = join28(home, ".config/opencode/plugins");
37033
+ const localPlugins = join29(home, ".config/opencode/plugins");
36223
37034
  safe5(localPlugins);
36224
- if (lstatSync20(localPlugins, { throwIfNoEntry: false }) && readdirSync7(localPlugins).some((name) => name !== "skills-cli.js"))
37035
+ if (lstatSync21(localPlugins, { throwIfNoEntry: false }) && readdirSync8(localPlugins).some((name) => name !== "skills-cli.js"))
36225
37036
  unresolved("additional local plugin hooks require review");
36226
37037
  } 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))
37038
+ 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
37039
  unresolved("external or foreign local plugins require review");
36229
37040
  } else if (agent === "hermes") {
36230
- for (const directory of [join28(home, ".hermes/plugins"), join28(home, ".hermes/hermes-agent")]) {
37041
+ for (const directory of [join29(home, ".hermes/plugins"), join29(home, ".hermes/hermes-agent")]) {
36231
37042
  safe5(directory);
36232
- if (lstatSync20(directory, { throwIfNoEntry: false }))
37043
+ if (lstatSync21(directory, { throwIfNoEntry: false }))
36233
37044
  unresolved("installed runtime/plugin discovery requires reviewed source bindings");
36234
37045
  }
36235
37046
  if (Bun.which("hermes") || Object.keys(config2.plugins ?? {}).length)
@@ -36237,32 +37048,32 @@ function resolveAgentDiscovery(options) {
36237
37048
  } else if (agent === "gemini") {
36238
37049
  if (Object.keys(config2.extensions ?? {}).length || config2.skills?.paths?.length)
36239
37050
  unresolved("custom extension or skill paths");
36240
- const directory = join28(home, ".gemini/extensions");
37051
+ const directory = join29(home, ".gemini/extensions");
36241
37052
  safe5(directory);
36242
- if (lstatSync20(directory, { throwIfNoEntry: false }))
36243
- for (const name of readdirSync7(directory)) {
36244
- const root = join28(directory, name);
37053
+ if (lstatSync21(directory, { throwIfNoEntry: false }))
37054
+ for (const name of readdirSync8(directory)) {
37055
+ const root = join29(directory, name);
36245
37056
  safe5(root);
36246
- if (!lstatSync20(root)?.isDirectory())
37057
+ if (!lstatSync21(root)?.isDirectory())
36247
37058
  continue;
36248
- const raw = witness(join28(root, "gemini-extension.json"));
37059
+ const raw = witness(join29(root, "gemini-extension.json"));
36249
37060
  if (raw === null)
36250
37061
  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)
37062
+ const manifest = parseConfig(raw, join29(root, "gemini-extension.json"));
37063
+ if (manifest.hooks !== undefined || witness(join29(root, "hooks/hooks.json")) !== null || witness(join29(root, ".gemini-extension-install.json")) !== null)
36253
37064
  unresolved("extension hooks or linked registration require review");
36254
- roots.add(join28(root, "skills"));
37065
+ roots.add(join29(root, "skills"));
36255
37066
  }
36256
37067
  }
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))) } : {} };
37068
+ 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
37069
  }
36259
37070
  var DISCOVERY_RUNTIME_COMMANDS, realpathOrNull = (path) => {
36260
37071
  try {
36261
- return realpathSync6(path);
37072
+ return realpathSync8(path);
36262
37073
  } catch {
36263
37074
  return null;
36264
37075
  }
36265
- }, digest = (text2) => createHash20("sha256").update(text2).digest("hex");
37076
+ }, digest2 = (text2) => createHash21("sha256").update(text2).digest("hex");
36266
37077
  var init_agent_discovery = __esm(() => {
36267
37078
  init_sumi_settings_witness();
36268
37079
  init_agent_policy_limits();
@@ -36283,16 +37094,17 @@ var init_agent_discovery = __esm(() => {
36283
37094
  init_native_discovery_roots();
36284
37095
  init_codex_native_compatibility();
36285
37096
  init_retained_review_artifacts();
37097
+ init_codex_semantic_cache_witness();
36286
37098
  init_agent_discovery_directories();
36287
37099
  DISCOVERY_RUNTIME_COMMANDS = Object.freeze({ gemini: "gemini" });
36288
37100
  });
36289
37101
 
36290
37102
  // src/lib/authoring-path.ts
36291
- import { lstatSync as lstatSync21, realpathSync as realpathSync7 } from "fs";
37103
+ import { lstatSync as lstatSync22, realpathSync as realpathSync9 } from "fs";
36292
37104
  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";
37105
+ import { basename as basename10, dirname as dirname20, join as join30, resolve as resolve21, sep as sep10 } from "path";
36294
37106
  function pathParts(path) {
36295
- return resolve20(path).split(sep9).filter(Boolean);
37107
+ return resolve21(path).split(sep10).filter(Boolean);
36296
37108
  }
36297
37109
  function nativeRootMatch(path) {
36298
37110
  const parts = pathParts(path);
@@ -36306,24 +37118,24 @@ function nativeRootMatch(path) {
36306
37118
  return;
36307
37119
  }
36308
37120
  function physicalPath(path) {
36309
- let cursor = resolve20(path);
37121
+ let cursor = resolve21(path);
36310
37122
  const suffix = [];
36311
- while (!lstatSync21(cursor, { throwIfNoEntry: false })) {
37123
+ while (!lstatSync22(cursor, { throwIfNoEntry: false })) {
36312
37124
  suffix.unshift(basename10(cursor));
36313
- const parent = dirname19(cursor);
37125
+ const parent = dirname20(cursor);
36314
37126
  if (parent === cursor)
36315
- return resolve20(path);
37127
+ return resolve21(path);
36316
37128
  cursor = parent;
36317
37129
  }
36318
- return resolve20(realpathSync7(cursor), ...suffix);
37130
+ return resolve21(realpathSync9(cursor), ...suffix);
36319
37131
  }
36320
37132
  function contains(root, path) {
36321
- return path === root || path.startsWith(root + sep9);
37133
+ return path === root || path.startsWith(root + sep10);
36322
37134
  }
36323
37135
  function configuredRoots(home, explicitHome) {
36324
- const homeData = join29(home, ".hasna", "skills");
37136
+ const homeData = join30(home, ".hasna", "skills");
36325
37137
  const homePolicy = readManagedSkillPolicySnapshot(homeData);
36326
- const configuredPolicy = !explicitHome && resolve20(getDataDirReadOnly()) !== resolve20(homeData) ? readManagedSkillPolicySnapshot(getDataDirReadOnly()) : null;
37138
+ const configuredPolicy = !explicitHome && resolve21(getDataDirReadOnly()) !== resolve21(homeData) ? readManagedSkillPolicySnapshot(getDataDirReadOnly()) : null;
36327
37139
  const policy = homePolicy ?? configuredPolicy;
36328
37140
  const bridge = policy?.value.bridge;
36329
37141
  if (bridge && (typeof bridge.home !== "string" || physicalPath(bridge.home) !== physicalPath(home))) {
@@ -36352,8 +37164,8 @@ function configuredRoots(home, explicitHome) {
36352
37164
  admitBinding(binding);
36353
37165
  continue;
36354
37166
  }
36355
- const nativeHome = join29(home, agent === "opencode" ? ".config/opencode" : `.${agent}`);
36356
- if (!lstatSync21(nativeHome, { throwIfNoEntry: false }))
37167
+ const nativeHome = join30(home, agent === "opencode" ? ".config/opencode" : `.${agent}`);
37168
+ if (!lstatSync22(nativeHome, { throwIfNoEntry: false }))
36357
37169
  continue;
36358
37170
  roots.push(...resolveAgentDiscovery({ home, agent, canonical: physicalPath }).roots);
36359
37171
  }
@@ -36362,22 +37174,22 @@ function configuredRoots(home, explicitHome) {
36362
37174
  function assertPortableAuthoringPath(path, options = {}) {
36363
37175
  if (typeof path !== "string" || !path || path.includes("\x00"))
36364
37176
  throw new Error("Invalid portable authoring path");
36365
- const lexical = resolve20(path);
37177
+ const lexical = resolve21(path);
36366
37178
  const physical = physicalPath(lexical);
36367
37179
  const candidates = [lexical, physical];
36368
37180
  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"));
37181
+ const home = resolve21(options.homeDir ?? homedir3());
37182
+ const defaults = NATIVE_DISCOVERY_ROOTS.map((parts) => join30(home, ...parts));
37183
+ defaults.push(join30(home, ".codex/plugins/cache"), join30(home, ".claude/plugins/cache"), join30(home, ".claude/plugins/synced"), join30(home, ".gemini/extensions"));
36372
37184
  for (const root of defaults) {
36373
- if (candidates.some((candidate) => contains(resolve20(root), candidate) || contains(physicalPath(root), candidate)))
37185
+ if (candidates.some((candidate) => contains(resolve21(root), candidate) || contains(physicalPath(root), candidate)))
36374
37186
  native ??= root;
36375
37187
  }
36376
37188
  if (native) {
36377
37189
  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
37190
  }
36379
37191
  for (const root of configuredRoots(home, options.homeDir !== undefined)) {
36380
- if (candidates.some((candidate) => contains(resolve20(root), candidate) || contains(physicalPath(root), candidate))) {
37192
+ if (candidates.some((candidate) => contains(resolve21(root), candidate) || contains(physicalPath(root), candidate))) {
36381
37193
  throw new Error(`Refusing portable Skills authoring below configured native discovery root: ${lexical}`);
36382
37194
  }
36383
37195
  }
@@ -36397,29 +37209,29 @@ import {
36397
37209
  existsSync as existsSync12,
36398
37210
  mkdirSync as mkdirSync8,
36399
37211
  mkdtempSync,
36400
- readdirSync as readdirSync8,
36401
- realpathSync as realpathSync8,
37212
+ readdirSync as readdirSync9,
37213
+ realpathSync as realpathSync10,
36402
37214
  renameSync as renameSync3,
36403
37215
  rmSync as rmSync3,
36404
37216
  statSync as statSync8,
36405
37217
  writeFileSync as writeFileSync6
36406
37218
  } 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";
37219
+ 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
37220
  function getPortableSkillsRoot(options = {}) {
36409
37221
  return resolvePortableSkillsRoot(options, true);
36410
37222
  }
36411
37223
  function resolvePortableSkillsRoot(options, migrate) {
36412
37224
  if (options.rootDir)
36413
37225
  return options.rootDir;
36414
- const appDir = options.homeDir ? join30(options.homeDir, ".hasna", "skills") : migrate ? getDataDir() : getDataDirReadOnly();
36415
- const cache = join30(appDir, SKILLS_CACHE_DIRNAME);
37226
+ const appDir = options.homeDir ? join31(options.homeDir, ".hasna", "skills") : migrate ? getDataDir() : getDataDirReadOnly();
37227
+ const cache = join31(appDir, SKILLS_CACHE_DIRNAME);
36416
37228
  if (isOwnerLayoutMigrated(appDir) && safeIsDirectory(cache))
36417
37229
  return cache;
36418
- const installed = join30(appDir, INSTALLED_SKILLS_DIRNAME);
37230
+ const installed = join31(appDir, INSTALLED_SKILLS_DIRNAME);
36419
37231
  return installed;
36420
37232
  }
36421
37233
  function getPortableSkillPath(name, options = {}) {
36422
- return join30(getPortableSkillsRoot(options), normalizePortableSkillName(name));
37234
+ return join31(getPortableSkillsRoot(options), normalizePortableSkillName(name));
36423
37235
  }
36424
37236
  function findPortableSkill(name, options = {}) {
36425
37237
  let normalized;
@@ -36442,10 +37254,10 @@ function listPortableSkills(options = {}) {
36442
37254
  if (!safeIsDirectory(root))
36443
37255
  return [];
36444
37256
  const skills = [];
36445
- for (const entry of readdirSync8(root).sort()) {
37257
+ for (const entry of readdirSync9(root).sort()) {
36446
37258
  if (entry.startsWith("."))
36447
37259
  continue;
36448
- const path = join30(root, entry);
37260
+ const path = join31(root, entry);
36449
37261
  if (!safeIsDirectory(path))
36450
37262
  continue;
36451
37263
  try {
@@ -36478,9 +37290,9 @@ function isOfficialSkillName(name) {
36478
37290
  function scaffoldPortableSkill(name, options = {}) {
36479
37291
  const skillName = normalizeNewPortableSkillName(name);
36480
37292
  const readOnlyRoot = resolvePortableSkillsRoot(options, false);
36481
- assertPortableAuthoringPath(join30(readOnlyRoot, skillName), options);
37293
+ assertPortableAuthoringPath(join31(readOnlyRoot, skillName), options);
36482
37294
  const root = getPortableSkillsRoot(options);
36483
- const skillPath = join30(root, skillName);
37295
+ const skillPath = join31(root, skillName);
36484
37296
  assertPortableAuthoringPath(skillPath, options);
36485
37297
  if (existsSync12(skillPath)) {
36486
37298
  if (!options.overwrite)
@@ -36499,20 +37311,20 @@ function scaffoldPortableSkill(name, options = {}) {
36499
37311
  return { name: skillName, path: skillPath, manifest, created: true };
36500
37312
  }
36501
37313
  function physicalImportPath(path) {
36502
- let ancestor = resolve21(path);
37314
+ let ancestor = resolve22(path);
36503
37315
  const suffix = [];
36504
37316
  while (!existsSync12(ancestor)) {
36505
37317
  suffix.unshift(basename11(ancestor));
36506
- ancestor = dirname20(ancestor);
37318
+ ancestor = dirname21(ancestor);
36507
37319
  }
36508
- return join30(realpathSync8(ancestor), ...suffix);
37320
+ return join31(realpathSync10(ancestor), ...suffix);
36509
37321
  }
36510
37322
  function assertDisjointImportPaths(source, destination) {
36511
- const sourcePath = realpathSync8(source);
37323
+ const sourcePath = realpathSync10(source);
36512
37324
  const destinationPath = physicalImportPath(destination);
36513
37325
  const contains2 = (parent, child2) => {
36514
- const path = relative6(parent, child2);
36515
- return path === "" || !isAbsolute19(path) && path !== ".." && !path.startsWith(`..${sep10}`);
37326
+ const path = relative8(parent, child2);
37327
+ return path === "" || !isAbsolute20(path) && path !== ".." && !path.startsWith(`..${sep11}`);
36516
37328
  };
36517
37329
  if (contains2(sourcePath, destinationPath) || contains2(destinationPath, sourcePath)) {
36518
37330
  throw new Error("Source and destination skill directories must not overlap");
@@ -36531,11 +37343,11 @@ function portPortableSkill(sourcePath, options = {}) {
36531
37343
  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
37344
  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
37345
  }
36534
- const readOnlyDestination = join30(resolvePortableSkillsRoot(options, false), skillName);
37346
+ const readOnlyDestination = join31(resolvePortableSkillsRoot(options, false), skillName);
36535
37347
  assertPortableAuthoringPath(readOnlyDestination, options);
36536
37348
  assertDisjointImportPaths(absoluteSource, readOnlyDestination);
36537
37349
  const root = getPortableSkillsRoot(options);
36538
- const destination = join30(root, skillName);
37350
+ const destination = join31(root, skillName);
36539
37351
  assertPortableAuthoringPath(destination, options);
36540
37352
  assertDisjointImportPaths(absoluteSource, destination);
36541
37353
  if (existsSync12(destination)) {
@@ -36543,7 +37355,7 @@ function portPortableSkill(sourcePath, options = {}) {
36543
37355
  throw new Error(`Skill '${skillName}' already exists at ${destination}`);
36544
37356
  rmSync3(destination, { recursive: true, force: true });
36545
37357
  }
36546
- mkdirSync8(dirname20(destination), { recursive: true });
37358
+ mkdirSync8(dirname21(destination), { recursive: true });
36547
37359
  copySkillDirectory(absoluteSource, destination);
36548
37360
  const base = {
36549
37361
  ...inferred,
@@ -36567,8 +37379,8 @@ function validatePortableSkillDirectory(name, skillPath) {
36567
37379
  const warnings = [...base.warnings];
36568
37380
  let manifest;
36569
37381
  if (existsSync12(skillPath)) {
36570
- const skillJsonPath = join30(skillPath, "skill.json");
36571
- const skillMdPath = join30(skillPath, "SKILL.md");
37382
+ const skillJsonPath = join31(skillPath, "skill.json");
37383
+ const skillMdPath = join31(skillPath, "SKILL.md");
36572
37384
  if (!existsSync12(skillJsonPath) && !existsSync12(skillMdPath)) {
36573
37385
  add3(issues, "portable.manifest_missing", "Missing portable manifest: expected SKILL.md frontmatter and/or skill.json");
36574
37386
  }
@@ -36588,7 +37400,7 @@ function validatePortableSkillDirectory(name, skillPath) {
36588
37400
  add3(issues, "portable.version_missing", "Portable manifest missing version");
36589
37401
  }
36590
37402
  const contractIssues = validatePortableManifestContract(manifest, {
36591
- strict: existsSync12(join30(skillPath, "skill.json")),
37403
+ strict: existsSync12(join31(skillPath, "skill.json")),
36592
37404
  skillPath
36593
37405
  });
36594
37406
  for (const issue2 of contractIssues)
@@ -36628,7 +37440,7 @@ function validatePortableSkillDirectory(name, skillPath) {
36628
37440
  add3(issues, "portable.command_entry_unsafe", `Command '${command.name}' entry '${command.entry}' must stay inside the skill directory`);
36629
37441
  continue;
36630
37442
  }
36631
- const entryPath = join30(skillPath, command.entry);
37443
+ const entryPath = join31(skillPath, command.entry);
36632
37444
  if (!existsSync12(entryPath))
36633
37445
  add3(issues, "portable.command_entry_missing", `Command '${command.name}' entry '${command.entry}' is missing`);
36634
37446
  else if (statSync8(entryPath).isDirectory())
@@ -36639,7 +37451,7 @@ function validatePortableSkillDirectory(name, skillPath) {
36639
37451
  } catch (error61) {
36640
37452
  add3(issues, "portable.manifest_invalid", error61.message);
36641
37453
  }
36642
- if (manifest?.kind !== "instruction" && !existsSync12(join30(skillPath, "AGENTS.md"))) {
37454
+ if (manifest?.kind !== "instruction" && !existsSync12(join31(skillPath, "AGENTS.md"))) {
36643
37455
  add3(issues, "portable.agents_missing", "Missing AGENTS.md with build-out instructions for coding agents");
36644
37456
  }
36645
37457
  }
@@ -36677,7 +37489,7 @@ function safeIsDirectory(path) {
36677
37489
  }
36678
37490
  }
36679
37491
  function isSafeRelativePath2(value) {
36680
- if (!value.trim() || isAbsolute19(value))
37492
+ if (!value.trim() || isAbsolute20(value))
36681
37493
  return false;
36682
37494
  const normalized = normalize4(value).replace(/\\/g, "/");
36683
37495
  return normalized !== ".." && !normalized.startsWith("../") && !normalized.includes("/../");
@@ -36866,8 +37678,8 @@ var init_search = __esm(() => {
36866
37678
  });
36867
37679
 
36868
37680
  // src/lib/registry.ts
36869
- import { existsSync as existsSync13, readFileSync as readFileSync17, readdirSync as readdirSync9 } from "fs";
36870
- import { join as join31 } from "path";
37681
+ import { existsSync as existsSync13, readFileSync as readFileSync17, readdirSync as readdirSync10 } from "fs";
37682
+ import { join as join32 } from "path";
36871
37683
  function parseSkillMdFrontmatter(content) {
36872
37684
  const match = content.match(/^---\n([\s\S]*?)\n---/);
36873
37685
  if (!match)
@@ -36904,11 +37716,11 @@ function discoverSkillsInDir(dir, source = "custom") {
36904
37716
  return [];
36905
37717
  const result = [];
36906
37718
  try {
36907
- const entries = readdirSync9(dir, { withFileTypes: true });
37719
+ const entries = readdirSync10(dir, { withFileTypes: true });
36908
37720
  for (const entry of entries) {
36909
37721
  if (!entry.isDirectory())
36910
37722
  continue;
36911
- const skillMdPath = join31(dir, entry.name, "SKILL.md");
37723
+ const skillMdPath = join32(dir, entry.name, "SKILL.md");
36912
37724
  if (!existsSync13(skillMdPath))
36913
37725
  continue;
36914
37726
  let content;
@@ -36928,7 +37740,7 @@ function discoverSkillsInDir(dir, source = "custom") {
36928
37740
  category: fm.category || "Development Tools",
36929
37741
  tags: fm.tags || [],
36930
37742
  ...fm.kind ? { kind: fm.kind } : {},
36931
- ...isHostedMetadataSkillDir(join31(dir, entry.name)) ? { serverOwned: true } : {},
37743
+ ...isHostedMetadataSkillDir(join32(dir, entry.name)) ? { serverOwned: true } : {},
36932
37744
  source
36933
37745
  });
36934
37746
  }
@@ -36940,12 +37752,12 @@ function findExtensionSkillPath(name) {
36940
37752
  if (!config2.extensionsDir || !existsSync13(config2.extensionsDir))
36941
37753
  return null;
36942
37754
  try {
36943
- const entries = readdirSync9(config2.extensionsDir, { withFileTypes: true });
37755
+ const entries = readdirSync10(config2.extensionsDir, { withFileTypes: true });
36944
37756
  for (const entry of entries) {
36945
37757
  if (!entry.isDirectory())
36946
37758
  continue;
36947
- const skillDir = join31(config2.extensionsDir, entry.name);
36948
- const skillMdPath = join31(skillDir, "SKILL.md");
37759
+ const skillDir = join32(config2.extensionsDir, entry.name);
37760
+ const skillMdPath = join32(skillDir, "SKILL.md");
36949
37761
  if (!existsSync13(skillMdPath))
36950
37762
  continue;
36951
37763
  let content;
@@ -37362,7 +38174,7 @@ var init_v4 = __esm(() => {
37362
38174
  });
37363
38175
 
37364
38176
  // src/lib/canonical-json.ts
37365
- import { createHash as createHash21 } from "crypto";
38177
+ import { createHash as createHash22 } from "crypto";
37366
38178
  function canonicalJson2(value, maximumBytes = 2 * 1024 * 1024) {
37367
38179
  return canonicalJsonAtDepth(value, maximumBytes, 64);
37368
38180
  }
@@ -37406,7 +38218,7 @@ function canonicalJsonAtDepth(value, maximumBytes, maximumDepth) {
37406
38218
  return visit3(value, 0);
37407
38219
  }
37408
38220
  function canonicalJsonSha256(value, maximumBytes) {
37409
- return createHash21("sha256").update(canonicalJson2(value, maximumBytes)).digest("hex");
38221
+ return createHash22("sha256").update(canonicalJson2(value, maximumBytes)).digest("hex");
37410
38222
  }
37411
38223
  var init_canonical_json = () => {};
37412
38224
 
@@ -37516,14 +38328,14 @@ function requireResult(value) {
37516
38328
  if (!value)
37517
38329
  throw new RemoteRecurringReadError;
37518
38330
  }
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);
38331
+ function termsIntegrity(terms, hash4, identity4, own2) {
38332
+ requireResult(terms.organizationId === identity4.organization.id && (!own2 || terms.approvedByUserId === identity4.user.id && terms.approvedMembershipId === identity4.user.membershipId));
38333
+ requireResult(canonicalJsonSha256(terms) === hash4);
37522
38334
  requireResult(canonicalJsonSha256({ skill: terms.skill, input: terms.input, args: terms.args, runtime: terms.runtime }) === terms.payloadSha256);
37523
38335
  requireResult(Date.parse(terms.expiresAt) > Date.parse(terms.startsAt));
37524
38336
  }
37525
- function previewIntegrity(value, identity3) {
37526
- termsIntegrity(value.terms, value.termsSha256, identity3, true);
38337
+ function previewIntegrity(value, identity4) {
38338
+ termsIntegrity(value.terms, value.termsSha256, identity4, true);
37527
38339
  requireResult(Date.parse(value.approvalDeadline) > Date.parse(value.quote.quotedAt));
37528
38340
  const anchor2 = Date.parse(value.terms.startsAt), end = Date.parse(value.terms.expiresAt), cadence = value.terms.everyMinutes * 60000;
37529
38341
  requireResult(value.firstDueInstants.every((at, i) => Date.parse(at) === anchor2 + i * cadence && Date.parse(at) < end));
@@ -37531,7 +38343,7 @@ function previewIntegrity(value, identity3) {
37531
38343
  const day = Date.parse(value.firstPeriod.startsAt);
37532
38344
  requireResult(day % 86400000 === 0 && day <= anchor2 && anchor2 < Date.parse(value.firstPeriod.endsAt) && Date.parse(value.firstPeriod.endsAt) === day + 86400000);
37533
38345
  }
37534
- function parseRecurringResult(action, value, input2, identity3) {
38346
+ function parseRecurringResult(action, value, input2, identity4) {
37535
38347
  const wrappers = { preview: 1, draft: 1, activate: 2, list: 3, get: 1, occurrences: 0, revoke: 0 };
37536
38348
  canonicalJsonAtDepth(value, 64 * 1024 * 1024, 64 + wrappers[action]);
37537
38349
  const result = results[action].parse(value);
@@ -37540,7 +38352,7 @@ function parseRecurringResult(action, value, input2, identity3) {
37540
38352
  const row = input2;
37541
38353
  if (action === "preview" || action === "draft") {
37542
38354
  const p = result;
37543
- previewIntegrity(p, identity3);
38355
+ previewIntegrity(p, identity4);
37544
38356
  if (action === "draft")
37545
38357
  requireResult(p.draftId === row.draftId);
37546
38358
  else {
@@ -37559,7 +38371,7 @@ function parseRecurringResult(action, value, input2, identity3) {
37559
38371
  }
37560
38372
  const views = action === "list" ? result.items : action === "get" ? [result] : action === "activate" ? [result.consent] : [];
37561
38373
  for (const view of views) {
37562
- termsIntegrity(view.terms, view.termsSha256, identity3, action === "activate");
38374
+ termsIntegrity(view.terms, view.termsSha256, identity4, action === "activate");
37563
38375
  requireResult(view.state === "revoked" === (view.revokedAt !== null));
37564
38376
  if (action === "get")
37565
38377
  requireResult(view.consentId === row.consentId);
@@ -37585,7 +38397,7 @@ function parseRecurringResult(action, value, input2, identity3) {
37585
38397
  }
37586
38398
  return result;
37587
38399
  }
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;
38400
+ 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
38401
  var init_remote_recurring = __esm(() => {
37590
38402
  init_v4();
37591
38403
  init_canonical_json();
@@ -37651,7 +38463,7 @@ var init_remote_recurring = __esm(() => {
37651
38463
  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
38464
  instant2 = exports_external.string().max(32).datetime();
37653
38465
  integer2 = exports_external.number().int().min(0).max(MAX_RECURRING_CREDITS);
37654
- digest2 = exports_external.string().regex(/^[a-f0-9]{64}$/);
38466
+ digest3 = exports_external.string().regex(/^[a-f0-9]{64}$/);
37655
38467
  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
38468
  inputs = {
37657
38469
  preview: recurringRequestSchema,
@@ -37677,7 +38489,7 @@ var init_remote_recurring = __esm(() => {
37677
38489
  contractVersion: exports_external.literal(1),
37678
38490
  draftId: uuid3,
37679
38491
  terms: recurringTermsSchema,
37680
- termsSha256: digest2,
38492
+ termsSha256: digest3,
37681
38493
  quote: exports_external.object({ costCredits: integer2, quotedAt: instant2, admissionReprices: exports_external.literal(true) }),
37682
38494
  approvalDeadline: instant2,
37683
38495
  firstDueInstants: exports_external.array(instant2).min(1).max(5),
@@ -37689,7 +38501,7 @@ var init_remote_recurring = __esm(() => {
37689
38501
  consentId: uuid3,
37690
38502
  scheduleId: uuid3,
37691
38503
  terms: recurringTermsSchema,
37692
- termsSha256: digest2,
38504
+ termsSha256: digest3,
37693
38505
  state: exports_external.enum(["active", "revoked", "expired"]),
37694
38506
  activatedAt: instant2,
37695
38507
  revokedAt: instant2.nullable(),
@@ -37943,10 +38755,10 @@ function sessionToken(value) {
37943
38755
  return value;
37944
38756
  }
37945
38757
  function parseWorkspaceSession(value, expected) {
37946
- const identity3 = parseWorkspaceIdentity(value, expected.userId);
37947
- if (identity3.user.membershipId !== expected.membershipId)
38758
+ const identity4 = parseWorkspaceIdentity(value, expected.userId);
38759
+ if (identity4.user.membershipId !== expected.membershipId)
37948
38760
  throw new WorkspaceIdentityMismatchError;
37949
- return { token: sessionToken(value.token), ...identity3 };
38761
+ return { token: sessionToken(value.token), ...identity4 };
37950
38762
  }
37951
38763
  function parseWorkspaceLogin(value, expectedUserId) {
37952
38764
  const user = record5(value) && value.user;
@@ -38157,13 +38969,13 @@ var init_remote_workspace_leave = __esm(() => {
38157
38969
 
38158
38970
  // src/lib/auth-store.ts
38159
38971
  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";
38972
+ import { basename as basename12, dirname as dirname22, join as join33 } from "path";
38161
38973
  function getAuthFilePath(env = process.env) {
38162
38974
  return skillsCredentialFilePath(env);
38163
38975
  }
38164
38976
  function getIdentityFilePath(env = process.env) {
38165
38977
  const file2 = skillsCredentialFilePath(env);
38166
- return join32(dirname21(file2), basename12(file2).replace(/^credentials/, "identity") + ".json");
38978
+ return join33(dirname22(file2), basename12(file2).replace(/^credentials/, "identity") + ".json");
38167
38979
  }
38168
38980
  function getApiUrl(action, env = process.env, options = {}) {
38169
38981
  return requireSkillsApiOrigin(action, env, options);
@@ -38391,10 +39203,10 @@ async function readQuoteUnavailableCode(response) {
38391
39203
  let timer;
38392
39204
  let deadlineExceeded = false;
38393
39205
  const expired = Symbol("quote body deadline");
38394
- const deadline = new Promise((resolve22) => {
39206
+ const deadline = new Promise((resolve23) => {
38395
39207
  timer = setTimeout(() => {
38396
39208
  deadlineExceeded = true;
38397
- resolve22(expired);
39209
+ resolve23(expired);
38398
39210
  reader.cancel().catch(() => {});
38399
39211
  }, 1500);
38400
39212
  });
@@ -38697,16 +39509,16 @@ class RemoteSkillsClient {
38697
39509
  async listAccountWorkspaces(expectedUserId) {
38698
39510
  const expected = expectedUserId === undefined ? undefined : workspaceExpectedUserId(expectedUserId);
38699
39511
  const connection = new RemoteSkillsClient(this.apiKey, this.apiUrl);
38700
- let identity3;
39512
+ let identity4;
38701
39513
  if (expected !== undefined) {
38702
39514
  const value = await connection.requestWorkspaceSelection("/api/auth/whoami");
38703
39515
  if (!value || typeof value !== "object" || value.authMethod !== "jwt")
38704
39516
  throw new RemoteWorkspaceSelectionError("/api/v1/account/workspaces", "INTERACTIVE_SESSION_REQUIRED");
38705
- identity3 = parseWorkspaceIdentity(value, expected);
39517
+ identity4 = parseWorkspaceIdentity(value, expected);
38706
39518
  }
38707
39519
  const result = parseAccountWorkspaces(await connection.requestWorkspaceSelection("/api/v1/account/workspaces"));
38708
39520
  const current = result.workspaces.find((workspace) => workspace.current);
38709
- if (identity3 && (current.membershipId !== identity3.user.membershipId || current.organization.id !== identity3.organization.id))
39521
+ if (identity4 && (current.membershipId !== identity4.user.membershipId || current.organization.id !== identity4.organization.id))
38710
39522
  throw new WorkspaceIdentityMismatchError;
38711
39523
  return result;
38712
39524
  }
@@ -38724,10 +39536,10 @@ class RemoteSkillsClient {
38724
39536
  const verified = await new RemoteSkillsClient(selected.token, connection.apiUrl).requestWorkspaceSelection("/api/auth/whoami");
38725
39537
  if (!verified || typeof verified !== "object" || verified.authMethod !== "jwt")
38726
39538
  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)
39539
+ const identity4 = parseWorkspaceIdentity(verified, target.userId);
39540
+ if (identity4.user.membershipId !== target.membershipId || identity4.organization.id !== selected.organization.id)
38729
39541
  throw new WorkspaceIdentityMismatchError;
38730
- return { token: selected.token, ...identity3 };
39542
+ return { token: selected.token, ...identity4 };
38731
39543
  }
38732
39544
  async requestWorkspaceSelection(path, options) {
38733
39545
  let response;
@@ -38811,8 +39623,8 @@ class RemoteSkillsClient {
38811
39623
  const value = await connection.requestWorkspaceSelection("/api/auth/whoami");
38812
39624
  if (!value || typeof value !== "object" || value.authMethod !== "jwt")
38813
39625
  throw new RemoteWorkspaceLeaveError("INTERACTIVE_SESSION_REQUIRED");
38814
- const identity3 = parseWorkspaceIdentity(value, captured.context.userId);
38815
- if (identity3.user.membershipId !== captured.context.membershipId)
39626
+ const identity4 = parseWorkspaceIdentity(value, captured.context.userId);
39627
+ if (identity4.user.membershipId !== captured.context.membershipId)
38816
39628
  throw new WorkspaceIdentityMismatchError;
38817
39629
  let response, body;
38818
39630
  try {
@@ -38827,7 +39639,7 @@ class RemoteSkillsClient {
38827
39639
  throw new RemoteWorkspaceLeaveError(code);
38828
39640
  throw new RemoteWorkspaceLeaveUnconfirmedError;
38829
39641
  }
38830
- return parseWorkspaceLeaveResult(body, captured.context.membershipId, identity3.organization.id);
39642
+ return parseWorkspaceLeaveResult(body, captured.context.membershipId, identity4.organization.id);
38831
39643
  }
38832
39644
  listWorkspaceInvitations(context, options = {}) {
38833
39645
  return this.requestWorkspaceInvitation(context, "list", options);
@@ -38853,8 +39665,8 @@ class RemoteSkillsClient {
38853
39665
  const identityValue = await connection.requestWorkspaceSelection("/api/auth/whoami");
38854
39666
  if (!identityValue || typeof identityValue !== "object" || identityValue.authMethod !== "jwt")
38855
39667
  throw new RemoteWorkspaceInvitationError("INTERACTIVE_SESSION_REQUIRED");
38856
- const identity3 = parseWorkspaceIdentity(identityValue, target.userId);
38857
- if (identity3.user.membershipId !== target.membershipId)
39668
+ const identity4 = parseWorkspaceIdentity(identityValue, target.userId);
39669
+ if (identity4.user.membershipId !== target.membershipId)
38858
39670
  throw new WorkspaceIdentityMismatchError;
38859
39671
  const request = invitationRequest(action, captured), read2 = action === "list" || action === "get";
38860
39672
  let response, value;
@@ -38871,7 +39683,7 @@ class RemoteSkillsClient {
38871
39683
  throw read2 ? new RemoteWorkspaceInvitationReadError : new RemoteWorkspaceInvitationUnconfirmedError;
38872
39684
  }
38873
39685
  try {
38874
- return parseInvitationResult(action, value, captured, identity3.organization.id);
39686
+ return parseInvitationResult(action, value, captured, identity4.organization.id);
38875
39687
  } catch {
38876
39688
  throw read2 ? new RemoteWorkspaceInvitationReadError : new RemoteWorkspaceInvitationUnconfirmedError;
38877
39689
  }
@@ -38912,7 +39724,7 @@ class RemoteSkillsClient {
38912
39724
  } catch {
38913
39725
  throw new RemoteRecurringUnavailableError;
38914
39726
  }
38915
- let identity3, identityValue;
39727
+ let identity4, identityValue;
38916
39728
  try {
38917
39729
  const response = await connection.request("/api/auth/whoami");
38918
39730
  if (!response.ok) {
@@ -38921,8 +39733,8 @@ class RemoteSkillsClient {
38921
39733
  }
38922
39734
  identityValue = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(await readBoundedResponse(response, 64 * 1024)));
38923
39735
  const observedUser = identityValue.user?.id;
38924
- identity3 = parseWorkspaceIdentity(identityValue, target?.userId ?? workspaceExpectedUserId(observedUser));
38925
- if (target && identity3.user.membershipId !== target.membershipId)
39736
+ identity4 = parseWorkspaceIdentity(identityValue, target?.userId ?? workspaceExpectedUserId(observedUser));
39737
+ if (target && identity4.user.membershipId !== target.membershipId)
38926
39738
  throw new WorkspaceIdentityMismatchError;
38927
39739
  } catch {
38928
39740
  throw new RemoteRecurringReadError;
@@ -38932,16 +39744,16 @@ class RemoteSkillsClient {
38932
39744
  throw new RemoteRecurringError("RECURRING_HUMAN_APPROVAL_REQUIRED");
38933
39745
  assertRecurringCapability(capability, "draft");
38934
39746
  const selected = captured;
38935
- const draft = await connection.dispatchRecurring("draft", { draftId: selected.draftId }, identity3);
39747
+ const draft = await connection.dispatchRecurring("draft", { draftId: selected.draftId }, identity4);
38936
39748
  if (!draft || draft.termsSha256 !== selected.approval.acceptedTermsSha256)
38937
39749
  throw new RemoteRecurringError("RECURRING_TERMS_UNAVAILABLE");
38938
39750
  }
38939
39751
  let selectedConsent;
38940
39752
  if (action === "occurrences") {
38941
39753
  assertRecurringCapability(capability, "get");
38942
- selectedConsent = await connection.dispatchRecurring("get", { consentId: captured.consentId }, identity3);
39754
+ selectedConsent = await connection.dispatchRecurring("get", { consentId: captured.consentId }, identity4);
38943
39755
  }
38944
- const result = await connection.dispatchRecurring(action, captured, identity3);
39756
+ const result = await connection.dispatchRecurring(action, captured, identity4);
38945
39757
  if (action === "occurrences") {
38946
39758
  const items = result.items;
38947
39759
  if (items.length && (!selectedConsent || items.some((item) => item.scheduleId !== selectedConsent.scheduleId)))
@@ -38949,7 +39761,7 @@ class RemoteSkillsClient {
38949
39761
  }
38950
39762
  return result;
38951
39763
  }
38952
- async dispatchRecurring(action, input2, identity3) {
39764
+ async dispatchRecurring(action, input2, identity4) {
38953
39765
  const request = recurringRequest(action, input2);
38954
39766
  let response, value;
38955
39767
  try {
@@ -38969,7 +39781,7 @@ class RemoteSkillsClient {
38969
39781
  try {
38970
39782
  if (response.status !== 200 || value === null)
38971
39783
  throw new RemoteRecurringReadError;
38972
- return parseRecurringResult(action, value, input2, identity3);
39784
+ return parseRecurringResult(action, value, input2, identity4);
38973
39785
  } catch {
38974
39786
  throw request.read ? new RemoteRecurringReadError : new RemoteRecurringUnconfirmedError;
38975
39787
  }
@@ -39632,13 +40444,13 @@ var init_remote_invitation_recovery = __esm(() => {
39632
40444
  });
39633
40445
 
39634
40446
  // src/lib/remote-private-publications.ts
39635
- import { createHash as createHash22 } from "crypto";
40447
+ import { createHash as createHash23 } from "crypto";
39636
40448
  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)
40449
+ 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
40450
  return bad();
39639
40451
  try {
39640
40452
  const manifest = JSON.parse(value.manifestText);
39641
- if (!record9(manifest) || manifest.version !== value.version || validatePortableManifestContract(manifest, { strict: true }).length || !hash3(manifest.provenance?.content_hash))
40453
+ if (!record9(manifest) || manifest.version !== value.version || validatePortableManifestContract(manifest, { strict: true }).length || !hash4(manifest.provenance?.content_hash))
39642
40454
  return bad();
39643
40455
  } catch {
39644
40456
  return bad();
@@ -39646,7 +40458,7 @@ function checkedPublicationDeclaration(value) {
39646
40458
  return Object.freeze({ ...value });
39647
40459
  }
39648
40460
  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)
40461
+ 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
40462
  return invalid4();
39651
40463
  if (declaration && ["version", "expectedCurrentVersionId", "archiveSha256", "archiveByteSize"].some((k) => value[k] !== declaration[k]))
39652
40464
  return invalid4();
@@ -39877,12 +40689,12 @@ class RemotePrivatePublicationsClient {
39877
40689
  previous = view;
39878
40690
  if (!["queued", "verifying"].includes(view.state) || Date.now() >= until)
39879
40691
  return view;
39880
- await new Promise((resolve22) => {
40692
+ await new Promise((resolve23) => {
39881
40693
  const timer = setTimeout(done, Math.min(1000, until - Date.now()));
39882
40694
  function done() {
39883
40695
  clearTimeout(timer);
39884
40696
  options.signal?.removeEventListener("abort", done);
39885
- resolve22();
40697
+ resolve23();
39886
40698
  }
39887
40699
  options.signal?.addEventListener("abort", done, { once: true });
39888
40700
  });
@@ -39893,7 +40705,7 @@ var PRIVATE_PUBLICATION_MAX_BYTES, failures2, PrivatePublicationError, bad = ()
39893
40705
  throw new PrivatePublicationError("INVALID_PUBLICATION_INPUT", "Invalid publication input or recovery data.");
39894
40706
  }, invalid4 = () => {
39895
40707
  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");
40708
+ }, 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
40709
  var init_remote_private_publications = __esm(() => {
39898
40710
  init_fleet_credentials();
39899
40711
  init_remote_workspace_selection();
@@ -40170,10 +40982,10 @@ var init_remote_auth = __esm(() => {
40170
40982
  });
40171
40983
 
40172
40984
  // 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";
40985
+ 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
40986
  function stat2(path) {
40175
40987
  try {
40176
- return lstatSync22(path);
40988
+ return lstatSync23(path);
40177
40989
  } catch (error61) {
40178
40990
  if (error61.code === "ENOENT")
40179
40991
  return null;
@@ -40183,17 +40995,17 @@ function stat2(path) {
40183
40995
  function safeText(file2) {
40184
40996
  if (stat2(file2) === null)
40185
40997
  return null;
40186
- const fd = openSync16(file2, constants14.O_RDONLY | constants14.O_NOFOLLOW | constants14.O_NONBLOCK);
40998
+ const fd = openSync17(file2, constants15.O_RDONLY | constants15.O_NOFOLLOW | constants15.O_NONBLOCK);
40187
40999
  try {
40188
- const s = fstatSync16(fd);
41000
+ const s = fstatSync17(fd);
40189
41001
  if (!s.isFile() || s.size > 65536 || ![256, 384].includes(s.mode & 4095) || process.getuid && s.uid !== process.getuid())
40190
41002
  return fail("The selected profile must use bounded owner-only regular files.");
40191
41003
  return readFileSync19(fd, "utf8");
40192
41004
  } finally {
40193
- closeSync16(fd);
41005
+ closeSync17(fd);
40194
41006
  }
40195
41007
  }
40196
- function checkIdentityMetadata(file2, identity3) {
41008
+ function checkIdentityMetadata(file2, identity4) {
40197
41009
  const text3 = safeText(file2);
40198
41010
  if (text3 === null)
40199
41011
  return;
@@ -40205,7 +41017,7 @@ function checkIdentityMetadata(file2, identity3) {
40205
41017
  }
40206
41018
  if (!value || typeof value !== "object" || Array.isArray(value))
40207
41019
  return fail("The profile identity metadata is invalid.");
40208
- for (const [key, expected] of Object.entries({ userId: identity3.user.id, orgId: identity3.organization.id })) {
41020
+ for (const [key, expected] of Object.entries({ userId: identity4.user.id, orgId: identity4.organization.id })) {
40209
41021
  if (value[key] !== undefined && value[key] !== expected)
40210
41022
  return fail("The profile identity metadata does not match its authenticated key. Sign in again before managing this workspace.");
40211
41023
  }
@@ -40227,10 +41039,10 @@ function prepareProfileWorkspace(action, source = process.env) {
40227
41039
  const connection = await resolveSkillsConnection(env);
40228
41040
  if (!connection || connection.apiOrigin !== origin)
40229
41041
  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);
41042
+ const identity4 = await keyIdentity(connection.apiKey, origin);
41043
+ checkIdentityMetadata(getIdentityFilePath(env), identity4);
40232
41044
  unchanged3();
40233
- const context = { userId: identity3.user.id, membershipId: identity3.user.membershipId };
41045
+ const context = { userId: identity4.user.id, membershipId: identity4.user.membershipId };
40234
41046
  return { origin, context, unchanged: unchanged3 };
40235
41047
  } };
40236
41048
  }
@@ -40311,15 +41123,15 @@ async function prepareRecurringCustomer(requested, source = process.env) {
40311
41123
  await assertCurrent();
40312
41124
  const value = await new RemoteSkillsClient(connection.apiKey, connection.apiOrigin).getIdentity();
40313
41125
  const user = value.user;
40314
- const identity3 = parseWorkspaceIdentity(value, context?.userId ?? workspaceExpectedUserId(user?.id));
41126
+ const identity4 = parseWorkspaceIdentity(value, context?.userId ?? workspaceExpectedUserId(user?.id));
40315
41127
  await assertCurrent();
40316
- if (value.authMethod !== "api_key" || context && identity3.user.membershipId !== context.membershipId)
41128
+ if (value.authMethod !== "api_key" || context && identity4.user.membershipId !== context.membershipId)
40317
41129
  changed();
40318
- const binding = JSON.stringify([identity3.user.id, identity3.user.membershipId, identity3.organization.id]);
41130
+ const binding = JSON.stringify([identity4.user.id, identity4.user.membershipId, identity4.organization.id]);
40319
41131
  if (originalIdentity !== undefined && originalIdentity !== binding)
40320
41132
  changed();
40321
41133
  originalIdentity = binding;
40322
- if (verification(identity3.user.email) !== normalized)
41134
+ if (verification(identity4.user.email) !== normalized)
40323
41135
  throw new RecurringCustomerError("RECURRING_ACCOUNT_EMAIL_MISMATCH", "Use the selected account's current email. No verification request or recurring activation was submitted.");
40324
41136
  return normalized;
40325
41137
  }
@@ -40402,8 +41214,8 @@ var init_recurring_customer = __esm(() => {
40402
41214
  });
40403
41215
 
40404
41216
  // 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";
41217
+ 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";
41218
+ import { dirname as dirname23, isAbsolute as isAbsolute21, join as join34, resolve as resolve23 } from "path";
40407
41219
  import { randomUUID as randomUUID2 } from "crypto";
40408
41220
 
40409
41221
  class RecoveryOwner {
@@ -40411,75 +41223,75 @@ class RecoveryOwner {
40411
41223
  parents = [];
40412
41224
  constructor(directory) {
40413
41225
  this.directory = directory;
40414
- if (!isAbsolute20(directory) || resolve22(directory) !== directory || realpathSync9(directory) !== directory)
41226
+ if (!isAbsolute21(directory) || resolve23(directory) !== directory || realpathSync11(directory) !== directory)
40415
41227
  invalid5();
40416
- for (let path = directory;; path = dirname22(path)) {
40417
- const stat3 = lstatSync23(path);
41228
+ for (let path = directory;; path = dirname23(path)) {
41229
+ const stat3 = lstatSync24(path);
40418
41230
  if (!stat3.isDirectory() || stat3.isSymbolicLink())
40419
41231
  invalid5();
40420
41232
  this.parents.push({ path, dev: stat3.dev, ino: stat3.ino });
40421
- if (path === dirname22(path))
41233
+ if (path === dirname23(path))
40422
41234
  break;
40423
41235
  }
40424
41236
  this.assert();
40425
41237
  }
40426
41238
  assert() {
40427
- if (realpathSync9(this.directory) !== this.directory)
41239
+ if (realpathSync11(this.directory) !== this.directory)
40428
41240
  invalid5();
40429
41241
  for (const prior of this.parents) {
40430
- const now = lstatSync23(prior.path);
41242
+ const now = lstatSync24(prior.path);
40431
41243
  if (!now.isDirectory() || now.isSymbolicLink() || now.dev !== prior.dev || now.ino !== prior.ino)
40432
41244
  invalid5();
40433
41245
  }
40434
- const own2 = lstatSync23(this.directory);
41246
+ const own2 = lstatSync24(this.directory);
40435
41247
  if ((own2.mode & 511) !== 448 || (own2.mode & 3584) !== 0 || process.getuid && own2.uid !== process.getuid())
40436
41248
  invalid5();
40437
41249
  }
40438
41250
  read(name) {
40439
41251
  this.assert();
40440
- const fd = openSync17(join33(this.directory, name), constants15.O_RDONLY | constants15.O_NOFOLLOW | constants15.O_NONBLOCK);
41252
+ const fd = openSync18(join34(this.directory, name), constants16.O_RDONLY | constants16.O_NOFOLLOW | constants16.O_NONBLOCK);
40441
41253
  try {
40442
- const before = fstatSync17(fd);
41254
+ const before = fstatSync18(fd);
40443
41255
  if (!before.isFile() || before.nlink !== 1 || (before.mode & 4095) !== 384 || before.size < 1 || before.size > 8192 || process.getuid && before.uid !== process.getuid())
40444
41256
  invalid5();
40445
41257
  const bytes = Buffer.alloc(before.size + 1);
40446
41258
  let size = 0;
40447
41259
  while (size < bytes.length) {
40448
- const n2 = readSync11(fd, bytes, size, bytes.length - size, size);
41260
+ const n2 = readSync12(fd, bytes, size, bytes.length - size, size);
40449
41261
  if (!n2)
40450
41262
  break;
40451
41263
  size += n2;
40452
41264
  }
40453
- const after = fstatSync17(fd), path = lstatSync23(join33(this.directory, name));
41265
+ const after = fstatSync18(fd), path = lstatSync24(join34(this.directory, name));
40454
41266
  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
41267
  invalid5();
40456
41268
  this.assert();
40457
41269
  return new TextDecoder("utf-8", { fatal: true }).decode(bytes.subarray(0, size));
40458
41270
  } finally {
40459
- closeSync17(fd);
41271
+ closeSync18(fd);
40460
41272
  }
40461
41273
  }
40462
41274
  write(name, value) {
40463
41275
  this.assert();
40464
41276
  const bytes = canonicalJson2(value, 8192) + `
40465
41277
  `;
40466
- const fd = openSync17(join33(this.directory, name), constants15.O_WRONLY | constants15.O_CREAT | constants15.O_EXCL | constants15.O_NOFOLLOW, 384);
41278
+ const fd = openSync18(join34(this.directory, name), constants16.O_WRONLY | constants16.O_CREAT | constants16.O_EXCL | constants16.O_NOFOLLOW, 384);
40467
41279
  try {
40468
41280
  writeFileSync9(fd, bytes);
40469
41281
  fsyncSync5(fd);
40470
41282
  } finally {
40471
- closeSync17(fd);
41283
+ closeSync18(fd);
40472
41284
  }
40473
41285
  this.assert();
40474
41286
  this.sync();
40475
41287
  }
40476
41288
  sync() {
40477
41289
  this.assert();
40478
- const fd = openSync17(this.directory, constants15.O_RDONLY | constants15.O_NOFOLLOW);
41290
+ const fd = openSync18(this.directory, constants16.O_RDONLY | constants16.O_NOFOLLOW);
40479
41291
  try {
40480
41292
  fsyncSync5(fd);
40481
41293
  } finally {
40482
- closeSync17(fd);
41294
+ closeSync18(fd);
40483
41295
  }
40484
41296
  }
40485
41297
  saveState(state, expected) {
@@ -40490,30 +41302,30 @@ class RecoveryOwner {
40490
41302
  if (this.read("state.json") !== expected)
40491
41303
  invalid5();
40492
41304
  this.assert();
40493
- renameSync6(join33(this.directory, name), join33(this.directory, "state.json"));
41305
+ renameSync6(join34(this.directory, name), join34(this.directory, "state.json"));
40494
41306
  this.sync();
40495
41307
  }
40496
41308
  async locked(action) {
40497
41309
  this.assert();
40498
41310
  let fd;
40499
41311
  try {
40500
- fd = openSync17(join33(this.directory, "operation.lock"), constants15.O_WRONLY | constants15.O_CREAT | constants15.O_EXCL | constants15.O_NOFOLLOW, 384);
41312
+ fd = openSync18(join34(this.directory, "operation.lock"), constants16.O_WRONLY | constants16.O_CREAT | constants16.O_EXCL | constants16.O_NOFOLLOW, 384);
40501
41313
  } catch {
40502
41314
  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
41315
  }
40504
- const owner2 = fstatSync17(fd);
41316
+ const owner2 = fstatSync18(fd);
40505
41317
  try {
40506
41318
  writeFileSync9(fd, JSON.stringify({ pid: process.pid }));
40507
41319
  fsyncSync5(fd);
40508
41320
  this.sync();
40509
41321
  return await action();
40510
41322
  } finally {
40511
- closeSync17(fd);
41323
+ closeSync18(fd);
40512
41324
  this.assert();
40513
- const now = lstatSync23(join33(this.directory, "operation.lock"));
41325
+ const now = lstatSync24(join34(this.directory, "operation.lock"));
40514
41326
  if (owner2.dev !== now.dev || owner2.ino !== now.ino || !now.isFile() || now.isSymbolicLink())
40515
41327
  invalid5();
40516
- unlinkSync5(join33(this.directory, "operation.lock"));
41328
+ unlinkSync5(join34(this.directory, "operation.lock"));
40517
41329
  this.sync();
40518
41330
  }
40519
41331
  }
@@ -40546,7 +41358,7 @@ function base(customer, organizationId) {
40546
41358
  };
40547
41359
  }
40548
41360
  function create(directory, intent) {
40549
- if (!isAbsolute20(directory) || resolve22(directory) !== directory || realpathSync9(dirname22(directory)) !== dirname22(directory))
41361
+ if (!isAbsolute21(directory) || resolve23(directory) !== directory || realpathSync11(dirname23(directory)) !== dirname23(directory))
40550
41362
  invalid5();
40551
41363
  mkdirSync11(directory, { mode: 448 });
40552
41364
  const owner2 = new RecoveryOwner(directory), checked = intentSchema.parse(intent), intentSha256 = canonicalJsonSha256(checked);
@@ -40709,12 +41521,12 @@ var init_recurring_recovery = __esm(() => {
40709
41521
  });
40710
41522
 
40711
41523
  // src/lib/recurring-surface.ts
40712
- import { isAbsolute as isAbsolute21 } from "path";
41524
+ import { isAbsolute as isAbsolute22 } from "path";
40713
41525
  function recurringMcpSchema(action) {
40714
41526
  return action === "activate" ? recurringSurfaceSchemas.activate.extend({ code, confirm: exports_external.literal(true) }) : recurringSurfaceSchemas[action];
40715
41527
  }
40716
- function expectedDraft(draft, hash4) {
40717
- if (!draft || draft.termsSha256 !== hash4)
41528
+ function expectedDraft(draft, hash5) {
41529
+ if (!draft || draft.termsSha256 !== hash5)
40718
41530
  throw new RemoteRecurringError("RECURRING_TERMS_UNAVAILABLE");
40719
41531
  return draft;
40720
41532
  }
@@ -40814,7 +41626,7 @@ var init_recurring_surface = __esm(() => {
40814
41626
  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
41627
  context = { userId: uuid13.optional(), membershipId: uuid13.optional() };
40816
41628
  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");
41629
+ directory = exports_external.string().max(4096).refine(isAbsolute22, "Use an absolute recovery directory");
40818
41630
  email4 = exports_external.string().trim().toLowerCase().email().max(254);
40819
41631
  code = exports_external.string().regex(/^\d{6}$/);
40820
41632
  recurringSurfaceSchemas = {
@@ -42643,21 +43455,21 @@ var init_credential_state = __esm(() => {
42643
43455
  });
42644
43456
 
42645
43457
  // 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";
43458
+ import { createHash as createHash24, randomBytes } from "crypto";
43459
+ import { existsSync as existsSync15, mkdirSync as mkdirSync12, readFileSync as readFileSync20, readdirSync as readdirSync11, statSync as statSync10, writeFileSync as writeFileSync10 } from "fs";
43460
+ import { extname, join as join35, relative as relative9 } from "path";
42649
43461
  function createSkillRun(params, targetDir = process.cwd()) {
42650
43462
  const now = new Date;
42651
43463
  const id = createRunId(now);
42652
43464
  const day = now.toISOString().slice(0, 10);
42653
43465
  const skillName = normalizeSkillName(params.skill);
42654
43466
  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);
43467
+ const runDir = join35(root, "runs", day, id);
43468
+ const logsDir = join35(runDir, "logs");
43469
+ const exportDir = join35(root, "exports", skillName, id);
42658
43470
  mkdirSync12(logsDir, { recursive: true });
42659
43471
  mkdirSync12(exportDir, { recursive: true });
42660
- mkdirSync12(join34(root, "tmp"), { recursive: true });
43472
+ mkdirSync12(join35(root, "tmp"), { recursive: true });
42661
43473
  const record10 = {
42662
43474
  id,
42663
43475
  skill: skillName,
@@ -42709,22 +43521,22 @@ function updateSkillRun(context2, patch) {
42709
43521
  return context2.record;
42710
43522
  }
42711
43523
  function writeRunLogs(context2, stdout = "", stderr = "") {
42712
- writeFileSync10(join34(context2.logsDir, "stdout.log"), stdout);
42713
- writeFileSync10(join34(context2.logsDir, "stderr.log"), stderr);
43524
+ writeFileSync10(join35(context2.logsDir, "stdout.log"), stdout);
43525
+ writeFileSync10(join35(context2.logsDir, "stderr.log"), stderr);
42714
43526
  }
42715
43527
  function appendRunEvent(context2, event, data = {}) {
42716
43528
  const line = JSON.stringify({ ts: new Date().toISOString(), event, ...data }) + `
42717
43529
  `;
42718
- const path = join34(context2.runDir, "events.ndjson");
43530
+ const path = join35(context2.runDir, "events.ndjson");
42719
43531
  const previous = existsSync15(path) ? readFileSync20(path, "utf-8") : "";
42720
43532
  writeFileSync10(path, previous + line);
42721
43533
  }
42722
43534
  function findSkillRun(runId, targetDir = process.cwd()) {
42723
- const runsRoot = join34(getProjectStateDir(targetDir), "runs");
43535
+ const runsRoot = join35(getProjectStateDir(targetDir), "runs");
42724
43536
  if (!existsSync15(runsRoot))
42725
43537
  return null;
42726
- for (const day of readdirSync10(runsRoot)) {
42727
- const record10 = readRunRecord(join34(runsRoot, day, runId));
43538
+ for (const day of readdirSync11(runsRoot)) {
43539
+ const record10 = readRunRecord(join35(runsRoot, day, runId));
42728
43540
  if (record10)
42729
43541
  return record10;
42730
43542
  }
@@ -42741,11 +43553,11 @@ function skillRunEnv(context2) {
42741
43553
  };
42742
43554
  }
42743
43555
  function writeRunRecord(context2) {
42744
- writeFileSync10(join34(context2.runDir, "run.json"), JSON.stringify(context2.record, null, 2) + `
43556
+ writeFileSync10(join35(context2.runDir, "run.json"), JSON.stringify(context2.record, null, 2) + `
42745
43557
  `);
42746
43558
  }
42747
43559
  function writeArtifactsManifest(context2, artifacts) {
42748
- writeFileSync10(join34(context2.runDir, "artifacts.json"), JSON.stringify({ runId: context2.record.id, artifacts }, null, 2) + `
43560
+ writeFileSync10(join35(context2.runDir, "artifacts.json"), JSON.stringify({ runId: context2.record.id, artifacts }, null, 2) + `
42749
43561
  `);
42750
43562
  }
42751
43563
  function collectRunArtifacts(context2) {
@@ -42758,14 +43570,14 @@ function collectRunArtifacts(context2) {
42758
43570
  artifacts.push({
42759
43571
  path: toProjectRelative(context2.targetDir, path),
42760
43572
  mime: mimeForPath(path),
42761
- sha256: createHash23("sha256").update(bytes).digest("hex"),
43573
+ sha256: createHash24("sha256").update(bytes).digest("hex"),
42762
43574
  sizeBytes: stat3.size
42763
43575
  });
42764
43576
  }
42765
43577
  return artifacts.sort((a, b) => a.path.localeCompare(b.path));
42766
43578
  }
42767
43579
  function readRunRecord(runDir) {
42768
- const path = join34(runDir, "run.json");
43580
+ const path = join35(runDir, "run.json");
42769
43581
  if (!existsSync15(path))
42770
43582
  return null;
42771
43583
  try {
@@ -42776,8 +43588,8 @@ function readRunRecord(runDir) {
42776
43588
  }
42777
43589
  function walkFiles(dir) {
42778
43590
  const files = [];
42779
- for (const entry of readdirSync10(dir)) {
42780
- const full = join34(dir, entry);
43591
+ for (const entry of readdirSync11(dir)) {
43592
+ const full = join35(dir, entry);
42781
43593
  if (statSync10(full).isDirectory())
42782
43594
  files.push(...walkFiles(full));
42783
43595
  else
@@ -42789,7 +43601,7 @@ function createRunId(now) {
42789
43601
  return `run_${now.getTime().toString(36)}_${randomBytes(4).toString("hex")}`;
42790
43602
  }
42791
43603
  function toProjectRelative(targetDir, path) {
42792
- const rel = relative7(targetDir, path).split(/[\\/]/).join("/");
43604
+ const rel = relative9(targetDir, path).split(/[\\/]/).join("/");
42793
43605
  return rel.startsWith(".") ? rel : `./${rel}`;
42794
43606
  }
42795
43607
  function mimeForPath(path) {
@@ -43030,11 +43842,11 @@ var init_cloud_executions = __esm(() => {
43030
43842
  // node_modules/@hasna/secrets/dist/sdk.js
43031
43843
  import { isIP as isIP2 } from "net";
43032
43844
  import { spawnSync as spawnSync5 } from "child_process";
43033
- import { closeSync as closeSync18, fstatSync as fstatSync18, openSync as openSync18, readFileSync as readFileSync21 } from "fs";
43845
+ import { closeSync as closeSync19, fstatSync as fstatSync19, openSync as openSync19, readFileSync as readFileSync21 } from "fs";
43034
43846
  import { O_NOFOLLOW as O_NOFOLLOW3, O_NONBLOCK as O_NONBLOCK3, O_RDONLY as O_RDONLY3 } from "constants";
43035
43847
  import { createRequire as createRequire2 } from "module";
43036
43848
  import { hostname as osHostname2 } from "os";
43037
- import { isAbsolute as isAbsolute22, join as join35 } from "path";
43849
+ import { isAbsolute as isAbsolute23, join as join36 } from "path";
43038
43850
  import { createRequire as createRequire22 } from "module";
43039
43851
  function envToken2(name) {
43040
43852
  return name.toUpperCase().replace(/-/g, "_");
@@ -43058,21 +43870,21 @@ function homeDir2(env) {
43058
43870
  }
43059
43871
  function absoluteOverride2(env, key) {
43060
43872
  const value = env[key]?.trim();
43061
- return value && isAbsolute22(value) ? value : null;
43873
+ return value && isAbsolute23(value) ? value : null;
43062
43874
  }
43063
43875
  function hasnaHomeDir2(env) {
43064
43876
  const override = absoluteOverride2(env, HASNA_HOME_ENV_KEY2);
43065
43877
  if (override)
43066
43878
  return override;
43067
43879
  const home = homeDir2(env);
43068
- return home ? join35(home, HASNA_HOME_DIR2) : null;
43880
+ return home ? join36(home, HASNA_HOME_DIR2) : null;
43069
43881
  }
43070
43882
  function appConfigDir2(name, env) {
43071
43883
  const configRoot = absoluteOverride2(env, HASNA_CONFIG_HOME_ENV_KEY2);
43072
43884
  if (configRoot)
43073
- return join35(configRoot, name);
43885
+ return join36(configRoot, name);
43074
43886
  const root = hasnaHomeDir2(env);
43075
- return root ? join35(root, name, CONFIG_SUBDIR2) : null;
43887
+ return root ? join36(root, name, CONFIG_SUBDIR2) : null;
43076
43888
  }
43077
43889
  function credentialDiskSourceList2(name, env, profile = null) {
43078
43890
  if (!SAFE_APP_SLUG2.test(name))
@@ -43081,7 +43893,7 @@ function credentialDiskSourceList2(name, env, profile = null) {
43081
43893
  if (!directory2)
43082
43894
  return [];
43083
43895
  const file2 = profile ? `${CREDENTIALS_FILE2}-${profile}` : CREDENTIALS_FILE2;
43084
- return [{ path: join35(directory2, file2), tier: "disk" }];
43896
+ return [{ path: join36(directory2, file2), tier: "disk" }];
43085
43897
  }
43086
43898
  function credentialDiskSources2(name, env) {
43087
43899
  return credentialDiskSourceList2(name, env, null).map((s) => s.path);
@@ -43135,7 +43947,7 @@ function readAppConfigFile2(path) {
43135
43947
  };
43136
43948
  let fd = -1;
43137
43949
  try {
43138
- fd = openSync18(path, O_RDONLY3 | O_NOFOLLOW3 | O_NONBLOCK3);
43950
+ fd = openSync19(path, O_RDONLY3 | O_NOFOLLOW3 | O_NONBLOCK3);
43139
43951
  } catch (error61) {
43140
43952
  const code2 = error61.code;
43141
43953
  if (code2 === "ENOENT" || code2 === "ENOTDIR")
@@ -43145,7 +43957,7 @@ function readAppConfigFile2(path) {
43145
43957
  unsafe(`the path could not be opened (${code2 ?? "unknown error"})`);
43146
43958
  }
43147
43959
  try {
43148
- const before = fstatSync18(fd);
43960
+ const before = fstatSync19(fd);
43149
43961
  if (!before.isFile())
43150
43962
  unsafe("the path is not a regular file");
43151
43963
  if (!configFileModeAllowed2(before.mode)) {
@@ -43157,14 +43969,14 @@ function readAppConfigFile2(path) {
43157
43969
  if (before.size > MAX_CREDENTIAL_FILE_BYTES2)
43158
43970
  unsafe("the file exceeds the size limit");
43159
43971
  const bytes = readFileSync21(fd);
43160
- const after = fstatSync18(fd);
43972
+ const after = fstatSync19(fd);
43161
43973
  if (!configFileReadsCoherent2(before, after)) {
43162
43974
  unsafe("the file changed while being read");
43163
43975
  }
43164
43976
  return parseEnvFile2(bytes.toString("utf8"));
43165
43977
  } finally {
43166
43978
  if (fd !== -1)
43167
- closeSync18(fd);
43979
+ closeSync19(fd);
43168
43980
  }
43169
43981
  }
43170
43982
  function readCredentialFile2(path, apiKeyKeys) {
@@ -44195,7 +45007,7 @@ function createSecretsClientFromEnv(env = process.env, overrides = {}) {
44195
45007
  });
44196
45008
  return new SecretsClient({ ...clientOverrides, baseUrl, apiKey });
44197
45009
  }
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;
45010
+ 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
45011
  var init_sdk = __esm(() => {
44200
45012
  init_transport2 = __esm2(() => {
44201
45013
  CredentialResolutionError2 = class CredentialResolutionError3 extends Error {
@@ -44330,75 +45142,75 @@ var init_sdk = __esm(() => {
44330
45142
  });
44331
45143
 
44332
45144
  // 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";
45145
+ import { constants as constants17, closeSync as closeSync20, fstatSync as fstatSync20, openSync as openSync20, readSync as readSync13, realpathSync as realpathSync12 } from "fs";
44334
45146
  import { hostname as stationHostname } from "os";
44335
45147
  function selectedSecretBindingsTemplate(scope, names, createClient = createSecretsClientFromEnv) {
44336
45148
  let secretsAuthority;
44337
45149
  try {
44338
45150
  secretsAuthority = createClient().baseUrl;
44339
45151
  } catch {
44340
- return refuse4("LOCAL_SECRET_UNAVAILABLE", "Configure the Secrets CLI authority and authentication before preparing execution bindings.");
45152
+ return refuse5("LOCAL_SECRET_UNAVAILABLE", "Configure the Secrets CLI authority and authentication before preparing execution bindings.");
44341
45153
  }
44342
45154
  const { authority, workspaceId, profileRevision, slug: slug2, version: version2, bundleDigest } = scope.selection;
44343
45155
  return {
44344
45156
  schema: "hasna.skills-secret-bindings.v1",
44345
45157
  selection: { authority, workspaceId, profileId: scope.profileId, profileRevision, slug: slug2, version: version2, bundleDigest },
44346
- consumer: { stationId: process.env.HASNA_STATION || stationHostname(), workspaceDirectory: realpathSync10(scope.cwd) },
45158
+ consumer: { stationId: process.env.HASNA_STATION || stationHostname(), workspaceDirectory: realpathSync12(scope.cwd) },
44347
45159
  secretsAuthority,
44348
45160
  bindings: Object.fromEntries(names.map((name) => [name, ""]))
44349
45161
  };
44350
45162
  }
44351
- function refuse4(code2, message) {
45163
+ function refuse5(code2, message) {
44352
45164
  throw new SkillSelectionError(code2, message);
44353
45165
  }
44354
45166
  function record10(value) {
44355
45167
  return !!value && typeof value === "object" && !Array.isArray(value);
44356
45168
  }
44357
- function exactKeys2(value, keys2) {
45169
+ function exactKeys3(value, keys2) {
44358
45170
  return Object.keys(value).length === keys2.length && keys2.every((key) => Object.hasOwn(value, key));
44359
45171
  }
44360
- function identifier3(value) {
45172
+ function identifier4(value) {
44361
45173
  return typeof value === "string" && value.length > 0 && value.length <= 2048 && !/[\x00-\x20\x7f]/.test(value);
44362
45174
  }
44363
45175
  function declaredSecretNames(value) {
44364
45176
  if (value === undefined)
44365
45177
  return [];
44366
45178
  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).");
45179
+ return refuse5("INVALID_SKILL_MANIFEST", "Runtime environment references must be unique uppercase identifiers (at most 32).");
44368
45180
  }
44369
45181
  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.");
45182
+ return refuse5("INVALID_SKILL_MANIFEST", "Runtime environment references cannot override execution controls.");
44371
45183
  }
44372
45184
  return value;
44373
45185
  }
44374
45186
  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.");
45187
+ 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)) {
45188
+ return refuse5("INVALID_SECRET_BINDINGS", "Secret bindings do not match the hasna.skills-secret-bindings.v1 contract.");
44377
45189
  }
44378
45190
  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
45191
  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.");
45192
+ return refuse5("SECRET_BINDING_SCOPE_MISMATCH", "Secret bindings do not match the exact selected authority, workspace, profile, revision, version and digest.");
44381
45193
  }
44382
45194
  let workspaceDirectory;
44383
45195
  try {
44384
- workspaceDirectory = realpathSync10(scope.cwd);
45196
+ workspaceDirectory = realpathSync12(scope.cwd);
44385
45197
  } catch {
44386
- return refuse4("SECRET_BINDING_CONSUMER_MISMATCH", "The execution workspace cannot be resolved.");
45198
+ return refuse5("SECRET_BINDING_CONSUMER_MISMATCH", "The execution workspace cannot be resolved.");
44387
45199
  }
44388
45200
  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.");
45201
+ return refuse5("SECRET_BINDING_CONSUMER_MISMATCH", "Secret bindings do not match this station and canonical workspace directory.");
44390
45202
  }
44391
45203
  try {
44392
- if (!identifier3(value.secretsAuthority))
45204
+ if (!identifier4(value.secretsAuthority))
44393
45205
  throw new Error;
44394
45206
  const url2 = new URL(value.secretsAuthority);
44395
45207
  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
45208
  throw new Error;
44397
45209
  } catch {
44398
- return refuse4("INVALID_SECRET_BINDINGS", "Secret bindings require a canonical HTTPS Secrets /v1 authority (loopback HTTP is allowed).");
45210
+ return refuse5("INVALID_SECRET_BINDINGS", "Secret bindings require a canonical HTTPS Secrets /v1 authority (loopback HTTP is allowed).");
44399
45211
  }
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.");
45212
+ 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 === ".."))) {
45213
+ return refuse5("INVALID_SECRET_BINDINGS", "Bind every declared environment name exactly once to a vault key; undeclared bindings and values are refused.");
44402
45214
  }
44403
45215
  return structuredClone(value);
44404
45216
  }
@@ -44409,10 +45221,10 @@ async function resolveSelectedSecrets(bindings, createClient = createSecretsClie
44409
45221
  try {
44410
45222
  client = createClient();
44411
45223
  } catch {
44412
- return refuse4("LOCAL_SECRET_UNAVAILABLE", "The configured Secrets client could not authenticate. No ambient credential fallback was attempted.");
45224
+ return refuse5("LOCAL_SECRET_UNAVAILABLE", "The configured Secrets client could not authenticate. No ambient credential fallback was attempted.");
44413
45225
  }
44414
45226
  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.");
45227
+ return refuse5("SECRET_BINDING_AUTHORITY_MISMATCH", "The configured Secrets authority differs from the reviewed binding. No secret was requested.");
44416
45228
  const env = {};
44417
45229
  const signal = AbortSignal.timeout(15000);
44418
45230
  try {
@@ -44424,7 +45236,7 @@ async function resolveSelectedSecrets(bindings, createClient = createSecretsClie
44424
45236
  }
44425
45237
  return env;
44426
45238
  } 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.");
45239
+ 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
45240
  }
44429
45241
  }
44430
45242
  function redactExecutionSecrets(text3, env) {
@@ -44572,10 +45384,10 @@ __export(exports_selected_run, {
44572
45384
  prepareSelectedSecretBindings: () => prepareSelectedSecretBindings,
44573
45385
  executeSelectedLocal: () => executeSelectedLocal
44574
45386
  });
44575
- import { createHash as createHash24 } from "crypto";
45387
+ import { createHash as createHash25 } from "crypto";
44576
45388
  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";
45389
+ import { mkdirSync as mkdirSync13, mkdtempSync as mkdtempSync3, writeFileSync as writeFileSync11, realpathSync as realpathSync13 } from "fs";
45390
+ import { dirname as dirname24, join as join37, resolve as resolve24 } from "path";
44579
45391
  import { tmpdir, hostname as stationHostname2 } from "os";
44580
45392
  async function resolveSelectedRun(spec, profileId, options = {}) {
44581
45393
  const context2 = await resolveSelectionContext(profileId, options);
@@ -44655,7 +45467,7 @@ async function executeSelectedLocal(selected, options = {}) {
44655
45467
  throw new SkillSelectionError("INVALID_SECRET_BINDINGS", "Explicit environment values must be bounded strings without NUL bytes.");
44656
45468
  secretEnv[name] = value;
44657
45469
  }
44658
- const runDirectory = mkdtempSync3(join36(tmpdir(), "skills-execution-"));
45470
+ const runDirectory = mkdtempSync3(join37(tmpdir(), "skills-execution-"));
44659
45471
  const paths = new SkillEntryPaths;
44660
45472
  for (const entry of entries) {
44661
45473
  paths.add(entry.path, 100, () => {
@@ -44663,12 +45475,12 @@ async function executeSelectedLocal(selected, options = {}) {
44663
45475
  }, () => {
44664
45476
  throw new SkillSelectionError("INVALID_BUNDLE_PATH", "The execution bundle path exceeds its limit.");
44665
45477
  });
44666
- const destination = join36(runDirectory, entry.path);
44667
- mkdirSync13(dirname23(destination), { recursive: true, mode: 448 });
45478
+ const destination = join37(runDirectory, entry.path);
45479
+ mkdirSync13(dirname24(destination), { recursive: true, mode: 448 });
44668
45480
  writeFileSync11(destination, entry.bytes, { flag: "wx", mode: entry.mode & 511 });
44669
45481
  }
44670
45482
  env.SKILLS_INPUT_JSON = input2;
44671
- env.SKILLS_WORKSPACE_DIR = resolve23(options.cwd ?? process.cwd());
45483
+ env.SKILLS_WORKSPACE_DIR = resolve24(options.cwd ?? process.cwd());
44672
45484
  env.SKILLS_RUN_DIR = runDirectory;
44673
45485
  if (runtime.version) {
44674
45486
  const version2 = await subprocess([executable, ...runtimeName === "bun" ? ["--no-env-file"] : [], "--version"], runDirectory, env, "", Math.min(timeoutMs, 5000));
@@ -44681,7 +45493,7 @@ async function executeSelectedLocal(selected, options = {}) {
44681
45493
  const { authority: authority2, workspaceId, profileRevision, slug: slug2, version: version2, bundleDigest } = selection2;
44682
45494
  const request2 = {
44683
45495
  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()) }
45496
+ consumer: { stationId: process.env.HASNA_STATION || stationHostname2(), workspaceDirectory: realpathSync13(options.cwd ?? process.cwd()) }
44685
45497
  };
44686
45498
  const grant = await (options.resolveExecutionGrant ?? resolveExecutionGrant)(request2);
44687
45499
  if (!grant || !grantIdentifier(grant.policyRevision) || !grantIdentifier(grant.grantId))
@@ -44691,20 +45503,20 @@ async function executeSelectedLocal(selected, options = {}) {
44691
45503
  }
44692
45504
  if (bindings)
44693
45505
  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);
45506
+ const result = await subprocess([executable, ...runtimeName === "bun" ? ["--no-env-file"] : [], join37(runDirectory, declaredEntry), ...args], runDirectory, { ...env, ...secretEnv }, input2, timeoutMs);
44695
45507
  result.stdout = redactExecutionSecrets(result.stdout, secretEnv);
44696
45508
  result.stderr = redactExecutionSecrets(result.stderr, secretEnv);
44697
45509
  const receipt = {
44698
45510
  selection: selection2,
44699
45511
  target: "local",
44700
45512
  runtime: runtimeName,
44701
- inputDigest: `sha256:${createHash24("sha256").update(input2).digest("hex")}`,
45513
+ inputDigest: `sha256:${createHash25("sha256").update(input2).digest("hex")}`,
44702
45514
  runDirectory,
44703
45515
  ...executionGrant ? { executionGrant } : {},
44704
45516
  ...bindings ? { secretBinding: { schema: bindings.schema, selection: bindings.selection, consumer: bindings.consumer, secretsAuthority: bindings.secretsAuthority, bindings: bindings.bindings } } : {},
44705
45517
  ...result
44706
45518
  };
44707
- writeFileSync11(join36(runDirectory, ".execution-receipt.json"), JSON.stringify({ ...receipt, stdout: undefined, stderr: undefined }), { mode: 384 });
45519
+ writeFileSync11(join37(runDirectory, ".execution-receipt.json"), JSON.stringify({ ...receipt, stdout: undefined, stderr: undefined }), { mode: 384 });
44708
45520
  return receipt;
44709
45521
  }
44710
45522
  async function subprocess(command, cwd, env, input2, timeoutMs) {
@@ -44893,8 +45705,8 @@ var init_blog_article = __esm(() => {
44893
45705
  });
44894
45706
 
44895
45707
  // 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";
45708
+ import { existsSync as existsSync16, readdirSync as readdirSync12, statSync as statSync11 } from "fs";
45709
+ import { join as join38 } from "path";
44898
45710
  function registerOperationTools(server) {
44899
45711
  server.registerTool("cloud_skill_eligibility", {
44900
45712
  title: "Cloud Skill Eligibility",
@@ -45370,8 +46182,8 @@ function registerOperationTools(server) {
45370
46182
  let skillCount = 0;
45371
46183
  if (exists) {
45372
46184
  try {
45373
- skillCount = readdirSync11(agentSkillsPath).filter((f) => {
45374
- const full = join37(agentSkillsPath, f);
46185
+ skillCount = readdirSync12(agentSkillsPath).filter((f) => {
46186
+ const full = join38(agentSkillsPath, f);
45375
46187
  return !f.startsWith(".") && statSync11(full).isDirectory();
45376
46188
  }).length;
45377
46189
  } catch {}
@@ -45439,14 +46251,14 @@ var init_operation_tools = __esm(() => {
45439
46251
 
45440
46252
  // src/lib/feedback.ts
45441
46253
  import { appendFileSync, existsSync as existsSync17, mkdirSync as mkdirSync14 } from "fs";
45442
- import { dirname as dirname24, join as join38 } from "path";
46254
+ import { dirname as dirname25, join as join39 } from "path";
45443
46255
  import { Database } from "bun:sqlite";
45444
46256
  function getFeedbackDbPath() {
45445
- return join38(getDataDir(), "skills.db");
46257
+ return join39(getDataDir(), "skills.db");
45446
46258
  }
45447
46259
  function getFeedbackDb() {
45448
46260
  const dbPath = getFeedbackDbPath();
45449
- const dir = dirname24(dbPath);
46261
+ const dir = dirname25(dbPath);
45450
46262
  if (!existsSync17(dir))
45451
46263
  mkdirSync14(dir, { recursive: true });
45452
46264
  const db = new Database(dbPath);
@@ -45474,8 +46286,8 @@ function saveFeedback(input2) {
45474
46286
  throw new Error("Feedback message is required");
45475
46287
  const category = input2.category ?? "general";
45476
46288
  if (isApiMode()) {
45477
- const path = join38(getDataDir(), "feedback.jsonl");
45478
- const dir = dirname24(path);
46289
+ const path = join39(getDataDir(), "feedback.jsonl");
46290
+ const dir = dirname25(path);
45479
46291
  if (!existsSync17(dir))
45480
46292
  mkdirSync14(dir, { recursive: true });
45481
46293
  appendFileSync(path, JSON.stringify({ message, category, email: input2.email ?? null, agent: input2.agent ?? null, version: input2.version ?? null, createdAt: new Date().toISOString() }) + `
@@ -45639,9 +46451,9 @@ var init_resource_meta_tools = __esm(() => {
45639
46451
 
45640
46452
  // src/lib/scheduler.ts
45641
46453
  import { existsSync as existsSync18, readFileSync as readFileSync22, writeFileSync as writeFileSync12, mkdirSync as mkdirSync15 } from "fs";
45642
- import { join as join39 } from "path";
46454
+ import { join as join40 } from "path";
45643
46455
  function getSchedulesPath(targetDir = process.cwd()) {
45644
- return join39(targetDir, ".skills", "schedules.json");
46456
+ return join40(targetDir, ".skills", "schedules.json");
45645
46457
  }
45646
46458
  function loadSchedules(targetDir = process.cwd()) {
45647
46459
  const path = getSchedulesPath(targetDir);
@@ -45654,7 +46466,7 @@ function loadSchedules(targetDir = process.cwd()) {
45654
46466
  }
45655
46467
  function saveSchedules(data, targetDir = process.cwd()) {
45656
46468
  const path = getSchedulesPath(targetDir);
45657
- const dir = join39(targetDir, ".skills");
46469
+ const dir = join40(targetDir, ".skills");
45658
46470
  if (!existsSync18(dir))
45659
46471
  mkdirSync15(dir, { recursive: true });
45660
46472
  writeFileSync12(path, JSON.stringify(data, null, 2));
@@ -45926,16 +46738,16 @@ var init_schedule_tools = __esm(() => {
45926
46738
  });
45927
46739
 
45928
46740
  // src/lib/native-storage.ts
45929
- import { createHash as createHash25, createHmac } from "crypto";
46741
+ import { createHash as createHash26, createHmac } from "crypto";
45930
46742
  import {
45931
46743
  existsSync as existsSync19,
45932
46744
  mkdirSync as mkdirSync16,
45933
46745
  readFileSync as readFileSync23,
45934
- readdirSync as readdirSync12,
46746
+ readdirSync as readdirSync13,
45935
46747
  statSync as statSync12,
45936
46748
  writeFileSync as writeFileSync13
45937
46749
  } from "fs";
45938
- import { dirname as dirname25, join as join40, normalize as normalize5, relative as relative8, sep as sep11 } from "path";
46750
+ import { dirname as dirname26, join as join41, normalize as normalize5, relative as relative10, sep as sep12 } from "path";
45939
46751
  function resolveSkillsNativeStorageConfig(env = process.env) {
45940
46752
  assertNoRetiredModeEnvVars(env, {
45941
46753
  app: SKILLS_ENV_NAMESPACE,
@@ -45976,7 +46788,7 @@ function getSkillsNativeStorageStatus(options = {}) {
45976
46788
  local: {
45977
46789
  dataDir: getDataDir(),
45978
46790
  projectStateDir: getProjectStateDir(targetDir),
45979
- feedbackDbPath: join40(getDataDir(), "skills.db")
46791
+ feedbackDbPath: join41(getDataDir(), "skills.db")
45980
46792
  },
45981
46793
  remote: {
45982
46794
  databaseConfigured: Boolean(config2.databaseUrl),
@@ -45999,11 +46811,11 @@ function exportSkillsLocalSnapshot(targetDir = process.cwd(), options = {}) {
45999
46811
  if (existsSync19(projectStateDir)) {
46000
46812
  for (const filePath of walkFiles2(projectStateDir)) {
46001
46813
  const bytes = readFileSync23(filePath);
46002
- const relativePath = toPosix(relative8(targetDir, filePath));
46814
+ const relativePath = toPosix(relative10(targetDir, filePath));
46003
46815
  files.push({
46004
46816
  path: relativePath,
46005
46817
  sizeBytes: bytes.byteLength,
46006
- sha256: createHash25("sha256").update(bytes).digest("hex"),
46818
+ sha256: createHash26("sha256").update(bytes).digest("hex"),
46007
46819
  ...options.includeFileContents ? { contentBase64: Buffer.from(bytes).toString("base64") } : {}
46008
46820
  });
46009
46821
  }
@@ -46056,8 +46868,8 @@ function parsePositiveInteger(value) {
46056
46868
  }
46057
46869
  function walkFiles2(dir) {
46058
46870
  const files = [];
46059
- for (const entry of readdirSync12(dir)) {
46060
- const full = join40(dir, entry);
46871
+ for (const entry of readdirSync13(dir)) {
46872
+ const full = join41(dir, entry);
46061
46873
  const stats = statSync12(full);
46062
46874
  if (stats.isDirectory())
46063
46875
  files.push(...walkFiles2(full));
@@ -46295,73 +47107,73 @@ var init_private_publication_customer = __esm(() => {
46295
47107
  });
46296
47108
 
46297
47109
  // 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";
47110
+ 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";
47111
+ import { dirname as dirname27, isAbsolute as isAbsolute24, join as join42, resolve as resolve25 } from "path";
46300
47112
  import { randomUUID as randomUUID3 } from "crypto";
46301
47113
  function safeDirectory(directory2) {
46302
- if (!isAbsolute23(directory2) || directory2 !== resolve24(directory2) || realpathSync12(directory2) !== directory2)
47114
+ if (!isAbsolute24(directory2) || directory2 !== resolve25(directory2) || realpathSync14(directory2) !== directory2)
46303
47115
  return fail2();
46304
- for (let path = directory2;; path = dirname26(path)) {
46305
- const stat3 = lstatSync24(path);
47116
+ for (let path = directory2;; path = dirname27(path)) {
47117
+ const stat3 = lstatSync25(path);
46306
47118
  if (!stat3.isDirectory() || stat3.isSymbolicLink())
46307
47119
  return fail2();
46308
- if (path === dirname26(path))
47120
+ if (path === dirname27(path))
46309
47121
  break;
46310
47122
  }
46311
- const own2 = lstatSync24(directory2);
47123
+ const own2 = lstatSync25(directory2);
46312
47124
  if ((own2.mode & 63) !== 0 || process.getuid && own2.uid !== process.getuid())
46313
47125
  return fail2();
46314
47126
  return { dev: own2.dev, ino: own2.ino };
46315
47127
  }
46316
- function unchangedDirectory(directory2, identity3) {
47128
+ function unchangedDirectory(directory2, identity4) {
46317
47129
  const now = safeDirectory(directory2);
46318
- if (now.dev !== identity3.dev || now.ino !== identity3.ino)
47130
+ if (now.dev !== identity4.dev || now.ino !== identity4.ino)
46319
47131
  return fail2();
46320
47132
  }
46321
47133
  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);
47134
+ const identity4 = safeDirectory(directory2), file2 = join42(directory2, name);
47135
+ const fd = openSync21(file2, constants18.O_RDONLY | constants18.O_NOFOLLOW);
46324
47136
  try {
46325
- const stat3 = fstatSync20(fd);
47137
+ const stat3 = fstatSync21(fd);
46326
47138
  if (!stat3.isFile() || stat3.nlink !== 1 || stat3.size > max || stat3.size < 1 || (stat3.mode & 63) !== 0 || process.getuid && stat3.uid !== process.getuid())
46327
47139
  return fail2();
46328
47140
  const buffer = Buffer.alloc(Math.min(max, stat3.size) + 1);
46329
47141
  let length = 0;
46330
47142
  while (length < buffer.length) {
46331
- const count = readSync13(fd, buffer, length, buffer.length - length, length);
47143
+ const count = readSync14(fd, buffer, length, buffer.length - length, length);
46332
47144
  if (count === 0)
46333
47145
  break;
46334
47146
  length += count;
46335
47147
  }
46336
- const bytes = buffer.subarray(0, length), after = fstatSync20(fd);
46337
- unchangedDirectory(directory2, identity3);
47148
+ const bytes = buffer.subarray(0, length), after = fstatSync21(fd);
47149
+ unchangedDirectory(directory2, identity4);
46338
47150
  if (bytes.length !== stat3.size || stat3.size !== after.size || stat3.mtimeMs !== after.mtimeMs || stat3.ctimeMs !== after.ctimeMs)
46339
47151
  return fail2();
46340
47152
  return bytes;
46341
47153
  } finally {
46342
- closeSync20(fd);
47154
+ closeSync21(fd);
46343
47155
  }
46344
47156
  }
46345
47157
  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);
47158
+ const fd = openSync21(join42(directory2, name), constants18.O_WRONLY | constants18.O_CREAT | constants18.O_EXCL | constants18.O_NOFOLLOW, 384);
46347
47159
  try {
46348
47160
  writeFileSync14(fd, bytes);
46349
47161
  fsyncSync6(fd);
46350
47162
  } finally {
46351
- closeSync20(fd);
47163
+ closeSync21(fd);
46352
47164
  }
46353
47165
  }
46354
47166
  function save(directory2, value) {
46355
- const identity3 = safeDirectory(directory2), temporary = `.receipt-${randomUUID3()}.json`;
47167
+ const identity4 = safeDirectory(directory2), temporary = `.receipt-${randomUUID3()}.json`;
46356
47168
  writeOwned(directory2, temporary, JSON.stringify(value) + `
46357
47169
  `);
46358
- unchangedDirectory(directory2, identity3);
46359
- renameSync7(join41(directory2, temporary), join41(directory2, "receipt.json"));
46360
- const fd = openSync20(directory2, constants17.O_RDONLY | constants17.O_NOFOLLOW);
47170
+ unchangedDirectory(directory2, identity4);
47171
+ renameSync7(join42(directory2, temporary), join42(directory2, "receipt.json"));
47172
+ const fd = openSync21(directory2, constants18.O_RDONLY | constants18.O_NOFOLLOW);
46361
47173
  try {
46362
47174
  fsyncSync6(fd);
46363
47175
  } finally {
46364
- closeSync20(fd);
47176
+ closeSync21(fd);
46365
47177
  }
46366
47178
  }
46367
47179
  function bind(client, receipt) {
@@ -46369,23 +47181,23 @@ function bind(client, receipt) {
46369
47181
  throw new PrivatePublicationError("PUBLICATION_IDENTITY_CHANGED", "The fresh session does not match the recovery directory's server, account and membership.");
46370
47182
  }
46371
47183
  async function locked(directory2, action) {
46372
- const identity3 = safeDirectory(directory2), file2 = join41(directory2, "operation.lock");
47184
+ const identity4 = safeDirectory(directory2), file2 = join42(directory2, "operation.lock");
46373
47185
  let fd;
46374
47186
  try {
46375
- fd = openSync20(file2, constants17.O_WRONLY | constants17.O_CREAT | constants17.O_EXCL | constants17.O_NOFOLLOW, 384);
47187
+ fd = openSync21(file2, constants18.O_WRONLY | constants18.O_CREAT | constants18.O_EXCL | constants18.O_NOFOLLOW, 384);
46376
47188
  } catch {
46377
47189
  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
47190
  }
46379
- const lock = fstatSync20(fd);
47191
+ const lock = fstatSync21(fd);
46380
47192
  try {
46381
47193
  writeFileSync14(fd, JSON.stringify({ pid: process.pid }) + `
46382
47194
  `);
46383
47195
  fsyncSync6(fd);
46384
47196
  return await action();
46385
47197
  } finally {
46386
- closeSync20(fd);
46387
- unchangedDirectory(directory2, identity3);
46388
- const now = lstatSync24(file2);
47198
+ closeSync21(fd);
47199
+ unchangedDirectory(directory2, identity4);
47200
+ const now = lstatSync25(file2);
46389
47201
  if (now.dev !== lock.dev || now.ino !== lock.ino || !now.isFile() || now.isSymbolicLink())
46390
47202
  fail2();
46391
47203
  unlinkSync6(file2);
@@ -46437,15 +47249,15 @@ async function preparePrivatePublication(client, sourceDirectory, recoveryDirect
46437
47249
  phase: "prepared",
46438
47250
  intent: null
46439
47251
  };
46440
- if (!isAbsolute23(recoveryDirectory) || resolve24(recoveryDirectory) !== recoveryDirectory || realpathSync12(dirname26(recoveryDirectory)) !== dirname26(recoveryDirectory))
47252
+ if (!isAbsolute24(recoveryDirectory) || resolve25(recoveryDirectory) !== recoveryDirectory || realpathSync14(dirname27(recoveryDirectory)) !== dirname27(recoveryDirectory))
46441
47253
  return fail2();
46442
47254
  mkdirSync17(recoveryDirectory, { mode: 448 });
46443
47255
  safeDirectory(recoveryDirectory);
46444
- const parent = openSync20(dirname26(recoveryDirectory), constants17.O_RDONLY | constants17.O_NOFOLLOW);
47256
+ const parent = openSync21(dirname27(recoveryDirectory), constants18.O_RDONLY | constants18.O_NOFOLLOW);
46445
47257
  try {
46446
47258
  fsyncSync6(parent);
46447
47259
  } finally {
46448
- closeSync20(parent);
47260
+ closeSync21(parent);
46449
47261
  }
46450
47262
  writeOwned(recoveryDirectory, "bundle.tgz", packed.bytes);
46451
47263
  save(recoveryDirectory, receipt);
@@ -46538,10 +47350,10 @@ var init_private_publication_recovery = __esm(() => {
46538
47350
  });
46539
47351
 
46540
47352
  // src/mcp/private-publication-tools.ts
46541
- import { isAbsolute as isAbsolute24 } from "path";
47353
+ import { isAbsolute as isAbsolute25 } from "path";
46542
47354
  function registerPrivatePublicationTools(server) {
46543
47355
  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");
47356
+ const directory2 = exports_external.string().max(4096).refine(isAbsolute25, "Use an absolute local directory");
46545
47357
  const verification2 = { email: exports_external.string().email().max(254), code: exports_external.string().regex(/^\d{6}$/), userId: uuid9, membershipId: uuid9, recoveryDirectory: directory2 };
46546
47358
  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
47359
  const handler = (action) => async (value) => {
@@ -46974,19 +47786,19 @@ async function connectMcpForNode() {
46974
47786
  return { server: server2, transport };
46975
47787
  }
46976
47788
  function readBody(req) {
46977
- return new Promise((resolve25, reject) => {
47789
+ return new Promise((resolve26, reject) => {
46978
47790
  const chunks = [];
46979
47791
  req.on("data", (chunk) => chunks.push(Buffer.from(chunk)));
46980
47792
  req.on("end", () => {
46981
47793
  const raw = Buffer.concat(chunks).toString("utf-8");
46982
47794
  if (!raw.trim()) {
46983
- resolve25(undefined);
47795
+ resolve26(undefined);
46984
47796
  return;
46985
47797
  }
46986
47798
  try {
46987
- resolve25(JSON.parse(raw));
47799
+ resolve26(JSON.parse(raw));
46988
47800
  } catch {
46989
- resolve25(undefined);
47801
+ resolve26(undefined);
46990
47802
  }
46991
47803
  });
46992
47804
  req.on("error", reject);
@@ -47028,9 +47840,9 @@ async function startSkillsMcpHttpServer(options = {}) {
47028
47840
  }
47029
47841
  }
47030
47842
  });
47031
- await new Promise((resolve25, reject) => {
47843
+ await new Promise((resolve26, reject) => {
47032
47844
  httpServer.once("error", reject);
47033
- httpServer.listen(port, hostname4, () => resolve25());
47845
+ httpServer.listen(port, hostname4, () => resolve26());
47034
47846
  });
47035
47847
  const address = httpServer.address();
47036
47848
  const listenPort = typeof address === "object" && address ? address.port : port;