@hasna/skills 0.10.80 → 0.10.81

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.80",
26
+ version: "0.10.81",
27
27
  description: "Skills library for AI coding agents",
28
28
  type: "module",
29
29
  bin: {
@@ -20974,13 +20974,13 @@ function parseSkillFrontmatter(content) {
20974
20974
  }
20975
20975
  return Object.keys(result).length > 0 ? result : null;
20976
20976
  }
20977
- function validateSkillDirectory(name, skillPath, registryMeta) {
20977
+ function validateSkillDirectory(name, skillPath, registryMeta, options = {}) {
20978
20978
  const bareName = name;
20979
20979
  const issues = [];
20980
20980
  const warnings = [];
20981
20981
  let packageDeclaresHosted = false;
20982
20982
  let packageSkillSource;
20983
- let resolvedKind = "executable";
20983
+ let resolvedKind = options.kind ?? "executable";
20984
20984
  const metadata = {
20985
20985
  binCommands: [],
20986
20986
  docFiles: []
@@ -21042,7 +21042,8 @@ function validateSkillDirectory(name, skillPath, registryMeta) {
21042
21042
  }
21043
21043
  if (frontmatter.kind !== undefined) {
21044
21044
  if (VALID_SKILL_KINDS.includes(frontmatter.kind)) {
21045
- resolvedKind = frontmatter.kind;
21045
+ if (options.kind === undefined)
21046
+ resolvedKind = frontmatter.kind;
21046
21047
  } else {
21047
21048
  add(issues, "skill.kind_invalid", `SKILL.md kind '${frontmatter.kind}' is not one of: ${VALID_SKILL_KINDS.join(", ")}`);
21048
21049
  }
@@ -32310,7 +32311,7 @@ function codexPluginRootCapabilityEntry(name) {
32310
32311
  function isCodexSkillDocumentName(name) {
32311
32312
  return foldCodexPluginEntryName(name) === "skill.md";
32312
32313
  }
32313
- var CODEX_PLUGIN_MANIFEST_LOCATIONS, CODEX_PLUGIN_MANIFEST_DIRECTORIES, CODEX_PLUGIN_ROOT_CAPABILITY_ENTRIES;
32314
+ var CODEX_PLUGIN_MANIFEST_LOCATIONS, CODEX_PLUGIN_MANIFEST_DIRECTORIES, CODEX_PLUGIN_ROOT_CAPABILITY_ENTRIES, CODEX_PLUGIN_MANIFEST_KNOWN_KEYS, CODEX_PLUGIN_DEFAULT_SKILLS_PATHS;
32314
32315
  var init_codex_plugin_capability_paths = __esm(() => {
32315
32316
  CODEX_PLUGIN_MANIFEST_LOCATIONS = Object.freeze([
32316
32317
  "plugin.json",
@@ -32331,6 +32332,8 @@ var init_codex_plugin_capability_paths = __esm(() => {
32331
32332
  "commands",
32332
32333
  "agents"
32333
32334
  ]);
32335
+ CODEX_PLUGIN_MANIFEST_KNOWN_KEYS = Object.freeze(["name", "version", "description", "author", "homepage", "repository", "license", "keywords", "interface", "skills", "apps"]);
32336
+ CODEX_PLUGIN_DEFAULT_SKILLS_PATHS = Object.freeze(["./skills", "./skills/"]);
32334
32337
  });
32335
32338
 
32336
32339
  // src/lib/codex-hook-mcp-dependencies.ts
@@ -33665,11 +33668,14 @@ var init_codex_hook_rpc = __esm(() => {
33665
33668
  });
33666
33669
 
33667
33670
  // src/lib/codex-native-skill-catalog.ts
33668
- import { realpathSync as realpathSync4 } from "fs";
33669
- import { isAbsolute as isAbsolute14, normalize as normalize3 } from "path";
33671
+ import { lstatSync as lstatSync14, readdirSync as readdirSync5, readFileSync as readFileSync12, realpathSync as realpathSync4 } from "fs";
33672
+ import { basename as basename8, dirname as dirname15, isAbsolute as isAbsolute14, join as join19, normalize as normalize3 } from "path";
33673
+ function codexPluginIsRemote(plugin) {
33674
+ return plugin !== undefined && (plugin.sourceType === "remote" || plugin.remotePluginId !== undefined);
33675
+ }
33670
33676
  function codexPluginSourceIsConfigControlled(plugin) {
33671
33677
  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"];
33672
- return Boolean(plugin.sourceType && ["local", "git", "npm"].includes(plugin.sourceType) && plugin.sourceSha256 && /^[a-f0-9]{64}$/.test(plugin.sourceSha256) && !plugin.remotePluginId && !remoteRealms.includes(plugin.id.slice(plugin.id.lastIndexOf("@") + 1)));
33678
+ return Boolean(plugin.sourceType && ["local", "git", "npm"].includes(plugin.sourceType) && plugin.sourceSha256 && /^[a-f0-9]{64}$/.test(plugin.sourceSha256) && !codexPluginIsRemote(plugin) && !remoteRealms.includes(plugin.id.slice(plugin.id.lastIndexOf("@") + 1)));
33673
33679
  }
33674
33680
  function refuse() {
33675
33681
  throw new Error("CODEX_NATIVE_SKILL_CATALOG_INVALID");
@@ -33759,16 +33765,16 @@ var init_codex_native_skill_catalog = __esm(() => {
33759
33765
  });
33760
33766
 
33761
33767
  // src/lib/codex-plugin-skill-controls.ts
33762
- import { basename as basename8, dirname as dirname15, join as join19, relative as relative5, resolve as resolve14, sep as sep8 } from "path";
33763
- import { lstatSync as lstatSync14, readdirSync as readdirSync5, readFileSync as readFileSync12, readlinkSync as readlinkSync3, realpathSync as realpathSync5 } from "fs";
33768
+ import { basename as basename9, dirname as dirname16, join as join20, relative as relative5, resolve as resolve14, sep as sep8 } from "path";
33769
+ import { lstatSync as lstatSync15, readdirSync as readdirSync6, readFileSync as readFileSync13, readlinkSync as readlinkSync3, realpathSync as realpathSync5 } from "fs";
33764
33770
  function refuse2() {
33765
33771
  throw new Error("CODEX_NATIVE_SKILL_IDENTITY_UNSUPPORTED: review native plugin names and hook controls");
33766
33772
  }
33767
33773
  function codexRemoteInstallReceipt(parent, read) {
33768
33774
  try {
33769
- if (!lstatSync14(parent).isDirectory() || realpathSync5(parent) !== parent)
33775
+ if (!lstatSync15(parent).isDirectory() || realpathSync5(parent) !== parent)
33770
33776
  return null;
33771
- const path = join19(parent, ".codex-remote-plugin-install.json"), stat2 = lstatSync14(path, { throwIfNoEntry: false });
33777
+ const path = join20(parent, ".codex-remote-plugin-install.json"), stat2 = lstatSync15(path, { throwIfNoEntry: false });
33772
33778
  if (!stat2?.isFile() || stat2.isSymbolicLink() || stat2.size > 16384)
33773
33779
  return null;
33774
33780
  const text2 = read(path);
@@ -33830,7 +33836,7 @@ function mcpControls(path, read) {
33830
33836
  function isBundledCleanupHooks(root, namespace, value) {
33831
33837
  const object5 = (v) => Boolean(v && typeof v === "object" && !Array.isArray(v));
33832
33838
  const exactKeys = (v, keys) => Object.keys(v).length === keys.length && keys.every((key2) => Object.hasOwn(v, key2));
33833
- if (basename8(dirname15(root)) !== namespace || basename8(dirname15(dirname15(root))) !== "openai-bundled")
33839
+ if (basename9(dirname16(root)) !== namespace || basename9(dirname16(dirname16(root))) !== "openai-bundled")
33834
33840
  return false;
33835
33841
  const server = namespace === "unified-computer-use" ? "cua_repl" : ["browser", "chrome", "chrome-dev", "chrome-internal", "computer-use"].includes(namespace) ? "node_repl" : undefined;
33836
33842
  if (!server || !object5(value) || !exactKeys(value, ["hooks"]) || !object5(value.hooks))
@@ -33854,8 +33860,8 @@ function readCodexPluginRootControls(root, read) {
33854
33860
  return rootControls(root, read);
33855
33861
  }
33856
33862
  function rootControls(root, read) {
33857
- const manifestPath = join19(root, ".codex-plugin/plugin.json"), manifestFile = lstatSync14(manifestPath, { throwIfNoEntry: false });
33858
- if (!lstatSync14(join19(root, ".codex-plugin"), { throwIfNoEntry: false })?.isDirectory() || !manifestFile?.isFile() || manifestFile.size > 1024 * 1024)
33863
+ const manifestPath = join20(root, ".codex-plugin/plugin.json"), manifestFile = lstatSync15(manifestPath, { throwIfNoEntry: false });
33864
+ if (!lstatSync15(join20(root, ".codex-plugin"), { throwIfNoEntry: false })?.isDirectory() || !manifestFile?.isFile() || manifestFile.size > 1024 * 1024)
33859
33865
  refuse2();
33860
33866
  let manifest, manifestSha256;
33861
33867
  try {
@@ -33867,12 +33873,12 @@ function rootControls(root, read) {
33867
33873
  }
33868
33874
  if (!manifest || typeof manifest !== "object" || Array.isArray(manifest) || !identifier2(manifest.name))
33869
33875
  refuse2();
33870
- const cacheVersion = basename8(root), declaredVersion = manifest.version === undefined ? "" : typeof manifest.version === "string" ? manifest.version.trim() : null;
33876
+ const cacheVersion = basename9(root), declaredVersion = manifest.version === undefined ? "" : typeof manifest.version === "string" ? manifest.version.trim() : null;
33871
33877
  if (declaredVersion === null || (declaredVersion ? declaredVersion !== cacheVersion : cacheVersion !== CODEX_DEFAULT_AGENT_PLUGIN_VERSION))
33872
33878
  refuse2();
33873
- if (manifest.hooks !== undefined && !isBundledCleanupHooks(root, manifest.name, manifest.hooks) || manifest.commands !== undefined || manifest.mcpServers !== undefined && manifest.mcpServers !== "./.mcp.json" || manifest.apps !== undefined && manifest.apps !== "./.app.json" || lstatSync14(join19(root, "hooks"), { throwIfNoEntry: false }))
33879
+ if (manifest.hooks !== undefined && !isBundledCleanupHooks(root, manifest.name, manifest.hooks) || manifest.commands !== undefined || manifest.mcpServers !== undefined && manifest.mcpServers !== "./.mcp.json" || manifest.apps !== undefined && manifest.apps !== "./.app.json" || lstatSync15(join20(root, "hooks"), { throwIfNoEntry: false }))
33874
33880
  refuse2();
33875
- const mcp = join19(root, ".mcp.json"), mcpPresent = lstatSync14(mcp, { throwIfNoEntry: false });
33881
+ const mcp = join20(root, ".mcp.json"), mcpPresent = lstatSync15(mcp, { throwIfNoEntry: false });
33876
33882
  if (manifest.hooks !== undefined && (manifest.mcpServers !== undefined || mcpPresent))
33877
33883
  refuse2();
33878
33884
  if (mcpPresent && (!mcpPresent.isFile() || mcpPresent.isSymbolicLink() || mcpPresent.size > 1024 * 1024 || realpathSync5(mcp) !== mcp))
@@ -33880,7 +33886,7 @@ function rootControls(root, read) {
33880
33886
  if (Boolean(mcpPresent) !== (manifest.mcpServers !== undefined))
33881
33887
  refuse2();
33882
33888
  const mcpSha256 = mcpPresent ? mcpControls(mcp, read) : undefined;
33883
- const app = join19(root, ".app.json"), present = lstatSync14(app, { throwIfNoEntry: false });
33889
+ const app = join20(root, ".app.json"), present = lstatSync15(app, { throwIfNoEntry: false });
33884
33890
  if (present && (!present.isFile() || present.isSymbolicLink() || present.size > 1024 * 1024))
33885
33891
  refuse2();
33886
33892
  if (manifest.apps !== undefined && !present)
@@ -33912,12 +33918,12 @@ function documentIdentity(document2, cache, read) {
33912
33918
  }
33913
33919
  if (!front || typeof front !== "object" || !identifier2(front.name) || typeof front.description !== "string" || !front.description.trim())
33914
33920
  refuse2();
33915
- for (let root = dirname15(document2), depth = 0;root.startsWith(cache + sep8) && depth < 12; root = dirname15(root), depth++) {
33916
- const path = join19(root, ".codex-plugin", "plugin.json");
33917
- if (!lstatSync14(path, { throwIfNoEntry: false }))
33921
+ for (let root = dirname16(document2), depth = 0;root.startsWith(cache + sep8) && depth < 12; root = dirname16(root), depth++) {
33922
+ const path = join20(root, ".codex-plugin", "plugin.json");
33923
+ if (!lstatSync15(path, { throwIfNoEntry: false }))
33918
33924
  continue;
33919
- const manifestFile = lstatSync14(path);
33920
- if (!lstatSync14(join19(root, ".codex-plugin")).isDirectory() || !manifestFile.isFile() || manifestFile.size > 1024 * 1024)
33925
+ const manifestFile = lstatSync15(path);
33926
+ if (!lstatSync15(join20(root, ".codex-plugin")).isDirectory() || !manifestFile.isFile() || manifestFile.size > 1024 * 1024)
33921
33927
  refuse2();
33922
33928
  let manifest;
33923
33929
  try {
@@ -33930,9 +33936,9 @@ function documentIdentity(document2, cache, read) {
33930
33936
  if (!manifest || typeof manifest !== "object" || Array.isArray(manifest) || !identifier2(manifest.name))
33931
33937
  refuse2();
33932
33938
  const declaredVersion = manifest.version === undefined ? "" : typeof manifest.version === "string" ? manifest.version.trim() : null;
33933
- if (declaredVersion === null || (declaredVersion ? declaredVersion !== basename8(root) : basename8(root) !== CODEX_DEFAULT_AGENT_PLUGIN_VERSION))
33939
+ if (declaredVersion === null || (declaredVersion ? declaredVersion !== basename9(root) : basename9(root) !== CODEX_DEFAULT_AGENT_PLUGIN_VERSION))
33934
33940
  refuse2();
33935
- return { name: `${manifest.name}:${front.name}`, namespace: manifest.name, pluginParent: dirname15(root), root };
33941
+ return { name: `${manifest.name}:${front.name}`, namespace: manifest.name, pluginParent: dirname16(root), root };
33936
33942
  }
33937
33943
  refuse2();
33938
33944
  }
@@ -33948,7 +33954,7 @@ function classifyCodexPluginCacheDocument(document2, cache, read) {
33948
33954
  return null;
33949
33955
  try {
33950
33956
  const located = documentIdentity(document2, cache, read), parsed = identity3(document2, cache, read);
33951
- if (!lstatSync14(document2).isFile() || realpathSync5(document2) !== document2 || realpathSync5(located.root) !== located.root || realpathSync5(located.pluginParent) !== located.pluginParent || realpathSync5(join19(located.root, ".codex-plugin/plugin.json")) !== join19(located.root, ".codex-plugin/plugin.json"))
33957
+ if (!lstatSync15(document2).isFile() || realpathSync5(document2) !== document2 || realpathSync5(located.root) !== located.root || realpathSync5(located.pluginParent) !== located.pluginParent || realpathSync5(join20(located.root, ".codex-plugin/plugin.json")) !== join20(located.root, ".codex-plugin/plugin.json"))
33952
33958
  return null;
33953
33959
  const parts = relative5(cache, parsed.pluginParent).split(sep8);
33954
33960
  if (parts.length !== 2 || parts.some((part) => !identifier2(part)) || parts[1] !== parsed.namespace)
@@ -33963,11 +33969,11 @@ function reviewedDisabledCodexPluginParent(cache, parent, controls, rules) {
33963
33969
  const parts = relative5(cache, parent).split(sep8), enrolled = controls.filter((control) => control.pluginParent === parent);
33964
33970
  if (resolve14(parent) !== parent || parts.length !== 2 || parts.some((part) => !identifier2(part)) || !enrolled.length || !Array.isArray(rules))
33965
33971
  return false;
33966
- for (let cursor = parent;; cursor = dirname15(cursor)) {
33967
- const stat2 = lstatSync14(cursor, { throwIfNoEntry: false });
33972
+ for (let cursor = parent;; cursor = dirname16(cursor)) {
33973
+ const stat2 = lstatSync15(cursor, { throwIfNoEntry: false });
33968
33974
  if (stat2 && (!stat2.isDirectory() || stat2.isSymbolicLink()))
33969
33975
  return false;
33970
- if (dirname15(cursor) === cursor)
33976
+ if (dirname16(cursor) === cursor)
33971
33977
  break;
33972
33978
  }
33973
33979
  return enrolled.every((control) => control.namespace === parts[1] && control.pluginId === `${parts[1]}@${parts[0]}` && remotePluginIdentifier(control.remotePluginId) && control.skillsOnly === true && !control.appSha256 && !control.mcpSha256 && control.name.startsWith(control.namespace + ":") && /^[a-f0-9]{64}$/.test(control.manifestSha256) && rules.some((rule) => typeof rule?.name === "string" && rule.name.trim() === control.name && rule.enabled === false) && !rules.some((rule) => (typeof rule?.name === "string" && rule.name.trim() === control.name || typeof rule?.path === "string" && (rule.path === parent || rule.path.startsWith(parent + sep8))) && rule.enabled !== false));
@@ -33976,36 +33982,36 @@ function reviewedDisabledCodexPluginParent(cache, parent, controls, rules) {
33976
33982
  }
33977
33983
  }
33978
33984
  function absentDisabledCodexPluginParent(cache, parent, controls, rules) {
33979
- return reviewedDisabledCodexPluginParent(cache, parent, controls, rules) && !lstatSync14(parent, { throwIfNoEntry: false });
33985
+ return reviewedDisabledCodexPluginParent(cache, parent, controls, rules) && !lstatSync15(parent, { throwIfNoEntry: false });
33980
33986
  }
33981
33987
  function reviewedRetiredCodexRoot(cache, root, controls, rules, read, allowAbsent = false) {
33982
33988
  try {
33983
- const parent = dirname15(root), parts = relative5(cache, parent).split(sep8), enrolled = controls.filter((control) => control.pluginParent === parent);
33984
- if (resolve14(root) !== root || parts.length !== 2 || parts.some((part) => !identifier2(part)) || !basename8(root) || basename8(root) === "latest" || !enrolled.length || !Array.isArray(rules))
33989
+ const parent = dirname16(root), parts = relative5(cache, parent).split(sep8), enrolled = controls.filter((control) => control.pluginParent === parent);
33990
+ if (resolve14(root) !== root || parts.length !== 2 || parts.some((part) => !identifier2(part)) || !basename9(root) || basename9(root) === "latest" || !enrolled.length || !Array.isArray(rules))
33985
33991
  return false;
33986
- for (let cursor = root;; cursor = dirname15(cursor)) {
33987
- const stat2 = lstatSync14(cursor, { throwIfNoEntry: false });
33992
+ for (let cursor = root;; cursor = dirname16(cursor)) {
33993
+ const stat2 = lstatSync15(cursor, { throwIfNoEntry: false });
33988
33994
  if (stat2 && (!stat2.isDirectory() || stat2.isSymbolicLink()))
33989
33995
  return false;
33990
- if (dirname15(cursor) === cursor)
33996
+ if (dirname16(cursor) === cursor)
33991
33997
  break;
33992
33998
  }
33993
33999
  if (!enrolled.every((control) => control.namespace === parts[1] && control.pluginId === `${parts[1]}@${parts[0]}` && remotePluginIdentifier(control.remotePluginId) && control.skillsOnly === true && !control.appSha256 && !control.mcpSha256 && control.name.startsWith(control.namespace + ":") && /^[a-f0-9]{64}$/.test(control.manifestSha256) && rules.some((rule) => typeof rule?.name === "string" && rule.name.trim() === control.name && rule.enabled === false) && !rules.some((rule) => (typeof rule?.name === "string" && rule.name.trim() === control.name || typeof rule?.path === "string" && (rule.path === parent || rule.path === root || rule.path.startsWith(root + sep8))) && rule.enabled !== false)))
33994
34000
  return false;
33995
- if (!lstatSync14(root, { throwIfNoEntry: false }))
33996
- return allowAbsent && (lstatSync14(parent, { throwIfNoEntry: false }) ? enrolled.every((control) => remoteInstallationMatches(parent, control.remotePluginId, read)) : absentDisabledCodexPluginParent(cache, parent, controls, rules));
34001
+ if (!lstatSync15(root, { throwIfNoEntry: false }))
34002
+ return allowAbsent && (lstatSync15(parent, { throwIfNoEntry: false }) ? enrolled.every((control) => remoteInstallationMatches(parent, control.remotePluginId, read)) : absentDisabledCodexPluginParent(cache, parent, controls, rules));
33997
34003
  if (!enrolled.every((control) => remoteInstallationMatches(parent, control.remotePluginId, read)))
33998
34004
  return false;
33999
34005
  const parsed = rootControls(root, read);
34000
- if (JSON.parse(read(join19(root, ".codex-plugin/plugin.json"))).hooks !== undefined)
34006
+ if (JSON.parse(read(join20(root, ".codex-plugin/plugin.json"))).hooks !== undefined)
34001
34007
  return false;
34002
34008
  if (!enrolled.some((control) => control.namespace === parsed.namespace && control.manifestSha256 === parsed.manifestSha256 && !parsed.appSha256 && !parsed.mcpSha256))
34003
34009
  return false;
34004
34010
  let entries = 0;
34005
- const emptySkills = (directory, depth) => depth <= 64 && readdirSync5(directory).every((name) => {
34011
+ const emptySkills = (directory, depth) => depth <= 64 && readdirSync6(directory).every((name) => {
34006
34012
  if (++entries > 4096 || name === "SKILL.md")
34007
34013
  return false;
34008
- const path = join19(directory, name), stat2 = lstatSync14(path);
34014
+ const path = join20(directory, name), stat2 = lstatSync15(path);
34009
34015
  return !stat2.isSymbolicLink() && (stat2.isFile() || stat2.isDirectory() && emptySkills(path, depth + 1));
34010
34016
  });
34011
34017
  return emptySkills(root, 0);
@@ -34021,26 +34027,26 @@ function reviewedCodexPluginCapabilitiesUnchanged(cache, controls, read, rules)
34021
34027
  for (const parent of new Set(controls.map((control) => control.pluginParent))) {
34022
34028
  if (absentDisabledCodexPluginParent(cache, parent, controls, rules))
34023
34029
  continue;
34024
- if (!parent.startsWith(cache + sep8) || !lstatSync14(parent, { throwIfNoEntry: false })?.isDirectory() || realpathSync5(parent) !== parent)
34030
+ if (!parent.startsWith(cache + sep8) || !lstatSync15(parent, { throwIfNoEntry: false })?.isDirectory() || realpathSync5(parent) !== parent)
34025
34031
  return false;
34026
34032
  for (const control of controls.filter((control2) => control2.pluginParent === parent)) {
34027
34033
  if (control.remotePluginId !== undefined && !remoteInstallationMatches(parent, control.remotePluginId, read))
34028
34034
  return false;
34029
34035
  }
34030
- const names = readdirSync5(parent);
34036
+ const names = readdirSync6(parent);
34031
34037
  entries += names.length;
34032
34038
  if (entries > 4096)
34033
34039
  return false;
34034
34040
  for (const name of names) {
34035
- let root = join19(parent, name), stat2 = lstatSync14(root);
34041
+ let root = join20(parent, name), stat2 = lstatSync15(root);
34036
34042
  if (stat2.isSymbolicLink()) {
34037
34043
  const target = resolve14(parent, readlinkSync3(root));
34038
- if (name !== "latest" || dirname15(target) !== parent || !lstatSync14(target).isDirectory() || realpathSync5(target) !== target)
34044
+ if (name !== "latest" || dirname16(target) !== parent || !lstatSync15(target).isDirectory() || realpathSync5(target) !== target)
34039
34045
  return false;
34040
34046
  root = target;
34041
- stat2 = lstatSync14(root);
34047
+ stat2 = lstatSync15(root);
34042
34048
  }
34043
- if (!stat2.isDirectory() || ![".codex-plugin/plugin.json", ".app.json", "hooks", ".mcp.json"].some((path) => lstatSync14(join19(root, path), { throwIfNoEntry: false })))
34049
+ if (!stat2.isDirectory() || ![".codex-plugin/plugin.json", ".app.json", "hooks", ".mcp.json"].some((path) => lstatSync15(join20(root, path), { throwIfNoEntry: false })))
34044
34050
  continue;
34045
34051
  const parsed = rootControls(root, read);
34046
34052
  if (!controls.some((control) => control.pluginParent === parent && control.namespace === parsed.namespace && control.manifestSha256 === parsed.manifestSha256 && control.appSha256 === parsed.appSha256 && control.mcpSha256 === parsed.mcpSha256))
@@ -34055,9 +34061,9 @@ function reviewedCodexPluginCapabilitiesUnchanged(cache, controls, read, rules)
34055
34061
  function sourceInputUnchanged(input2, cache, read) {
34056
34062
  try {
34057
34063
  const parts = relative5(cache, input2.pluginParent).split(sep8);
34058
- 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 })) || resolve14(input2.sourceRoot) !== input2.sourceRoot || !lstatSync14(input2.sourceRoot).isDirectory() || realpathSync5(input2.sourceRoot) !== input2.sourceRoot || input2.sourceRoot === cache || input2.sourceRoot.startsWith(cache + sep8) || cache.startsWith(input2.sourceRoot + sep8))
34064
+ 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 })) || resolve14(input2.sourceRoot) !== input2.sourceRoot || !lstatSync15(input2.sourceRoot).isDirectory() || realpathSync5(input2.sourceRoot) !== input2.sourceRoot || input2.sourceRoot === cache || input2.sourceRoot.startsWith(cache + sep8) || cache.startsWith(input2.sourceRoot + sep8))
34059
34065
  return false;
34060
- const path = join19(input2.sourceRoot, ".codex-plugin/plugin.json"), stat2 = lstatSync14(path);
34066
+ const path = join20(input2.sourceRoot, ".codex-plugin/plugin.json"), stat2 = lstatSync15(path);
34061
34067
  if (!stat2.isFile() || stat2.size > 1024 * 1024 || realpathSync5(path) !== path)
34062
34068
  return false;
34063
34069
  const text2 = read(path);
@@ -34080,11 +34086,12 @@ var identifier2 = (v) => typeof v === "string" && /^[A-Za-z0-9_-]{1,64}$/.test(v
34080
34086
  var init_codex_plugin_skill_controls = __esm(() => {
34081
34087
  init_claude_settings_witness();
34082
34088
  init_codex_native_compatibility();
34089
+ init_codex_plugin_capability_paths();
34083
34090
  init_codex_native_skill_catalog();
34084
34091
  });
34085
34092
 
34086
34093
  // src/lib/codex-vendor-refresh.ts
34087
- var CODEX_VENDOR_MARKETPLACES, CODEX_REMOTE_VENDOR_MARKETPLACES, OTHER_PLUGIN_CONTROLS, VENDOR_MANIFEST_KEYS, DEFAULT_SKILLS_PATHS;
34094
+ var CODEX_VENDOR_MARKETPLACES, CODEX_REMOTE_VENDOR_MARKETPLACES, OTHER_PLUGIN_CONTROLS;
34088
34095
  var init_codex_vendor_refresh = __esm(() => {
34089
34096
  init_claude_settings_witness();
34090
34097
  init_codex_plugin_skill_controls();
@@ -34092,8 +34099,6 @@ var init_codex_vendor_refresh = __esm(() => {
34092
34099
  CODEX_VENDOR_MARKETPLACES = Object.freeze(["openai-bundled", "openai-curated", "openai-curated-remote"]);
34093
34100
  CODEX_REMOTE_VENDOR_MARKETPLACES = Object.freeze(["openai-curated-remote"]);
34094
34101
  OTHER_PLUGIN_CONTROLS = Object.freeze(CODEX_PLUGIN_ROOT_CAPABILITY_ENTRIES.filter((entry) => entry !== ".codex-plugin" && entry !== ".app.json"));
34095
- VENDOR_MANIFEST_KEYS = Object.freeze(["name", "version", "description", "author", "homepage", "repository", "license", "keywords", "interface", "skills", "apps"]);
34096
- DEFAULT_SKILLS_PATHS = Object.freeze(["./skills", "./skills/"]);
34097
34102
  });
34098
34103
 
34099
34104
  // src/lib/claude-plugin-manifest-witness.ts
@@ -34537,19 +34542,19 @@ function capturePreparationProcess(child2, platform = process.platform, signalGr
34537
34542
  }
34538
34543
 
34539
34544
  // src/lib/dependency-preparation.ts
34540
- import { constants as constants9, closeSync as closeSync12, fstatSync as fstatSync12, lstatSync as lstatSync15, mkdirSync as mkdirSync5, openSync as openSync12, readFileSync as readFileSync13, readdirSync as readdirSync6, rmdirSync as rmdirSync2, unlinkSync as unlinkSync3, ftruncateSync, writeSync as writeSync2 } from "fs";
34541
- import { join as join20 } from "path";
34545
+ import { constants as constants9, closeSync as closeSync12, fstatSync as fstatSync12, lstatSync as lstatSync16, mkdirSync as mkdirSync5, openSync as openSync12, readFileSync as readFileSync14, readdirSync as readdirSync7, rmdirSync as rmdirSync2, unlinkSync as unlinkSync3, ftruncateSync, writeSync as writeSync2 } from "fs";
34546
+ import { join as join21 } from "path";
34542
34547
  function hasDependencyPreparationMarker(skillPath) {
34543
34548
  try {
34544
- lstatSync15(join20(skillPath, DEPENDENCY_PREPARATION_MARKER));
34549
+ lstatSync16(join21(skillPath, DEPENDENCY_PREPARATION_MARKER));
34545
34550
  return true;
34546
34551
  } catch (error61) {
34547
34552
  return error61.code !== "ENOENT";
34548
34553
  }
34549
34554
  }
34550
34555
  function claimPreparation(skillPath) {
34551
- const marker = join20(skillPath, DEPENDENCY_PREPARATION_MARKER);
34552
- const state = join20(marker, "state.json"), active = join20(marker, "active");
34556
+ const marker = join21(skillPath, DEPENDENCY_PREPARATION_MARKER);
34557
+ const state = join21(marker, "state.json"), active = join21(marker, "active");
34553
34558
  let created = false;
34554
34559
  try {
34555
34560
  mkdirSync5(marker, { mode: 448 });
@@ -34560,14 +34565,14 @@ function claimPreparation(skillPath) {
34560
34565
  }
34561
34566
  let fd;
34562
34567
  try {
34563
- if (!lstatSync15(marker).isDirectory() || lstatSync15(marker).isSymbolicLink())
34568
+ if (!lstatSync16(marker).isDirectory() || lstatSync16(marker).isSymbolicLink())
34564
34569
  return;
34565
34570
  if (!created) {
34566
- if (readdirSync6(marker).some((name) => name !== "state.json"))
34571
+ if (readdirSync7(marker).some((name) => name !== "state.json"))
34567
34572
  return;
34568
- if (!lstatSync15(state).isFile() || lstatSync15(state).isSymbolicLink() || lstatSync15(state).size > 1024)
34573
+ if (!lstatSync16(state).isFile() || lstatSync16(state).isSymbolicLink() || lstatSync16(state).size > 1024)
34569
34574
  return;
34570
- const previous = JSON.parse(readFileSync13(state, "utf8"));
34575
+ const previous = JSON.parse(readFileSync14(state, "utf8"));
34571
34576
  if (previous.version !== 1 || previous.status !== "failed" || Object.keys(previous).length !== 2)
34572
34577
  return;
34573
34578
  }
@@ -34700,6 +34705,9 @@ async function prepareSkillDependencies(skillPath, env, timeoutMs = DEFAULT_PREP
34700
34705
  var DEPENDENCY_PREPARATION_MARKER = ".skills-dependency-preparation", RECOVERY = "Skill dependency preparation is incomplete. Confirm no installer is running, successfully run bun install --no-save in the skill directory, then remove only .skills-dependency-preparation. See docs/skill-standard.md#recovering-interrupted-dependency-preparation.", DEFAULT_PREPARATION_TIMEOUT_MS = 60000;
34701
34706
  var init_dependency_preparation = () => {};
34702
34707
 
34708
+ // src/lib/codex-native-config.ts
34709
+ var init_codex_native_config = () => {};
34710
+
34703
34711
  // src/lib/codex-native-skill-policy.ts
34704
34712
  var MAX_EXECUTABLE_BYTES, MAX_BRIDGE_DOCUMENT_BYTES, CODEX_NATIVE_POLICY_HELPER_MAX_OUTPUT_BYTES, executableDigestMemory;
34705
34713
  var init_codex_native_skill_policy = __esm(() => {
@@ -34711,8 +34719,8 @@ var init_codex_native_skill_policy = __esm(() => {
34711
34719
 
34712
34720
  // src/lib/codex-semantic-cache-witness.ts
34713
34721
  import { createHash as createHash18 } from "crypto";
34714
- import { constants as constants10, closeSync as closeSync13, fstatSync as fstatSync13, lstatSync as lstatSync16, openSync as openSync13, readSync as readSync7, readdirSync as readdirSync7, realpathSync as realpathSync6 } from "fs";
34715
- import { basename as basename9, dirname as dirname16, isAbsolute as isAbsolute15, join as join21, relative as relative6, resolve as resolve15, sep as sep9 } from "path";
34722
+ import { constants as constants10, closeSync as closeSync13, fstatSync as fstatSync13, lstatSync as lstatSync17, openSync as openSync13, readSync as readSync7, readdirSync as readdirSync8, realpathSync as realpathSync6 } from "fs";
34723
+ import { basename as basename10, dirname as dirname17, isAbsolute as isAbsolute15, join as join22, relative as relative6, resolve as resolve15, sep as sep9 } from "path";
34716
34724
  function codexLocalMarketplaceMapsPlugin(text2, marketplace, plugin) {
34717
34725
  try {
34718
34726
  hashNativeJsonControls(text2);
@@ -34734,7 +34742,7 @@ function codexLocalMarketplaceMapsPlugin(text2, marketplace, plugin) {
34734
34742
  }
34735
34743
  }
34736
34744
  function defaultRead(path) {
34737
- const before = lstatSync16(path, { throwIfNoEntry: false, bigint: true });
34745
+ const before = lstatSync17(path, { throwIfNoEntry: false, bigint: true });
34738
34746
  if (before === undefined)
34739
34747
  return refuse3();
34740
34748
  if (!before.isFile() || before.isSymbolicLink() || before.size > BigInt(MAX_DOCUMENT_BYTES))
@@ -34825,7 +34833,7 @@ function assertWitnessShape(value) {
34825
34833
  const row = candidate;
34826
34834
  const remote = row.installation === "remote-receipt";
34827
34835
  const local = row.installation === "local-marketplace";
34828
- if (!exactKeys(row, ["role", "pluginId", "namespace", "pluginParent", "installation", "manifestSha256", "hooksSha256"], remote ? ["remotePluginId", "receiptSha256"] : local ? ["marketplaceSourcePath", "marketplaceSha256"] : []) || row.role !== "reviewed-hook" || !identifier4(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) || remote && (typeof row.remotePluginId !== "string" || !/^[A-Za-z0-9_~-]{1,1024}$/.test(row.remotePluginId) || !digest(row.receiptSha256)) || local && (typeof row.marketplaceSourcePath !== "string" || !isAbsolute15(row.marketplaceSourcePath) || resolve15(row.marketplaceSourcePath) !== row.marketplaceSourcePath || basename9(row.marketplaceSourcePath) !== "marketplace.json" || !digest(row.marketplaceSha256)) || !remote && !local || !digest(row.manifestSha256) || !digest(row.hooksSha256) || hookParentPaths.has(row.pluginParent) || controlParents.has(row.pluginParent) || appOnlyParentPaths.has(row.pluginParent))
34836
+ if (!exactKeys(row, ["role", "pluginId", "namespace", "pluginParent", "installation", "manifestSha256", "hooksSha256"], remote ? ["remotePluginId", "receiptSha256"] : local ? ["marketplaceSourcePath", "marketplaceSha256"] : []) || row.role !== "reviewed-hook" || !identifier4(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) || remote && (typeof row.remotePluginId !== "string" || !/^[A-Za-z0-9_~-]{1,1024}$/.test(row.remotePluginId) || !digest(row.receiptSha256)) || local && (typeof row.marketplaceSourcePath !== "string" || !isAbsolute15(row.marketplaceSourcePath) || resolve15(row.marketplaceSourcePath) !== row.marketplaceSourcePath || basename10(row.marketplaceSourcePath) !== "marketplace.json" || !digest(row.marketplaceSha256)) || !remote && !local || !digest(row.manifestSha256) || !digest(row.hooksSha256) || hookParentPaths.has(row.pluginParent) || controlParents.has(row.pluginParent) || appOnlyParentPaths.has(row.pluginParent))
34829
34837
  refuse3();
34830
34838
  hookParentPaths.add(row.pluginParent);
34831
34839
  }
@@ -34857,23 +34865,23 @@ function assertWitnessShape(value) {
34857
34865
  function assertCanonicalDirectory(path) {
34858
34866
  if (resolve15(path) !== path || realpathSync6(path) !== path)
34859
34867
  refuse3();
34860
- for (let cursor = path;; cursor = dirname16(cursor)) {
34861
- const stat2 = lstatSync16(cursor, { throwIfNoEntry: false });
34868
+ for (let cursor = path;; cursor = dirname17(cursor)) {
34869
+ const stat2 = lstatSync17(cursor, { throwIfNoEntry: false });
34862
34870
  if (stat2 && (!stat2.isDirectory() || stat2.isSymbolicLink()))
34863
34871
  refuse3();
34864
- if (dirname16(cursor) === cursor)
34872
+ if (dirname17(cursor) === cursor)
34865
34873
  break;
34866
34874
  }
34867
34875
  }
34868
34876
  function walkSafeTree(path, state, depth = 0, root = path) {
34869
34877
  if (depth > 64 || ++state.entries > 16384)
34870
34878
  refuse3();
34871
- const names = readdirSync7(path).sort();
34879
+ const names = readdirSync8(path).sort();
34872
34880
  const files = [];
34873
34881
  for (const name of names) {
34874
34882
  if (!name || name === "." || name === ".." || name.includes(sep9) || ++state.entries > 16384)
34875
34883
  refuse3();
34876
- const child2 = join21(path, name), stat2 = lstatSync16(child2, { bigint: true });
34884
+ const child2 = join22(path, name), stat2 = lstatSync17(child2, { bigint: true });
34877
34885
  state.members.push(child2);
34878
34886
  state.signature.push(`${relative6(root, child2)}\x00${stat2.mode}\x00${stat2.dev}\x00${stat2.ino}\x00${stat2.isDirectory() ? 0 : stat2.size}`);
34879
34887
  state.timestamps.set(child2, `${stat2.mtimeNs}\x00${stat2.ctimeNs}`);
@@ -34890,7 +34898,7 @@ function walkSafeTree(path, state, depth = 0, root = path) {
34890
34898
  }
34891
34899
  function treeSnapshot(cacheRoot) {
34892
34900
  const state = { entries: 0, members: [], signature: [], timestamps: new Map };
34893
- const rootStat = lstatSync16(cacheRoot, { throwIfNoEntry: false, bigint: true });
34901
+ const rootStat = lstatSync17(cacheRoot, { throwIfNoEntry: false, bigint: true });
34894
34902
  if (rootStat === undefined)
34895
34903
  return refuse3();
34896
34904
  if (!rootStat.isDirectory() || rootStat.isSymbolicLink() || realpathSync6(cacheRoot) !== cacheRoot)
@@ -34910,7 +34918,7 @@ function assertSameTree(before, after, semanticPaths) {
34910
34918
  function trackedBoundedRead(read) {
34911
34919
  const observed = new Map;
34912
34920
  const stableStat = (path, max) => {
34913
- const stat2 = lstatSync16(path, { throwIfNoEntry: false, bigint: true });
34921
+ const stat2 = lstatSync17(path, { throwIfNoEntry: false, bigint: true });
34914
34922
  if (stat2 === undefined)
34915
34923
  return refuse3();
34916
34924
  if (!stat2.isFile() || stat2.isSymbolicLink() || stat2.size > BigInt(max) || realpathSync6(path) !== path)
@@ -34966,7 +34974,7 @@ function controlProjection(controls, read) {
34966
34974
  ...control.mcpSha256 === undefined ? {} : { mcpSha256: control.mcpSha256 }
34967
34975
  };
34968
34976
  if (row.remotePluginId !== undefined) {
34969
- const receipt = join21(row.pluginParent, ".codex-remote-plugin-install.json"), stat2 = lstatSync16(receipt, { throwIfNoEntry: false });
34977
+ const receipt = join22(row.pluginParent, ".codex-remote-plugin-install.json"), stat2 = lstatSync17(receipt, { throwIfNoEntry: false });
34970
34978
  if (!stat2?.isFile() || stat2.isSymbolicLink() || stat2.size > 16384)
34971
34979
  refuse3();
34972
34980
  try {
@@ -34998,10 +35006,10 @@ function appOnlyParentProjection(cacheRoot, parents2, read) {
34998
35006
  if (resolve15(parent.pluginParent) !== parent.pluginParent || parts.length !== 2 || parts.some((part) => !identifier4(part)) || parent.pluginId !== `${parent.namespace}@${parts[0]}` || parts[1] !== parent.namespace || seen.has(parent.pluginParent))
34999
35007
  refuse3();
35000
35008
  seen.add(parent.pluginParent);
35001
- const parentStat = lstatSync16(parent.pluginParent, { throwIfNoEntry: false });
35009
+ const parentStat = lstatSync17(parent.pluginParent, { throwIfNoEntry: false });
35002
35010
  if (!parentStat?.isDirectory() || parentStat.isSymbolicLink() || realpathSync6(parent.pluginParent) !== parent.pluginParent)
35003
35011
  refuse3();
35004
- const receipt = join21(parent.pluginParent, ".codex-remote-plugin-install.json"), receiptStat = lstatSync16(receipt, { throwIfNoEntry: false });
35012
+ const receipt = join22(parent.pluginParent, ".codex-remote-plugin-install.json"), receiptStat = lstatSync17(receipt, { throwIfNoEntry: false });
35005
35013
  if (!receiptStat?.isFile() || receiptStat.isSymbolicLink() || receiptStat.size > 16384)
35006
35014
  refuse3();
35007
35015
  let receiptText = "";
@@ -35014,13 +35022,13 @@ function appOnlyParentProjection(cacheRoot, parents2, read) {
35014
35022
  } catch {
35015
35023
  refuse3();
35016
35024
  }
35017
- const versions2 = readdirSync7(parent.pluginParent).filter((name) => name !== ".codex-remote-plugin-install.json");
35025
+ const versions2 = readdirSync8(parent.pluginParent).filter((name) => name !== ".codex-remote-plugin-install.json");
35018
35026
  if (!versions2.length || versions2.length > 4096)
35019
35027
  refuse3();
35020
35028
  const materializations = versions2.map((version2) => {
35021
35029
  if (!/^[A-Za-z0-9][A-Za-z0-9._+-]{0,127}$/.test(version2))
35022
35030
  refuse3();
35023
- const root = join21(parent.pluginParent, version2), stat2 = lstatSync16(root, { throwIfNoEntry: false });
35031
+ const root = join22(parent.pluginParent, version2), stat2 = lstatSync17(root, { throwIfNoEntry: false });
35024
35032
  if (!stat2?.isDirectory() || stat2.isSymbolicLink() || realpathSync6(root) !== root)
35025
35033
  refuse3();
35026
35034
  const rootControls2 = readCodexPluginRootControls(root, read);
@@ -35060,7 +35068,7 @@ function assertJsonValue(value, depth = 0, budget2 = { members: 0 }) {
35060
35068
  }
35061
35069
  }
35062
35070
  function reviewedHookControls(root, read) {
35063
- const manifestPath = join21(root, ".codex-plugin/plugin.json"), hooksPath = join21(root, "hooks/hooks.json");
35071
+ const manifestPath = join22(root, ".codex-plugin/plugin.json"), hooksPath = join22(root, "hooks/hooks.json");
35064
35072
  let manifest, manifestSha256, hooks, hooksSha256;
35065
35073
  try {
35066
35074
  const manifestText = read(manifestPath);
@@ -35073,7 +35081,7 @@ function reviewedHookControls(root, read) {
35073
35081
  } catch {
35074
35082
  return refuse3();
35075
35083
  }
35076
- if (!plainObject(manifest) || !exactKeys(manifest, ["name", "version", "hooks"], ["description"]) || !identifier4(manifest.name) || typeof manifest.version !== "string" || manifest.version !== basename9(root) || manifest.hooks !== "./hooks/hooks.json" || manifest.description !== undefined && (typeof manifest.description !== "string" || !manifest.description.trim() || manifest.description.length > 1024))
35084
+ if (!plainObject(manifest) || !exactKeys(manifest, ["name", "version", "hooks"], ["description"]) || !identifier4(manifest.name) || typeof manifest.version !== "string" || manifest.version !== basename10(root) || manifest.hooks !== "./hooks/hooks.json" || manifest.description !== undefined && (typeof manifest.description !== "string" || !manifest.description.trim() || manifest.description.length > 1024))
35077
35085
  refuse3();
35078
35086
  const manifestRecord = manifest;
35079
35087
  if (!plainObject(hooks) || !exactKeys(hooks, ["hooks"], ["description"]) || !plainObject(hooks.hooks) || hooks.description !== undefined && typeof hooks.description !== "string")
@@ -35104,16 +35112,16 @@ function reviewedHookParentProjection(cacheRoot, parents2, read) {
35104
35112
  const seen = new Set, rows = [];
35105
35113
  for (const parent of parents2) {
35106
35114
  const remote = parent?.installation === "remote-receipt", local = parent?.installation === "local-marketplace";
35107
- if (!parent || !exactKeys(parent, ["installation", "namespace", "pluginId", "pluginParent", "role"], remote ? ["remotePluginId"] : local ? ["marketplaceSourcePath", "marketplaceSha256"] : []) || parent.role !== "reviewed-hook" || !identifier4(parent.namespace) || !/^[A-Za-z0-9_-]{1,64}@[A-Za-z0-9_-]{1,64}$/.test(parent.pluginId) || typeof parent.pluginParent !== "string" || remote && (typeof parent.remotePluginId !== "string" || !/^[A-Za-z0-9_~-]{1,1024}$/.test(parent.remotePluginId)) || local && (typeof parent.marketplaceSourcePath !== "string" || !isAbsolute15(parent.marketplaceSourcePath) || resolve15(parent.marketplaceSourcePath) !== parent.marketplaceSourcePath || basename9(parent.marketplaceSourcePath) !== "marketplace.json" || !digest(parent.marketplaceSha256)) || !remote && !local)
35115
+ if (!parent || !exactKeys(parent, ["installation", "namespace", "pluginId", "pluginParent", "role"], remote ? ["remotePluginId"] : local ? ["marketplaceSourcePath", "marketplaceSha256"] : []) || parent.role !== "reviewed-hook" || !identifier4(parent.namespace) || !/^[A-Za-z0-9_-]{1,64}@[A-Za-z0-9_-]{1,64}$/.test(parent.pluginId) || typeof parent.pluginParent !== "string" || remote && (typeof parent.remotePluginId !== "string" || !/^[A-Za-z0-9_~-]{1,1024}$/.test(parent.remotePluginId)) || local && (typeof parent.marketplaceSourcePath !== "string" || !isAbsolute15(parent.marketplaceSourcePath) || resolve15(parent.marketplaceSourcePath) !== parent.marketplaceSourcePath || basename10(parent.marketplaceSourcePath) !== "marketplace.json" || !digest(parent.marketplaceSha256)) || !remote && !local)
35108
35116
  refuse3();
35109
35117
  const parts = relative6(cacheRoot, parent.pluginParent).split(sep9);
35110
35118
  if (!isAbsolute15(parent.pluginParent) || resolve15(parent.pluginParent) !== parent.pluginParent || parts.length !== 2 || parts.some((part) => !identifier4(part)) || parts[1] !== parent.namespace || parent.pluginId !== `${parent.namespace}@${parts[0]}` || seen.has(parent.pluginParent))
35111
35119
  refuse3();
35112
35120
  seen.add(parent.pluginParent);
35113
- const parentStat = lstatSync16(parent.pluginParent, { throwIfNoEntry: false });
35121
+ const parentStat = lstatSync17(parent.pluginParent, { throwIfNoEntry: false });
35114
35122
  if (!parentStat?.isDirectory() || parentStat.isSymbolicLink() || realpathSync6(parent.pluginParent) !== parent.pluginParent)
35115
35123
  refuse3();
35116
- const receiptPath = join21(parent.pluginParent, ".codex-remote-plugin-install.json"), receiptStat = lstatSync16(receiptPath, { throwIfNoEntry: false });
35124
+ const receiptPath = join22(parent.pluginParent, ".codex-remote-plugin-install.json"), receiptStat = lstatSync17(receiptPath, { throwIfNoEntry: false });
35117
35125
  let receiptText;
35118
35126
  if (remote) {
35119
35127
  if (!receiptStat?.isFile() || receiptStat.isSymbolicLink() || receiptStat.size > MAX_RECEIPT_BYTES)
@@ -35140,10 +35148,10 @@ function reviewedHookParentProjection(cacheRoot, parents2, read) {
35140
35148
  if (createHash18("sha256").update(marketplaceText).digest("hex") !== parent.marketplaceSha256 || !codexLocalMarketplaceMapsPlugin(marketplaceText, parts[0], parent.namespace))
35141
35149
  refuse3();
35142
35150
  }
35143
- const materializations = readdirSync7(parent.pluginParent).filter((name) => name !== ".codex-remote-plugin-install.json").map((version2) => {
35151
+ const materializations = readdirSync8(parent.pluginParent).filter((name) => name !== ".codex-remote-plugin-install.json").map((version2) => {
35144
35152
  if (!/^[A-Za-z0-9][A-Za-z0-9._+-]{0,127}$/.test(version2))
35145
35153
  refuse3();
35146
- const root = join21(parent.pluginParent, version2), stat2 = lstatSync16(root, { throwIfNoEntry: false });
35154
+ const root = join22(parent.pluginParent, version2), stat2 = lstatSync17(root, { throwIfNoEntry: false });
35147
35155
  if (!stat2?.isDirectory() || stat2.isSymbolicLink() || realpathSync6(root) !== root)
35148
35156
  refuse3();
35149
35157
  const controls = reviewedHookControls(root, read);
@@ -35172,17 +35180,17 @@ function assertParents(cacheRoot, controls, appOnlyParents, hookParents, files,
35172
35180
  const rel = relative6(cacheRoot, file2), parts = rel.split(sep9);
35173
35181
  if (parts.length < 3 || !identifier4(parts[0]) || !identifier4(parts[1]))
35174
35182
  refuse3();
35175
- actual.add(join21(cacheRoot, parts[0], parts[1]));
35183
+ actual.add(join22(cacheRoot, parts[0], parts[1]));
35176
35184
  }
35177
- const actualMarkets = readdirSync7(cacheRoot);
35185
+ const actualMarkets = readdirSync8(cacheRoot);
35178
35186
  if (actualMarkets.length !== expectedMarkets.size || actualMarkets.some((market) => !expectedMarkets.has(market)))
35179
35187
  refuse3();
35180
35188
  for (const market of actualMarkets) {
35181
- const marketPath = join21(cacheRoot, market), marketStat = lstatSync16(marketPath);
35189
+ const marketPath = join22(cacheRoot, market), marketStat = lstatSync17(marketPath);
35182
35190
  if (!identifier4(market) || !marketStat.isDirectory() || marketStat.isSymbolicLink())
35183
35191
  refuse3();
35184
- for (const plugin of readdirSync7(marketPath)) {
35185
- const parent = join21(marketPath, plugin), stat2 = lstatSync16(parent);
35192
+ for (const plugin of readdirSync8(marketPath)) {
35193
+ const parent = join22(marketPath, plugin), stat2 = lstatSync17(parent);
35186
35194
  if (!identifier4(plugin) || !stat2.isDirectory() || stat2.isSymbolicLink())
35187
35195
  refuse3();
35188
35196
  actual.add(parent);
@@ -35194,8 +35202,8 @@ function assertParents(cacheRoot, controls, appOnlyParents, hookParents, files,
35194
35202
  const parts = relative6(cacheRoot, member).split(sep9);
35195
35203
  if (parts.length < 3)
35196
35204
  continue;
35197
- const parent = join21(cacheRoot, parts[0], parts[1]);
35198
- const root = join21(parent, parts[2]);
35205
+ const parent = join22(cacheRoot, parts[0], parts[1]);
35206
+ const root = join22(parent, parts[2]);
35199
35207
  const base = parts[parts.length - 1], folded = foldCodexPluginEntryName(base);
35200
35208
  if (parts.length === 3 && (codexPluginRootCapabilityEntry(base) !== null || isCodexSkillDocumentName(base)))
35201
35209
  refuse3();
@@ -35208,11 +35216,11 @@ function assertParents(cacheRoot, controls, appOnlyParents, hookParents, files,
35208
35216
  refuse3();
35209
35217
  if (parts.some((part) => CODEX_PLUGIN_MANIFEST_DIRECTORIES.includes(foldCodexPluginEntryName(part))) && (parts.length < 4 || parts[3] !== ".codex-plugin" || (parts.length === 4 ? base !== ".codex-plugin" : parts.length !== 5 || base !== "plugin.json")))
35210
35218
  refuse3();
35211
- if ([".app.json", ".mcp.json"].includes(folded) && (parts.length !== 4 || dirname16(member) !== root))
35219
+ if ([".app.json", ".mcp.json"].includes(folded) && (parts.length !== 4 || dirname17(member) !== root))
35212
35220
  refuse3();
35213
35221
  if ([".app.json", ".mcp.json"].includes(folded) && hookParents.some((reviewed) => reviewed.pluginParent === parent))
35214
35222
  refuse3();
35215
- if ((rootEntry === "hooks" || folded === "hooks.json") && (![4, 5].includes(parts.length) || parts[3] !== "hooks" || (parts.length === 4 ? base !== "hooks" : base !== "hooks.json") || !hookParents.some((reviewed) => reviewed.pluginParent === join21(cacheRoot, parts[0], parts[1]))))
35223
+ if ((rootEntry === "hooks" || folded === "hooks.json") && (![4, 5].includes(parts.length) || parts[3] !== "hooks" || (parts.length === 4 ? base !== "hooks" : base !== "hooks.json") || !hookParents.some((reviewed) => reviewed.pluginParent === join22(cacheRoot, parts[0], parts[1]))))
35216
35224
  refuse3();
35217
35225
  }
35218
35226
  }
@@ -35242,14 +35250,14 @@ function assertSkillMaterializations(cacheRoot, controls, files, read) {
35242
35250
  const expectedNames = new Set(rows.map((row) => row.name));
35243
35251
  if (expectedNames.size !== rows.length)
35244
35252
  refuse3();
35245
- const entries = readdirSync7(parent);
35253
+ const entries = readdirSync8(parent);
35246
35254
  let roots = 0;
35247
35255
  for (const entry of entries) {
35248
35256
  if (entry === ".codex-remote-plugin-install.json")
35249
35257
  continue;
35250
35258
  if (!/^[A-Za-z0-9][A-Za-z0-9._+-]{0,127}$/.test(entry))
35251
35259
  refuse3();
35252
- const root = join21(parent, entry), stat2 = lstatSync16(root, { throwIfNoEntry: false });
35260
+ const root = join22(parent, entry), stat2 = lstatSync17(root, { throwIfNoEntry: false });
35253
35261
  if (!stat2?.isDirectory() || stat2.isSymbolicLink() || realpathSync6(root) !== root)
35254
35262
  refuse3();
35255
35263
  const actualControls = readCodexPluginRootControls(root, read);
@@ -35274,8 +35282,8 @@ function assertSkillMaterializations(cacheRoot, controls, files, read) {
35274
35282
  const rel = relative6(cacheRoot, file2).split(sep9);
35275
35283
  if (rel.length < 4)
35276
35284
  refuse3();
35277
- const parent = join21(cacheRoot, rel[0], rel[1]);
35278
- if (!byParent.has(parent) || !expectedByRoot.has(`${byParent.get(parent)[0].pluginId}\x00${join21(parent, rel[2])}`))
35285
+ const parent = join22(cacheRoot, rel[0], rel[1]);
35286
+ if (!byParent.has(parent) || !expectedByRoot.has(`${byParent.get(parent)[0].pluginId}\x00${join22(parent, rel[2])}`))
35279
35287
  refuse3();
35280
35288
  }
35281
35289
  return expectedByRoot;
@@ -35336,11 +35344,11 @@ function captureCodexSemanticCacheWitness(options) {
35336
35344
  const rootNames = new Map;
35337
35345
  for (const document2 of docs) {
35338
35346
  const rel = relative6(options.cacheRoot, document2).split(sep9);
35339
- if (appOnlyParents.some((parent) => parent.pluginParent === join21(options.cacheRoot, rel[0], rel[1])))
35347
+ if (appOnlyParents.some((parent) => parent.pluginParent === join22(options.cacheRoot, rel[0], rel[1])))
35340
35348
  refuse3();
35341
- if (hookParents.some((parent) => parent.pluginParent === join21(options.cacheRoot, rel[0], rel[1])))
35349
+ if (hookParents.some((parent) => parent.pluginParent === join22(options.cacheRoot, rel[0], rel[1])))
35342
35350
  refuse3();
35343
- const documentStat = lstatSync16(document2, { throwIfNoEntry: false });
35351
+ const documentStat = lstatSync17(document2, { throwIfNoEntry: false });
35344
35352
  if (!documentStat?.isFile() || documentStat.isSymbolicLink() || documentStat.size > MAX_DOCUMENT_BYTES)
35345
35353
  refuse3();
35346
35354
  const identity4 = classifyCodexPluginCacheDocument(document2, options.cacheRoot, read);
@@ -35474,8 +35482,8 @@ var init_codex_node_modules = __esm(() => {
35474
35482
  });
35475
35483
 
35476
35484
  // src/lib/managed-policy.ts
35477
- import { closeSync as closeSync14, constants as constants11, fstatSync as fstatSync14, lstatSync as lstatSync17, openSync as openSync14, readSync as readSync8 } from "fs";
35478
- import { join as join22 } from "path";
35485
+ import { closeSync as closeSync14, constants as constants11, fstatSync as fstatSync14, lstatSync as lstatSync18, openSync as openSync14, readSync as readSync8 } from "fs";
35486
+ import { join as join23 } from "path";
35479
35487
  function refusal(reason2 = "is unreadable") {
35480
35488
  return new SkillSelectionError("INVALID_AGENT_POLICY", `The Skills agent loading policy ${reason2}; refusing legacy fallback.`);
35481
35489
  }
@@ -35500,10 +35508,10 @@ function parseManagedSkillPolicy(text2) {
35500
35508
  return value;
35501
35509
  }
35502
35510
  function readManagedSkillPolicySnapshot(dataDir2 = getDataDirReadOnly()) {
35503
- const path = join22(dataDir2, "agent-policy.json");
35511
+ const path = join23(dataDir2, "agent-policy.json");
35504
35512
  let descriptor, observed = false;
35505
35513
  try {
35506
- const stat2 = lstatSync17(path);
35514
+ const stat2 = lstatSync18(path);
35507
35515
  observed = true;
35508
35516
  if (!stat2.isFile() || stat2.isSymbolicLink())
35509
35517
  throw refusal();
@@ -35529,7 +35537,7 @@ function readManagedSkillPolicySnapshot(dataDir2 = getDataDirReadOnly()) {
35529
35537
  return { text: text2, value: parseManagedSkillPolicy(text2) };
35530
35538
  } catch (error61) {
35531
35539
  if (error61.code === "ENOENT" && !observed) {
35532
- if (lstatSync17(path, { throwIfNoEntry: false }) === undefined)
35540
+ if (lstatSync18(path, { throwIfNoEntry: false }) === undefined)
35533
35541
  return null;
35534
35542
  }
35535
35543
  if (error61 instanceof SkillSelectionError)
@@ -35655,8 +35663,8 @@ var init_hook_diagnostics = __esm(() => {
35655
35663
 
35656
35664
  // src/lib/agent-sumi.ts
35657
35665
  import { spawnSync as spawnSync4 } from "child_process";
35658
- import { accessSync, constants as constants12, existsSync as existsSync8, lstatSync as lstatSync18, realpathSync as realpathSync7, statSync as statSync8 } from "fs";
35659
- import { delimiter, isAbsolute as isAbsolute16, join as join23, resolve as resolve16 } from "path";
35666
+ import { accessSync, constants as constants12, existsSync as existsSync8, lstatSync as lstatSync19, realpathSync as realpathSync7, statSync as statSync8 } from "fs";
35667
+ import { delimiter, isAbsolute as isAbsolute16, join as join24, resolve as resolve16 } from "path";
35660
35668
  function recordWithKeys(value, keys) {
35661
35669
  return value !== null && typeof value === "object" && !Array.isArray(value) && Object.keys(value).length === keys.length && keys.every((key2) => Object.hasOwn(value, key2));
35662
35670
  }
@@ -35706,11 +35714,11 @@ function validPathPlan(value, home, cwd) {
35706
35714
  const legacyConfigRoot = value.legacyRoots.config;
35707
35715
  if (typeof configRoot !== "string" || legacyConfigRoot !== null && typeof legacyConfigRoot !== "string")
35708
35716
  return false;
35709
- if (value.configFiles.canonical !== join23(configRoot, "sumi.json") || value.skillRoots.canonical !== join23(configRoot, "skills"))
35717
+ if (value.configFiles.canonical !== join24(configRoot, "sumi.json") || value.skillRoots.canonical !== join24(configRoot, "skills"))
35710
35718
  return false;
35711
35719
  if (legacyConfigRoot === null)
35712
35720
  return value.configFiles.legacy === null && value.skillRoots.legacy === null;
35713
- return value.configFiles.legacy === join23(legacyConfigRoot, "sumi.json") && value.skillRoots.legacy === join23(legacyConfigRoot, "skills");
35721
+ return value.configFiles.legacy === join24(legacyConfigRoot, "sumi.json") && value.skillRoots.legacy === join24(legacyConfigRoot, "skills");
35714
35722
  }
35715
35723
  function sumiPathPlan(home, cwd = process.cwd(), env = process.env) {
35716
35724
  for (const key2 of ["SUMI_CONFIG", "SUMI_CONFIG_CONTENT"])
@@ -35761,7 +35769,7 @@ function selectedConfigDirectory(plan) {
35761
35769
  const canonical9 = plan.roots.config, legacy = plan.legacyRoots.config;
35762
35770
  if (legacy === null)
35763
35771
  return existsSync8(canonical9) ? realpathSync7(canonical9) : canonical9;
35764
- const canonicalStat = lstatSync18(canonical9, { throwIfNoEntry: false }), legacyStat = lstatSync18(legacy, { throwIfNoEntry: false });
35772
+ const canonicalStat = lstatSync19(canonical9, { throwIfNoEntry: false }), legacyStat = lstatSync19(legacy, { throwIfNoEntry: false });
35765
35773
  if (canonicalStat && legacyStat && realpathSync7(canonical9) !== realpathSync7(legacy))
35766
35774
  throw new Error("Sumi config roots conflict; complete native home adoption before Skills integration");
35767
35775
  const selected = canonicalStat ? canonical9 : legacyStat ? legacy : canonical9;
@@ -35776,7 +35784,7 @@ function sumiConfigDirectory(home, env = process.env, cwd = process.cwd()) {
35776
35784
  return selectedConfigDirectory(sumiPathPlan(home, cwd, env));
35777
35785
  }
35778
35786
  function sumiConfigPath(home, cwd = process.cwd(), env = process.env) {
35779
- return join23(sumiConfigDirectory(home, env, cwd), "sumi.json");
35787
+ return join24(sumiConfigDirectory(home, env, cwd), "sumi.json");
35780
35788
  }
35781
35789
  var SUMI_PATH_SELECTORS, SUMI_PATH_KEYS, SUMI_PATH_OUTPUT_LIMIT, SumiPathResolverError;
35782
35790
  var init_agent_sumi = __esm(() => {
@@ -35795,9 +35803,9 @@ var init_agent_sumi = __esm(() => {
35795
35803
  });
35796
35804
 
35797
35805
  // src/lib/codex-hook-trust-files.ts
35798
- import { closeSync as closeSync15, constants as constants13, fstatSync as fstatSync15, fsyncSync as fsyncSync3, lstatSync as lstatSync19, openSync as openSync15, readlinkSync as readlinkSync4, readSync as readSync9, writeFileSync as writeFileSync4 } from "fs";
35806
+ import { closeSync as closeSync15, constants as constants13, fstatSync as fstatSync15, fsyncSync as fsyncSync3, lstatSync as lstatSync20, openSync as openSync15, readlinkSync as readlinkSync4, readSync as readSync9, writeFileSync as writeFileSync4 } from "fs";
35799
35807
  import { createHash as createHash20 } from "crypto";
35800
- import { dirname as dirname17, isAbsolute as isAbsolute17, resolve as resolve17 } from "path";
35808
+ import { dirname as dirname18, isAbsolute as isAbsolute17, resolve as resolve17 } from "path";
35801
35809
  function need8(value, code) {
35802
35810
  if (!value)
35803
35811
  throw new Error(`CODEX_HOOK_TRUST_${code}`);
@@ -35806,18 +35814,18 @@ function trustedAncestorOwner(uid2) {
35806
35814
  return BigInt(uid2) === 0n || BigInt(uid2) === BigInt(process.getuid());
35807
35815
  }
35808
35816
  function safeParents(file2) {
35809
- for (let p = dirname17(file2);; p = dirname17(p)) {
35810
- const s = lstatSync19(p);
35817
+ for (let p = dirname18(file2);; p = dirname18(p)) {
35818
+ const s = lstatSync20(p);
35811
35819
  need8(s.isDirectory() && !s.isSymbolicLink() && trustedAncestorOwner(s.uid), "UNSAFE_PARENT");
35812
35820
  need8((s.mode & 18) === 0 || s.uid === 0 && (s.mode & 512) !== 0, "UNSAFE_PARENT");
35813
- if (dirname17(p) === p)
35821
+ if (dirname18(p) === p)
35814
35822
  break;
35815
35823
  }
35816
35824
  }
35817
35825
  function snapshot(file2, privateFile = false, options = {}) {
35818
35826
  const readOnlyPackage = options.readOnlyPackage === true && !privateFile;
35819
35827
  safeParents(file2);
35820
- const initial = lstatSync19(file2, { bigint: true });
35828
+ const initial = lstatSync20(file2, { bigint: true });
35821
35829
  need8(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");
35822
35830
  need8(initial.size <= 8n * 1024n * 1024n, "FILE_BOUND");
35823
35831
  const fd = openSync15(file2, constants13.O_RDONLY | constants13.O_NOFOLLOW | constants13.O_NONBLOCK);
@@ -35832,7 +35840,7 @@ function snapshot(file2, privateFile = false, options = {}) {
35832
35840
  break;
35833
35841
  length += n2;
35834
35842
  }
35835
- need8(length === Number(before.size) && sameStat(before, fstatSync15(fd, { bigint: true })) && sameStat(before, lstatSync19(file2, { bigint: true })), "INPUT_CHANGED");
35843
+ need8(length === Number(before.size) && sameStat(before, fstatSync15(fd, { bigint: true })) && sameStat(before, lstatSync20(file2, { bigint: true })), "INPUT_CHANGED");
35836
35844
  const content = bytes.subarray(0, length), text2 = new TextDecoder("utf-8", { fatal: true }).decode(content);
35837
35845
  return { file: file2, privateFile, readOnlyPackage, text: text2, bytes: content, stat: before, sha256: createHash20("sha256").update(content).digest("hex") };
35838
35846
  } finally {
@@ -35899,25 +35907,25 @@ var init_runtime_launcher = __esm(() => {
35899
35907
 
35900
35908
  // src/lib/retained-review-artifacts.ts
35901
35909
  import { createHash as createHash21 } from "crypto";
35902
- import { constants as constants14, closeSync as closeSync16, fstatSync as fstatSync16, fsyncSync as fsyncSync4, lstatSync as lstatSync20, mkdirSync as mkdirSync6, openSync as openSync16, readSync as readSync10, writeSync as writeSync3 } from "fs";
35903
- import { dirname as dirname18, isAbsolute as isAbsolute18, join as join24, resolve as resolve18, sep as sep10 } from "path";
35910
+ import { constants as constants14, closeSync as closeSync16, fstatSync as fstatSync16, fsyncSync as fsyncSync4, lstatSync as lstatSync21, mkdirSync as mkdirSync6, openSync as openSync16, readSync as readSync10, writeSync as writeSync3 } from "fs";
35911
+ import { dirname as dirname19, isAbsolute as isAbsolute18, join as join25, resolve as resolve18, sep as sep10 } from "path";
35904
35912
  function keys(value, names) {
35905
35913
  return Boolean(value && typeof value === "object" && !Array.isArray(value) && Object.keys(value).length === names.length && names.every((name) => Object.hasOwn(value, name)));
35906
35914
  }
35907
35915
  function safe4(path) {
35908
35916
  need9(typeof path === "string" && path.length <= AGENT_POLICY_LIMITS.pathCharacters && isAbsolute18(path) && resolve18(path) === path && !/[\x00-\x1f\x7f]/.test(path));
35909
- for (let cursor = path;; cursor = dirname18(cursor)) {
35910
- const stat2 = lstatSync20(cursor, { throwIfNoEntry: false });
35917
+ for (let cursor = path;; cursor = dirname19(cursor)) {
35918
+ const stat2 = lstatSync21(cursor, { throwIfNoEntry: false });
35911
35919
  need9(!stat2?.isSymbolicLink());
35912
35920
  if (cursor !== path && stat2)
35913
35921
  need9(stat2.isDirectory());
35914
- if (dirname18(cursor) === cursor)
35922
+ if (dirname19(cursor) === cursor)
35915
35923
  break;
35916
35924
  }
35917
35925
  }
35918
35926
  function readExact(path) {
35919
35927
  safe4(path);
35920
- const before = lstatSync20(path, { throwIfNoEntry: false });
35928
+ const before = lstatSync21(path, { throwIfNoEntry: false });
35921
35929
  need9(before?.isFile() && before.nlink === 1 && before.size <= AGENT_POLICY_LIMITS.discoveryRawSourceBytes && (before.mode & 63) === 0 && (process.getuid === undefined || before.uid === process.getuid()));
35922
35930
  const fd = openSync16(path, constants14.O_RDONLY | constants14.O_NOFOLLOW | constants14.O_NONBLOCK);
35923
35931
  try {
@@ -35931,7 +35939,7 @@ function readExact(path) {
35931
35939
  offset += count;
35932
35940
  }
35933
35941
  need9(readSync10(fd, Buffer.alloc(1), 0, 1, null) === 0);
35934
- const after = fstatSync16(fd), current = lstatSync20(path, { throwIfNoEntry: false });
35942
+ const after = fstatSync16(fd), current = lstatSync21(path, { throwIfNoEntry: false });
35935
35943
  safe4(path);
35936
35944
  need9(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);
35937
35945
  const text2 = new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(bytes);
@@ -35948,20 +35956,20 @@ function catalogDigest(text2) {
35948
35956
  } catch {
35949
35957
  return refuse4();
35950
35958
  }
35951
- need9(catalog && typeof catalog === "object" && !Array.isArray(catalog) && Object.keys(catalog).every((key2) => ["version", "cwd", "skills", "plugins"].includes(key2)) && typeof catalog.version === "string" && supportsCodexNativeCapability(catalog.version, "installed-plugin-review"));
35959
+ need9(catalog && typeof catalog === "object" && !Array.isArray(catalog) && Object.keys(catalog).every((key2) => ["version", "cwd", "skills", "plugins", "remoteReceipts"].includes(key2)) && typeof catalog.version === "string" && supportsCodexNativeCapability(catalog.version, "installed-plugin-review"));
35952
35960
  const skills = projectCodexNativeSkillCatalog({ data: [{ cwd: catalog.cwd, errors: [], skills: catalog.skills }] }, catalog.cwd);
35953
35961
  const plugins = catalog.plugins === undefined ? undefined : projectCodexInstalledPluginEntries(catalog.plugins);
35954
35962
  return sha3(JSON.stringify({ version: catalog.version, cwd: catalog.cwd, skills, ...plugins === undefined ? {} : { plugins } }));
35955
35963
  }
35956
35964
  function retainedArtifactPath(metadata) {
35957
- return join24(metadata.storeRoot, "agent-discovery", "artifacts", metadata.sha256, "catalog.json");
35965
+ return join25(metadata.storeRoot, "agent-discovery", "artifacts", metadata.sha256, "catalog.json");
35958
35966
  }
35959
35967
  function validRetainedArtifact(value) {
35960
35968
  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" && isAbsolute18(path) && resolve18(path) === path && path.length <= AGENT_POLICY_LIMITS.pathCharacters && !/[\x00-\x1f\x7f]/.test(path));
35961
35969
  }
35962
35970
  function privateStore(storeRoot) {
35963
35971
  safe4(storeRoot);
35964
- const stat2 = lstatSync20(storeRoot, { throwIfNoEntry: false });
35972
+ const stat2 = lstatSync21(storeRoot, { throwIfNoEntry: false });
35965
35973
  need9(!stat2 || stat2.isDirectory() && (stat2.mode & 18) === 0 && (process.getuid === undefined || stat2.uid === process.getuid()));
35966
35974
  }
35967
35975
  function verifyRetainedReviewArtifact(source, storeRoot) {
@@ -35970,8 +35978,8 @@ function verifyRetainedReviewArtifact(source, storeRoot) {
35970
35978
  privateStore(artifact.storeRoot);
35971
35979
  const text2 = readExact(source.path);
35972
35980
  need9(sha3(text2) === artifact.sha256 && catalogDigest(text2) === artifact.catalogSha256);
35973
- for (let parent = dirname18(source.path);parent !== artifact.storeRoot; parent = dirname18(parent)) {
35974
- const stat2 = lstatSync20(parent);
35981
+ for (let parent = dirname19(source.path);parent !== artifact.storeRoot; parent = dirname19(parent)) {
35982
+ const stat2 = lstatSync21(parent);
35975
35983
  need9(stat2.isDirectory() && (stat2.mode & 63) === 0 && (process.getuid === undefined || stat2.uid === process.getuid()));
35976
35984
  }
35977
35985
  }
@@ -35991,6 +35999,8 @@ var init_retained_review_artifacts = __esm(() => {
35991
35999
  var init_agent_integration = __esm(() => {
35992
36000
  init_sumi_settings_witness();
35993
36001
  init_codex_corpus_write();
36002
+ init_codex_hook_rpc();
36003
+ init_codex_native_config();
35994
36004
  init_codex_plugin_skill_controls();
35995
36005
  init_codex_native_skill_policy();
35996
36006
  init_codex_native_skill_catalog();
@@ -36050,20 +36060,20 @@ var init_skill_aliases = __esm(() => {
36050
36060
  });
36051
36061
 
36052
36062
  // src/lib/project-state.ts
36053
- import { existsSync as existsSync9, mkdirSync as mkdirSync7, readFileSync as readFileSync14, writeFileSync as writeFileSync5 } from "fs";
36054
- import { join as join25 } from "path";
36063
+ import { existsSync as existsSync9, mkdirSync as mkdirSync7, readFileSync as readFileSync15, writeFileSync as writeFileSync5 } from "fs";
36064
+ import { join as join26 } from "path";
36055
36065
  function getProjectStateDir(targetDir = process.cwd()) {
36056
- return join25(targetDir, SKILLS_PROJECT_DIR);
36066
+ return join26(targetDir, SKILLS_PROJECT_DIR);
36057
36067
  }
36058
36068
  function getProjectConfigPath(targetDir = process.cwd()) {
36059
- return join25(getProjectStateDir(targetDir), PROJECT_CONFIG_FILE);
36069
+ return join26(getProjectStateDir(targetDir), PROJECT_CONFIG_FILE);
36060
36070
  }
36061
36071
  function loadProjectConfig(targetDir = process.cwd()) {
36062
36072
  const path = getProjectConfigPath(targetDir);
36063
36073
  if (!existsSync9(path))
36064
36074
  return null;
36065
36075
  try {
36066
- return normalizeProjectConfig(JSON.parse(readFileSync14(path, "utf-8")));
36076
+ return normalizeProjectConfig(JSON.parse(readFileSync15(path, "utf-8")));
36067
36077
  } catch {
36068
36078
  return null;
36069
36079
  }
@@ -36171,8 +36181,8 @@ var init_project_state = __esm(() => {
36171
36181
  });
36172
36182
 
36173
36183
  // src/lib/installer.ts
36174
- import { existsSync as existsSync10, readFileSync as readFileSync15, rmSync as rmSync2 } from "fs";
36175
- import { join as join26 } from "path";
36184
+ import { existsSync as existsSync10, readFileSync as readFileSync16, rmSync as rmSync2 } from "fs";
36185
+ import { join as join27 } from "path";
36176
36186
  import { homedir as homedir2 } from "os";
36177
36187
  function getSkillPath(name) {
36178
36188
  const skillName = normalizeSkillName(getCanonicalSkillName(name));
@@ -36182,7 +36192,7 @@ function getSkillPath(name) {
36182
36192
  const extensionPath = findExtensionSkillPath(skillName);
36183
36193
  if (extensionPath)
36184
36194
  return extensionPath;
36185
- return join26(getPortableSkillsRoot(), skillName);
36195
+ return join27(getPortableSkillsRoot(), skillName);
36186
36196
  }
36187
36197
  function getCanonicalSkillName(name) {
36188
36198
  return getSkill(name)?.name ?? resolveSkillAlias(normalizeSkillSlug(name));
@@ -36236,11 +36246,11 @@ function getAgentSkillsDir(agent, scope = "global", projectDir) {
36236
36246
  const base = projectDir || process.cwd();
36237
36247
  switch (agent) {
36238
36248
  case "pi":
36239
- return scope === "project" ? join26(base, ".pi", "skills") : join26(homedir2(), ".pi", "agent", "skills");
36249
+ return scope === "project" ? join27(base, ".pi", "skills") : join27(homedir2(), ".pi", "agent", "skills");
36240
36250
  case "opencode":
36241
- return scope === "project" ? join26(base, ".opencode", "skills") : join26(homedir2(), ".config", "opencode", "skills");
36251
+ return scope === "project" ? join27(base, ".opencode", "skills") : join27(homedir2(), ".config", "opencode", "skills");
36242
36252
  default:
36243
- return scope === "project" ? join26(base, `.${agent}`, "skills") : join26(homedir2(), `.${agent}`, "skills");
36253
+ return scope === "project" ? join27(base, `.${agent}`, "skills") : join27(homedir2(), `.${agent}`, "skills");
36244
36254
  }
36245
36255
  }
36246
36256
  function warnMissingDependencies(name, targetDir) {
@@ -36255,11 +36265,11 @@ function warnMissingDependencies(name, targetDir) {
36255
36265
  }
36256
36266
  }
36257
36267
  function readBundledSkillVersion(name) {
36258
- const pkgPath = join26(getSkillPath(name), "package.json");
36268
+ const pkgPath = join27(getSkillPath(name), "package.json");
36259
36269
  if (!existsSync10(pkgPath))
36260
36270
  return "unknown";
36261
36271
  try {
36262
- const pkg = JSON.parse(readFileSync15(pkgPath, "utf-8"));
36272
+ const pkg = JSON.parse(readFileSync16(pkgPath, "utf-8"));
36263
36273
  return pkg.version || "unknown";
36264
36274
  } catch {
36265
36275
  return "unknown";
@@ -36324,16 +36334,16 @@ var init_skill_doc_file = __esm(() => {
36324
36334
  });
36325
36335
 
36326
36336
  // src/lib/skillinfo.ts
36327
- import { existsSync as existsSync11, readFileSync as readFileSync16 } from "fs";
36328
- import { join as join27 } from "path";
36337
+ import { existsSync as existsSync11, readFileSync as readFileSync17 } from "fs";
36338
+ import { join as join28 } from "path";
36329
36339
  function isInstructionSkillDir(skillPath, meta3) {
36330
36340
  if (meta3?.kind === "instruction")
36331
36341
  return true;
36332
- const skillMdPath = join27(skillPath, "SKILL.md");
36342
+ const skillMdPath = join28(skillPath, "SKILL.md");
36333
36343
  if (!existsSync11(skillMdPath))
36334
36344
  return false;
36335
36345
  try {
36336
- return parseSkillFrontmatter(readFileSync16(skillMdPath, "utf-8"))?.kind === "instruction";
36346
+ return parseSkillFrontmatter(readFileSync17(skillMdPath, "utf-8"))?.kind === "instruction";
36337
36347
  } catch {
36338
36348
  return false;
36339
36349
  }
@@ -36343,9 +36353,9 @@ function getSkillDocs(name) {
36343
36353
  if (!existsSync11(skillPath))
36344
36354
  return null;
36345
36355
  return {
36346
- skillMd: readIfExists(join27(skillPath, "SKILL.md")),
36347
- readme: readIfExists(join27(skillPath, "README.md")),
36348
- claudeMd: readIfExists(join27(skillPath, "CLAUDE.md"))
36356
+ skillMd: readIfExists(join28(skillPath, "SKILL.md")),
36357
+ readme: readIfExists(join28(skillPath, "README.md")),
36358
+ claudeMd: readIfExists(join28(skillPath, "CLAUDE.md"))
36349
36359
  };
36350
36360
  }
36351
36361
  function getSkillBestDoc(name, file2) {
@@ -36361,14 +36371,14 @@ function getSkillRequirements(name) {
36361
36371
  return null;
36362
36372
  const texts = [];
36363
36373
  for (const file2 of ["SKILL.md", "README.md", "CLAUDE.md", ".env.example", ".env.local.example"]) {
36364
- const content = readIfExists(join27(skillPath, file2));
36374
+ const content = readIfExists(join28(skillPath, file2));
36365
36375
  if (content)
36366
36376
  texts.push(content);
36367
36377
  }
36368
36378
  const meta3 = getSkill(name);
36369
36379
  let dependencies = {};
36370
36380
  try {
36371
- dependencies = JSON.parse(readFileSync16(join27(skillPath, "package.json"), "utf8")).dependencies || {};
36381
+ dependencies = JSON.parse(readFileSync17(join28(skillPath, "package.json"), "utf8")).dependencies || {};
36372
36382
  } catch {}
36373
36383
  return getSkillRequirementsFromContent(name, texts, dependencies, meta3);
36374
36384
  }
@@ -36430,13 +36440,13 @@ async function runSkill(name, args, options = {}) {
36430
36440
  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'.`
36431
36441
  };
36432
36442
  }
36433
- const pkgPath = join27(skillPath, "package.json");
36443
+ const pkgPath = join28(skillPath, "package.json");
36434
36444
  if (!existsSync11(pkgPath)) {
36435
36445
  return { exitCode: 1, error: `No package.json in skill '${name}'` };
36436
36446
  }
36437
36447
  let entryPoint2;
36438
36448
  try {
36439
- const pkg = JSON.parse(readFileSync16(pkgPath, "utf-8"));
36449
+ const pkg = JSON.parse(readFileSync17(pkgPath, "utf-8"));
36440
36450
  if (pkg.bin) {
36441
36451
  const binValues = Object.values(pkg.bin);
36442
36452
  entryPoint2 = binValues[0];
@@ -36450,12 +36460,12 @@ async function runSkill(name, args, options = {}) {
36450
36460
  } catch {
36451
36461
  return { exitCode: 1, error: `Failed to parse package.json for skill '${name}'` };
36452
36462
  }
36453
- const entryPath = join27(skillPath, entryPoint2);
36463
+ const entryPath = join28(skillPath, entryPoint2);
36454
36464
  if (!existsSync11(entryPath)) {
36455
36465
  return { exitCode: 1, error: `Entry point '${entryPoint2}' not found in skill '${name}'` };
36456
36466
  }
36457
36467
  const env = { ...process.env, ...options.env };
36458
- if (!existsSync11(join27(skillPath, "node_modules")) || hasDependencyPreparationMarker(skillPath)) {
36468
+ if (!existsSync11(join28(skillPath, "node_modules")) || hasDependencyPreparationMarker(skillPath)) {
36459
36469
  const failure = await prepareSkillDependencies(skillPath, env, options.preparationTimeoutMs);
36460
36470
  if (failure)
36461
36471
  return failure;
@@ -36481,7 +36491,7 @@ async function runSkill(name, args, options = {}) {
36481
36491
  function detectProjectSkills(cwd = process.cwd()) {
36482
36492
  let pkg;
36483
36493
  try {
36484
- pkg = JSON.parse(readFileSync16(join27(cwd, "package.json"), "utf8"));
36494
+ pkg = JSON.parse(readFileSync17(join28(cwd, "package.json"), "utf8"));
36485
36495
  } catch {
36486
36496
  return { detected: [], recommended: [] };
36487
36497
  }
@@ -36518,7 +36528,7 @@ function extractEnvVars(text2) {
36518
36528
  function readIfExists(path) {
36519
36529
  try {
36520
36530
  if (existsSync11(path)) {
36521
- return readFileSync16(path, "utf-8");
36531
+ return readFileSync17(path, "utf-8");
36522
36532
  }
36523
36533
  } catch {}
36524
36534
  return null;
@@ -36846,7 +36856,7 @@ var init_selected_manifest = __esm(() => {
36846
36856
  });
36847
36857
 
36848
36858
  // src/lib/plugin-admission.ts
36849
- import { isAbsolute as isAbsolute19, join as join28, resolve as resolve19 } from "path";
36859
+ import { isAbsolute as isAbsolute19, join as join29, resolve as resolve19 } from "path";
36850
36860
  function validatePluginTarget(value) {
36851
36861
  pluginKeys(value, ["schemaVersion", "pluginId", "registrations", "native", "resolver"]);
36852
36862
  pluginNeed(value.schemaVersion === 1, "Invalid plugin admission target");
@@ -37007,12 +37017,12 @@ function pluginResolverCommand(binding) {
37007
37017
  }
37008
37018
  function pluginBindingPath(storeRoot, id) {
37009
37019
  pluginNeed(/^[a-f0-9]{64}$/.test(id), "Invalid plugin binding identifier");
37010
- return join28(storeRoot, "bindings", `${id}.json`);
37020
+ return join29(storeRoot, "bindings", `${id}.json`);
37011
37021
  }
37012
37022
  function pluginReceiptPath(storeRoot, id, digest2) {
37013
37023
  pluginNeed(/^[a-f0-9]{64}$/.test(id), "Invalid plugin binding identifier");
37014
37024
  pluginDigest(digest2);
37015
- return join28(storeRoot, "receipts", id, `${digest2.slice(7)}.json`);
37025
+ return join29(storeRoot, "receipts", id, `${digest2.slice(7)}.json`);
37016
37026
  }
37017
37027
  function readPluginBinding(storeRoot, id) {
37018
37028
  const value = readPluginJson(pluginBindingPath(storeRoot, id));
@@ -37032,7 +37042,7 @@ function readPluginAdmissionReceipt(storeRoot, id, digest2) {
37032
37042
  pluginNeed(receipt.plan.bindingId === id && receipt.plan.planDigest === digest2, "Plugin receipt identity differs from its filename");
37033
37043
  const binding = readPluginBinding(storeRoot, id);
37034
37044
  pluginNeed(canonicalJson(binding) === canonicalJson(receipt.plan.binding) && receipt.plan.sourceCommand === pluginResolverCommand(binding), "Plugin receipt binding changed");
37035
- pluginNeed(receipt.materializedPath === join28(storeRoot, "objects", id, digest2.slice(7)), "Plugin receipt points outside its immutable materialization");
37045
+ pluginNeed(receipt.materializedPath === join29(storeRoot, "objects", id, digest2.slice(7)), "Plugin receipt points outside its immutable materialization");
37036
37046
  pluginText(receipt.admittedAt, 64);
37037
37047
  pluginNeed(Number.isFinite(Date.parse(receipt.admittedAt)), "Invalid plugin admission time");
37038
37048
  return receipt;
@@ -37049,8 +37059,8 @@ var init_plugin_admission = __esm(() => {
37049
37059
  });
37050
37060
 
37051
37061
  // src/lib/plugin-discovery.ts
37052
- import { closeSync as closeSync17, constants as constants15, fstatSync as fstatSync17, lstatSync as lstatSync21, openSync as openSync17, opendirSync as opendirSync3, readSync as readSync11 } from "fs";
37053
- import { basename as basename10, dirname as dirname19, isAbsolute as isAbsolute20, join as join29, resolve as resolve20 } from "path";
37062
+ import { closeSync as closeSync17, constants as constants15, fstatSync as fstatSync17, lstatSync as lstatSync22, openSync as openSync17, opendirSync as opendirSync3, readSync as readSync11 } from "fs";
37063
+ import { basename as basename11, dirname as dirname20, isAbsolute as isAbsolute20, join as join30, resolve as resolve20 } from "path";
37054
37064
  function validateManagedPluginWitnesses(value) {
37055
37065
  pluginNeed(Array.isArray(value) && value.length > 0 && value.length <= PLUGIN_PROJECTION_LIMITS.registrations, "Invalid managed plugin witness collection");
37056
37066
  const seen = new Set;
@@ -37065,15 +37075,15 @@ function validateManagedPluginWitnesses(value) {
37065
37075
  function safe5(path) {
37066
37076
  pluginText(path);
37067
37077
  pluginNeed(isAbsolute20(path) && resolve20(path) === path, "Invalid plugin registry path");
37068
- for (let at = path;; at = dirname19(at)) {
37069
- pluginNeed(!lstatSync21(at, { throwIfNoEntry: false })?.isSymbolicLink(), "Plugin registry path traverses a symlink");
37070
- if (at === dirname19(at))
37078
+ for (let at = path;; at = dirname20(at)) {
37079
+ pluginNeed(!lstatSync22(at, { throwIfNoEntry: false })?.isSymbolicLink(), "Plugin registry path traverses a symlink");
37080
+ if (at === dirname20(at))
37071
37081
  break;
37072
37082
  }
37073
37083
  }
37074
37084
  function readRegistry(path) {
37075
37085
  safe5(path);
37076
- const initial = lstatSync21(path);
37086
+ const initial = lstatSync22(path);
37077
37087
  pluginNeed(initial.isFile() && initial.size <= 1024 * 1024, "Plugin registry is not a bounded regular file");
37078
37088
  const fd = openSync17(path, constants15.O_RDONLY | constants15.O_NOFOLLOW | constants15.O_NONBLOCK);
37079
37089
  try {
@@ -37087,7 +37097,7 @@ function readRegistry(path) {
37087
37097
  break;
37088
37098
  length += count;
37089
37099
  }
37090
- const after = fstatSync17(fd), current = lstatSync21(path);
37100
+ const after = fstatSync17(fd), current = lstatSync22(path);
37091
37101
  safe5(path);
37092
37102
  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");
37093
37103
  let value;
@@ -37117,7 +37127,7 @@ function hashManagedPluginRegistry(path, managed) {
37117
37127
  seen.add(target.pluginId);
37118
37128
  const rows = plugins[target.pluginId];
37119
37129
  pluginNeed(Array.isArray(rows) && rows.length === target.registrations.length, "Managed plugin registration membership changed");
37120
- const [name, market] = target.pluginId.split("@"), cacheRoot = join29(dirname19(path), "cache", market, name);
37130
+ const [name, market] = target.pluginId.split("@"), cacheRoot = join30(dirname20(path), "cache", market, name);
37121
37131
  const scopes = new Set, approvals = new Map, currentFiles = new Map;
37122
37132
  plugins[target.pluginId] = rows.map((row) => {
37123
37133
  pluginNeed(pluginObject(row), "Invalid managed plugin registration");
@@ -37130,10 +37140,10 @@ function hashManagedPluginRegistry(path, managed) {
37130
37140
  pluginText(row.sourceProducerPath);
37131
37141
  pluginText(row.lastUpdated, 64);
37132
37142
  pluginNeed(Number.isFinite(Date.parse(row.lastUpdated)), "Invalid managed plugin update timestamp");
37133
- pluginNeed(/^(?:[A-Za-z0-9][A-Za-z0-9._+-]*-)?[a-f0-9]{12}$/.test(row.version) && row.installPath === join29(cacheRoot, row.version), "Managed plugin cache path or version is outside its registration");
37143
+ pluginNeed(/^(?:[A-Za-z0-9][A-Za-z0-9._+-]*-)?[a-f0-9]{12}$/.test(row.version) && row.installPath === join30(cacheRoot, row.version), "Managed plugin cache path or version is outside its registration");
37134
37144
  const approval = (producer) => {
37135
37145
  pluginText(producer);
37136
- const digest2 = `sha256:${basename10(producer)}`;
37146
+ const digest2 = `sha256:${basename11(producer)}`;
37137
37147
  const receipt2 = readPluginAdmissionReceipt(witness.storeRoot, witness.bindingId, digest2);
37138
37148
  pluginNeed(receipt2.materializedPath === producer, "Managed producer path is not an approved immutable projection");
37139
37149
  if (!verified.has(producer)) {
@@ -37160,7 +37170,7 @@ function hashManagedPluginRegistry(path, managed) {
37160
37170
  return Object.fromEntries(Object.entries(row).filter(([key2]) => !["version", "installPath", "sourceProducerPath", "previousProducerPaths", "lastUpdated"].includes(key2)));
37161
37171
  });
37162
37172
  safe5(cacheRoot);
37163
- const before = lstatSync21(cacheRoot);
37173
+ const before = lstatSync22(cacheRoot);
37164
37174
  pluginNeed(before.isDirectory(), "Invalid managed plugin cache root");
37165
37175
  const directory = opendirSync3(cacheRoot), names = [];
37166
37176
  try {
@@ -37173,17 +37183,17 @@ function hashManagedPluginRegistry(path, managed) {
37173
37183
  directory.closeSync();
37174
37184
  }
37175
37185
  for (const version2 of names.sort()) {
37176
- const files = pluginFileWitnesses(snapshotPluginTree(join29(cacheRoot, version2), { nativeRuntime: `claude-${target.native.version}` }));
37186
+ const files = pluginFileWitnesses(snapshotPluginTree(join30(cacheRoot, version2), { nativeRuntime: `claude-${target.native.version}` }));
37177
37187
  verifiedBytes += files.reduce((total, file2) => total + file2.size, 0);
37178
37188
  pluginNeed(verifiedBytes <= 256 * 1024 * 1024, "Managed plugin verification exceeds its aggregate byte budget");
37179
37189
  const serialized = JSON.stringify(files);
37180
- const expected = currentFiles.get(join29(cacheRoot, version2));
37190
+ const expected = currentFiles.get(join30(cacheRoot, version2));
37181
37191
  pluginNeed(expected === undefined || serialized === expected, "Current native cache differs from its exact registered producer receipt");
37182
37192
  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");
37183
37193
  }
37184
37194
  for (const row of rows)
37185
37195
  pluginNeed(names.includes(row.version), "Managed native plugin installation is missing");
37186
- const after = lstatSync21(cacheRoot);
37196
+ const after = lstatSync22(cacheRoot);
37187
37197
  safe5(cacheRoot);
37188
37198
  pluginNeed(before.dev === after.dev && before.ino === after.ino && before.mtimeMs === after.mtimeMs && before.ctimeMs === after.ctimeMs, "Managed cache version membership changed during verification");
37189
37199
  }
@@ -37198,8 +37208,8 @@ var init_plugin_discovery = __esm(() => {
37198
37208
 
37199
37209
  // src/lib/claude-marketplace-registry.ts
37200
37210
  import { createHash as createHash22 } from "crypto";
37201
- import { closeSync as closeSync18, constants as constants16, fstatSync as fstatSync18, lstatSync as lstatSync22, openSync as openSync18, readSync as readSync12 } from "fs";
37202
- import { basename as basename11, dirname as dirname20, isAbsolute as isAbsolute21, resolve as resolve21 } from "path";
37211
+ import { closeSync as closeSync18, constants as constants16, fstatSync as fstatSync18, lstatSync as lstatSync23, openSync as openSync18, readSync as readSync12 } from "fs";
37212
+ import { basename as basename12, dirname as dirname21, isAbsolute as isAbsolute21, resolve as resolve21 } from "path";
37203
37213
  function need10(value, reason2) {
37204
37214
  if (!value)
37205
37215
  throw new Error(`Claude marketplace registry ${reason2}`);
@@ -37209,19 +37219,19 @@ function absolutePath4(value) {
37209
37219
  }
37210
37220
  function parents2(path) {
37211
37221
  const result = [];
37212
- for (let at = dirname20(path);; at = dirname20(at)) {
37213
- const stat2 = lstatSync22(at, { bigint: true });
37222
+ for (let at = dirname21(path);; at = dirname21(at)) {
37223
+ const stat2 = lstatSync23(at, { bigint: true });
37214
37224
  need10(stat2.isDirectory() && !stat2.isSymbolicLink(), "path traverses a symlink or non-directory");
37215
37225
  result.push([at, stat2]);
37216
- if (at === dirname20(at))
37226
+ if (at === dirname21(at))
37217
37227
  return result;
37218
37228
  }
37219
37229
  }
37220
37230
  function readRegistry2(path, budget2) {
37221
37231
  absolutePath4(path);
37222
- need10(basename11(path) === "known_marketplaces.json", "requires known_marketplaces.json");
37232
+ need10(basename12(path) === "known_marketplaces.json", "requires known_marketplaces.json");
37223
37233
  need10(Number.isSafeInteger(budget2.remaining) && budget2.remaining >= 0, "has an invalid byte budget");
37224
- const ancestors2 = parents2(path), initial = lstatSync22(path, { bigint: true });
37234
+ const ancestors2 = parents2(path), initial = lstatSync23(path, { bigint: true });
37225
37235
  need10(initial.isFile() && !initial.isSymbolicLink() && initial.size <= BigInt(CLAUDE_MARKETPLACE_REGISTRY_LIMITS.bytes), "is not a bounded regular file");
37226
37236
  need10(initial.size <= BigInt(budget2.remaining), "exceeds its aggregate byte limit");
37227
37237
  const fd = openSync18(path, constants16.O_RDONLY | constants16.O_NOFOLLOW | constants16.O_NONBLOCK);
@@ -37236,10 +37246,10 @@ function readRegistry2(path, budget2) {
37236
37246
  break;
37237
37247
  length += count;
37238
37248
  }
37239
- const after = fstatSync18(fd, { bigint: true }), current = lstatSync22(path, { bigint: true });
37249
+ const after = fstatSync18(fd, { bigint: true }), current = lstatSync23(path, { bigint: true });
37240
37250
  need10(current.isFile() && sameFile2(opened, after) && sameFile2(after, current) && BigInt(length) === opened.size, "changed during read");
37241
37251
  for (const [ancestor, before] of ancestors2) {
37242
- const now = lstatSync22(ancestor, { bigint: true });
37252
+ const now = lstatSync23(ancestor, { bigint: true });
37243
37253
  need10(now.isDirectory() && before.dev === now.dev && before.ino === now.ino && before.mode === now.mode, "parent changed during read");
37244
37254
  }
37245
37255
  budget2.remaining -= length;
@@ -37426,8 +37436,8 @@ var init_codex_hook_discovery_recovery = __esm(() => {
37426
37436
 
37427
37437
  // src/lib/agent-discovery.ts
37428
37438
  import { createHash as createHash24 } from "crypto";
37429
- import { lstatSync as lstatSync23, readFileSync as readFileSync17, readdirSync as readdirSync8, realpathSync as realpathSync8 } from "fs";
37430
- import { basename as basename12, dirname as dirname21, isAbsolute as isAbsolute22, join as join30, relative as relative7, resolve as resolve22, sep as sep11 } from "path";
37439
+ import { lstatSync as lstatSync24, readFileSync as readFileSync18, readdirSync as readdirSync9, realpathSync as realpathSync8 } from "fs";
37440
+ import { basename as basename13, dirname as dirname22, isAbsolute as isAbsolute22, join as join31, relative as relative7, resolve as resolve22, sep as sep11 } from "path";
37431
37441
  import { isDeepStrictEqual as isDeepStrictEqual5 } from "util";
37432
37442
  function discoveryExecutable(agent) {
37433
37443
  const command = DISCOVERY_RUNTIME_COMMANDS[agent];
@@ -37450,10 +37460,10 @@ function parseConfig(text2, path, toml = false) {
37450
37460
  function safe6(path) {
37451
37461
  if (!isAbsolute22(path) || path.includes("\x00"))
37452
37462
  throw new Error("Expected an absolute native discovery path");
37453
- for (let cursor = path;; cursor = dirname21(cursor)) {
37454
- if (lstatSync23(cursor, { throwIfNoEntry: false })?.isSymbolicLink())
37463
+ for (let cursor = path;; cursor = dirname22(cursor)) {
37464
+ if (lstatSync24(cursor, { throwIfNoEntry: false })?.isSymbolicLink())
37455
37465
  throw new Error(`Refusing symlink native discovery input: ${cursor}`);
37456
- if (dirname21(cursor) === cursor)
37466
+ if (dirname22(cursor) === cursor)
37457
37467
  break;
37458
37468
  }
37459
37469
  }
@@ -37461,19 +37471,19 @@ function read(path, changes) {
37461
37471
  safe6(path);
37462
37472
  if (changes?.has(path))
37463
37473
  return changes.get(path);
37464
- const stat2 = lstatSync23(path, { throwIfNoEntry: false });
37474
+ const stat2 = lstatSync24(path, { throwIfNoEntry: false });
37465
37475
  if (!stat2)
37466
37476
  return null;
37467
37477
  if (!stat2.isFile() || stat2.size > 16 * 1024 * 1024)
37468
37478
  throw new Error(`Unsupported or oversized native discovery input: ${path}`);
37469
- return readFileSync17(path, "utf8");
37479
+ return readFileSync18(path, "utf8");
37470
37480
  }
37471
37481
  function assertReviewedClaudeCacheClosures(home, config2, review, canonical9) {
37472
37482
  const enabledIds = Object.entries(config2.enabledPlugins ?? {}).filter(([, enabled]) => enabled === true).map(([id]) => id);
37473
37483
  if (enabledIds.length === 0)
37474
37484
  return;
37475
- const registryPath = canonical9(join30(home, ".claude/plugins/installed_plugins.json"));
37476
- const cacheAliasRoot = join30(home, ".claude/plugins/cache");
37485
+ const registryPath = canonical9(join31(home, ".claude/plugins/installed_plugins.json"));
37486
+ const cacheAliasRoot = join31(home, ".claude/plugins/cache");
37477
37487
  const cacheRoot = canonical9(cacheAliasRoot);
37478
37488
  const registryText = read(registryPath);
37479
37489
  if (registryText === null)
@@ -37494,7 +37504,7 @@ function assertReviewedClaudeCacheClosures(home, config2, review, canonical9) {
37494
37504
  throw new Error("Reviewed Claude enabled plugin registration requires an object with an installPath string");
37495
37505
  }
37496
37506
  if ([cacheAliasRoot, cacheRoot].some((root) => row.installPath === root || row.installPath.startsWith(root + sep11))) {
37497
- if (!cachePath(row.installPath) || row.installPath.length > AGENT_POLICY_LIMITS.pathCharacters || row.version !== undefined && (typeof row.version !== "string" || basename12(row.installPath) !== row.version)) {
37507
+ if (!cachePath(row.installPath) || row.installPath.length > AGENT_POLICY_LIMITS.pathCharacters || row.version !== undefined && (typeof row.version !== "string" || basename13(row.installPath) !== row.version)) {
37498
37508
  throw new Error("Reviewed Claude discovery has a malformed active cache registration");
37499
37509
  }
37500
37510
  if (row.scope === "user" && (row.projectPath === undefined || row.projectPath === null)) {} else if (row.scope === "project" && typeof row.projectPath === "string" && isAbsolute22(row.projectPath) && resolve22(row.projectPath) === row.projectPath && row.projectPath.length <= AGENT_POLICY_LIMITS.pathCharacters) {} else
@@ -37515,11 +37525,11 @@ function assertReviewedClaudeCacheClosures(home, config2, review, canonical9) {
37515
37525
  };
37516
37526
  for (const root of activeRoots) {
37517
37527
  safe6(root);
37518
- const rootStat = lstatSync23(root, { throwIfNoEntry: false });
37528
+ const rootStat = lstatSync24(root, { throwIfNoEntry: false });
37519
37529
  if (!rootStat?.isDirectory() || realpathSync8(root) !== root)
37520
37530
  throw new Error("Reviewed Claude active cache plugin root is missing or unsafe");
37521
- const manifestPath = join30(root, ".claude-plugin/plugin.json");
37522
- const manifestStat = lstatSync23(manifestPath, { throwIfNoEntry: false });
37531
+ const manifestPath = join31(root, ".claude-plugin/plugin.json");
37532
+ const manifestStat = lstatSync24(manifestPath, { throwIfNoEntry: false });
37523
37533
  let manifest;
37524
37534
  if (manifestStat) {
37525
37535
  if (!manifestStat.isFile())
@@ -37534,8 +37544,8 @@ function assertReviewedClaudeCacheClosures(home, config2, review, canonical9) {
37534
37544
  } 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)) {
37535
37545
  throw new Error("Reviewed Claude active cache plugin manifest absence requires a path-bytes witness");
37536
37546
  }
37537
- const roots = new Set([join30(root, "skills")]);
37538
- if (lstatSync23(join30(root, "SKILL.md"), { throwIfNoEntry: false })?.isFile())
37547
+ const roots = new Set([join31(root, "skills")]);
37548
+ if (lstatSync24(join31(root, "SKILL.md"), { throwIfNoEntry: false })?.isFile())
37539
37549
  roots.add(root);
37540
37550
  const declared = manifest?.skills === undefined ? ["./skills"] : typeof manifest.skills === "string" ? [manifest.skills] : manifest.skills;
37541
37551
  if (!Array.isArray(declared) || declared.some((path) => typeof path !== "string"))
@@ -37544,13 +37554,13 @@ function assertReviewedClaudeCacheClosures(home, config2, review, canonical9) {
37544
37554
  const path = resolve22(root, value);
37545
37555
  if (path !== root && !path.startsWith(root + sep11))
37546
37556
  throw new Error("Reviewed Claude active cache plugin skill path escapes its root");
37547
- roots.add(path.endsWith(`${sep11}SKILL.md`) ? dirname21(path) : path);
37557
+ roots.add(path.endsWith(`${sep11}SKILL.md`) ? dirname22(path) : path);
37548
37558
  }
37549
37559
  for (const skillRoot of roots)
37550
37560
  if (!review.roots.includes(skillRoot))
37551
37561
  throw new Error("Reviewed Claude active cache plugin skill root is not covered");
37552
- const hooksPath = join30(root, "hooks/hooks.json");
37553
- const hooksStat = lstatSync23(hooksPath, { throwIfNoEntry: false });
37562
+ const hooksPath = join31(root, "hooks/hooks.json");
37563
+ const hooksStat = lstatSync24(hooksPath, { throwIfNoEntry: false });
37554
37564
  if (hooksStat) {
37555
37565
  if (!hooksStat.isFile())
37556
37566
  throw new Error("Reviewed Claude plugin hook manifest is unsupported");
@@ -37688,18 +37698,18 @@ function absentCodexSkillRoots(binding, tolerance) {
37688
37698
  return [];
37689
37699
  if (binding.agent !== "codex" || !Array.isArray(controls) || controls.length > 4096)
37690
37700
  throw new Error("Invalid disabled Codex discovery proof");
37691
- if (binding.method !== "reviewed" || controls.every((control) => lstatSync23(control.pluginParent, { throwIfNoEntry: false })))
37701
+ if (binding.method !== "reviewed" || controls.every((control) => lstatSync24(control.pluginParent, { throwIfNoEntry: false })))
37692
37702
  return [];
37693
- const cache = dirname21(dirname21(controls[0].pluginParent)), config2 = join30(dirname21(dirname21(cache)), "config.toml");
37703
+ const cache = dirname22(dirname22(controls[0].pluginParent)), config2 = join31(dirname22(dirname22(cache)), "config.toml");
37694
37704
  const source = binding.sources.find((source2) => source2.path === config2 && source2.sha256 !== null && source2.format === undefined && source2.fields === undefined);
37695
37705
  if (!source || !codexConfigWitnessCurrent(source, tolerance))
37696
37706
  throw new Error("Missing current disabled Codex configuration witness");
37697
37707
  const rules = Bun.TOML.parse(read(config2)).skills?.config ?? [];
37698
37708
  return [...new Set(controls.map((control) => control.pluginParent))].filter((parent) => !codexDirectHookSelects(cache, parent) && absentDisabledCodexPluginParent(cache, parent, controls, rules));
37699
37709
  }
37700
- function codexDirectHookSelects(cache, root, configPath = join30(dirname21(dirname21(cache)), "config.toml")) {
37701
- const codex = dirname21(configPath), config2 = Bun.TOML.parse(read(configPath) ?? "");
37702
- const hooks = read(join30(codex, "hooks.json"));
37710
+ function codexDirectHookSelects(cache, root, configPath = join31(dirname22(dirname22(cache)), "config.toml")) {
37711
+ const codex = dirname22(configPath), config2 = Bun.TOML.parse(read(configPath) ?? "");
37712
+ const hooks = read(join31(codex, "hooks.json"));
37703
37713
  if (hooks !== null)
37704
37714
  hashNativeJsonControls(hooks);
37705
37715
  return JSON.stringify(config2.hooks ?? {}).includes(root) || hooks !== null && JSON.stringify(JSON.parse(hooks)).includes(root);
@@ -37711,7 +37721,7 @@ function retiredCodexRoots(binding, tolerance) {
37711
37721
  const controls = binding.codexDisabledPluginSkills;
37712
37722
  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)
37713
37723
  throw new Error("Invalid retired Codex materialization proof");
37714
- const cache = dirname21(dirname21(controls[0].pluginParent)), config2 = join30(dirname21(dirname21(cache)), "config.toml");
37724
+ const cache = dirname22(dirname22(controls[0].pluginParent)), config2 = join31(dirname22(dirname22(cache)), "config.toml");
37715
37725
  const source = binding.sources.find((source2) => source2.path === config2 && source2.sha256 !== null && source2.format === undefined && source2.fields === undefined);
37716
37726
  if (!source || !codexConfigWitnessCurrent(source, tolerance))
37717
37727
  throw new Error("Missing current retired Codex configuration witness");
@@ -37719,7 +37729,7 @@ function retiredCodexRoots(binding, tolerance) {
37719
37729
  if ((proof.parents ?? []).some((parent) => codexDirectHookSelects(cache, parent) || !reviewedDisabledCodexPluginParent(cache, parent, controls, rules)) || !reviewedCodexPluginCapabilitiesUnchanged(cache, controls, (path) => read(path), rules))
37720
37730
  throw new Error("Retired Codex parent capabilities changed");
37721
37731
  for (const root of proof.roots) {
37722
- const manifest = binding.sources.find((source2) => source2.path === join30(root, ".codex-plugin/plugin.json") && source2.sha256 !== null && source2.format === undefined && source2.fields === undefined && [undefined, "bytes"].includes(source2.hashMode));
37732
+ const manifest = binding.sources.find((source2) => source2.path === join31(root, ".codex-plugin/plugin.json") && source2.sha256 !== null && source2.format === undefined && source2.fields === undefined && [undefined, "bytes"].includes(source2.hashMode));
37723
37733
  if (!manifest || codexDirectHookSelects(cache, root) || !reviewedRetiredCodexRoot(cache, root, controls, rules, (path) => read(path), true))
37724
37734
  throw new Error("Retired Codex materialization changed");
37725
37735
  }
@@ -37730,7 +37740,7 @@ function retainableAbsentWitness(source) {
37730
37740
  return null;
37731
37741
  if ([undefined, "bytes"].includes(source.hashMode))
37732
37742
  return "bytes";
37733
- if (source.hashMode === "claude-plugin-manifest-v1" && source.sha256 !== null && source.path.endsWith(join30(sep11, ".claude-plugin", "plugin.json")))
37743
+ if (source.hashMode === "claude-plugin-manifest-v1" && source.sha256 !== null && source.path.endsWith(join31(sep11, ".claude-plugin", "plugin.json")))
37734
37744
  return "claude-plugin-manifest-v1";
37735
37745
  if (source.hashMode === CLAUDE_ORPHAN_MARKER_MODE && source.sha256 !== null && isClaudePluginCacheOrphanMarker(source.path))
37736
37746
  return CLAUDE_ORPHAN_MARKER_MODE;
@@ -37755,11 +37765,11 @@ function absentRetiredClaudeRoots(binding) {
37755
37765
  const cache = source.path.slice(0, at + marker.length - 1), parts = source.path.slice(at + marker.length).split(sep11);
37756
37766
  if (parts.length < 4 || parts.slice(0, 3).some((part) => !part || part === "." || part === ".."))
37757
37767
  continue;
37758
- const root = join30(cache, ...parts.slice(0, 3));
37768
+ const root = join31(cache, ...parts.slice(0, 3));
37759
37769
  safe6(root);
37760
- if (lstatSync23(root, { throwIfNoEntry: false }))
37770
+ if (lstatSync24(root, { throwIfNoEntry: false }))
37761
37771
  continue;
37762
- const claude = dirname21(dirname21(cache)), settings = join30(claude, "settings.json"), registry2 = join30(claude, "plugins/installed_plugins.json");
37772
+ const claude = dirname22(dirname22(cache)), settings = join31(claude, "settings.json"), registry2 = join31(claude, "plugins/installed_plugins.json");
37763
37773
  const full = (path) => binding.sources.find((item) => item.path === path && item.sha256 !== null && item.format === undefined && item.fields === undefined);
37764
37774
  const configSource = full(settings), registrySource = full(registry2);
37765
37775
  if (!configSource || !registrySource || projected(configSource) !== configSource.sha256 || projected(registrySource) !== registrySource.sha256)
@@ -37802,9 +37812,9 @@ function absentRetiredClaudeRoots(binding) {
37802
37812
  if (!targetValid || !targetScopes.has("user\x00"))
37803
37813
  continue;
37804
37814
  const active = rows[0]?.installPath;
37805
- if (typeof active !== "string" || rows[0]?.version !== basename12(active) || dirname21(active) !== dirname21(root) || active === root || !lstatSync23(active, { throwIfNoEntry: false })?.isDirectory() || realpathSync8(active) !== active)
37815
+ if (typeof active !== "string" || rows[0]?.version !== basename13(active) || dirname22(active) !== dirname22(root) || active === root || !lstatSync24(active, { throwIfNoEntry: false })?.isDirectory() || realpathSync8(active) !== active)
37806
37816
  continue;
37807
- const activeManifest = full(join30(active, ".claude-plugin/plugin.json"));
37817
+ const activeManifest = full(join31(active, ".claude-plugin/plugin.json"));
37808
37818
  if (!activeManifest || projected(activeManifest) !== activeManifest.sha256)
37809
37819
  continue;
37810
37820
  result.add(root);
@@ -37815,10 +37825,10 @@ function codexSemanticCacheSourceRole(source, cacheRoot, parents3, hookParents =
37815
37825
  if (!isAbsolute22(source.path) || resolve22(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")
37816
37826
  return false;
37817
37827
  const parts = relative7(cacheRoot, source.path).split(sep11);
37818
- if (parts.length < 3 || !parents3.includes(join30(cacheRoot, parts[0], parts[1])))
37828
+ if (parts.length < 3 || !parents3.includes(join31(cacheRoot, parts[0], parts[1])))
37819
37829
  return false;
37820
37830
  const tail = parts.slice(3).join("/");
37821
- const parent = join30(cacheRoot, parts[0], parts[1]);
37831
+ const parent = join31(cacheRoot, parts[0], parts[1]);
37822
37832
  return parts.length === 5 && tail === ".codex-plugin/plugin.json" && source.sha256 !== null || parts.length === 4 && [".app.json", ".mcp.json"].includes(tail) && source.sha256 !== null || parts.length === 5 && tail === "hooks/hooks.json" && hookParents.includes(parent) && source.sha256 !== null || source.sha256 === null && (parts.length === 4 && tail === "SKILL.md" || parts.length === 5 && tail === "hooks/hooks.json");
37823
37833
  }
37824
37834
  function codexSemanticCacheDirectoryRole(path, cacheRoot) {
@@ -37827,9 +37837,9 @@ function codexSemanticCacheDirectoryRole(path, cacheRoot) {
37827
37837
  function assertCodexSemanticCacheHookSafety(cacheRoot, parents3, configPath, hookRootAlias = null) {
37828
37838
  const selectionRoots = [cacheRoot, ...parents3];
37829
37839
  if (hookRootAlias !== null) {
37830
- if (!hookRootAlias || Object.keys(hookRootAlias).length !== 2 || [hookRootAlias.alias, hookRootAlias.target].some((path) => typeof path !== "string" || !isAbsolute22(path) || resolve22(path) !== path || /[\x00-\x1f\x7f]/.test(path)) || hookRootAlias.target !== dirname21(configPath) || cacheRoot !== join30(hookRootAlias.target, "plugins/cache") || !lstatSync23(hookRootAlias.alias, { throwIfNoEntry: false })?.isSymbolicLink() || realpathSync8(hookRootAlias.alias) !== hookRootAlias.target || realpathSync8(hookRootAlias.target) !== hookRootAlias.target)
37840
+ if (!hookRootAlias || Object.keys(hookRootAlias).length !== 2 || [hookRootAlias.alias, hookRootAlias.target].some((path) => typeof path !== "string" || !isAbsolute22(path) || resolve22(path) !== path || /[\x00-\x1f\x7f]/.test(path)) || hookRootAlias.target !== dirname22(configPath) || cacheRoot !== join31(hookRootAlias.target, "plugins/cache") || !lstatSync24(hookRootAlias.alias, { throwIfNoEntry: false })?.isSymbolicLink() || realpathSync8(hookRootAlias.alias) !== hookRootAlias.target || realpathSync8(hookRootAlias.target) !== hookRootAlias.target)
37831
37841
  throw new Error("Reviewed semantic cache hook alias changed");
37832
- selectionRoots.push(...selectionRoots.map((root) => join30(hookRootAlias.alias, relative7(hookRootAlias.target, root))));
37842
+ selectionRoots.push(...selectionRoots.map((root) => join31(hookRootAlias.alias, relative7(hookRootAlias.target, root))));
37833
37843
  }
37834
37844
  selectionRoots.push("plugins/cache");
37835
37845
  if (selectionRoots.some((parent) => codexDirectHookSelects(cacheRoot, parent, configPath)))
@@ -37849,7 +37859,7 @@ function verifyCodexSemanticCacheDiscovery(binding, reviewedRootAliases) {
37849
37859
  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))
37850
37860
  throw new Error("Invalid Codex semantic cache discovery proof");
37851
37861
  const cacheRoot = proof.witness.cacheRoot;
37852
- if (controls.some((control) => dirname21(dirname21(control.pluginParent)) !== cacheRoot))
37862
+ if (controls.some((control) => dirname22(dirname22(control.pluginParent)) !== cacheRoot))
37853
37863
  throw new Error("Codex semantic cache names another enrolled cache");
37854
37864
  const reviewedHookParents = proof.reviewedHookParents ?? [];
37855
37865
  if (!Array.isArray(reviewedHookParents) || reviewedHookParents.length > 4096 || reviewedHookParents.some((parent) => !parent || !(parent.installation === "remote-receipt" && Object.keys(parent).sort().join(",") === "installation,namespace,pluginId,pluginParent,remotePluginId,role" && typeof parent.remotePluginId === "string" || parent.installation === "local-marketplace" && Object.keys(parent).sort().join(",") === "installation,marketplaceSha256,marketplaceSourcePath,namespace,pluginId,pluginParent,role" && typeof parent.marketplaceSourcePath === "string" && /^[a-f0-9]{64}$/.test(parent.marketplaceSha256 ?? "")) || parent.role !== "reviewed-hook" || typeof parent.pluginId !== "string" || typeof parent.namespace !== "string" || typeof parent.pluginParent !== "string") || new Set(reviewedHookParents.map((parent) => parent.pluginParent)).size !== reviewedHookParents.length || !isDeepStrictEqual5((proof.witness.hookParents ?? []).map(({ manifestSha256: _manifest, hooksSha256: _hooks, receiptSha256: _receipt, ...parent }) => parent), reviewedHookParents)) {
@@ -37865,7 +37875,7 @@ function verifyCodexSemanticCacheDiscovery(binding, reviewedRootAliases) {
37865
37875
  if (!directories.length || !isDeepStrictEqual5(sources, proof.supersededSources) || !isDeepStrictEqual5(directories, proof.supersededDirectories))
37866
37876
  throw new Error("Codex semantic cache provenance changed");
37867
37877
  const configPath = proof.configPath;
37868
- if (!isAbsolute22(configPath) || resolve22(configPath) !== configPath || basename12(configPath) !== "config.toml" || /[\x00-\x1f\x7f]/.test(configPath))
37878
+ if (!isAbsolute22(configPath) || resolve22(configPath) !== configPath || basename13(configPath) !== "config.toml" || /[\x00-\x1f\x7f]/.test(configPath))
37869
37879
  throw new Error("Invalid semantic cache configuration source");
37870
37880
  const configSource = binding.sources.find((source) => source.path === configPath && source.sha256 !== null && source.format === undefined && source.fields === undefined);
37871
37881
  if (!configSource || projected(configSource) !== configSource.sha256)
@@ -37898,7 +37908,7 @@ function verifyAgentDiscovery(binding, codexRecovery, reviewedRootAliases, witne
37898
37908
  const projection = binding.codexRetiredMaterializations.directories.filter((directory) => !semanticDirectory(directory.path));
37899
37909
  if (projection.length !== ordinary.length || projection.some((item, index) => item.path !== ordinary[index]?.path))
37900
37910
  throw new Error("Missing retired Codex directory projection");
37901
- const omitted = [...retiredRoots, ...(binding.codexRetiredMaterializations.parents ?? []).filter((parent) => !lstatSync23(parent, { throwIfNoEntry: false }))];
37911
+ const omitted = [...retiredRoots, ...(binding.codexRetiredMaterializations.parents ?? []).filter((parent) => !lstatSync24(parent, { throwIfNoEntry: false }))];
37902
37912
  if (projection.every((item) => Array.isArray(item.entries)))
37903
37913
  verifyDiscoveryDirectoryProjection(projection, omitted, witnessTolerance);
37904
37914
  else {
@@ -37915,7 +37925,7 @@ function verifyAgentDiscovery(binding, codexRecovery, reviewedRootAliases, witne
37915
37925
  verifyDiscoveryDirectories(ordinary, [], witnessTolerance);
37916
37926
  verifyDiscoveryDirectories(projected2, installationRoots, witnessTolerance);
37917
37927
  }
37918
- const absentRoots = [...absentCodexSkillRoots(binding, witnessTolerance), ...absentRetiredClaudeRoots(binding), ...retiredRoots.filter((root) => !lstatSync23(root, { throwIfNoEntry: false }))];
37928
+ const absentRoots = [...absentCodexSkillRoots(binding, witnessTolerance), ...absentRetiredClaudeRoots(binding), ...retiredRoots.filter((root) => !lstatSync24(root, { throwIfNoEntry: false }))];
37919
37929
  const budget2 = discoveryByteBudget();
37920
37930
  for (const source of binding.sources) {
37921
37931
  assertMarketplaceBinding(binding, source);
@@ -37953,12 +37963,12 @@ function verifyAgentDiscovery(binding, codexRecovery, reviewedRootAliases, witne
37953
37963
  safe6(root);
37954
37964
  for (const root of absentRoots) {
37955
37965
  safe6(root);
37956
- if (lstatSync23(root, { throwIfNoEntry: false }))
37966
+ if (lstatSync24(root, { throwIfNoEntry: false }))
37957
37967
  throw new Error("Retired native materialization changed during discovery verification");
37958
37968
  }
37959
37969
  }
37960
37970
  function claudeControlSource(source) {
37961
- return CLAUDE_CONTROL_WITNESS_MODES.has(source.hashMode ?? "") || CLAUDE_CONTROL_FILES.has(basename12(source.path)) && !source.path.includes(`${sep11}.claude${sep11}plugins${sep11}cache${sep11}`);
37971
+ return CLAUDE_CONTROL_WITNESS_MODES.has(source.hashMode ?? "") || CLAUDE_CONTROL_FILES.has(basename13(source.path)) && !source.path.includes(`${sep11}.claude${sep11}plugins${sep11}cache${sep11}`);
37962
37972
  }
37963
37973
  function retainedAbsentClaudeRoot(absentRoots, source) {
37964
37974
  return claudeControlSource(source) ? undefined : retainedAbsentRoot(absentRoots, source);
@@ -37969,13 +37979,13 @@ function codexInstallationRoots(binding) {
37969
37979
  return [];
37970
37980
  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)
37971
37981
  throw new Error("Invalid native installation input proof");
37972
- const cache = dirname21(dirname21(proof.plugins[0].pluginParent));
37973
- const config2 = join30(dirname21(dirname21(cache)), "config.toml"), home = dirname21(dirname21(dirname21(cache)));
37982
+ const cache = dirname22(dirname22(proof.plugins[0].pluginParent));
37983
+ const config2 = join31(dirname22(dirname22(cache)), "config.toml"), home = dirname22(dirname22(dirname22(cache)));
37974
37984
  const configSource = binding.sources.find((source) => source.path === config2 && source.sha256 !== null && (!source.format || source.format === "toml" && source.fields?.includes("plugins")));
37975
- const nativeRoots = NATIVE_SKILL_ROOTS.filter(([agent]) => agent === "codex").map(([, path]) => join30(home, path));
37976
- if (!configSource || proof.plugins.some((input2) => nativeRoots.some((root) => root === input2.sourceRoot || root.startsWith(input2.sourceRoot + sep11) || input2.sourceRoot.startsWith(root + sep11)) || binding.sources.some((source) => basename12(source.path) === "config.toml" && (source.path === input2.sourceRoot || source.path.startsWith(input2.sourceRoot + sep11)))))
37985
+ const nativeRoots = NATIVE_SKILL_ROOTS.filter(([agent]) => agent === "codex").map(([, path]) => join31(home, path));
37986
+ if (!configSource || proof.plugins.some((input2) => nativeRoots.some((root) => root === input2.sourceRoot || root.startsWith(input2.sourceRoot + sep11) || input2.sourceRoot.startsWith(root + sep11)) || binding.sources.some((source) => basename13(source.path) === "config.toml" && (source.path === input2.sourceRoot || source.path.startsWith(input2.sourceRoot + sep11)))))
37977
37987
  throw new Error("Native installation input overlaps configuration or loading roots");
37978
- if (proof.plugins.some((input2) => dirname21(dirname21(input2.pluginParent)) !== cache || !binding.sources.some((source) => source.path === join30(input2.sourceRoot, ".codex-plugin/plugin.json") && source.sha256 !== null && source.format === undefined && source.fields === undefined)))
37988
+ if (proof.plugins.some((input2) => dirname22(dirname22(input2.pluginParent)) !== cache || !binding.sources.some((source) => source.path === join31(input2.sourceRoot, ".codex-plugin/plugin.json") && source.sha256 !== null && source.format === undefined && source.fields === undefined)))
37979
37989
  throw new Error("Missing native installation input source witness");
37980
37990
  return reviewedCodexPluginSourceRoots(cache, proof.plugins, (path) => {
37981
37991
  const text2 = read(path);
@@ -37991,13 +38001,13 @@ function assertMarketplaceBinding(binding, source) {
37991
38001
  throw new Error("Provider executable witnesses require explicit reviewed Codex V6");
37992
38002
  if (source.hashMode === "codex-settings-v6" && (new Set(binding.sources.map((row) => row.path)).size !== binding.sources.length || !Array.isArray(source.hookSources) || source.hookSources.some((hook) => !binding.sources.some((row) => row.path === hook.path && row.sha256 === hook.sha256 && [undefined, "bytes"].includes(row.hashMode) && row.format === undefined && row.fields === undefined))))
37993
38003
  throw new Error("Missing independently reviewed Codex hook source population");
37994
- if (source.hashMode === "claude-plugin-manifest-v1" && (binding.agent !== "claude" || basename12(source.path) !== "plugin.json" || !source.path.endsWith(join30(sep11, ".claude-plugin", "plugin.json"))))
38004
+ if (source.hashMode === "claude-plugin-manifest-v1" && (binding.agent !== "claude" || basename13(source.path) !== "plugin.json" || !source.path.endsWith(join31(sep11, ".claude-plugin", "plugin.json"))))
37995
38005
  throw new Error("Claude plugin manifest witnesses require Claude plugin discovery");
37996
- if (source.hashMode === "sumi-settings-v1" && (binding.agent !== "sumi" || binding.method !== "reviewed" || basename12(source.path) !== "sumi.json"))
38006
+ if (source.hashMode === "sumi-settings-v1" && (binding.agent !== "sumi" || binding.method !== "reviewed" || basename13(source.path) !== "sumi.json"))
37997
38007
  throw new Error("Sumi settings witnesses require explicit reviewed Sumi configuration");
37998
- 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" || source.hashMode === "codex-settings-v6")) && (binding.agent !== "codex" || binding.method !== "reviewed" || basename12(source.path) !== "config.toml"))
38008
+ 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" || source.hashMode === "codex-settings-v6")) && (binding.agent !== "codex" || binding.method !== "reviewed" || basename13(source.path) !== "config.toml"))
37999
38009
  throw new Error("Codex settings witnesses require explicit reviewed Codex configuration");
38000
- 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" || basename12(source.path) !== "settings.json"))
38010
+ 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" || basename13(source.path) !== "settings.json"))
38001
38011
  throw new Error("Claude settings witnesses require explicit reviewed Claude configuration");
38002
38012
  if ((source.hashMode === "claude-marketplace-registry" || source.hashMode === "claude-marketplace-registry-v2") && (binding.agent !== "claude" || binding.method !== "reviewed"))
38003
38013
  throw new Error("Claude marketplace witnesses require explicit reviewed Claude discovery");
@@ -38005,11 +38015,11 @@ function assertMarketplaceBinding(binding, source) {
38005
38015
  throw new Error("Claude marketplace entry witnesses require explicit reviewed Claude discovery of one named entry");
38006
38016
  }
38007
38017
  function hashReviewedExecutable(path, budget2) {
38008
- const before = lstatSync23(path, { bigint: true });
38018
+ const before = lstatSync24(path, { bigint: true });
38009
38019
  if (before.size < 0n || before.size > BigInt(budget2.remaining))
38010
38020
  throw new Error("Discovery aggregate executable byte limit exceeded");
38011
38021
  const digest3 = pluginExecutableDigest(path).slice(7);
38012
- const after = lstatSync23(path, { bigint: true });
38022
+ const after = lstatSync24(path, { bigint: true });
38013
38023
  for (const key2 of ["dev", "ino", "size", "mode", "uid", "gid", "nlink", "mtimeNs", "ctimeNs"]) {
38014
38024
  if (before[key2] !== after[key2])
38015
38025
  throw new Error("Discovery executable changed during budgeted capture");
@@ -38020,7 +38030,7 @@ function hashReviewedExecutable(path, budget2) {
38020
38030
  function agentDiscoveryConfigPath(home, agent) {
38021
38031
  if (agent === "sumi")
38022
38032
  return sumiConfigPath(home);
38023
- return join30(home, agent === "hermes" ? ".hermes/config.yaml" : agent === "opencode" ? ".config/opencode/opencode.json" : `.${agent}/${agent === "codex" ? "config.toml" : agent === "cursor" ? "hooks.json" : "settings.json"}`);
38033
+ return join31(home, agent === "hermes" ? ".hermes/config.yaml" : agent === "opencode" ? ".config/opencode/opencode.json" : `.${agent}/${agent === "codex" ? "config.toml" : agent === "cursor" ? "hooks.json" : "settings.json"}`);
38024
38034
  }
38025
38035
  function resolveAgentDiscovery(options) {
38026
38036
  const canonical9 = options.canonical ?? resolve22, home = resolve22(options.home), agent = options.agent;
@@ -38044,42 +38054,42 @@ function resolveAgentDiscovery(options) {
38044
38054
  const review = options.reviewed?.agents.find((item) => item.agent === agent);
38045
38055
  if (agent === "sumi") {
38046
38056
  const directory = sumiConfigDirectory(home);
38047
- if (witness(join30(directory, "sumi.jsonc")) !== null)
38057
+ if (witness(join31(directory, "sumi.jsonc")) !== null)
38048
38058
  unresolved("JSONC configuration requires a supported format adapter");
38049
- for (const root of [directory, join30(home, ".claude"), join30(home, ".agents")])
38059
+ for (const root of [directory, join31(home, ".claude"), join31(home, ".agents")])
38050
38060
  for (const name of ["skill", "skills"])
38051
- roots.add(canonical9(join30(root, name)));
38061
+ roots.add(canonical9(join31(root, name)));
38052
38062
  if (config2.skills !== undefined && (!Array.isArray(config2.skills) || config2.skills.some((path) => typeof path !== "string")))
38053
38063
  unresolved("skills must be a string array");
38054
38064
  for (const value of config2.skills ?? []) {
38055
38065
  if (typeof value !== "string" || /[\0$]/.test(value) || !value || !(isAbsolute22(value) || value.startsWith("~/")))
38056
38066
  unresolved("remote or relative skill sources need a dedicated discovery adapter");
38057
- roots.add(canonical9(value.startsWith("~/") ? join30(home, value.slice(2)) : value));
38067
+ roots.add(canonical9(value.startsWith("~/") ? join31(home, value.slice(2)) : value));
38058
38068
  }
38059
38069
  for (const key2 of ["plugin", "plugins"])
38060
38070
  if (config2[key2] !== undefined && !Array.isArray(config2[key2]))
38061
38071
  unresolved(`${key2} must be an array`);
38062
- const plugins = [join30(directory, "plugin"), join30(directory, "plugins")];
38072
+ const plugins = [join31(directory, "plugin"), join31(directory, "plugins")];
38063
38073
  for (const path of plugins) {
38064
38074
  safe6(path);
38065
- if (lstatSync23(path, { throwIfNoEntry: false })?.isDirectory())
38066
- for (const name of readdirSync8(path).sort()) {
38075
+ if (lstatSync24(path, { throwIfNoEntry: false })?.isDirectory())
38076
+ for (const name of readdirSync9(path).sort()) {
38067
38077
  if (name === "skills-cli.js" && path === plugins[1])
38068
38078
  continue;
38069
- const target = join30(path, name);
38070
- if (!lstatSync23(target).isFile())
38079
+ const target = join31(path, name);
38080
+ if (!lstatSync24(target).isFile())
38071
38081
  unresolved("local plugin packages need a dedicated discovery adapter");
38072
38082
  witness(target);
38073
38083
  }
38074
38084
  }
38075
38085
  for (const root of roots) {
38076
38086
  safe6(root);
38077
- if (lstatSync23(root, { throwIfNoEntry: false })?.isDirectory() && readdirSync8(root).some((name) => name.endsWith(".md")))
38087
+ if (lstatSync24(root, { throwIfNoEntry: false })?.isDirectory() && readdirSync9(root).some((name) => name.endsWith(".md")))
38078
38088
  unresolved("flat markdown skills require a dedicated native migration adapter");
38079
38089
  }
38080
38090
  }
38081
38091
  if (agent === "hermes") {
38082
- const profile = witness(join30(home, ".hermes/active_profile"));
38092
+ const profile = witness(join31(home, ".hermes/active_profile"));
38083
38093
  if (profile?.trim() && profile.trim() !== "default")
38084
38094
  unresolved("a non-default profile is active");
38085
38095
  const declared = config2.skills?.external_dirs ?? [], paths = typeof declared === "string" ? [declared] : declared;
@@ -38093,7 +38103,7 @@ function resolveAgentDiscovery(options) {
38093
38103
  continue;
38094
38104
  if (normalized.startsWith("~") && normalized !== "~" && !normalized.startsWith("~/"))
38095
38105
  unresolved("user-specific tilde expansion requires a separate discovery adapter");
38096
- const path = normalized === "~" ? home : normalized.startsWith("~/") ? join30(home, normalized.slice(2)) : resolve22(home, ".hermes", normalized);
38106
+ const path = normalized === "~" ? home : normalized.startsWith("~/") ? join31(home, normalized.slice(2)) : resolve22(home, ".hermes", normalized);
38097
38107
  safe6(path);
38098
38108
  roots.add(path);
38099
38109
  }
@@ -38102,24 +38112,24 @@ function resolveAgentDiscovery(options) {
38102
38112
  const executable = options.executable === undefined ? discoveryExecutable(agent) : options.executable;
38103
38113
  if (executable) {
38104
38114
  let packageRoot;
38105
- for (let directory = dirname21(executable.target), depth = 0;depth < 8; directory = dirname21(directory), depth++) {
38106
- const path = join30(directory, "package.json"), raw = read(path);
38115
+ for (let directory = dirname22(executable.target), depth = 0;depth < 8; directory = dirname22(directory), depth++) {
38116
+ const path = join31(directory, "package.json"), raw = read(path);
38107
38117
  if (raw !== null && parseConfig(raw, path).name === "@google/gemini-cli") {
38108
38118
  packageRoot = directory;
38109
38119
  witness(path);
38110
38120
  break;
38111
38121
  }
38112
- if (dirname21(directory) === directory)
38122
+ if (dirname22(directory) === directory)
38113
38123
  break;
38114
38124
  }
38115
38125
  if (!packageRoot)
38116
38126
  unresolved("installed Gemini package layout is not recognized");
38117
- const builtinRoot = join30(packageRoot, "bundle/builtin");
38127
+ const builtinRoot = join31(packageRoot, "bundle/builtin");
38118
38128
  safe6(builtinRoot);
38119
- if (!lstatSync23(builtinRoot, { throwIfNoEntry: false })?.isDirectory())
38129
+ if (!lstatSync24(builtinRoot, { throwIfNoEntry: false })?.isDirectory())
38120
38130
  unresolved("installed Gemini builtin root is missing");
38121
- for (const name of readdirSync8(builtinRoot).sort()) {
38122
- const text2 = witness(join30(builtinRoot, name, "SKILL.md"));
38131
+ for (const name of readdirSync9(builtinRoot).sort()) {
38132
+ const text2 = witness(join31(builtinRoot, name, "SKILL.md"));
38123
38133
  const match = text2?.match(/^---\r?\n[\s\S]*?^name:\s*([a-z0-9][a-z0-9-]*)\s*$/m);
38124
38134
  if (!match?.[1] || builtinNames.includes(match[1]))
38125
38135
  unresolved("installed Gemini builtin name is missing or ambiguous");
@@ -38165,10 +38175,10 @@ function resolveAgentDiscovery(options) {
38165
38175
  if (agent === "claude" && source.format === undefined && source.fields === undefined && source.managedPlugins === undefined && source.reviewArtifact === undefined && [undefined, "bytes", "path-bytes"].includes(source.hashMode) && isClaudePluginCacheOrphanMarker(source.path)) {
38166
38176
  return { path: source.path, hashMode: CLAUDE_ORPHAN_MARKER_MODE, sha256: hashClaudePluginCacheOrphanMarker(source.path) };
38167
38177
  }
38168
- if (agent !== "claude" || source.sha256 === null || source.format !== undefined || source.fields !== undefined || source.managedPlugins !== undefined || source.hashMode !== undefined && source.hashMode !== "bytes" || basename12(source.path) !== "plugin.json" || !source.path.endsWith(join30(sep11, ".claude-plugin", "plugin.json")))
38178
+ if (agent !== "claude" || source.sha256 === null || source.format !== undefined || source.fields !== undefined || source.managedPlugins !== undefined || source.hashMode !== undefined && source.hashMode !== "bytes" || basename13(source.path) !== "plugin.json" || !source.path.endsWith(join31(sep11, ".claude-plugin", "plugin.json")))
38169
38179
  return source;
38170
- const pluginRoot = dirname21(dirname21(source.path)), hooksPath = join30(pluginRoot, "hooks/hooks.json");
38171
- const hookStat = lstatSync23(hooksPath, { throwIfNoEntry: false });
38180
+ const pluginRoot = dirname22(dirname22(source.path)), hooksPath = join31(pluginRoot, "hooks/hooks.json");
38181
+ const hookStat = lstatSync24(hooksPath, { throwIfNoEntry: false });
38172
38182
  const text2 = read(source.path);
38173
38183
  if (text2 === null)
38174
38184
  throw new Error("Reviewed Claude plugin manifest is missing");
@@ -38196,7 +38206,7 @@ function resolveAgentDiscovery(options) {
38196
38206
  assertReviewedClaudeCacheClosures(home, config2, review, canonical9);
38197
38207
  for (const root of absentRoots) {
38198
38208
  safe6(root);
38199
- if (lstatSync23(root, { throwIfNoEntry: false }))
38209
+ if (lstatSync24(root, { throwIfNoEntry: false }))
38200
38210
  throw new Error("Retired native materialization changed during discovery review");
38201
38211
  }
38202
38212
  const combined = [...reviewedSources, ...reviewedSourcesWithManifestProjection];
@@ -38206,39 +38216,39 @@ function resolveAgentDiscovery(options) {
38206
38216
  function plugin(root) {
38207
38217
  root = canonical9(root);
38208
38218
  safe6(root);
38209
- const manifestPath = join30(root, agent === "claude" ? ".claude-plugin/plugin.json" : ".codex-plugin/plugin.json");
38219
+ const manifestPath = join31(root, agent === "claude" ? ".claude-plugin/plugin.json" : ".codex-plugin/plugin.json");
38210
38220
  const raw = witness(manifestPath, undefined, undefined, agent === "claude" ? "claude-plugin-manifest-v1" : undefined);
38211
38221
  if (raw === null)
38212
38222
  unresolved("plugin manifest missing");
38213
38223
  const manifest = parseConfig(raw, manifestPath);
38214
- const hooks = witness(join30(root, "hooks/hooks.json"));
38224
+ const hooks = witness(join31(root, "hooks/hooks.json"));
38215
38225
  if (manifest.hooks !== undefined || hooks !== null)
38216
38226
  unresolved("plugin hooks require a separate no-skill-injection review");
38217
- const commands = join30(root, "commands");
38227
+ const commands = join31(root, "commands");
38218
38228
  safe6(commands);
38219
- if (agent === "claude" && (manifest.commands !== undefined || lstatSync23(commands, { throwIfNoEntry: false })?.isDirectory() && readdirSync8(commands).length))
38229
+ if (agent === "claude" && (manifest.commands !== undefined || lstatSync24(commands, { throwIfNoEntry: false })?.isDirectory() && readdirSync9(commands).length))
38220
38230
  unresolved("legacy command discovery requires retirement or a dedicated format adapter");
38221
- const rootSkill = witness(join30(root, "SKILL.md"));
38231
+ const rootSkill = witness(join31(root, "SKILL.md"));
38222
38232
  if (rootSkill !== null)
38223
38233
  roots.add(root);
38224
38234
  const declared = manifest.skills === undefined ? ["./skills"] : typeof manifest.skills === "string" ? [manifest.skills] : manifest.skills;
38225
38235
  if (!Array.isArray(declared) || declared.some((path) => typeof path !== "string"))
38226
38236
  unresolved("unsupported plugin skill paths");
38227
38237
  if (agent === "claude")
38228
- roots.add(join30(root, "skills"));
38238
+ roots.add(join31(root, "skills"));
38229
38239
  for (const value of declared) {
38230
38240
  const path = resolve22(root, value);
38231
38241
  if (path !== root && !path.startsWith(root + sep11))
38232
38242
  unresolved("plugin skill path escapes its root");
38233
- roots.add(path.endsWith(`${sep11}SKILL.md`) ? dirname21(path) : path);
38243
+ roots.add(path.endsWith(`${sep11}SKILL.md`) ? dirname22(path) : path);
38234
38244
  }
38235
38245
  }
38236
38246
  if (agent === "claude") {
38237
- const registrations = witness(join30(home, ".claude/plugins/installed_plugins.json"));
38238
- const installed = registrations === null ? {} : parseConfig(registrations, join30(home, ".claude/plugins/installed_plugins.json")).plugins;
38239
- const commands = canonical9(join30(home, ".claude/commands"));
38247
+ const registrations = witness(join31(home, ".claude/plugins/installed_plugins.json"));
38248
+ const installed = registrations === null ? {} : parseConfig(registrations, join31(home, ".claude/plugins/installed_plugins.json")).plugins;
38249
+ const commands = canonical9(join31(home, ".claude/commands"));
38240
38250
  safe6(commands);
38241
- if (lstatSync23(commands, { throwIfNoEntry: false })?.isDirectory() && readdirSync8(commands).length)
38251
+ if (lstatSync24(commands, { throwIfNoEntry: false })?.isDirectory() && readdirSync9(commands).length)
38242
38252
  unresolved("legacy home command discovery requires a dedicated format adapter");
38243
38253
  for (const [id, enabled] of Object.entries(config2.enabledPlugins ?? {})) {
38244
38254
  if (enabled === false)
@@ -38260,16 +38270,16 @@ function resolveAgentDiscovery(options) {
38260
38270
  const market = config2.marketplaces?.[marketplace] ?? (marketplace === "personal" ? { source_type: "local", source: home } : undefined);
38261
38271
  if (split < 1 || market?.source_type !== "local" || typeof market.source !== "string" || !isAbsolute22(market.source))
38262
38272
  unresolved("enabled plugin marketplace is not an explicit local source");
38263
- const catalogText = witness(join30(market.source, ".agents/plugins/marketplace.json"));
38273
+ const catalogText = witness(join31(market.source, ".agents/plugins/marketplace.json"));
38264
38274
  if (catalogText === null)
38265
38275
  unresolved("marketplace catalog missing");
38266
- const catalog = parseConfig(catalogText, join30(market.source, ".agents/plugins/marketplace.json")), matches = Array.isArray(catalog.plugins) ? catalog.plugins.filter((item) => item.name === name) : [];
38276
+ const catalog = parseConfig(catalogText, join31(market.source, ".agents/plugins/marketplace.json")), matches = Array.isArray(catalog.plugins) ? catalog.plugins.filter((item) => item.name === name) : [];
38267
38277
  if (matches.length !== 1 || matches[0]?.source?.source !== "local" || typeof matches[0]?.source?.path !== "string")
38268
38278
  unresolved("plugin catalog source is missing or ambiguous");
38269
38279
  plugin(resolve22(market.source, matches[0].source.path));
38270
38280
  }
38271
38281
  } else if (agent === "opencode") {
38272
- if (witness(join30(home, ".config/opencode/opencode.jsonc")) !== null || witness(join30(home, ".config/opencode/config.json")) !== null)
38282
+ if (witness(join31(home, ".config/opencode/opencode.jsonc")) !== null || witness(join31(home, ".config/opencode/config.json")) !== null)
38273
38283
  unresolved("additional config layers require review");
38274
38284
  if ((config2.plugin?.length ?? 0) > 0 || config2.skills?.urls?.length)
38275
38285
  unresolved("external plugin or remote skill source");
@@ -38278,17 +38288,17 @@ function resolveAgentDiscovery(options) {
38278
38288
  unresolved("relative or malformed added skill root");
38279
38289
  roots.add(path);
38280
38290
  }
38281
- const localPlugins = join30(home, ".config/opencode/plugins");
38291
+ const localPlugins = join31(home, ".config/opencode/plugins");
38282
38292
  safe6(localPlugins);
38283
- if (lstatSync23(localPlugins, { throwIfNoEntry: false }) && readdirSync8(localPlugins).some((name) => name !== "skills-cli.js"))
38293
+ if (lstatSync24(localPlugins, { throwIfNoEntry: false }) && readdirSync9(localPlugins).some((name) => name !== "skills-cli.js"))
38284
38294
  unresolved("additional local plugin hooks require review");
38285
38295
  } else if (agent === "sumi") {
38286
- if ((config2.plugin?.length ?? 0) > 0 || (config2.plugins?.length ?? 0) > 0 || sources.some((source) => source.path !== canonical9(configPath) && source.path !== canonical9(join30(sumiConfigDirectory(home), "sumi.jsonc")) && source.sha256 !== null))
38296
+ if ((config2.plugin?.length ?? 0) > 0 || (config2.plugins?.length ?? 0) > 0 || sources.some((source) => source.path !== canonical9(configPath) && source.path !== canonical9(join31(sumiConfigDirectory(home), "sumi.jsonc")) && source.sha256 !== null))
38287
38297
  unresolved("external or foreign local plugins require review");
38288
38298
  } else if (agent === "hermes") {
38289
- for (const directory of [join30(home, ".hermes/plugins"), join30(home, ".hermes/hermes-agent")]) {
38299
+ for (const directory of [join31(home, ".hermes/plugins"), join31(home, ".hermes/hermes-agent")]) {
38290
38300
  safe6(directory);
38291
- if (lstatSync23(directory, { throwIfNoEntry: false }))
38301
+ if (lstatSync24(directory, { throwIfNoEntry: false }))
38292
38302
  unresolved("installed runtime/plugin discovery requires reviewed source bindings");
38293
38303
  }
38294
38304
  if (Bun.which("hermes") || Object.keys(config2.plugins ?? {}).length)
@@ -38296,24 +38306,24 @@ function resolveAgentDiscovery(options) {
38296
38306
  } else if (agent === "gemini") {
38297
38307
  if (Object.keys(config2.extensions ?? {}).length || config2.skills?.paths?.length)
38298
38308
  unresolved("custom extension or skill paths");
38299
- const directory = join30(home, ".gemini/extensions");
38309
+ const directory = join31(home, ".gemini/extensions");
38300
38310
  safe6(directory);
38301
- if (lstatSync23(directory, { throwIfNoEntry: false }))
38302
- for (const name of readdirSync8(directory)) {
38303
- const root = join30(directory, name);
38311
+ if (lstatSync24(directory, { throwIfNoEntry: false }))
38312
+ for (const name of readdirSync9(directory)) {
38313
+ const root = join31(directory, name);
38304
38314
  safe6(root);
38305
- if (!lstatSync23(root)?.isDirectory())
38315
+ if (!lstatSync24(root)?.isDirectory())
38306
38316
  continue;
38307
- const raw = witness(join30(root, "gemini-extension.json"));
38317
+ const raw = witness(join31(root, "gemini-extension.json"));
38308
38318
  if (raw === null)
38309
38319
  unresolved("extension registration missing");
38310
- const manifest = parseConfig(raw, join30(root, "gemini-extension.json"));
38311
- if (manifest.hooks !== undefined || witness(join30(root, "hooks/hooks.json")) !== null || witness(join30(root, ".gemini-extension-install.json")) !== null)
38320
+ const manifest = parseConfig(raw, join31(root, "gemini-extension.json"));
38321
+ if (manifest.hooks !== undefined || witness(join31(root, "hooks/hooks.json")) !== null || witness(join31(root, ".gemini-extension-install.json")) !== null)
38312
38322
  unresolved("extension hooks or linked registration require review");
38313
- roots.add(join30(root, "skills"));
38323
+ roots.add(join31(root, "skills"));
38314
38324
  }
38315
38325
  }
38316
- return { agent, roots: [...roots].sort(), sources, method: "automatic", ...agent === "gemini" ? { builtinNames } : {}, ...agent === "hermes" ? { directories: captureDiscoveryDirectories([join30(home, ".hermes/plugins"), join30(home, ".hermes/hermes-agent")].map((path) => canonical9(path))) } : {} };
38326
+ return { agent, roots: [...roots].sort(), sources, method: "automatic", ...agent === "gemini" ? { builtinNames } : {}, ...agent === "hermes" ? { directories: captureDiscoveryDirectories([join31(home, ".hermes/plugins"), join31(home, ".hermes/hermes-agent")].map((path) => canonical9(path))) } : {} };
38317
38327
  }
38318
38328
  var DISCOVERY_RUNTIME_COMMANDS, realpathOrNull = (path) => {
38319
38329
  try {
@@ -38358,9 +38368,9 @@ var init_agent_discovery = __esm(() => {
38358
38368
  });
38359
38369
 
38360
38370
  // src/lib/authoring-path.ts
38361
- import { lstatSync as lstatSync24, realpathSync as realpathSync9 } from "fs";
38371
+ import { lstatSync as lstatSync25, realpathSync as realpathSync9 } from "fs";
38362
38372
  import { homedir as homedir3 } from "os";
38363
- import { basename as basename13, dirname as dirname22, join as join31, resolve as resolve23, sep as sep12 } from "path";
38373
+ import { basename as basename14, dirname as dirname23, join as join32, resolve as resolve23, sep as sep12 } from "path";
38364
38374
  function pathParts(path) {
38365
38375
  return resolve23(path).split(sep12).filter(Boolean);
38366
38376
  }
@@ -38378,9 +38388,9 @@ function nativeRootMatch(path) {
38378
38388
  function physicalPath(path) {
38379
38389
  let cursor = resolve23(path);
38380
38390
  const suffix = [];
38381
- while (!lstatSync24(cursor, { throwIfNoEntry: false })) {
38382
- suffix.unshift(basename13(cursor));
38383
- const parent = dirname22(cursor);
38391
+ while (!lstatSync25(cursor, { throwIfNoEntry: false })) {
38392
+ suffix.unshift(basename14(cursor));
38393
+ const parent = dirname23(cursor);
38384
38394
  if (parent === cursor)
38385
38395
  return resolve23(path);
38386
38396
  cursor = parent;
@@ -38391,7 +38401,7 @@ function contains(root, path) {
38391
38401
  return path === root || path.startsWith(root + sep12);
38392
38402
  }
38393
38403
  function configuredRoots(home, explicitHome) {
38394
- const homeData = join31(home, ".hasna", "skills");
38404
+ const homeData = join32(home, ".hasna", "skills");
38395
38405
  const homePolicy = readManagedSkillPolicySnapshot(homeData);
38396
38406
  const configuredPolicy = !explicitHome && resolve23(getDataDirReadOnly()) !== resolve23(homeData) ? readManagedSkillPolicySnapshot(getDataDirReadOnly()) : null;
38397
38407
  const policy = homePolicy ?? configuredPolicy;
@@ -38422,8 +38432,8 @@ function configuredRoots(home, explicitHome) {
38422
38432
  admitBinding(binding);
38423
38433
  continue;
38424
38434
  }
38425
- const nativeHome = join31(home, agent === "opencode" ? ".config/opencode" : `.${agent}`);
38426
- if (!lstatSync24(nativeHome, { throwIfNoEntry: false }))
38435
+ const nativeHome = join32(home, agent === "opencode" ? ".config/opencode" : `.${agent}`);
38436
+ if (!lstatSync25(nativeHome, { throwIfNoEntry: false }))
38427
38437
  continue;
38428
38438
  roots.push(...resolveAgentDiscovery({ home, agent, canonical: physicalPath }).roots);
38429
38439
  }
@@ -38437,8 +38447,8 @@ function assertPortableAuthoringPath(path, options = {}) {
38437
38447
  const candidates = [lexical, physical];
38438
38448
  let native = candidates.map(nativeRootMatch).find(Boolean);
38439
38449
  const home = resolve23(options.homeDir ?? homedir3());
38440
- const defaults = NATIVE_DISCOVERY_ROOTS.map((parts) => join31(home, ...parts));
38441
- defaults.push(join31(home, ".codex/plugins/cache"), join31(home, ".claude/plugins/cache"), join31(home, ".claude/plugins/synced"), join31(home, ".gemini/extensions"));
38450
+ const defaults = NATIVE_DISCOVERY_ROOTS.map((parts) => join32(home, ...parts));
38451
+ defaults.push(join32(home, ".codex/plugins/cache"), join32(home, ".claude/plugins/cache"), join32(home, ".claude/plugins/synced"), join32(home, ".gemini/extensions"));
38442
38452
  for (const root of defaults) {
38443
38453
  if (candidates.some((candidate) => contains(resolve23(root), candidate) || contains(physicalPath(root), candidate)))
38444
38454
  native ??= root;
@@ -38467,29 +38477,29 @@ import {
38467
38477
  existsSync as existsSync12,
38468
38478
  mkdirSync as mkdirSync8,
38469
38479
  mkdtempSync,
38470
- readdirSync as readdirSync9,
38480
+ readdirSync as readdirSync10,
38471
38481
  realpathSync as realpathSync10,
38472
38482
  renameSync as renameSync3,
38473
38483
  rmSync as rmSync3,
38474
38484
  statSync as statSync9,
38475
38485
  writeFileSync as writeFileSync6
38476
38486
  } from "fs";
38477
- import { basename as basename14, dirname as dirname23, isAbsolute as isAbsolute23, join as join32, normalize as normalize4, relative as relative8, resolve as resolve24, sep as sep13 } from "path";
38487
+ import { basename as basename15, dirname as dirname24, isAbsolute as isAbsolute23, join as join33, normalize as normalize4, relative as relative8, resolve as resolve24, sep as sep13 } from "path";
38478
38488
  function getPortableSkillsRoot(options = {}) {
38479
38489
  return resolvePortableSkillsRoot(options, true);
38480
38490
  }
38481
38491
  function resolvePortableSkillsRoot(options, migrate) {
38482
38492
  if (options.rootDir)
38483
38493
  return options.rootDir;
38484
- const appDir = options.homeDir ? join32(options.homeDir, ".hasna", "skills") : migrate ? getDataDir() : getDataDirReadOnly();
38485
- const cache = join32(appDir, SKILLS_CACHE_DIRNAME);
38494
+ const appDir = options.homeDir ? join33(options.homeDir, ".hasna", "skills") : migrate ? getDataDir() : getDataDirReadOnly();
38495
+ const cache = join33(appDir, SKILLS_CACHE_DIRNAME);
38486
38496
  if (isOwnerLayoutMigrated(appDir) && safeIsDirectory(cache))
38487
38497
  return cache;
38488
- const installed = join32(appDir, INSTALLED_SKILLS_DIRNAME);
38498
+ const installed = join33(appDir, INSTALLED_SKILLS_DIRNAME);
38489
38499
  return installed;
38490
38500
  }
38491
38501
  function getPortableSkillPath(name, options = {}) {
38492
- return join32(getPortableSkillsRoot(options), normalizePortableSkillName(name));
38502
+ return join33(getPortableSkillsRoot(options), normalizePortableSkillName(name));
38493
38503
  }
38494
38504
  function findPortableSkill(name, options = {}) {
38495
38505
  let normalized;
@@ -38512,10 +38522,10 @@ function listPortableSkills(options = {}) {
38512
38522
  if (!safeIsDirectory(root))
38513
38523
  return [];
38514
38524
  const skills = [];
38515
- for (const entry of readdirSync9(root).sort()) {
38525
+ for (const entry of readdirSync10(root).sort()) {
38516
38526
  if (entry.startsWith("."))
38517
38527
  continue;
38518
- const path = join32(root, entry);
38528
+ const path = join33(root, entry);
38519
38529
  if (!safeIsDirectory(path))
38520
38530
  continue;
38521
38531
  try {
@@ -38548,9 +38558,9 @@ function isOfficialSkillName(name) {
38548
38558
  function scaffoldPortableSkill(name, options = {}) {
38549
38559
  const skillName = normalizeNewPortableSkillName(name);
38550
38560
  const readOnlyRoot = resolvePortableSkillsRoot(options, false);
38551
- assertPortableAuthoringPath(join32(readOnlyRoot, skillName), options);
38561
+ assertPortableAuthoringPath(join33(readOnlyRoot, skillName), options);
38552
38562
  const root = getPortableSkillsRoot(options);
38553
- const skillPath = join32(root, skillName);
38563
+ const skillPath = join33(root, skillName);
38554
38564
  assertPortableAuthoringPath(skillPath, options);
38555
38565
  if (existsSync12(skillPath)) {
38556
38566
  if (!options.overwrite)
@@ -38572,10 +38582,10 @@ function physicalImportPath(path) {
38572
38582
  let ancestor = resolve24(path);
38573
38583
  const suffix = [];
38574
38584
  while (!existsSync12(ancestor)) {
38575
- suffix.unshift(basename14(ancestor));
38576
- ancestor = dirname23(ancestor);
38585
+ suffix.unshift(basename15(ancestor));
38586
+ ancestor = dirname24(ancestor);
38577
38587
  }
38578
- return join32(realpathSync10(ancestor), ...suffix);
38588
+ return join33(realpathSync10(ancestor), ...suffix);
38579
38589
  }
38580
38590
  function assertDisjointImportPaths(source, destination) {
38581
38591
  const sourcePath = realpathSync10(source);
@@ -38597,15 +38607,15 @@ function portPortableSkill(sourcePath, options = {}) {
38597
38607
  const explicitName = options.name != null;
38598
38608
  const skillName = normalizeNewPortableSkillName(options.name ?? inferred.name);
38599
38609
  if (isOfficialSkillName(skillName) && !options.allowShadow) {
38600
- const sourceSlug = safeNormalizeName(basename14(absoluteSource));
38601
- const via = explicitName ? `Name '${skillName}' matches a bundled official skill.` : `Inferred name '${skillName}'${sourceSlug && sourceSlug !== skillName ? ` (from source folder '${basename14(absoluteSource)}')` : ""} matches a bundled official skill.`;
38610
+ const sourceSlug = safeNormalizeName(basename15(absoluteSource));
38611
+ const via = explicitName ? `Name '${skillName}' matches a bundled official skill.` : `Inferred name '${skillName}'${sourceSlug && sourceSlug !== skillName ? ` (from source folder '${basename15(absoluteSource)}')` : ""} matches a bundled official skill.`;
38602
38612
  throw new Error(`${via} Importing it would shadow the official '${skillName}'. ` + `Pass --name to choose a different name, or --allow-shadow to override deliberately.`);
38603
38613
  }
38604
- const readOnlyDestination = join32(resolvePortableSkillsRoot(options, false), skillName);
38614
+ const readOnlyDestination = join33(resolvePortableSkillsRoot(options, false), skillName);
38605
38615
  assertPortableAuthoringPath(readOnlyDestination, options);
38606
38616
  assertDisjointImportPaths(absoluteSource, readOnlyDestination);
38607
38617
  const root = getPortableSkillsRoot(options);
38608
- const destination = join32(root, skillName);
38618
+ const destination = join33(root, skillName);
38609
38619
  assertPortableAuthoringPath(destination, options);
38610
38620
  assertDisjointImportPaths(absoluteSource, destination);
38611
38621
  if (existsSync12(destination)) {
@@ -38613,7 +38623,7 @@ function portPortableSkill(sourcePath, options = {}) {
38613
38623
  throw new Error(`Skill '${skillName}' already exists at ${destination}`);
38614
38624
  rmSync3(destination, { recursive: true, force: true });
38615
38625
  }
38616
- mkdirSync8(dirname23(destination), { recursive: true });
38626
+ mkdirSync8(dirname24(destination), { recursive: true });
38617
38627
  copySkillDirectory(absoluteSource, destination);
38618
38628
  const base = {
38619
38629
  ...inferred,
@@ -38632,18 +38642,29 @@ function safeNormalizeName(name) {
38632
38642
  }
38633
38643
  function validatePortableSkillDirectory(name, skillPath) {
38634
38644
  const normalizedName = normalizePortableSkillName(name);
38635
- const base = validateSkillDirectory(normalizedName, skillPath);
38645
+ let manifest;
38646
+ let manifestError;
38647
+ if (existsSync12(skillPath)) {
38648
+ try {
38649
+ manifest = readPortableSkillManifest(skillPath, normalizedName);
38650
+ } catch (error61) {
38651
+ manifestError = error61;
38652
+ }
38653
+ }
38654
+ const base = validateSkillDirectory(normalizedName, skillPath, undefined, { kind: manifest?.kind });
38636
38655
  const issues = [...base.issues];
38637
38656
  const warnings = [...base.warnings];
38638
- let manifest;
38639
38657
  if (existsSync12(skillPath)) {
38640
- const skillJsonPath = join32(skillPath, "skill.json");
38641
- const skillMdPath = join32(skillPath, "SKILL.md");
38658
+ const skillJsonPath = join33(skillPath, "skill.json");
38659
+ const skillMdPath = join33(skillPath, "SKILL.md");
38642
38660
  if (!existsSync12(skillJsonPath) && !existsSync12(skillMdPath)) {
38643
38661
  add3(issues, "portable.manifest_missing", "Missing portable manifest: expected SKILL.md frontmatter and/or skill.json");
38644
38662
  }
38645
38663
  try {
38646
- manifest = readPortableSkillManifest(skillPath, normalizedName);
38664
+ if (manifestError)
38665
+ throw manifestError;
38666
+ if (!manifest)
38667
+ throw new Error("Portable manifest could not be read");
38647
38668
  const isInstruction = manifest.kind === "instruction";
38648
38669
  if (manifest.name !== normalizedName) {
38649
38670
  add3(issues, "portable.name_mismatch", `Portable manifest name '${manifest.name}' does not match '${normalizedName}'`);
@@ -38658,27 +38679,11 @@ function validatePortableSkillDirectory(name, skillPath) {
38658
38679
  add3(issues, "portable.version_missing", "Portable manifest missing version");
38659
38680
  }
38660
38681
  const contractIssues = validatePortableManifestContract(manifest, {
38661
- strict: existsSync12(join32(skillPath, "skill.json")),
38682
+ strict: existsSync12(join33(skillPath, "skill.json")),
38662
38683
  skillPath
38663
38684
  });
38664
38685
  for (const issue2 of contractIssues)
38665
38686
  add3(issues, issue2.code, issue2.message);
38666
- if (manifest.kind === "instruction") {
38667
- const executableOnlyCodes = new Set([
38668
- "package.missing",
38669
- "package.bin_missing",
38670
- "skill.src_missing",
38671
- "skill.src_index_missing",
38672
- "skill.runtime_entrypoint_unsafe",
38673
- "skill.runtime_entrypoint_missing",
38674
- "skill.runtime_entrypoint_symlink",
38675
- "skill.runtime_entrypoint_not_file"
38676
- ]);
38677
- for (let i = issues.length - 1;i >= 0; i--) {
38678
- if (executableOnlyCodes.has(issues[i].code))
38679
- issues.splice(i, 1);
38680
- }
38681
- }
38682
38687
  if (!isInstruction && (!Array.isArray(manifest.inputs) || manifest.inputs.length === 0)) {
38683
38688
  add3(issues, "portable.inputs_missing", "Portable manifest must declare inputs");
38684
38689
  }
@@ -38698,7 +38703,7 @@ function validatePortableSkillDirectory(name, skillPath) {
38698
38703
  add3(issues, "portable.command_entry_unsafe", `Command '${command.name}' entry '${command.entry}' must stay inside the skill directory`);
38699
38704
  continue;
38700
38705
  }
38701
- const entryPath = join32(skillPath, command.entry);
38706
+ const entryPath = join33(skillPath, command.entry);
38702
38707
  if (!existsSync12(entryPath))
38703
38708
  add3(issues, "portable.command_entry_missing", `Command '${command.name}' entry '${command.entry}' is missing`);
38704
38709
  else if (statSync9(entryPath).isDirectory())
@@ -38709,7 +38714,7 @@ function validatePortableSkillDirectory(name, skillPath) {
38709
38714
  } catch (error61) {
38710
38715
  add3(issues, "portable.manifest_invalid", error61.message);
38711
38716
  }
38712
- if (manifest?.kind !== "instruction" && !existsSync12(join32(skillPath, "AGENTS.md"))) {
38717
+ if (manifest?.kind !== "instruction" && !existsSync12(join33(skillPath, "AGENTS.md"))) {
38713
38718
  add3(issues, "portable.agents_missing", "Missing AGENTS.md with build-out instructions for coding agents");
38714
38719
  }
38715
38720
  }
@@ -38847,8 +38852,8 @@ var init_registry_types = __esm(() => {
38847
38852
  });
38848
38853
 
38849
38854
  // src/lib/registry.ts
38850
- import { existsSync as existsSync13, readFileSync as readFileSync18, readdirSync as readdirSync10 } from "fs";
38851
- import { join as join33 } from "path";
38855
+ import { existsSync as existsSync13, readFileSync as readFileSync19, readdirSync as readdirSync11 } from "fs";
38856
+ import { join as join34 } from "path";
38852
38857
  function parseSkillMdFrontmatter(content) {
38853
38858
  const match = content.match(/^---\n([\s\S]*?)\n---/);
38854
38859
  if (!match)
@@ -38885,16 +38890,16 @@ function discoverSkillsInDir(dir, source = "custom") {
38885
38890
  return [];
38886
38891
  const result = [];
38887
38892
  try {
38888
- const entries = readdirSync10(dir, { withFileTypes: true });
38893
+ const entries = readdirSync11(dir, { withFileTypes: true });
38889
38894
  for (const entry of entries) {
38890
38895
  if (!entry.isDirectory())
38891
38896
  continue;
38892
- const skillMdPath = join33(dir, entry.name, "SKILL.md");
38897
+ const skillMdPath = join34(dir, entry.name, "SKILL.md");
38893
38898
  if (!existsSync13(skillMdPath))
38894
38899
  continue;
38895
38900
  let content;
38896
38901
  try {
38897
- content = readFileSync18(skillMdPath, "utf-8");
38902
+ content = readFileSync19(skillMdPath, "utf-8");
38898
38903
  } catch {
38899
38904
  continue;
38900
38905
  }
@@ -38909,7 +38914,7 @@ function discoverSkillsInDir(dir, source = "custom") {
38909
38914
  category: fm.category || "Development Tools",
38910
38915
  tags: fm.tags || [],
38911
38916
  ...fm.kind ? { kind: fm.kind } : {},
38912
- ...isHostedMetadataSkillDir(join33(dir, entry.name)) ? { serverOwned: true } : {},
38917
+ ...isHostedMetadataSkillDir(join34(dir, entry.name)) ? { serverOwned: true } : {},
38913
38918
  source
38914
38919
  });
38915
38920
  }
@@ -38921,17 +38926,17 @@ function findExtensionSkillPath(name) {
38921
38926
  if (!config2.extensionsDir || !existsSync13(config2.extensionsDir))
38922
38927
  return null;
38923
38928
  try {
38924
- const entries = readdirSync10(config2.extensionsDir, { withFileTypes: true });
38929
+ const entries = readdirSync11(config2.extensionsDir, { withFileTypes: true });
38925
38930
  for (const entry of entries) {
38926
38931
  if (!entry.isDirectory())
38927
38932
  continue;
38928
- const skillDir = join33(config2.extensionsDir, entry.name);
38929
- const skillMdPath = join33(skillDir, "SKILL.md");
38933
+ const skillDir = join34(config2.extensionsDir, entry.name);
38934
+ const skillMdPath = join34(skillDir, "SKILL.md");
38930
38935
  if (!existsSync13(skillMdPath))
38931
38936
  continue;
38932
38937
  let content;
38933
38938
  try {
38934
- content = readFileSync18(skillMdPath, "utf-8");
38939
+ content = readFileSync19(skillMdPath, "utf-8");
38935
38940
  } catch {
38936
38941
  continue;
38937
38942
  }
@@ -40143,14 +40148,14 @@ var init_remote_workspace_leave = __esm(() => {
40143
40148
  });
40144
40149
 
40145
40150
  // src/lib/auth-store.ts
40146
- import { chmodSync, existsSync as existsSync14, mkdirSync as mkdirSync9, readFileSync as readFileSync19, renameSync as renameSync4, statSync as statSync10, unlinkSync as unlinkSync4, writeFileSync as writeFileSync7 } from "fs";
40147
- import { basename as basename15, dirname as dirname24, join as join34 } from "path";
40151
+ import { chmodSync, existsSync as existsSync14, mkdirSync as mkdirSync9, readFileSync as readFileSync20, renameSync as renameSync4, statSync as statSync10, unlinkSync as unlinkSync4, writeFileSync as writeFileSync7 } from "fs";
40152
+ import { basename as basename16, dirname as dirname25, join as join35 } from "path";
40148
40153
  function getAuthFilePath(env = process.env) {
40149
40154
  return skillsCredentialFilePath(env);
40150
40155
  }
40151
40156
  function getIdentityFilePath(env = process.env) {
40152
40157
  const file2 = skillsCredentialFilePath(env);
40153
- return join34(dirname24(file2), basename15(file2).replace(/^credentials/, "identity") + ".json");
40158
+ return join35(dirname25(file2), basename16(file2).replace(/^credentials/, "identity") + ".json");
40154
40159
  }
40155
40160
  function getApiUrl(action, env = process.env, options = {}) {
40156
40161
  return requireSkillsApiOrigin(action, env, options);
@@ -40485,6 +40490,130 @@ var init_remote_permissions = __esm(() => {
40485
40490
  };
40486
40491
  });
40487
40492
 
40493
+ // src/lib/revision.ts
40494
+ import { createHash as createHash26 } from "crypto";
40495
+ function revisionIdOf(content) {
40496
+ const canonicalContent = {
40497
+ slug: content.slug,
40498
+ displayName: content.displayName,
40499
+ description: content.description,
40500
+ category: content.category,
40501
+ tags: content.tags,
40502
+ source: content.source,
40503
+ kind: content.kind,
40504
+ version: content.version ?? null,
40505
+ skillMd: content.skillMd ?? null,
40506
+ bundleSha256: content.bundleSha256 ?? null,
40507
+ bundleByteSize: content.bundleByteSize ?? null
40508
+ };
40509
+ if (content.lifecycle === "archived" || content.archiveReason !== undefined || content.replacementSlug !== undefined) {
40510
+ canonicalContent.lifecycle = content.lifecycle ?? "active";
40511
+ canonicalContent.archiveReason = content.archiveReason ?? null;
40512
+ canonicalContent.replacementSlug = content.replacementSlug ?? null;
40513
+ }
40514
+ const canonical9 = JSON.stringify(canonicalContent);
40515
+ return createHash26("sha256").update(canonical9).digest("hex");
40516
+ }
40517
+ var REVISION_ID_PATTERN;
40518
+ var init_revision = __esm(() => {
40519
+ REVISION_ID_PATTERN = /^[0-9a-f]{64}$/;
40520
+ });
40521
+
40522
+ // src/lib/skill-metadata-update.ts
40523
+ function metadataPatch(value) {
40524
+ if (!object7(value))
40525
+ throw new SkillMetadataUpdateError("INVALID_METADATA_PATCH");
40526
+ const keys2 = Object.keys(value);
40527
+ if (!keys2.length || keys2.some((key2) => !["category", "tags"].includes(key2)))
40528
+ throw new SkillMetadataUpdateError("INVALID_METADATA_PATCH");
40529
+ const copy = {};
40530
+ if (Object.hasOwn(value, "category"))
40531
+ copy.category = value.category;
40532
+ if (Object.hasOwn(value, "tags")) {
40533
+ const tags = value.tags;
40534
+ copy.tags = Array.isArray(tags) ? Array.from(tags) : tags;
40535
+ }
40536
+ if (Object.hasOwn(copy, "category") && !text3(copy.category))
40537
+ throw new SkillMetadataUpdateError("INVALID_METADATA_PATCH");
40538
+ if (Object.hasOwn(copy, "tags") && (!Array.isArray(copy.tags) || copy.tags.length > 100 || copy.tags.some((tag) => !text3(tag)) || new Set(copy.tags).size !== copy.tags.length))
40539
+ throw new SkillMetadataUpdateError("INVALID_METADATA_PATCH");
40540
+ return copy;
40541
+ }
40542
+ function metadataSnapshot(value, etag) {
40543
+ if (!object7(value) || !text3(value.slug) || !/^[a-z0-9][a-z0-9._-]*$/.test(value.slug) || ![value.displayName, value.description, value.category, value.publishedSource].every((field3) => typeof field3 === "string") || !Array.isArray(value.tags) || value.tags.some((tag) => typeof tag !== "string") || !["instruction", "executable"].includes(String(value.kind)) || typeof value.revisionId !== "string" || !REVISION_ID_PATTERN.test(value.revisionId) || etag !== `"${value.revisionId}"`)
40544
+ throw new SkillMetadataUpdateError("INVALID_METADATA_SNAPSHOT");
40545
+ const content = {
40546
+ slug: value.slug,
40547
+ displayName: value.displayName,
40548
+ description: value.description,
40549
+ category: value.category,
40550
+ tags: [...value.tags],
40551
+ source: value.publishedSource,
40552
+ kind: value.kind
40553
+ };
40554
+ for (const key2 of ["version", "skillMd", "bundleSha256", "archiveReason", "replacementSlug"]) {
40555
+ if (value[key2] !== undefined) {
40556
+ if (typeof value[key2] !== "string")
40557
+ throw new SkillMetadataUpdateError("INVALID_METADATA_SNAPSHOT");
40558
+ content[key2] = value[key2];
40559
+ }
40560
+ }
40561
+ if (value.bundleByteSize !== undefined) {
40562
+ if (!Number.isSafeInteger(value.bundleByteSize) || value.bundleByteSize < 0)
40563
+ throw new SkillMetadataUpdateError("INVALID_METADATA_SNAPSHOT");
40564
+ content.bundleByteSize = value.bundleByteSize;
40565
+ }
40566
+ if (value.lifecycle !== undefined) {
40567
+ if (value.lifecycle !== "active" && value.lifecycle !== "archived")
40568
+ throw new SkillMetadataUpdateError("INVALID_METADATA_SNAPSHOT");
40569
+ content.lifecycle = value.lifecycle;
40570
+ }
40571
+ if (revisionIdOf(content) !== value.revisionId)
40572
+ throw new SkillMetadataUpdateError("INVALID_METADATA_SNAPSHOT");
40573
+ return { content, revisionId: value.revisionId };
40574
+ }
40575
+ function metadataPlan(value) {
40576
+ if (!object7(value) || Object.keys(value).sort().join(",") !== "authority,before,expectedRevisionId,organizationId,originalDocument,patch,schemaVersion" || value.schemaVersion !== 1 || !text3(value.authority) || !text3(value.organizationId) || !object7(value.before) || typeof value.originalDocument !== "string" || Buffer.byteLength(value.originalDocument) > 2 * 1024 * 1024 || typeof value.expectedRevisionId !== "string" || !REVISION_ID_PATTERN.test(value.expectedRevisionId))
40577
+ throw new SkillMetadataUpdateError("INVALID_METADATA_PLAN");
40578
+ const before = metadataSnapshot({ ...value.before, publishedSource: value.before.source, revisionId: value.expectedRevisionId }, `"${value.expectedRevisionId}"`).content;
40579
+ let original;
40580
+ try {
40581
+ original = JSON.parse(value.originalDocument);
40582
+ } catch {
40583
+ throw new SkillMetadataUpdateError("INVALID_METADATA_PLAN");
40584
+ }
40585
+ const preserved = metadataSnapshot(original, `"${value.expectedRevisionId}"`);
40586
+ if (preserved.revisionId !== value.expectedRevisionId)
40587
+ throw new SkillMetadataUpdateError("INVALID_METADATA_PLAN");
40588
+ return {
40589
+ schemaVersion: 1,
40590
+ authority: value.authority,
40591
+ organizationId: value.organizationId,
40592
+ expectedRevisionId: value.expectedRevisionId,
40593
+ originalDocument: value.originalDocument,
40594
+ before,
40595
+ patch: metadataPatch(value.patch)
40596
+ };
40597
+ }
40598
+ var SkillMetadataUpdateError, object7 = (value) => value !== null && typeof value === "object" && !Array.isArray(value), text3 = (value) => typeof value === "string" && value.length > 0 && value.length <= 512 && !/[\x00-\x1f\x7f]/.test(value);
40599
+ var init_skill_metadata_update = __esm(() => {
40600
+ init_revision();
40601
+ SkillMetadataUpdateError = class SkillMetadataUpdateError extends Error {
40602
+ code;
40603
+ constructor(code) {
40604
+ super({
40605
+ METADATA_AUTH_REQUIRED: "Metadata updates require a signed-in Skills connection; use skills login.",
40606
+ INVALID_METADATA_PATCH: "Metadata patch accepts only category (a nonempty string) and tags (an array of unique nonempty strings).",
40607
+ INVALID_METADATA_SNAPSHOT: "The current skill must carry a matching quoted revision ETag and complete verifiable metadata, body and bundle identity.",
40608
+ INVALID_METADATA_PLAN: "The saved metadata plan must name its original revision, authority, organization, complete original content and category/tags-only patch.",
40609
+ METADATA_REVISION_CONFLICT: "The skill revision changed after preview; inspect it and prepare a new plan.",
40610
+ METADATA_UPDATE_UNCONFIRMED: "Metadata update could not be confirmed by authoritative readback; inspect the current revision before preparing another write."
40611
+ }[code]);
40612
+ this.code = code;
40613
+ }
40614
+ };
40615
+ });
40616
+
40488
40617
  // src/lib/remote-client.ts
40489
40618
  var exports_remote_client = {};
40490
40619
  __export(exports_remote_client, {
@@ -40562,6 +40691,89 @@ class RemoteSkillsClient {
40562
40691
  return null;
40563
40692
  return res.json();
40564
40693
  }
40694
+ async metadataOrganization() {
40695
+ const identity4 = await this.getIdentity();
40696
+ const organization2 = identity4.organization;
40697
+ if (typeof organization2?.id !== "string" || !organization2.id)
40698
+ throw new SkillMetadataUpdateError("INVALID_METADATA_SNAPSHOT");
40699
+ return organization2.id;
40700
+ }
40701
+ async readMetadataSnapshot(slug2) {
40702
+ const response = await this.request(`/api/v1/skills/${encodeURIComponent(slug2)}`);
40703
+ if (!response.ok)
40704
+ throw new RemoteRequestError("/api/v1/skills/:slug", response.status);
40705
+ const bytes = await readBoundedResponse(response, 2 * 1024 * 1024);
40706
+ const originalDocument = new TextDecoder("utf-8", { fatal: true }).decode(bytes);
40707
+ let value;
40708
+ try {
40709
+ value = JSON.parse(originalDocument);
40710
+ } catch {
40711
+ throw new SkillMetadataUpdateError("INVALID_METADATA_SNAPSHOT");
40712
+ }
40713
+ const snapshot2 = metadataSnapshot(value, response.headers.get("etag"));
40714
+ if (snapshot2.content.slug !== slug2)
40715
+ throw new SkillMetadataUpdateError("INVALID_METADATA_SNAPSHOT");
40716
+ return { ...snapshot2, originalDocument };
40717
+ }
40718
+ async prepareSkillMetadataUpdate(slug2, patch) {
40719
+ const captured = metadataPatch(patch);
40720
+ const organizationId = await this.metadataOrganization();
40721
+ const snapshot2 = await this.readMetadataSnapshot(slug2);
40722
+ return metadataPlan({
40723
+ schemaVersion: 1,
40724
+ authority: this.apiUrl,
40725
+ organizationId,
40726
+ expectedRevisionId: snapshot2.revisionId,
40727
+ originalDocument: snapshot2.originalDocument,
40728
+ before: snapshot2.content,
40729
+ patch: captured
40730
+ });
40731
+ }
40732
+ async applySkillMetadataUpdate(input2) {
40733
+ const plan = metadataPlan(input2);
40734
+ if (plan.authority !== this.apiUrl || await this.metadataOrganization() !== plan.organizationId)
40735
+ throw new SkillMetadataUpdateError("INVALID_METADATA_PLAN");
40736
+ const access = await this.getCapabilities({ refresh: true });
40737
+ if (access.permissions?.publish !== true)
40738
+ throw new RemoteSkillsPermissionError("publish");
40739
+ const current = await this.readMetadataSnapshot(plan.before.slug);
40740
+ if (current.revisionId !== plan.expectedRevisionId)
40741
+ throw new SkillMetadataUpdateError("METADATA_REVISION_CONFLICT");
40742
+ const expected = revisionIdOf({ ...plan.before, ...plan.patch });
40743
+ if (expected === current.revisionId)
40744
+ return { status: "unchanged", revisionId: expected };
40745
+ let uncertain = false;
40746
+ try {
40747
+ const response = await this.request(`/api/v1/skills/${encodeURIComponent(plan.before.slug)}`, {
40748
+ method: "PATCH",
40749
+ headers: { "If-Match": `"${plan.expectedRevisionId}"` },
40750
+ body: JSON.stringify(plan.patch)
40751
+ });
40752
+ if (!response.ok && response.status < 500)
40753
+ throw new RemoteRequestError("/api/v1/skills/:slug", response.status);
40754
+ if (!response.ok)
40755
+ uncertain = true;
40756
+ else {
40757
+ const bytes = await readBoundedResponse(response, 2 * 1024 * 1024);
40758
+ const written = metadataSnapshot(JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(bytes)), response.headers.get("etag"));
40759
+ if (written.revisionId !== expected)
40760
+ throw new SkillMetadataUpdateError("METADATA_UPDATE_UNCONFIRMED");
40761
+ }
40762
+ } catch (error61) {
40763
+ if (error61 instanceof RemoteRequestError && error61.status < 500)
40764
+ throw error61;
40765
+ uncertain = true;
40766
+ }
40767
+ let verified;
40768
+ try {
40769
+ verified = await this.readMetadataSnapshot(plan.before.slug);
40770
+ } catch {
40771
+ throw new SkillMetadataUpdateError("METADATA_UPDATE_UNCONFIRMED");
40772
+ }
40773
+ if (verified.revisionId !== expected)
40774
+ throw new SkillMetadataUpdateError("METADATA_UPDATE_UNCONFIRMED");
40775
+ return { status: uncertain ? "reconciled" : "applied", revisionId: expected };
40776
+ }
40565
40777
  async getSkillStatus(slug2) {
40566
40778
  const res = await this.request(`/api/v1/skills/${encodeURIComponent(slug2)}`, { method: "GET" });
40567
40779
  let body = null;
@@ -41432,6 +41644,8 @@ var init_remote_client = __esm(() => {
41432
41644
  init_remote_credit_checkout();
41433
41645
  init_remote_quote_errors();
41434
41646
  init_remote_permissions();
41647
+ init_skill_metadata_update();
41648
+ init_revision();
41435
41649
  RemoteRouteUnsupportedError = class RemoteRouteUnsupportedError extends Error {
41436
41650
  path;
41437
41651
  status;
@@ -41619,7 +41833,7 @@ var init_remote_invitation_recovery = __esm(() => {
41619
41833
  });
41620
41834
 
41621
41835
  // src/lib/remote-private-publications.ts
41622
- import { createHash as createHash26 } from "crypto";
41836
+ import { createHash as createHash27 } from "crypto";
41623
41837
  function checkedPrivateSkillCreate(value) {
41624
41838
  const refuse5 = (field3, accepted) => {
41625
41839
  throw new PrivatePublicationError("INVALID_SKILL_CREATE_INPUT", `Invalid ${field3}. ${accepted}`);
@@ -41915,7 +42129,7 @@ var PRIVATE_PUBLICATION_MAX_BYTES, skillCreateFailures, failures2, PrivatePublic
41915
42129
  throw new PrivatePublicationError("INVALID_PUBLICATION_INPUT", "Invalid publication input or recovery data.");
41916
42130
  }, invalid4 = () => {
41917
42131
  throw new PrivatePublicationError("INVALID_PUBLICATION_RESPONSE", "The server returned an invalid publication result.");
41918
- }, publicationUuid = (v) => typeof v === "string" && /^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/.test(v), hash4 = (v) => typeof v === "string" && /^[a-f0-9]{64}$/.test(v), record10 = (v) => !!v && typeof v === "object" && !Array.isArray(v), exact = (v, keys2) => record10(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) => createHash26("sha256").update(bytes).digest("hex");
42132
+ }, publicationUuid = (v) => typeof v === "string" && /^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/.test(v), hash4 = (v) => typeof v === "string" && /^[a-f0-9]{64}$/.test(v), record10 = (v) => !!v && typeof v === "object" && !Array.isArray(v), exact = (v, keys2) => record10(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) => createHash27("sha256").update(bytes).digest("hex");
41919
42133
  var init_remote_private_publications = __esm(() => {
41920
42134
  init_fleet_credentials();
41921
42135
  init_remote_workspace_selection();
@@ -41986,8 +42200,8 @@ async function requestAuthApi(instance, path, options) {
41986
42200
  apiUrl: safeUrl
41987
42201
  });
41988
42202
  }
41989
- const text3 = await res.text();
41990
- const body = text3 ? parseJsonBody(text3) : {};
42203
+ const text4 = await res.text();
42204
+ const body = text4 ? parseJsonBody(text4) : {};
41991
42205
  if (!res.ok) {
41992
42206
  const record11 = isRecord6(body) ? body : {};
41993
42207
  const detail = typeof record11.detail === "string" ? record11.detail : undefined;
@@ -42003,15 +42217,15 @@ async function requestAuthApi(instance, path, options) {
42003
42217
  }
42004
42218
  return body;
42005
42219
  }
42006
- function parseJsonBody(text3) {
42220
+ function parseJsonBody(text4) {
42007
42221
  try {
42008
- return JSON.parse(text3);
42222
+ return JSON.parse(text4);
42009
42223
  } catch {
42010
- return { detail: condenseErrorBody(text3) };
42224
+ return { detail: condenseErrorBody(text4) };
42011
42225
  }
42012
42226
  }
42013
- function condenseErrorBody(text3) {
42014
- const stripped = /<[a-z!/]/i.test(text3) ? text3.replace(/<(script|style)[\s\S]*?<\/\1>/gi, " ").replace(/<[^>]*>/g, " ") : text3;
42227
+ function condenseErrorBody(text4) {
42228
+ const stripped = /<[a-z!/]/i.test(text4) ? text4.replace(/<(script|style)[\s\S]*?<\/\1>/gi, " ").replace(/<[^>]*>/g, " ") : text4;
42015
42229
  const collapsed = stripped.replace(/\s+/g, " ").trim();
42016
42230
  if (collapsed.length <= MAX_ERROR_DETAIL_LENGTH)
42017
42231
  return collapsed;
@@ -42202,10 +42416,10 @@ var init_remote_auth = __esm(() => {
42202
42416
  });
42203
42417
 
42204
42418
  // src/lib/workspace-profile.ts
42205
- import { constants as constants17, closeSync as closeSync19, fstatSync as fstatSync19, lstatSync as lstatSync25, mkdirSync as mkdirSync10, mkdtempSync as mkdtempSync2, openSync as openSync19, readFileSync as readFileSync20, renameSync as renameSync5, rmSync as rmSync4, writeFileSync as writeFileSync8 } from "fs";
42419
+ import { constants as constants17, closeSync as closeSync19, fstatSync as fstatSync19, lstatSync as lstatSync26, mkdirSync as mkdirSync10, mkdtempSync as mkdtempSync2, openSync as openSync19, readFileSync as readFileSync21, renameSync as renameSync5, rmSync as rmSync4, writeFileSync as writeFileSync8 } from "fs";
42206
42420
  function stat2(path) {
42207
42421
  try {
42208
- return lstatSync25(path);
42422
+ return lstatSync26(path);
42209
42423
  } catch (error61) {
42210
42424
  if (error61.code === "ENOENT")
42211
42425
  return null;
@@ -42220,18 +42434,18 @@ function safeText(file2) {
42220
42434
  const s = fstatSync19(fd);
42221
42435
  if (!s.isFile() || s.size > 65536 || ![256, 384].includes(s.mode & 4095) || process.getuid && s.uid !== process.getuid())
42222
42436
  return fail("The selected profile must use bounded owner-only regular files.");
42223
- return readFileSync20(fd, "utf8");
42437
+ return readFileSync21(fd, "utf8");
42224
42438
  } finally {
42225
42439
  closeSync19(fd);
42226
42440
  }
42227
42441
  }
42228
42442
  function checkIdentityMetadata(file2, identity4) {
42229
- const text3 = safeText(file2);
42230
- if (text3 === null)
42443
+ const text4 = safeText(file2);
42444
+ if (text4 === null)
42231
42445
  return;
42232
42446
  let value;
42233
42447
  try {
42234
- value = JSON.parse(text3);
42448
+ value = JSON.parse(text4);
42235
42449
  } catch {
42236
42450
  return fail("The profile identity metadata is invalid. Sign in again before managing this workspace.");
42237
42451
  }
@@ -42434,8 +42648,8 @@ var init_recurring_customer = __esm(() => {
42434
42648
  });
42435
42649
 
42436
42650
  // src/lib/recurring-recovery.ts
42437
- import { constants as constants18, closeSync as closeSync20, fsyncSync as fsyncSync5, fstatSync as fstatSync20, lstatSync as lstatSync26, mkdirSync as mkdirSync11, openSync as openSync20, readSync as readSync13, realpathSync as realpathSync11, renameSync as renameSync6, unlinkSync as unlinkSync5, writeFileSync as writeFileSync9 } from "fs";
42438
- import { dirname as dirname25, isAbsolute as isAbsolute24, join as join35, resolve as resolve25 } from "path";
42651
+ import { constants as constants18, closeSync as closeSync20, fsyncSync as fsyncSync5, fstatSync as fstatSync20, lstatSync as lstatSync27, mkdirSync as mkdirSync11, openSync as openSync20, readSync as readSync13, realpathSync as realpathSync11, renameSync as renameSync6, unlinkSync as unlinkSync5, writeFileSync as writeFileSync9 } from "fs";
42652
+ import { dirname as dirname26, isAbsolute as isAbsolute24, join as join36, resolve as resolve25 } from "path";
42439
42653
  import { randomUUID as randomUUID3 } from "crypto";
42440
42654
 
42441
42655
  class RecoveryOwner {
@@ -42445,12 +42659,12 @@ class RecoveryOwner {
42445
42659
  this.directory = directory;
42446
42660
  if (!isAbsolute24(directory) || resolve25(directory) !== directory || realpathSync11(directory) !== directory)
42447
42661
  invalid5();
42448
- for (let path = directory;; path = dirname25(path)) {
42449
- const stat3 = lstatSync26(path);
42662
+ for (let path = directory;; path = dirname26(path)) {
42663
+ const stat3 = lstatSync27(path);
42450
42664
  if (!stat3.isDirectory() || stat3.isSymbolicLink())
42451
42665
  invalid5();
42452
42666
  this.parents.push({ path, dev: stat3.dev, ino: stat3.ino });
42453
- if (path === dirname25(path))
42667
+ if (path === dirname26(path))
42454
42668
  break;
42455
42669
  }
42456
42670
  this.assert();
@@ -42459,17 +42673,17 @@ class RecoveryOwner {
42459
42673
  if (realpathSync11(this.directory) !== this.directory)
42460
42674
  invalid5();
42461
42675
  for (const prior of this.parents) {
42462
- const now = lstatSync26(prior.path);
42676
+ const now = lstatSync27(prior.path);
42463
42677
  if (!now.isDirectory() || now.isSymbolicLink() || now.dev !== prior.dev || now.ino !== prior.ino)
42464
42678
  invalid5();
42465
42679
  }
42466
- const own2 = lstatSync26(this.directory);
42680
+ const own2 = lstatSync27(this.directory);
42467
42681
  if ((own2.mode & 511) !== 448 || (own2.mode & 3584) !== 0 || process.getuid && own2.uid !== process.getuid())
42468
42682
  invalid5();
42469
42683
  }
42470
42684
  read(name) {
42471
42685
  this.assert();
42472
- const fd = openSync20(join35(this.directory, name), constants18.O_RDONLY | constants18.O_NOFOLLOW | constants18.O_NONBLOCK);
42686
+ const fd = openSync20(join36(this.directory, name), constants18.O_RDONLY | constants18.O_NOFOLLOW | constants18.O_NONBLOCK);
42473
42687
  try {
42474
42688
  const before = fstatSync20(fd);
42475
42689
  if (!before.isFile() || before.nlink !== 1 || (before.mode & 4095) !== 384 || before.size < 1 || before.size > 8192 || process.getuid && before.uid !== process.getuid())
@@ -42482,7 +42696,7 @@ class RecoveryOwner {
42482
42696
  break;
42483
42697
  size += n2;
42484
42698
  }
42485
- const after = fstatSync20(fd), path = lstatSync26(join35(this.directory, name));
42699
+ const after = fstatSync20(fd), path = lstatSync27(join36(this.directory, name));
42486
42700
  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())
42487
42701
  invalid5();
42488
42702
  this.assert();
@@ -42495,7 +42709,7 @@ class RecoveryOwner {
42495
42709
  this.assert();
42496
42710
  const bytes = canonicalJson2(value, 8192) + `
42497
42711
  `;
42498
- const fd = openSync20(join35(this.directory, name), constants18.O_WRONLY | constants18.O_CREAT | constants18.O_EXCL | constants18.O_NOFOLLOW, 384);
42712
+ const fd = openSync20(join36(this.directory, name), constants18.O_WRONLY | constants18.O_CREAT | constants18.O_EXCL | constants18.O_NOFOLLOW, 384);
42499
42713
  try {
42500
42714
  writeFileSync9(fd, bytes);
42501
42715
  fsyncSync5(fd);
@@ -42522,14 +42736,14 @@ class RecoveryOwner {
42522
42736
  if (this.read("state.json") !== expected)
42523
42737
  invalid5();
42524
42738
  this.assert();
42525
- renameSync6(join35(this.directory, name), join35(this.directory, "state.json"));
42739
+ renameSync6(join36(this.directory, name), join36(this.directory, "state.json"));
42526
42740
  this.sync();
42527
42741
  }
42528
42742
  async locked(action) {
42529
42743
  this.assert();
42530
42744
  let fd;
42531
42745
  try {
42532
- fd = openSync20(join35(this.directory, "operation.lock"), constants18.O_WRONLY | constants18.O_CREAT | constants18.O_EXCL | constants18.O_NOFOLLOW, 384);
42746
+ fd = openSync20(join36(this.directory, "operation.lock"), constants18.O_WRONLY | constants18.O_CREAT | constants18.O_EXCL | constants18.O_NOFOLLOW, 384);
42533
42747
  } catch {
42534
42748
  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.");
42535
42749
  }
@@ -42542,10 +42756,10 @@ class RecoveryOwner {
42542
42756
  } finally {
42543
42757
  closeSync20(fd);
42544
42758
  this.assert();
42545
- const now = lstatSync26(join35(this.directory, "operation.lock"));
42759
+ const now = lstatSync27(join36(this.directory, "operation.lock"));
42546
42760
  if (owner2.dev !== now.dev || owner2.ino !== now.ino || !now.isFile() || now.isSymbolicLink())
42547
42761
  invalid5();
42548
- unlinkSync5(join35(this.directory, "operation.lock"));
42762
+ unlinkSync5(join36(this.directory, "operation.lock"));
42549
42763
  this.sync();
42550
42764
  }
42551
42765
  }
@@ -42578,7 +42792,7 @@ function base(customer, organizationId) {
42578
42792
  };
42579
42793
  }
42580
42794
  function create(directory, intent) {
42581
- if (!isAbsolute24(directory) || resolve25(directory) !== directory || realpathSync11(dirname25(directory)) !== dirname25(directory))
42795
+ if (!isAbsolute24(directory) || resolve25(directory) !== directory || realpathSync11(dirname26(directory)) !== dirname26(directory))
42582
42796
  invalid5();
42583
42797
  mkdirSync11(directory, { mode: 448 });
42584
42798
  const owner2 = new RecoveryOwner(directory), checked = intentSchema.parse(intent), intentSha256 = canonicalJsonSha256(checked);
@@ -44315,17 +44529,17 @@ var init_tool_primitives = __esm(() => {
44315
44529
 
44316
44530
  // src/lib/compact-output.ts
44317
44531
  function truncateText(value, maxChars = 96) {
44318
- const text3 = String(value ?? "").replace(/\s+/g, " ").trim();
44319
- if (text3.length <= maxChars)
44320
- return text3;
44321
- return `${text3.slice(0, Math.max(0, maxChars - 3)).trimEnd()}...`;
44532
+ const text4 = String(value ?? "").replace(/\s+/g, " ").trim();
44533
+ if (text4.length <= maxChars)
44534
+ return text4;
44535
+ return `${text4.slice(0, Math.max(0, maxChars - 3)).trimEnd()}...`;
44322
44536
  }
44323
44537
  function previewText(value, maxChars = DEFAULT_PREVIEW_CHARS) {
44324
- const text3 = String(value ?? "");
44538
+ const text4 = String(value ?? "");
44325
44539
  return {
44326
- text: text3.length > maxChars ? `${text3.slice(0, Math.max(0, maxChars - 3))}...` : text3,
44327
- length: text3.length,
44328
- truncated: text3.length > maxChars
44540
+ text: text4.length > maxChars ? `${text4.slice(0, Math.max(0, maxChars - 3))}...` : text4,
44541
+ length: text4.length,
44542
+ truncated: text4.length > maxChars
44329
44543
  };
44330
44544
  }
44331
44545
  function parsePageLimit(value, fallback, options = {}) {
@@ -44675,21 +44889,21 @@ var init_credential_state = __esm(() => {
44675
44889
  });
44676
44890
 
44677
44891
  // src/lib/run-state.ts
44678
- import { createHash as createHash27, randomBytes } from "crypto";
44679
- import { existsSync as existsSync15, mkdirSync as mkdirSync12, readFileSync as readFileSync21, readdirSync as readdirSync11, statSync as statSync11, writeFileSync as writeFileSync10 } from "fs";
44680
- import { extname, join as join36, relative as relative9 } from "path";
44892
+ import { createHash as createHash28, randomBytes } from "crypto";
44893
+ import { existsSync as existsSync15, mkdirSync as mkdirSync12, readFileSync as readFileSync22, readdirSync as readdirSync12, statSync as statSync11, writeFileSync as writeFileSync10 } from "fs";
44894
+ import { extname, join as join37, relative as relative9 } from "path";
44681
44895
  function createSkillRun(params, targetDir = process.cwd()) {
44682
44896
  const now = new Date;
44683
44897
  const id = createRunId(now);
44684
44898
  const day = now.toISOString().slice(0, 10);
44685
44899
  const skillName = normalizeSkillName(params.skill);
44686
44900
  const root = getProjectStateDir(targetDir);
44687
- const runDir = join36(root, "runs", day, id);
44688
- const logsDir = join36(runDir, "logs");
44689
- const exportDir = join36(root, "exports", skillName, id);
44901
+ const runDir = join37(root, "runs", day, id);
44902
+ const logsDir = join37(runDir, "logs");
44903
+ const exportDir = join37(root, "exports", skillName, id);
44690
44904
  mkdirSync12(logsDir, { recursive: true });
44691
44905
  mkdirSync12(exportDir, { recursive: true });
44692
- mkdirSync12(join36(root, "tmp"), { recursive: true });
44906
+ mkdirSync12(join37(root, "tmp"), { recursive: true });
44693
44907
  const record11 = {
44694
44908
  id,
44695
44909
  skill: skillName,
@@ -44741,22 +44955,22 @@ function updateSkillRun(context2, patch) {
44741
44955
  return context2.record;
44742
44956
  }
44743
44957
  function writeRunLogs(context2, stdout = "", stderr = "") {
44744
- writeFileSync10(join36(context2.logsDir, "stdout.log"), stdout);
44745
- writeFileSync10(join36(context2.logsDir, "stderr.log"), stderr);
44958
+ writeFileSync10(join37(context2.logsDir, "stdout.log"), stdout);
44959
+ writeFileSync10(join37(context2.logsDir, "stderr.log"), stderr);
44746
44960
  }
44747
44961
  function appendRunEvent(context2, event, data = {}) {
44748
44962
  const line = JSON.stringify({ ts: new Date().toISOString(), event, ...data }) + `
44749
44963
  `;
44750
- const path = join36(context2.runDir, "events.ndjson");
44751
- const previous = existsSync15(path) ? readFileSync21(path, "utf-8") : "";
44964
+ const path = join37(context2.runDir, "events.ndjson");
44965
+ const previous = existsSync15(path) ? readFileSync22(path, "utf-8") : "";
44752
44966
  writeFileSync10(path, previous + line);
44753
44967
  }
44754
44968
  function findSkillRun(runId, targetDir = process.cwd()) {
44755
- const runsRoot = join36(getProjectStateDir(targetDir), "runs");
44969
+ const runsRoot = join37(getProjectStateDir(targetDir), "runs");
44756
44970
  if (!existsSync15(runsRoot))
44757
44971
  return null;
44758
- for (const day of readdirSync11(runsRoot)) {
44759
- const record11 = readRunRecord(join36(runsRoot, day, runId));
44972
+ for (const day of readdirSync12(runsRoot)) {
44973
+ const record11 = readRunRecord(join37(runsRoot, day, runId));
44760
44974
  if (record11)
44761
44975
  return record11;
44762
44976
  }
@@ -44773,11 +44987,11 @@ function skillRunEnv(context2) {
44773
44987
  };
44774
44988
  }
44775
44989
  function writeRunRecord(context2) {
44776
- writeFileSync10(join36(context2.runDir, "run.json"), JSON.stringify(context2.record, null, 2) + `
44990
+ writeFileSync10(join37(context2.runDir, "run.json"), JSON.stringify(context2.record, null, 2) + `
44777
44991
  `);
44778
44992
  }
44779
44993
  function writeArtifactsManifest(context2, artifacts) {
44780
- writeFileSync10(join36(context2.runDir, "artifacts.json"), JSON.stringify({ runId: context2.record.id, artifacts }, null, 2) + `
44994
+ writeFileSync10(join37(context2.runDir, "artifacts.json"), JSON.stringify({ runId: context2.record.id, artifacts }, null, 2) + `
44781
44995
  `);
44782
44996
  }
44783
44997
  function collectRunArtifacts(context2) {
@@ -44786,30 +45000,30 @@ function collectRunArtifacts(context2) {
44786
45000
  const artifacts = [];
44787
45001
  for (const path of walkFiles(context2.exportDir)) {
44788
45002
  const stat3 = statSync11(path);
44789
- const bytes = readFileSync21(path);
45003
+ const bytes = readFileSync22(path);
44790
45004
  artifacts.push({
44791
45005
  path: toProjectRelative(context2.targetDir, path),
44792
45006
  mime: mimeForPath(path),
44793
- sha256: createHash27("sha256").update(bytes).digest("hex"),
45007
+ sha256: createHash28("sha256").update(bytes).digest("hex"),
44794
45008
  sizeBytes: stat3.size
44795
45009
  });
44796
45010
  }
44797
45011
  return artifacts.sort((a, b) => a.path.localeCompare(b.path));
44798
45012
  }
44799
45013
  function readRunRecord(runDir) {
44800
- const path = join36(runDir, "run.json");
45014
+ const path = join37(runDir, "run.json");
44801
45015
  if (!existsSync15(path))
44802
45016
  return null;
44803
45017
  try {
44804
- return JSON.parse(readFileSync21(path, "utf-8"));
45018
+ return JSON.parse(readFileSync22(path, "utf-8"));
44805
45019
  } catch {
44806
45020
  return null;
44807
45021
  }
44808
45022
  }
44809
45023
  function walkFiles(dir) {
44810
45024
  const files = [];
44811
- for (const entry of readdirSync11(dir)) {
44812
- const full = join36(dir, entry);
45025
+ for (const entry of readdirSync12(dir)) {
45026
+ const full = join37(dir, entry);
44813
45027
  if (statSync11(full).isDirectory())
44814
45028
  files.push(...walkFiles(full));
44815
45029
  else
@@ -45062,11 +45276,11 @@ var init_cloud_executions = __esm(() => {
45062
45276
  // node_modules/@hasna/secrets/dist/sdk.js
45063
45277
  import { isIP as isIP2 } from "net";
45064
45278
  import { spawnSync as spawnSync5 } from "child_process";
45065
- import { closeSync as closeSync21, fstatSync as fstatSync21, openSync as openSync21, readFileSync as readFileSync22 } from "fs";
45279
+ import { closeSync as closeSync21, fstatSync as fstatSync21, openSync as openSync21, readFileSync as readFileSync23 } from "fs";
45066
45280
  import { O_NOFOLLOW as O_NOFOLLOW3, O_NONBLOCK as O_NONBLOCK3, O_RDONLY as O_RDONLY3 } from "constants";
45067
45281
  import { createRequire as createRequire2 } from "module";
45068
45282
  import { hostname as osHostname2 } from "os";
45069
- import { isAbsolute as isAbsolute26, join as join37 } from "path";
45283
+ import { isAbsolute as isAbsolute26, join as join38 } from "path";
45070
45284
  import { createRequire as createRequire22 } from "module";
45071
45285
  function envToken2(name) {
45072
45286
  return name.toUpperCase().replace(/-/g, "_");
@@ -45097,14 +45311,14 @@ function hasnaHomeDir2(env) {
45097
45311
  if (override)
45098
45312
  return override;
45099
45313
  const home = homeDir2(env);
45100
- return home ? join37(home, HASNA_HOME_DIR2) : null;
45314
+ return home ? join38(home, HASNA_HOME_DIR2) : null;
45101
45315
  }
45102
45316
  function appConfigDir2(name, env) {
45103
45317
  const configRoot = absoluteOverride2(env, HASNA_CONFIG_HOME_ENV_KEY2);
45104
45318
  if (configRoot)
45105
- return join37(configRoot, name);
45319
+ return join38(configRoot, name);
45106
45320
  const root = hasnaHomeDir2(env);
45107
- return root ? join37(root, name, CONFIG_SUBDIR2) : null;
45321
+ return root ? join38(root, name, CONFIG_SUBDIR2) : null;
45108
45322
  }
45109
45323
  function credentialDiskSourceList2(name, env, profile = null) {
45110
45324
  if (!SAFE_APP_SLUG2.test(name))
@@ -45113,7 +45327,7 @@ function credentialDiskSourceList2(name, env, profile = null) {
45113
45327
  if (!directory2)
45114
45328
  return [];
45115
45329
  const file2 = profile ? `${CREDENTIALS_FILE2}-${profile}` : CREDENTIALS_FILE2;
45116
- return [{ path: join37(directory2, file2), tier: "disk" }];
45330
+ return [{ path: join38(directory2, file2), tier: "disk" }];
45117
45331
  }
45118
45332
  function credentialDiskSources2(name, env) {
45119
45333
  return credentialDiskSourceList2(name, env, null).map((s) => s.path);
@@ -45121,10 +45335,10 @@ function credentialDiskSources2(name, env) {
45121
45335
  function profileDiskSources2(name, env, profile) {
45122
45336
  return credentialDiskSourceList2(name, env, profile).map((s) => s.path);
45123
45337
  }
45124
- function parseEnvFile2(text3) {
45338
+ function parseEnvFile2(text4) {
45125
45339
  const values = new Map;
45126
45340
  const unusable = new Set;
45127
- for (const rawLine of text3.split(/\r?\n/)) {
45341
+ for (const rawLine of text4.split(/\r?\n/)) {
45128
45342
  const line = rawLine.trim();
45129
45343
  if (line.length === 0 || line.startsWith("#"))
45130
45344
  continue;
@@ -45188,7 +45402,7 @@ function readAppConfigFile2(path) {
45188
45402
  unsafe("the file is not owned by the current user");
45189
45403
  if (before.size > MAX_CREDENTIAL_FILE_BYTES2)
45190
45404
  unsafe("the file exceeds the size limit");
45191
- const bytes = readFileSync22(fd);
45405
+ const bytes = readFileSync23(fd);
45192
45406
  const after = fstatSync21(fd);
45193
45407
  if (!configFileReadsCoherent2(before, after)) {
45194
45408
  unsafe("the file changed while being read");
@@ -45364,8 +45578,8 @@ function keychainAccount2(env, options) {
45364
45578
  const user = env.USER?.trim();
45365
45579
  return user || null;
45366
45580
  }
45367
- function keychainFailureHint2(text3) {
45368
- const line = text3.split(/\r?\n/).find((entry) => entry.trim().length > 0)?.trim() ?? "";
45581
+ function keychainFailureHint2(text4) {
45582
+ const line = text4.split(/\r?\n/).find((entry) => entry.trim().length > 0)?.trim() ?? "";
45369
45583
  const clean = line.replace(/[\u0000-\u001f\u007f]/g, "").slice(0, 200);
45370
45584
  return clean ? `: ${clean}` : "";
45371
45585
  }
@@ -45943,12 +46157,12 @@ function createHasnaHttpTransportInternal(options, requestBindingProvider) {
45943
46157
  await response.body?.cancel();
45944
46158
  } catch {}
45945
46159
  } else {
45946
- const text3 = await response.text();
45947
- if (text3.length > 0) {
46160
+ const text4 = await response.text();
46161
+ if (text4.length > 0) {
45948
46162
  try {
45949
- parsed = JSON.parse(text3);
46163
+ parsed = JSON.parse(text4);
45950
46164
  } catch {
45951
- parsed = text3;
46165
+ parsed = text4;
45952
46166
  }
45953
46167
  }
45954
46168
  }
@@ -46051,13 +46265,13 @@ class SecretsClient {
46051
46265
  headers,
46052
46266
  redirect: "manual"
46053
46267
  });
46054
- const text3 = await response.text();
46268
+ const text4 = await response.text();
46055
46269
  let body = undefined;
46056
- if (text3) {
46270
+ if (text4) {
46057
46271
  try {
46058
- body = JSON.parse(text3);
46272
+ body = JSON.parse(text4);
46059
46273
  } catch {
46060
- body = text3;
46274
+ body = text4;
46061
46275
  }
46062
46276
  }
46063
46277
  if (!response.ok) {
@@ -46459,7 +46673,7 @@ async function resolveSelectedSecrets(bindings, createClient = createSecretsClie
46459
46673
  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.");
46460
46674
  }
46461
46675
  }
46462
- function redactExecutionSecrets(text3, env) {
46676
+ function redactExecutionSecrets(text4, env) {
46463
46677
  const values = new Set(Object.values(env).flatMap((value) => {
46464
46678
  let encoded = "";
46465
46679
  try {
@@ -46468,8 +46682,8 @@ function redactExecutionSecrets(text3, env) {
46468
46682
  return [value, JSON.stringify(value).slice(1, -1), Buffer.from(value).toString("base64"), encoded];
46469
46683
  }));
46470
46684
  for (const value of [...values].filter(Boolean).sort((a, b) => b.length - a.length))
46471
- text3 = text3.split(value).join("[REDACTED]");
46472
- return text3;
46685
+ text4 = text4.split(value).join("[REDACTED]");
46686
+ return text4;
46473
46687
  }
46474
46688
  var init_execution_secrets = __esm(() => {
46475
46689
  init_sdk();
@@ -46608,10 +46822,10 @@ __export(exports_selected_run, {
46608
46822
  executeSelectedLocal: () => executeSelectedLocal,
46609
46823
  declaredOperation: () => declaredOperation
46610
46824
  });
46611
- import { createHash as createHash28 } from "crypto";
46825
+ import { createHash as createHash29 } from "crypto";
46612
46826
  import { spawn as spawn2 } from "child_process";
46613
46827
  import { mkdirSync as mkdirSync13, mkdtempSync as mkdtempSync3, writeFileSync as writeFileSync11, realpathSync as realpathSync13 } from "fs";
46614
- import { dirname as dirname26, join as join38, resolve as resolve26 } from "path";
46828
+ import { dirname as dirname27, join as join39, resolve as resolve26 } from "path";
46615
46829
  import { tmpdir, hostname as stationHostname2 } from "os";
46616
46830
  async function resolveSelectedRun(spec, profileId, options = {}) {
46617
46831
  const context2 = await resolveSelectionContext(profileId, options);
@@ -46734,7 +46948,7 @@ async function executeSelectedLocal(selected, options = {}) {
46734
46948
  throw new SkillSelectionError("INVALID_SECRET_BINDINGS", "Explicit environment values must be bounded strings without NUL bytes.");
46735
46949
  secretEnv[name] = value;
46736
46950
  }
46737
- const runDirectory = mkdtempSync3(join38(tmpdir(), "skills-execution-"));
46951
+ const runDirectory = mkdtempSync3(join39(tmpdir(), "skills-execution-"));
46738
46952
  const paths = new SkillEntryPaths;
46739
46953
  for (const entry of entries) {
46740
46954
  paths.add(entry.path, 100, () => {
@@ -46742,8 +46956,8 @@ async function executeSelectedLocal(selected, options = {}) {
46742
46956
  }, () => {
46743
46957
  throw new SkillSelectionError("INVALID_BUNDLE_PATH", "The execution bundle path exceeds its limit.");
46744
46958
  });
46745
- const destination = join38(runDirectory, entry.path);
46746
- mkdirSync13(dirname26(destination), { recursive: true, mode: 448 });
46959
+ const destination = join39(runDirectory, entry.path);
46960
+ mkdirSync13(dirname27(destination), { recursive: true, mode: 448 });
46747
46961
  writeFileSync11(destination, entry.bytes, { flag: "wx", mode: entry.mode & 511 });
46748
46962
  }
46749
46963
  env.SKILLS_INPUT_JSON = input2;
@@ -46770,7 +46984,7 @@ async function executeSelectedLocal(selected, options = {}) {
46770
46984
  }
46771
46985
  if (bindings)
46772
46986
  secretEnv = await resolveSelectedSecrets(bindings, options.createSecretsClient);
46773
- const result = await subprocess([executable, ...runtimeName === "bun" ? ["--no-env-file"] : [], join38(runDirectory, declaredEntry), ...args], runDirectory, { ...env, ...secretEnv }, input2, timeoutMs);
46987
+ const result = await subprocess([executable, ...runtimeName === "bun" ? ["--no-env-file"] : [], join39(runDirectory, declaredEntry), ...args], runDirectory, { ...env, ...secretEnv }, input2, timeoutMs);
46774
46988
  result.stdout = redactExecutionSecrets(result.stdout, secretEnv);
46775
46989
  result.stderr = redactExecutionSecrets(result.stderr, secretEnv);
46776
46990
  const receipt = {
@@ -46778,13 +46992,13 @@ async function executeSelectedLocal(selected, options = {}) {
46778
46992
  target: "local",
46779
46993
  runtime: runtimeName,
46780
46994
  entrypoint: declaredEntry,
46781
- inputDigest: `sha256:${createHash28("sha256").update(input2).digest("hex")}`,
46995
+ inputDigest: `sha256:${createHash29("sha256").update(input2).digest("hex")}`,
46782
46996
  runDirectory,
46783
46997
  ...executionGrant ? { executionGrant } : {},
46784
46998
  ...bindings ? { secretBinding: { schema: bindings.schema, selection: bindings.selection, consumer: bindings.consumer, secretsAuthority: bindings.secretsAuthority, bindings: bindings.bindings } } : {},
46785
46999
  ...result
46786
47000
  };
46787
- writeFileSync11(join38(runDirectory, ".execution-receipt.json"), JSON.stringify({ ...receipt, stdout: undefined, stderr: undefined }), { mode: 384 });
47001
+ writeFileSync11(join39(runDirectory, ".execution-receipt.json"), JSON.stringify({ ...receipt, stdout: undefined, stderr: undefined }), { mode: 384 });
46788
47002
  return receipt;
46789
47003
  }
46790
47004
  async function subprocess(command, cwd, env, input2, timeoutMs) {
@@ -46973,8 +47187,8 @@ var init_blog_article = __esm(() => {
46973
47187
  });
46974
47188
 
46975
47189
  // src/mcp/operation-tools.ts
46976
- import { existsSync as existsSync16, readdirSync as readdirSync12, statSync as statSync12 } from "fs";
46977
- import { join as join39 } from "path";
47190
+ import { existsSync as existsSync16, readdirSync as readdirSync13, statSync as statSync12 } from "fs";
47191
+ import { join as join40 } from "path";
46978
47192
  function registerOperationTools(server) {
46979
47193
  server.registerTool("cloud_skill_eligibility", {
46980
47194
  title: "Cloud Skill Eligibility",
@@ -47455,8 +47669,8 @@ function registerOperationTools(server) {
47455
47669
  let skillCount = 0;
47456
47670
  if (exists) {
47457
47671
  try {
47458
- skillCount = readdirSync12(agentSkillsPath).filter((f) => {
47459
- const full = join39(agentSkillsPath, f);
47672
+ skillCount = readdirSync13(agentSkillsPath).filter((f) => {
47673
+ const full = join40(agentSkillsPath, f);
47460
47674
  return !f.startsWith(".") && statSync12(full).isDirectory();
47461
47675
  }).length;
47462
47676
  } catch {}
@@ -47524,14 +47738,14 @@ var init_operation_tools = __esm(() => {
47524
47738
 
47525
47739
  // src/lib/feedback.ts
47526
47740
  import { appendFileSync, existsSync as existsSync17, mkdirSync as mkdirSync14 } from "fs";
47527
- import { dirname as dirname27, join as join40 } from "path";
47741
+ import { dirname as dirname28, join as join41 } from "path";
47528
47742
  import { Database } from "bun:sqlite";
47529
47743
  function getFeedbackDbPath() {
47530
- return join40(getDataDir(), "skills.db");
47744
+ return join41(getDataDir(), "skills.db");
47531
47745
  }
47532
47746
  function getFeedbackDb() {
47533
47747
  const dbPath = getFeedbackDbPath();
47534
- const dir = dirname27(dbPath);
47748
+ const dir = dirname28(dbPath);
47535
47749
  if (!existsSync17(dir))
47536
47750
  mkdirSync14(dir, { recursive: true });
47537
47751
  const db = new Database(dbPath);
@@ -47559,8 +47773,8 @@ function saveFeedback(input2) {
47559
47773
  throw new Error("Feedback message is required");
47560
47774
  const category = input2.category ?? "general";
47561
47775
  if (isApiMode()) {
47562
- const path = join40(getDataDir(), "feedback.jsonl");
47563
- const dir = dirname27(path);
47776
+ const path = join41(getDataDir(), "feedback.jsonl");
47777
+ const dir = dirname28(path);
47564
47778
  if (!existsSync17(dir))
47565
47779
  mkdirSync14(dir, { recursive: true });
47566
47780
  appendFileSync(path, JSON.stringify({ message, category, email: input2.email ?? null, agent: input2.agent ?? null, version: input2.version ?? null, createdAt: new Date().toISOString() }) + `
@@ -47723,23 +47937,23 @@ var init_resource_meta_tools = __esm(() => {
47723
47937
  });
47724
47938
 
47725
47939
  // src/lib/scheduler.ts
47726
- import { existsSync as existsSync18, readFileSync as readFileSync23, writeFileSync as writeFileSync12, mkdirSync as mkdirSync15 } from "fs";
47727
- import { join as join41 } from "path";
47940
+ import { existsSync as existsSync18, readFileSync as readFileSync24, writeFileSync as writeFileSync12, mkdirSync as mkdirSync15 } from "fs";
47941
+ import { join as join42 } from "path";
47728
47942
  function getSchedulesPath(targetDir = process.cwd()) {
47729
- return join41(targetDir, ".skills", "schedules.json");
47943
+ return join42(targetDir, ".skills", "schedules.json");
47730
47944
  }
47731
47945
  function loadSchedules(targetDir = process.cwd()) {
47732
47946
  const path = getSchedulesPath(targetDir);
47733
47947
  if (existsSync18(path)) {
47734
47948
  try {
47735
- return JSON.parse(readFileSync23(path, "utf-8"));
47949
+ return JSON.parse(readFileSync24(path, "utf-8"));
47736
47950
  } catch {}
47737
47951
  }
47738
47952
  return { version: 1, schedules: [] };
47739
47953
  }
47740
47954
  function saveSchedules(data, targetDir = process.cwd()) {
47741
47955
  const path = getSchedulesPath(targetDir);
47742
- const dir = join41(targetDir, ".skills");
47956
+ const dir = join42(targetDir, ".skills");
47743
47957
  if (!existsSync18(dir))
47744
47958
  mkdirSync15(dir, { recursive: true });
47745
47959
  writeFileSync12(path, JSON.stringify(data, null, 2));
@@ -48011,16 +48225,16 @@ var init_schedule_tools = __esm(() => {
48011
48225
  });
48012
48226
 
48013
48227
  // src/lib/native-storage.ts
48014
- import { createHash as createHash29, createHmac } from "crypto";
48228
+ import { createHash as createHash30, createHmac } from "crypto";
48015
48229
  import {
48016
48230
  existsSync as existsSync19,
48017
48231
  mkdirSync as mkdirSync16,
48018
- readFileSync as readFileSync24,
48019
- readdirSync as readdirSync13,
48232
+ readFileSync as readFileSync25,
48233
+ readdirSync as readdirSync14,
48020
48234
  statSync as statSync13,
48021
48235
  writeFileSync as writeFileSync13
48022
48236
  } from "fs";
48023
- import { dirname as dirname28, join as join42, normalize as normalize5, relative as relative10, sep as sep14 } from "path";
48237
+ import { dirname as dirname29, join as join43, normalize as normalize5, relative as relative10, sep as sep14 } from "path";
48024
48238
  function resolveSkillsNativeStorageConfig(env = process.env) {
48025
48239
  assertNoRetiredModeEnvVars(env, {
48026
48240
  app: SKILLS_ENV_NAMESPACE,
@@ -48061,7 +48275,7 @@ function getSkillsNativeStorageStatus(options = {}) {
48061
48275
  local: {
48062
48276
  dataDir: getDataDir(),
48063
48277
  projectStateDir: getProjectStateDir(targetDir),
48064
- feedbackDbPath: join42(getDataDir(), "skills.db")
48278
+ feedbackDbPath: join43(getDataDir(), "skills.db")
48065
48279
  },
48066
48280
  remote: {
48067
48281
  databaseConfigured: Boolean(config2.databaseUrl),
@@ -48083,12 +48297,12 @@ function exportSkillsLocalSnapshot(targetDir = process.cwd(), options = {}) {
48083
48297
  const files = [];
48084
48298
  if (existsSync19(projectStateDir)) {
48085
48299
  for (const filePath of walkFiles2(projectStateDir)) {
48086
- const bytes = readFileSync24(filePath);
48300
+ const bytes = readFileSync25(filePath);
48087
48301
  const relativePath = toPosix(relative10(targetDir, filePath));
48088
48302
  files.push({
48089
48303
  path: relativePath,
48090
48304
  sizeBytes: bytes.byteLength,
48091
- sha256: createHash29("sha256").update(bytes).digest("hex"),
48305
+ sha256: createHash30("sha256").update(bytes).digest("hex"),
48092
48306
  ...options.includeFileContents ? { contentBase64: Buffer.from(bytes).toString("base64") } : {}
48093
48307
  });
48094
48308
  }
@@ -48141,8 +48355,8 @@ function parsePositiveInteger(value) {
48141
48355
  }
48142
48356
  function walkFiles2(dir) {
48143
48357
  const files = [];
48144
- for (const entry of readdirSync13(dir)) {
48145
- const full = join42(dir, entry);
48358
+ for (const entry of readdirSync14(dir)) {
48359
+ const full = join43(dir, entry);
48146
48360
  const stats = statSync13(full);
48147
48361
  if (stats.isDirectory())
48148
48362
  files.push(...walkFiles2(full));
@@ -48408,20 +48622,20 @@ var init_private_publication_customer = __esm(() => {
48408
48622
  });
48409
48623
 
48410
48624
  // src/lib/private-publication-recovery.ts
48411
- import { constants as constants20, closeSync as closeSync23, fsyncSync as fsyncSync6, fstatSync as fstatSync23, lstatSync as lstatSync27, mkdirSync as mkdirSync17, openSync as openSync23, readSync as readSync15, realpathSync as realpathSync14, renameSync as renameSync7, unlinkSync as unlinkSync6, writeFileSync as writeFileSync14 } from "fs";
48412
- import { dirname as dirname29, isAbsolute as isAbsolute27, join as join43, resolve as resolve27 } from "path";
48625
+ import { constants as constants20, closeSync as closeSync23, fsyncSync as fsyncSync6, fstatSync as fstatSync23, lstatSync as lstatSync28, mkdirSync as mkdirSync17, openSync as openSync23, readSync as readSync15, realpathSync as realpathSync14, renameSync as renameSync7, unlinkSync as unlinkSync6, writeFileSync as writeFileSync14 } from "fs";
48626
+ import { dirname as dirname30, isAbsolute as isAbsolute27, join as join44, resolve as resolve27 } from "path";
48413
48627
  import { randomUUID as randomUUID4 } from "crypto";
48414
48628
  function safeDirectory(directory2) {
48415
48629
  if (!isAbsolute27(directory2) || directory2 !== resolve27(directory2) || realpathSync14(directory2) !== directory2)
48416
48630
  return fail2();
48417
- for (let path = directory2;; path = dirname29(path)) {
48418
- const stat3 = lstatSync27(path);
48631
+ for (let path = directory2;; path = dirname30(path)) {
48632
+ const stat3 = lstatSync28(path);
48419
48633
  if (!stat3.isDirectory() || stat3.isSymbolicLink())
48420
48634
  return fail2();
48421
- if (path === dirname29(path))
48635
+ if (path === dirname30(path))
48422
48636
  break;
48423
48637
  }
48424
- const own2 = lstatSync27(directory2);
48638
+ const own2 = lstatSync28(directory2);
48425
48639
  if ((own2.mode & 63) !== 0 || process.getuid && own2.uid !== process.getuid())
48426
48640
  return fail2();
48427
48641
  return { dev: own2.dev, ino: own2.ino };
@@ -48432,7 +48646,7 @@ function unchangedDirectory(directory2, identity4) {
48432
48646
  return fail2();
48433
48647
  }
48434
48648
  function readOwned(directory2, name, max) {
48435
- const identity4 = safeDirectory(directory2), file2 = join43(directory2, name);
48649
+ const identity4 = safeDirectory(directory2), file2 = join44(directory2, name);
48436
48650
  const fd = openSync23(file2, constants20.O_RDONLY | constants20.O_NOFOLLOW);
48437
48651
  try {
48438
48652
  const stat3 = fstatSync23(fd);
@@ -48456,7 +48670,7 @@ function readOwned(directory2, name, max) {
48456
48670
  }
48457
48671
  }
48458
48672
  function writeOwned(directory2, name, bytes) {
48459
- const fd = openSync23(join43(directory2, name), constants20.O_WRONLY | constants20.O_CREAT | constants20.O_EXCL | constants20.O_NOFOLLOW, 384);
48673
+ const fd = openSync23(join44(directory2, name), constants20.O_WRONLY | constants20.O_CREAT | constants20.O_EXCL | constants20.O_NOFOLLOW, 384);
48460
48674
  try {
48461
48675
  writeFileSync14(fd, bytes);
48462
48676
  fsyncSync6(fd);
@@ -48469,7 +48683,7 @@ function save(directory2, value) {
48469
48683
  writeOwned(directory2, temporary, JSON.stringify(value) + `
48470
48684
  `);
48471
48685
  unchangedDirectory(directory2, identity4);
48472
- renameSync7(join43(directory2, temporary), join43(directory2, "receipt.json"));
48686
+ renameSync7(join44(directory2, temporary), join44(directory2, "receipt.json"));
48473
48687
  const fd = openSync23(directory2, constants20.O_RDONLY | constants20.O_NOFOLLOW);
48474
48688
  try {
48475
48689
  fsyncSync6(fd);
@@ -48482,7 +48696,7 @@ function bind(client, receipt) {
48482
48696
  throw new PrivatePublicationError("PUBLICATION_IDENTITY_CHANGED", "The fresh session does not match the recovery directory's server, account and membership.");
48483
48697
  }
48484
48698
  async function locked(directory2, action) {
48485
- const identity4 = safeDirectory(directory2), file2 = join43(directory2, "operation.lock");
48699
+ const identity4 = safeDirectory(directory2), file2 = join44(directory2, "operation.lock");
48486
48700
  let fd;
48487
48701
  try {
48488
48702
  fd = openSync23(file2, constants20.O_WRONLY | constants20.O_CREAT | constants20.O_EXCL | constants20.O_NOFOLLOW, 384);
@@ -48498,7 +48712,7 @@ async function locked(directory2, action) {
48498
48712
  } finally {
48499
48713
  closeSync23(fd);
48500
48714
  unchangedDirectory(directory2, identity4);
48501
- const now = lstatSync27(file2);
48715
+ const now = lstatSync28(file2);
48502
48716
  if (now.dev !== lock.dev || now.ino !== lock.ino || !now.isFile() || now.isSymbolicLink())
48503
48717
  fail2();
48504
48718
  unlinkSync6(file2);
@@ -48550,11 +48764,11 @@ async function preparePrivatePublication(client, sourceDirectory, recoveryDirect
48550
48764
  phase: "prepared",
48551
48765
  intent: null
48552
48766
  };
48553
- if (!isAbsolute27(recoveryDirectory) || resolve27(recoveryDirectory) !== recoveryDirectory || realpathSync14(dirname29(recoveryDirectory)) !== dirname29(recoveryDirectory))
48767
+ if (!isAbsolute27(recoveryDirectory) || resolve27(recoveryDirectory) !== recoveryDirectory || realpathSync14(dirname30(recoveryDirectory)) !== dirname30(recoveryDirectory))
48554
48768
  return fail2();
48555
48769
  mkdirSync17(recoveryDirectory, { mode: 448 });
48556
48770
  safeDirectory(recoveryDirectory);
48557
- const parent = openSync23(dirname29(recoveryDirectory), constants20.O_RDONLY | constants20.O_NOFOLLOW);
48771
+ const parent = openSync23(dirname30(recoveryDirectory), constants20.O_RDONLY | constants20.O_NOFOLLOW);
48558
48772
  try {
48559
48773
  fsyncSync6(parent);
48560
48774
  } finally {
@@ -49005,13 +49219,13 @@ function legacyInputSchema(rest) {
49005
49219
  function jsonSchema(schema, io) {
49006
49220
  if (schema === undefined || schema === null)
49007
49221
  return;
49008
- const object7 = isRawShape(schema) ? exports_external.object(schema) : schema;
49009
- const def = object7._zod?.def;
49222
+ const object8 = isRawShape(schema) ? exports_external.object(schema) : schema;
49223
+ const def = object8._zod?.def;
49010
49224
  if (!def)
49011
49225
  throw new Error("Skills MCP tool schemas must be built with this package's zod 4");
49012
49226
  if (def.type !== "object" && def.shape === undefined)
49013
49227
  return;
49014
- return exports_external.toJSONSchema(object7, { target: "draft-7", io });
49228
+ return exports_external.toJSONSchema(object8, { target: "draft-7", io });
49015
49229
  }
49016
49230
  var EMPTY_OBJECT_JSON_SCHEMA;
49017
49231
  var init_package_tool_list = __esm(() => {