@hasna/skills 0.10.80 → 0.10.82

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.82",
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
  }
@@ -23030,7 +23031,7 @@ function hashClaudePluginCacheOrphanMarker(path, budget2, changes) {
23030
23031
  if (!before)
23031
23032
  return null;
23032
23033
  const uid = process.getuid?.();
23033
- if (!before.isFile() || uid === undefined || before.uid !== uid || before.size > 32)
23034
+ if (!before.isFile() || uid === undefined || before.uid !== uid || before.size > 32 || (before.mode & 73) !== 0)
23034
23035
  throw new Error("Invalid Claude orphan marker file or owner");
23035
23036
  const fd = openSync7(path, constants4.O_RDONLY | constants4.O_NOFOLLOW | constants4.O_NONBLOCK);
23036
23037
  try {
@@ -30443,7 +30444,7 @@ function safe2(path) {
30443
30444
  function same2(before, after) {
30444
30445
  return Boolean(after && after.isDirectory() && before.dev === after.dev && before.ino === after.ino && before.mtimeMs === after.mtimeMs && before.ctimeMs === after.ctimeMs);
30445
30446
  }
30446
- function capture(path, budget2, excludedRoots, omittedRoots = [], rows) {
30447
+ function capture(path, budget2, excludedRoots, omittedRoots = [], rows, claudeMarkers) {
30447
30448
  safe2(path);
30448
30449
  if (omittedRoots.some((root2) => path === root2 || path.startsWith(root2 + "/")))
30449
30450
  return { path, sha256: null };
@@ -30471,6 +30472,11 @@ function capture(path, budget2, excludedRoots, omittedRoots = [], rows) {
30471
30472
  need3(child2.length <= AGENT_POLICY_LIMITS.pathCharacters, "Native discovery directory path limit exceeded");
30472
30473
  const stat = lstatSync8(child2);
30473
30474
  need3(stat.isFile() || stat.isDirectory(), "Refusing symlink or special native discovery directory member");
30475
+ if (claudeMarkers && isClaudePluginCacheOrphanMarker(child2)) {
30476
+ need3(hashClaudePluginCacheOrphanMarker(child2) !== null, "Claude orphan marker changed while reading directory");
30477
+ if (claudeMarkers === "omit")
30478
+ continue;
30479
+ }
30474
30480
  const row = JSON.stringify([childRelative, stat.isDirectory() ? "directory" : "file"]) + `
30475
30481
  `;
30476
30482
  budget2.bytes += Buffer.byteLength(row);
@@ -30527,25 +30533,33 @@ function verifyDiscoveryDirectoryProjection(directories, omittedRoots, tolerance
30527
30533
  witnessChanged(new NativeDiscoveryWitnessChange("membership", directories[i].path, "Native discovery directory membership changed outside retired Codex roots"), tolerance, tolerance?.acceptsMembership(directories[i].path) === true);
30528
30534
  }
30529
30535
  }
30530
- function captureDiscoveryDirectories(paths, excludedRoots = []) {
30536
+ function captureOrdinaryDirectories(paths, excludedRoots, claudeMarkers) {
30531
30537
  need3(Array.isArray(paths) && paths.length <= AGENT_POLICY_LIMITS.discoveryDirectories && new Set(paths).size === paths.length, "Invalid native discovery directory collection");
30532
30538
  const budget2 = { entries: 0, bytes: 0 };
30533
30539
  for (const root of excludedRoots)
30534
30540
  safe2(root);
30535
- return paths.map((path) => capture(path, budget2, excludedRoots));
30541
+ return paths.map((path) => capture(path, budget2, excludedRoots, [], undefined, claudeMarkers));
30542
+ }
30543
+ function captureDiscoveryDirectories(paths, excludedRoots = []) {
30544
+ return captureOrdinaryDirectories(paths, excludedRoots, "omit");
30536
30545
  }
30537
30546
  function verifyDiscoveryDirectories(directories, excludedRoots = [], tolerance) {
30538
30547
  need3(Array.isArray(directories) && directories.length <= AGENT_POLICY_LIMITS.discoveryDirectories, "Invalid native discovery directory collection");
30539
30548
  for (const directory of directories)
30540
30549
  need3(directory && typeof directory === "object" && (directory.sha256 === null || typeof directory.sha256 === "string" && /^[a-f0-9]{64}$/.test(directory.sha256)), "Invalid native discovery directory digest");
30541
30550
  const current = captureDiscoveryDirectories(directories.map((directory) => directory.path), excludedRoots);
30551
+ let legacy;
30542
30552
  for (let i = 0;i < directories.length; i++)
30543
30553
  if (current[i].sha256 !== directories[i].sha256) {
30554
+ legacy ??= captureOrdinaryDirectories(directories.map((directory) => directory.path), excludedRoots, "retain");
30555
+ if (legacy[i].sha256 === directories[i].sha256)
30556
+ continue;
30544
30557
  witnessChanged(new NativeDiscoveryWitnessChange("membership", directories[i].path, `Native discovery directory membership changed; run skills hook install with a fresh discovery review: ${directories[i].path}`), tolerance, tolerance?.acceptsMembership(directories[i].path) === true);
30545
30558
  }
30546
30559
  }
30547
30560
  var init_agent_discovery_directories = __esm(() => {
30548
30561
  init_agent_policy_limits();
30562
+ init_claude_plugin_cache_marker();
30549
30563
  init_native_discovery_witness_change();
30550
30564
  });
30551
30565
 
@@ -32310,7 +32324,7 @@ function codexPluginRootCapabilityEntry(name) {
32310
32324
  function isCodexSkillDocumentName(name) {
32311
32325
  return foldCodexPluginEntryName(name) === "skill.md";
32312
32326
  }
32313
- var CODEX_PLUGIN_MANIFEST_LOCATIONS, CODEX_PLUGIN_MANIFEST_DIRECTORIES, CODEX_PLUGIN_ROOT_CAPABILITY_ENTRIES;
32327
+ 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
32328
  var init_codex_plugin_capability_paths = __esm(() => {
32315
32329
  CODEX_PLUGIN_MANIFEST_LOCATIONS = Object.freeze([
32316
32330
  "plugin.json",
@@ -32331,6 +32345,8 @@ var init_codex_plugin_capability_paths = __esm(() => {
32331
32345
  "commands",
32332
32346
  "agents"
32333
32347
  ]);
32348
+ CODEX_PLUGIN_MANIFEST_KNOWN_KEYS = Object.freeze(["name", "version", "description", "author", "homepage", "repository", "license", "keywords", "interface", "skills", "apps"]);
32349
+ CODEX_PLUGIN_DEFAULT_SKILLS_PATHS = Object.freeze(["./skills", "./skills/"]);
32334
32350
  });
32335
32351
 
32336
32352
  // src/lib/codex-hook-mcp-dependencies.ts
@@ -33665,11 +33681,14 @@ var init_codex_hook_rpc = __esm(() => {
33665
33681
  });
33666
33682
 
33667
33683
  // src/lib/codex-native-skill-catalog.ts
33668
- import { realpathSync as realpathSync4 } from "fs";
33669
- import { isAbsolute as isAbsolute14, normalize as normalize3 } from "path";
33684
+ import { lstatSync as lstatSync14, readdirSync as readdirSync5, readFileSync as readFileSync12, realpathSync as realpathSync4 } from "fs";
33685
+ import { basename as basename8, dirname as dirname15, isAbsolute as isAbsolute14, join as join19, normalize as normalize3 } from "path";
33686
+ function codexPluginIsRemote(plugin) {
33687
+ return plugin !== undefined && (plugin.sourceType === "remote" || plugin.remotePluginId !== undefined);
33688
+ }
33670
33689
  function codexPluginSourceIsConfigControlled(plugin) {
33671
33690
  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)));
33691
+ 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
33692
  }
33674
33693
  function refuse() {
33675
33694
  throw new Error("CODEX_NATIVE_SKILL_CATALOG_INVALID");
@@ -33759,16 +33778,16 @@ var init_codex_native_skill_catalog = __esm(() => {
33759
33778
  });
33760
33779
 
33761
33780
  // 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";
33781
+ import { basename as basename9, dirname as dirname16, join as join20, relative as relative5, resolve as resolve14, sep as sep8 } from "path";
33782
+ import { lstatSync as lstatSync15, readdirSync as readdirSync6, readFileSync as readFileSync13, readlinkSync as readlinkSync3, realpathSync as realpathSync5 } from "fs";
33764
33783
  function refuse2() {
33765
33784
  throw new Error("CODEX_NATIVE_SKILL_IDENTITY_UNSUPPORTED: review native plugin names and hook controls");
33766
33785
  }
33767
33786
  function codexRemoteInstallReceipt(parent, read) {
33768
33787
  try {
33769
- if (!lstatSync14(parent).isDirectory() || realpathSync5(parent) !== parent)
33788
+ if (!lstatSync15(parent).isDirectory() || realpathSync5(parent) !== parent)
33770
33789
  return null;
33771
- const path = join19(parent, ".codex-remote-plugin-install.json"), stat2 = lstatSync14(path, { throwIfNoEntry: false });
33790
+ const path = join20(parent, ".codex-remote-plugin-install.json"), stat2 = lstatSync15(path, { throwIfNoEntry: false });
33772
33791
  if (!stat2?.isFile() || stat2.isSymbolicLink() || stat2.size > 16384)
33773
33792
  return null;
33774
33793
  const text2 = read(path);
@@ -33830,7 +33849,7 @@ function mcpControls(path, read) {
33830
33849
  function isBundledCleanupHooks(root, namespace, value) {
33831
33850
  const object5 = (v) => Boolean(v && typeof v === "object" && !Array.isArray(v));
33832
33851
  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")
33852
+ if (basename9(dirname16(root)) !== namespace || basename9(dirname16(dirname16(root))) !== "openai-bundled")
33834
33853
  return false;
33835
33854
  const server = namespace === "unified-computer-use" ? "cua_repl" : ["browser", "chrome", "chrome-dev", "chrome-internal", "computer-use"].includes(namespace) ? "node_repl" : undefined;
33836
33855
  if (!server || !object5(value) || !exactKeys(value, ["hooks"]) || !object5(value.hooks))
@@ -33854,8 +33873,8 @@ function readCodexPluginRootControls(root, read) {
33854
33873
  return rootControls(root, read);
33855
33874
  }
33856
33875
  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)
33876
+ const manifestPath = join20(root, ".codex-plugin/plugin.json"), manifestFile = lstatSync15(manifestPath, { throwIfNoEntry: false });
33877
+ if (!lstatSync15(join20(root, ".codex-plugin"), { throwIfNoEntry: false })?.isDirectory() || !manifestFile?.isFile() || manifestFile.size > 1024 * 1024)
33859
33878
  refuse2();
33860
33879
  let manifest, manifestSha256;
33861
33880
  try {
@@ -33867,12 +33886,12 @@ function rootControls(root, read) {
33867
33886
  }
33868
33887
  if (!manifest || typeof manifest !== "object" || Array.isArray(manifest) || !identifier2(manifest.name))
33869
33888
  refuse2();
33870
- const cacheVersion = basename8(root), declaredVersion = manifest.version === undefined ? "" : typeof manifest.version === "string" ? manifest.version.trim() : null;
33889
+ const cacheVersion = basename9(root), declaredVersion = manifest.version === undefined ? "" : typeof manifest.version === "string" ? manifest.version.trim() : null;
33871
33890
  if (declaredVersion === null || (declaredVersion ? declaredVersion !== cacheVersion : cacheVersion !== CODEX_DEFAULT_AGENT_PLUGIN_VERSION))
33872
33891
  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 }))
33892
+ 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
33893
  refuse2();
33875
- const mcp = join19(root, ".mcp.json"), mcpPresent = lstatSync14(mcp, { throwIfNoEntry: false });
33894
+ const mcp = join20(root, ".mcp.json"), mcpPresent = lstatSync15(mcp, { throwIfNoEntry: false });
33876
33895
  if (manifest.hooks !== undefined && (manifest.mcpServers !== undefined || mcpPresent))
33877
33896
  refuse2();
33878
33897
  if (mcpPresent && (!mcpPresent.isFile() || mcpPresent.isSymbolicLink() || mcpPresent.size > 1024 * 1024 || realpathSync5(mcp) !== mcp))
@@ -33880,7 +33899,7 @@ function rootControls(root, read) {
33880
33899
  if (Boolean(mcpPresent) !== (manifest.mcpServers !== undefined))
33881
33900
  refuse2();
33882
33901
  const mcpSha256 = mcpPresent ? mcpControls(mcp, read) : undefined;
33883
- const app = join19(root, ".app.json"), present = lstatSync14(app, { throwIfNoEntry: false });
33902
+ const app = join20(root, ".app.json"), present = lstatSync15(app, { throwIfNoEntry: false });
33884
33903
  if (present && (!present.isFile() || present.isSymbolicLink() || present.size > 1024 * 1024))
33885
33904
  refuse2();
33886
33905
  if (manifest.apps !== undefined && !present)
@@ -33912,12 +33931,12 @@ function documentIdentity(document2, cache, read) {
33912
33931
  }
33913
33932
  if (!front || typeof front !== "object" || !identifier2(front.name) || typeof front.description !== "string" || !front.description.trim())
33914
33933
  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 }))
33934
+ for (let root = dirname16(document2), depth = 0;root.startsWith(cache + sep8) && depth < 12; root = dirname16(root), depth++) {
33935
+ const path = join20(root, ".codex-plugin", "plugin.json");
33936
+ if (!lstatSync15(path, { throwIfNoEntry: false }))
33918
33937
  continue;
33919
- const manifestFile = lstatSync14(path);
33920
- if (!lstatSync14(join19(root, ".codex-plugin")).isDirectory() || !manifestFile.isFile() || manifestFile.size > 1024 * 1024)
33938
+ const manifestFile = lstatSync15(path);
33939
+ if (!lstatSync15(join20(root, ".codex-plugin")).isDirectory() || !manifestFile.isFile() || manifestFile.size > 1024 * 1024)
33921
33940
  refuse2();
33922
33941
  let manifest;
33923
33942
  try {
@@ -33930,9 +33949,9 @@ function documentIdentity(document2, cache, read) {
33930
33949
  if (!manifest || typeof manifest !== "object" || Array.isArray(manifest) || !identifier2(manifest.name))
33931
33950
  refuse2();
33932
33951
  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))
33952
+ if (declaredVersion === null || (declaredVersion ? declaredVersion !== basename9(root) : basename9(root) !== CODEX_DEFAULT_AGENT_PLUGIN_VERSION))
33934
33953
  refuse2();
33935
- return { name: `${manifest.name}:${front.name}`, namespace: manifest.name, pluginParent: dirname15(root), root };
33954
+ return { name: `${manifest.name}:${front.name}`, namespace: manifest.name, pluginParent: dirname16(root), root };
33936
33955
  }
33937
33956
  refuse2();
33938
33957
  }
@@ -33948,7 +33967,7 @@ function classifyCodexPluginCacheDocument(document2, cache, read) {
33948
33967
  return null;
33949
33968
  try {
33950
33969
  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"))
33970
+ 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
33971
  return null;
33953
33972
  const parts = relative5(cache, parsed.pluginParent).split(sep8);
33954
33973
  if (parts.length !== 2 || parts.some((part) => !identifier2(part)) || parts[1] !== parsed.namespace)
@@ -33963,11 +33982,11 @@ function reviewedDisabledCodexPluginParent(cache, parent, controls, rules) {
33963
33982
  const parts = relative5(cache, parent).split(sep8), enrolled = controls.filter((control) => control.pluginParent === parent);
33964
33983
  if (resolve14(parent) !== parent || parts.length !== 2 || parts.some((part) => !identifier2(part)) || !enrolled.length || !Array.isArray(rules))
33965
33984
  return false;
33966
- for (let cursor = parent;; cursor = dirname15(cursor)) {
33967
- const stat2 = lstatSync14(cursor, { throwIfNoEntry: false });
33985
+ for (let cursor = parent;; cursor = dirname16(cursor)) {
33986
+ const stat2 = lstatSync15(cursor, { throwIfNoEntry: false });
33968
33987
  if (stat2 && (!stat2.isDirectory() || stat2.isSymbolicLink()))
33969
33988
  return false;
33970
- if (dirname15(cursor) === cursor)
33989
+ if (dirname16(cursor) === cursor)
33971
33990
  break;
33972
33991
  }
33973
33992
  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 +33995,36 @@ function reviewedDisabledCodexPluginParent(cache, parent, controls, rules) {
33976
33995
  }
33977
33996
  }
33978
33997
  function absentDisabledCodexPluginParent(cache, parent, controls, rules) {
33979
- return reviewedDisabledCodexPluginParent(cache, parent, controls, rules) && !lstatSync14(parent, { throwIfNoEntry: false });
33998
+ return reviewedDisabledCodexPluginParent(cache, parent, controls, rules) && !lstatSync15(parent, { throwIfNoEntry: false });
33980
33999
  }
33981
34000
  function reviewedRetiredCodexRoot(cache, root, controls, rules, read, allowAbsent = false) {
33982
34001
  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))
34002
+ const parent = dirname16(root), parts = relative5(cache, parent).split(sep8), enrolled = controls.filter((control) => control.pluginParent === parent);
34003
+ if (resolve14(root) !== root || parts.length !== 2 || parts.some((part) => !identifier2(part)) || !basename9(root) || basename9(root) === "latest" || !enrolled.length || !Array.isArray(rules))
33985
34004
  return false;
33986
- for (let cursor = root;; cursor = dirname15(cursor)) {
33987
- const stat2 = lstatSync14(cursor, { throwIfNoEntry: false });
34005
+ for (let cursor = root;; cursor = dirname16(cursor)) {
34006
+ const stat2 = lstatSync15(cursor, { throwIfNoEntry: false });
33988
34007
  if (stat2 && (!stat2.isDirectory() || stat2.isSymbolicLink()))
33989
34008
  return false;
33990
- if (dirname15(cursor) === cursor)
34009
+ if (dirname16(cursor) === cursor)
33991
34010
  break;
33992
34011
  }
33993
34012
  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
34013
  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));
34014
+ if (!lstatSync15(root, { throwIfNoEntry: false }))
34015
+ return allowAbsent && (lstatSync15(parent, { throwIfNoEntry: false }) ? enrolled.every((control) => remoteInstallationMatches(parent, control.remotePluginId, read)) : absentDisabledCodexPluginParent(cache, parent, controls, rules));
33997
34016
  if (!enrolled.every((control) => remoteInstallationMatches(parent, control.remotePluginId, read)))
33998
34017
  return false;
33999
34018
  const parsed = rootControls(root, read);
34000
- if (JSON.parse(read(join19(root, ".codex-plugin/plugin.json"))).hooks !== undefined)
34019
+ if (JSON.parse(read(join20(root, ".codex-plugin/plugin.json"))).hooks !== undefined)
34001
34020
  return false;
34002
34021
  if (!enrolled.some((control) => control.namespace === parsed.namespace && control.manifestSha256 === parsed.manifestSha256 && !parsed.appSha256 && !parsed.mcpSha256))
34003
34022
  return false;
34004
34023
  let entries = 0;
34005
- const emptySkills = (directory, depth) => depth <= 64 && readdirSync5(directory).every((name) => {
34024
+ const emptySkills = (directory, depth) => depth <= 64 && readdirSync6(directory).every((name) => {
34006
34025
  if (++entries > 4096 || name === "SKILL.md")
34007
34026
  return false;
34008
- const path = join19(directory, name), stat2 = lstatSync14(path);
34027
+ const path = join20(directory, name), stat2 = lstatSync15(path);
34009
34028
  return !stat2.isSymbolicLink() && (stat2.isFile() || stat2.isDirectory() && emptySkills(path, depth + 1));
34010
34029
  });
34011
34030
  return emptySkills(root, 0);
@@ -34021,26 +34040,26 @@ function reviewedCodexPluginCapabilitiesUnchanged(cache, controls, read, rules)
34021
34040
  for (const parent of new Set(controls.map((control) => control.pluginParent))) {
34022
34041
  if (absentDisabledCodexPluginParent(cache, parent, controls, rules))
34023
34042
  continue;
34024
- if (!parent.startsWith(cache + sep8) || !lstatSync14(parent, { throwIfNoEntry: false })?.isDirectory() || realpathSync5(parent) !== parent)
34043
+ if (!parent.startsWith(cache + sep8) || !lstatSync15(parent, { throwIfNoEntry: false })?.isDirectory() || realpathSync5(parent) !== parent)
34025
34044
  return false;
34026
34045
  for (const control of controls.filter((control2) => control2.pluginParent === parent)) {
34027
34046
  if (control.remotePluginId !== undefined && !remoteInstallationMatches(parent, control.remotePluginId, read))
34028
34047
  return false;
34029
34048
  }
34030
- const names = readdirSync5(parent);
34049
+ const names = readdirSync6(parent);
34031
34050
  entries += names.length;
34032
34051
  if (entries > 4096)
34033
34052
  return false;
34034
34053
  for (const name of names) {
34035
- let root = join19(parent, name), stat2 = lstatSync14(root);
34054
+ let root = join20(parent, name), stat2 = lstatSync15(root);
34036
34055
  if (stat2.isSymbolicLink()) {
34037
34056
  const target = resolve14(parent, readlinkSync3(root));
34038
- if (name !== "latest" || dirname15(target) !== parent || !lstatSync14(target).isDirectory() || realpathSync5(target) !== target)
34057
+ if (name !== "latest" || dirname16(target) !== parent || !lstatSync15(target).isDirectory() || realpathSync5(target) !== target)
34039
34058
  return false;
34040
34059
  root = target;
34041
- stat2 = lstatSync14(root);
34060
+ stat2 = lstatSync15(root);
34042
34061
  }
34043
- if (!stat2.isDirectory() || ![".codex-plugin/plugin.json", ".app.json", "hooks", ".mcp.json"].some((path) => lstatSync14(join19(root, path), { throwIfNoEntry: false })))
34062
+ if (!stat2.isDirectory() || ![".codex-plugin/plugin.json", ".app.json", "hooks", ".mcp.json"].some((path) => lstatSync15(join20(root, path), { throwIfNoEntry: false })))
34044
34063
  continue;
34045
34064
  const parsed = rootControls(root, read);
34046
34065
  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 +34074,9 @@ function reviewedCodexPluginCapabilitiesUnchanged(cache, controls, read, rules)
34055
34074
  function sourceInputUnchanged(input2, cache, read) {
34056
34075
  try {
34057
34076
  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))
34077
+ 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
34078
  return false;
34060
- const path = join19(input2.sourceRoot, ".codex-plugin/plugin.json"), stat2 = lstatSync14(path);
34079
+ const path = join20(input2.sourceRoot, ".codex-plugin/plugin.json"), stat2 = lstatSync15(path);
34061
34080
  if (!stat2.isFile() || stat2.size > 1024 * 1024 || realpathSync5(path) !== path)
34062
34081
  return false;
34063
34082
  const text2 = read(path);
@@ -34080,11 +34099,12 @@ var identifier2 = (v) => typeof v === "string" && /^[A-Za-z0-9_-]{1,64}$/.test(v
34080
34099
  var init_codex_plugin_skill_controls = __esm(() => {
34081
34100
  init_claude_settings_witness();
34082
34101
  init_codex_native_compatibility();
34102
+ init_codex_plugin_capability_paths();
34083
34103
  init_codex_native_skill_catalog();
34084
34104
  });
34085
34105
 
34086
34106
  // src/lib/codex-vendor-refresh.ts
34087
- var CODEX_VENDOR_MARKETPLACES, CODEX_REMOTE_VENDOR_MARKETPLACES, OTHER_PLUGIN_CONTROLS, VENDOR_MANIFEST_KEYS, DEFAULT_SKILLS_PATHS;
34107
+ var CODEX_VENDOR_MARKETPLACES, CODEX_REMOTE_VENDOR_MARKETPLACES, OTHER_PLUGIN_CONTROLS;
34088
34108
  var init_codex_vendor_refresh = __esm(() => {
34089
34109
  init_claude_settings_witness();
34090
34110
  init_codex_plugin_skill_controls();
@@ -34092,8 +34112,6 @@ var init_codex_vendor_refresh = __esm(() => {
34092
34112
  CODEX_VENDOR_MARKETPLACES = Object.freeze(["openai-bundled", "openai-curated", "openai-curated-remote"]);
34093
34113
  CODEX_REMOTE_VENDOR_MARKETPLACES = Object.freeze(["openai-curated-remote"]);
34094
34114
  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
34115
  });
34098
34116
 
34099
34117
  // src/lib/claude-plugin-manifest-witness.ts
@@ -34537,19 +34555,19 @@ function capturePreparationProcess(child2, platform = process.platform, signalGr
34537
34555
  }
34538
34556
 
34539
34557
  // 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";
34558
+ 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";
34559
+ import { join as join21 } from "path";
34542
34560
  function hasDependencyPreparationMarker(skillPath) {
34543
34561
  try {
34544
- lstatSync15(join20(skillPath, DEPENDENCY_PREPARATION_MARKER));
34562
+ lstatSync16(join21(skillPath, DEPENDENCY_PREPARATION_MARKER));
34545
34563
  return true;
34546
34564
  } catch (error61) {
34547
34565
  return error61.code !== "ENOENT";
34548
34566
  }
34549
34567
  }
34550
34568
  function claimPreparation(skillPath) {
34551
- const marker = join20(skillPath, DEPENDENCY_PREPARATION_MARKER);
34552
- const state = join20(marker, "state.json"), active = join20(marker, "active");
34569
+ const marker = join21(skillPath, DEPENDENCY_PREPARATION_MARKER);
34570
+ const state = join21(marker, "state.json"), active = join21(marker, "active");
34553
34571
  let created = false;
34554
34572
  try {
34555
34573
  mkdirSync5(marker, { mode: 448 });
@@ -34560,14 +34578,14 @@ function claimPreparation(skillPath) {
34560
34578
  }
34561
34579
  let fd;
34562
34580
  try {
34563
- if (!lstatSync15(marker).isDirectory() || lstatSync15(marker).isSymbolicLink())
34581
+ if (!lstatSync16(marker).isDirectory() || lstatSync16(marker).isSymbolicLink())
34564
34582
  return;
34565
34583
  if (!created) {
34566
- if (readdirSync6(marker).some((name) => name !== "state.json"))
34584
+ if (readdirSync7(marker).some((name) => name !== "state.json"))
34567
34585
  return;
34568
- if (!lstatSync15(state).isFile() || lstatSync15(state).isSymbolicLink() || lstatSync15(state).size > 1024)
34586
+ if (!lstatSync16(state).isFile() || lstatSync16(state).isSymbolicLink() || lstatSync16(state).size > 1024)
34569
34587
  return;
34570
- const previous = JSON.parse(readFileSync13(state, "utf8"));
34588
+ const previous = JSON.parse(readFileSync14(state, "utf8"));
34571
34589
  if (previous.version !== 1 || previous.status !== "failed" || Object.keys(previous).length !== 2)
34572
34590
  return;
34573
34591
  }
@@ -34700,6 +34718,9 @@ async function prepareSkillDependencies(skillPath, env, timeoutMs = DEFAULT_PREP
34700
34718
  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
34719
  var init_dependency_preparation = () => {};
34702
34720
 
34721
+ // src/lib/codex-native-config.ts
34722
+ var init_codex_native_config = () => {};
34723
+
34703
34724
  // src/lib/codex-native-skill-policy.ts
34704
34725
  var MAX_EXECUTABLE_BYTES, MAX_BRIDGE_DOCUMENT_BYTES, CODEX_NATIVE_POLICY_HELPER_MAX_OUTPUT_BYTES, executableDigestMemory;
34705
34726
  var init_codex_native_skill_policy = __esm(() => {
@@ -34711,8 +34732,8 @@ var init_codex_native_skill_policy = __esm(() => {
34711
34732
 
34712
34733
  // src/lib/codex-semantic-cache-witness.ts
34713
34734
  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";
34735
+ 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";
34736
+ 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
34737
  function codexLocalMarketplaceMapsPlugin(text2, marketplace, plugin) {
34717
34738
  try {
34718
34739
  hashNativeJsonControls(text2);
@@ -34734,7 +34755,7 @@ function codexLocalMarketplaceMapsPlugin(text2, marketplace, plugin) {
34734
34755
  }
34735
34756
  }
34736
34757
  function defaultRead(path) {
34737
- const before = lstatSync16(path, { throwIfNoEntry: false, bigint: true });
34758
+ const before = lstatSync17(path, { throwIfNoEntry: false, bigint: true });
34738
34759
  if (before === undefined)
34739
34760
  return refuse3();
34740
34761
  if (!before.isFile() || before.isSymbolicLink() || before.size > BigInt(MAX_DOCUMENT_BYTES))
@@ -34825,7 +34846,7 @@ function assertWitnessShape(value) {
34825
34846
  const row = candidate;
34826
34847
  const remote = row.installation === "remote-receipt";
34827
34848
  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))
34849
+ 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
34850
  refuse3();
34830
34851
  hookParentPaths.add(row.pluginParent);
34831
34852
  }
@@ -34857,23 +34878,23 @@ function assertWitnessShape(value) {
34857
34878
  function assertCanonicalDirectory(path) {
34858
34879
  if (resolve15(path) !== path || realpathSync6(path) !== path)
34859
34880
  refuse3();
34860
- for (let cursor = path;; cursor = dirname16(cursor)) {
34861
- const stat2 = lstatSync16(cursor, { throwIfNoEntry: false });
34881
+ for (let cursor = path;; cursor = dirname17(cursor)) {
34882
+ const stat2 = lstatSync17(cursor, { throwIfNoEntry: false });
34862
34883
  if (stat2 && (!stat2.isDirectory() || stat2.isSymbolicLink()))
34863
34884
  refuse3();
34864
- if (dirname16(cursor) === cursor)
34885
+ if (dirname17(cursor) === cursor)
34865
34886
  break;
34866
34887
  }
34867
34888
  }
34868
34889
  function walkSafeTree(path, state, depth = 0, root = path) {
34869
34890
  if (depth > 64 || ++state.entries > 16384)
34870
34891
  refuse3();
34871
- const names = readdirSync7(path).sort();
34892
+ const names = readdirSync8(path).sort();
34872
34893
  const files = [];
34873
34894
  for (const name of names) {
34874
34895
  if (!name || name === "." || name === ".." || name.includes(sep9) || ++state.entries > 16384)
34875
34896
  refuse3();
34876
- const child2 = join21(path, name), stat2 = lstatSync16(child2, { bigint: true });
34897
+ const child2 = join22(path, name), stat2 = lstatSync17(child2, { bigint: true });
34877
34898
  state.members.push(child2);
34878
34899
  state.signature.push(`${relative6(root, child2)}\x00${stat2.mode}\x00${stat2.dev}\x00${stat2.ino}\x00${stat2.isDirectory() ? 0 : stat2.size}`);
34879
34900
  state.timestamps.set(child2, `${stat2.mtimeNs}\x00${stat2.ctimeNs}`);
@@ -34890,7 +34911,7 @@ function walkSafeTree(path, state, depth = 0, root = path) {
34890
34911
  }
34891
34912
  function treeSnapshot(cacheRoot) {
34892
34913
  const state = { entries: 0, members: [], signature: [], timestamps: new Map };
34893
- const rootStat = lstatSync16(cacheRoot, { throwIfNoEntry: false, bigint: true });
34914
+ const rootStat = lstatSync17(cacheRoot, { throwIfNoEntry: false, bigint: true });
34894
34915
  if (rootStat === undefined)
34895
34916
  return refuse3();
34896
34917
  if (!rootStat.isDirectory() || rootStat.isSymbolicLink() || realpathSync6(cacheRoot) !== cacheRoot)
@@ -34910,7 +34931,7 @@ function assertSameTree(before, after, semanticPaths) {
34910
34931
  function trackedBoundedRead(read) {
34911
34932
  const observed = new Map;
34912
34933
  const stableStat = (path, max) => {
34913
- const stat2 = lstatSync16(path, { throwIfNoEntry: false, bigint: true });
34934
+ const stat2 = lstatSync17(path, { throwIfNoEntry: false, bigint: true });
34914
34935
  if (stat2 === undefined)
34915
34936
  return refuse3();
34916
34937
  if (!stat2.isFile() || stat2.isSymbolicLink() || stat2.size > BigInt(max) || realpathSync6(path) !== path)
@@ -34966,7 +34987,7 @@ function controlProjection(controls, read) {
34966
34987
  ...control.mcpSha256 === undefined ? {} : { mcpSha256: control.mcpSha256 }
34967
34988
  };
34968
34989
  if (row.remotePluginId !== undefined) {
34969
- const receipt = join21(row.pluginParent, ".codex-remote-plugin-install.json"), stat2 = lstatSync16(receipt, { throwIfNoEntry: false });
34990
+ const receipt = join22(row.pluginParent, ".codex-remote-plugin-install.json"), stat2 = lstatSync17(receipt, { throwIfNoEntry: false });
34970
34991
  if (!stat2?.isFile() || stat2.isSymbolicLink() || stat2.size > 16384)
34971
34992
  refuse3();
34972
34993
  try {
@@ -34998,10 +35019,10 @@ function appOnlyParentProjection(cacheRoot, parents2, read) {
34998
35019
  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
35020
  refuse3();
35000
35021
  seen.add(parent.pluginParent);
35001
- const parentStat = lstatSync16(parent.pluginParent, { throwIfNoEntry: false });
35022
+ const parentStat = lstatSync17(parent.pluginParent, { throwIfNoEntry: false });
35002
35023
  if (!parentStat?.isDirectory() || parentStat.isSymbolicLink() || realpathSync6(parent.pluginParent) !== parent.pluginParent)
35003
35024
  refuse3();
35004
- const receipt = join21(parent.pluginParent, ".codex-remote-plugin-install.json"), receiptStat = lstatSync16(receipt, { throwIfNoEntry: false });
35025
+ const receipt = join22(parent.pluginParent, ".codex-remote-plugin-install.json"), receiptStat = lstatSync17(receipt, { throwIfNoEntry: false });
35005
35026
  if (!receiptStat?.isFile() || receiptStat.isSymbolicLink() || receiptStat.size > 16384)
35006
35027
  refuse3();
35007
35028
  let receiptText = "";
@@ -35014,13 +35035,13 @@ function appOnlyParentProjection(cacheRoot, parents2, read) {
35014
35035
  } catch {
35015
35036
  refuse3();
35016
35037
  }
35017
- const versions2 = readdirSync7(parent.pluginParent).filter((name) => name !== ".codex-remote-plugin-install.json");
35038
+ const versions2 = readdirSync8(parent.pluginParent).filter((name) => name !== ".codex-remote-plugin-install.json");
35018
35039
  if (!versions2.length || versions2.length > 4096)
35019
35040
  refuse3();
35020
35041
  const materializations = versions2.map((version2) => {
35021
35042
  if (!/^[A-Za-z0-9][A-Za-z0-9._+-]{0,127}$/.test(version2))
35022
35043
  refuse3();
35023
- const root = join21(parent.pluginParent, version2), stat2 = lstatSync16(root, { throwIfNoEntry: false });
35044
+ const root = join22(parent.pluginParent, version2), stat2 = lstatSync17(root, { throwIfNoEntry: false });
35024
35045
  if (!stat2?.isDirectory() || stat2.isSymbolicLink() || realpathSync6(root) !== root)
35025
35046
  refuse3();
35026
35047
  const rootControls2 = readCodexPluginRootControls(root, read);
@@ -35060,7 +35081,7 @@ function assertJsonValue(value, depth = 0, budget2 = { members: 0 }) {
35060
35081
  }
35061
35082
  }
35062
35083
  function reviewedHookControls(root, read) {
35063
- const manifestPath = join21(root, ".codex-plugin/plugin.json"), hooksPath = join21(root, "hooks/hooks.json");
35084
+ const manifestPath = join22(root, ".codex-plugin/plugin.json"), hooksPath = join22(root, "hooks/hooks.json");
35064
35085
  let manifest, manifestSha256, hooks, hooksSha256;
35065
35086
  try {
35066
35087
  const manifestText = read(manifestPath);
@@ -35073,7 +35094,7 @@ function reviewedHookControls(root, read) {
35073
35094
  } catch {
35074
35095
  return refuse3();
35075
35096
  }
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))
35097
+ 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
35098
  refuse3();
35078
35099
  const manifestRecord = manifest;
35079
35100
  if (!plainObject(hooks) || !exactKeys(hooks, ["hooks"], ["description"]) || !plainObject(hooks.hooks) || hooks.description !== undefined && typeof hooks.description !== "string")
@@ -35104,16 +35125,16 @@ function reviewedHookParentProjection(cacheRoot, parents2, read) {
35104
35125
  const seen = new Set, rows = [];
35105
35126
  for (const parent of parents2) {
35106
35127
  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)
35128
+ 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
35129
  refuse3();
35109
35130
  const parts = relative6(cacheRoot, parent.pluginParent).split(sep9);
35110
35131
  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
35132
  refuse3();
35112
35133
  seen.add(parent.pluginParent);
35113
- const parentStat = lstatSync16(parent.pluginParent, { throwIfNoEntry: false });
35134
+ const parentStat = lstatSync17(parent.pluginParent, { throwIfNoEntry: false });
35114
35135
  if (!parentStat?.isDirectory() || parentStat.isSymbolicLink() || realpathSync6(parent.pluginParent) !== parent.pluginParent)
35115
35136
  refuse3();
35116
- const receiptPath = join21(parent.pluginParent, ".codex-remote-plugin-install.json"), receiptStat = lstatSync16(receiptPath, { throwIfNoEntry: false });
35137
+ const receiptPath = join22(parent.pluginParent, ".codex-remote-plugin-install.json"), receiptStat = lstatSync17(receiptPath, { throwIfNoEntry: false });
35117
35138
  let receiptText;
35118
35139
  if (remote) {
35119
35140
  if (!receiptStat?.isFile() || receiptStat.isSymbolicLink() || receiptStat.size > MAX_RECEIPT_BYTES)
@@ -35140,10 +35161,10 @@ function reviewedHookParentProjection(cacheRoot, parents2, read) {
35140
35161
  if (createHash18("sha256").update(marketplaceText).digest("hex") !== parent.marketplaceSha256 || !codexLocalMarketplaceMapsPlugin(marketplaceText, parts[0], parent.namespace))
35141
35162
  refuse3();
35142
35163
  }
35143
- const materializations = readdirSync7(parent.pluginParent).filter((name) => name !== ".codex-remote-plugin-install.json").map((version2) => {
35164
+ const materializations = readdirSync8(parent.pluginParent).filter((name) => name !== ".codex-remote-plugin-install.json").map((version2) => {
35144
35165
  if (!/^[A-Za-z0-9][A-Za-z0-9._+-]{0,127}$/.test(version2))
35145
35166
  refuse3();
35146
- const root = join21(parent.pluginParent, version2), stat2 = lstatSync16(root, { throwIfNoEntry: false });
35167
+ const root = join22(parent.pluginParent, version2), stat2 = lstatSync17(root, { throwIfNoEntry: false });
35147
35168
  if (!stat2?.isDirectory() || stat2.isSymbolicLink() || realpathSync6(root) !== root)
35148
35169
  refuse3();
35149
35170
  const controls = reviewedHookControls(root, read);
@@ -35172,17 +35193,17 @@ function assertParents(cacheRoot, controls, appOnlyParents, hookParents, files,
35172
35193
  const rel = relative6(cacheRoot, file2), parts = rel.split(sep9);
35173
35194
  if (parts.length < 3 || !identifier4(parts[0]) || !identifier4(parts[1]))
35174
35195
  refuse3();
35175
- actual.add(join21(cacheRoot, parts[0], parts[1]));
35196
+ actual.add(join22(cacheRoot, parts[0], parts[1]));
35176
35197
  }
35177
- const actualMarkets = readdirSync7(cacheRoot);
35198
+ const actualMarkets = readdirSync8(cacheRoot);
35178
35199
  if (actualMarkets.length !== expectedMarkets.size || actualMarkets.some((market) => !expectedMarkets.has(market)))
35179
35200
  refuse3();
35180
35201
  for (const market of actualMarkets) {
35181
- const marketPath = join21(cacheRoot, market), marketStat = lstatSync16(marketPath);
35202
+ const marketPath = join22(cacheRoot, market), marketStat = lstatSync17(marketPath);
35182
35203
  if (!identifier4(market) || !marketStat.isDirectory() || marketStat.isSymbolicLink())
35183
35204
  refuse3();
35184
- for (const plugin of readdirSync7(marketPath)) {
35185
- const parent = join21(marketPath, plugin), stat2 = lstatSync16(parent);
35205
+ for (const plugin of readdirSync8(marketPath)) {
35206
+ const parent = join22(marketPath, plugin), stat2 = lstatSync17(parent);
35186
35207
  if (!identifier4(plugin) || !stat2.isDirectory() || stat2.isSymbolicLink())
35187
35208
  refuse3();
35188
35209
  actual.add(parent);
@@ -35194,8 +35215,8 @@ function assertParents(cacheRoot, controls, appOnlyParents, hookParents, files,
35194
35215
  const parts = relative6(cacheRoot, member).split(sep9);
35195
35216
  if (parts.length < 3)
35196
35217
  continue;
35197
- const parent = join21(cacheRoot, parts[0], parts[1]);
35198
- const root = join21(parent, parts[2]);
35218
+ const parent = join22(cacheRoot, parts[0], parts[1]);
35219
+ const root = join22(parent, parts[2]);
35199
35220
  const base = parts[parts.length - 1], folded = foldCodexPluginEntryName(base);
35200
35221
  if (parts.length === 3 && (codexPluginRootCapabilityEntry(base) !== null || isCodexSkillDocumentName(base)))
35201
35222
  refuse3();
@@ -35208,11 +35229,11 @@ function assertParents(cacheRoot, controls, appOnlyParents, hookParents, files,
35208
35229
  refuse3();
35209
35230
  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
35231
  refuse3();
35211
- if ([".app.json", ".mcp.json"].includes(folded) && (parts.length !== 4 || dirname16(member) !== root))
35232
+ if ([".app.json", ".mcp.json"].includes(folded) && (parts.length !== 4 || dirname17(member) !== root))
35212
35233
  refuse3();
35213
35234
  if ([".app.json", ".mcp.json"].includes(folded) && hookParents.some((reviewed) => reviewed.pluginParent === parent))
35214
35235
  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]))))
35236
+ 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
35237
  refuse3();
35217
35238
  }
35218
35239
  }
@@ -35242,14 +35263,14 @@ function assertSkillMaterializations(cacheRoot, controls, files, read) {
35242
35263
  const expectedNames = new Set(rows.map((row) => row.name));
35243
35264
  if (expectedNames.size !== rows.length)
35244
35265
  refuse3();
35245
- const entries = readdirSync7(parent);
35266
+ const entries = readdirSync8(parent);
35246
35267
  let roots = 0;
35247
35268
  for (const entry of entries) {
35248
35269
  if (entry === ".codex-remote-plugin-install.json")
35249
35270
  continue;
35250
35271
  if (!/^[A-Za-z0-9][A-Za-z0-9._+-]{0,127}$/.test(entry))
35251
35272
  refuse3();
35252
- const root = join21(parent, entry), stat2 = lstatSync16(root, { throwIfNoEntry: false });
35273
+ const root = join22(parent, entry), stat2 = lstatSync17(root, { throwIfNoEntry: false });
35253
35274
  if (!stat2?.isDirectory() || stat2.isSymbolicLink() || realpathSync6(root) !== root)
35254
35275
  refuse3();
35255
35276
  const actualControls = readCodexPluginRootControls(root, read);
@@ -35274,8 +35295,8 @@ function assertSkillMaterializations(cacheRoot, controls, files, read) {
35274
35295
  const rel = relative6(cacheRoot, file2).split(sep9);
35275
35296
  if (rel.length < 4)
35276
35297
  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])}`))
35298
+ const parent = join22(cacheRoot, rel[0], rel[1]);
35299
+ if (!byParent.has(parent) || !expectedByRoot.has(`${byParent.get(parent)[0].pluginId}\x00${join22(parent, rel[2])}`))
35279
35300
  refuse3();
35280
35301
  }
35281
35302
  return expectedByRoot;
@@ -35336,11 +35357,11 @@ function captureCodexSemanticCacheWitness(options) {
35336
35357
  const rootNames = new Map;
35337
35358
  for (const document2 of docs) {
35338
35359
  const rel = relative6(options.cacheRoot, document2).split(sep9);
35339
- if (appOnlyParents.some((parent) => parent.pluginParent === join21(options.cacheRoot, rel[0], rel[1])))
35360
+ if (appOnlyParents.some((parent) => parent.pluginParent === join22(options.cacheRoot, rel[0], rel[1])))
35340
35361
  refuse3();
35341
- if (hookParents.some((parent) => parent.pluginParent === join21(options.cacheRoot, rel[0], rel[1])))
35362
+ if (hookParents.some((parent) => parent.pluginParent === join22(options.cacheRoot, rel[0], rel[1])))
35342
35363
  refuse3();
35343
- const documentStat = lstatSync16(document2, { throwIfNoEntry: false });
35364
+ const documentStat = lstatSync17(document2, { throwIfNoEntry: false });
35344
35365
  if (!documentStat?.isFile() || documentStat.isSymbolicLink() || documentStat.size > MAX_DOCUMENT_BYTES)
35345
35366
  refuse3();
35346
35367
  const identity4 = classifyCodexPluginCacheDocument(document2, options.cacheRoot, read);
@@ -35474,8 +35495,8 @@ var init_codex_node_modules = __esm(() => {
35474
35495
  });
35475
35496
 
35476
35497
  // 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";
35498
+ import { closeSync as closeSync14, constants as constants11, fstatSync as fstatSync14, lstatSync as lstatSync18, openSync as openSync14, readSync as readSync8 } from "fs";
35499
+ import { join as join23 } from "path";
35479
35500
  function refusal(reason2 = "is unreadable") {
35480
35501
  return new SkillSelectionError("INVALID_AGENT_POLICY", `The Skills agent loading policy ${reason2}; refusing legacy fallback.`);
35481
35502
  }
@@ -35500,10 +35521,10 @@ function parseManagedSkillPolicy(text2) {
35500
35521
  return value;
35501
35522
  }
35502
35523
  function readManagedSkillPolicySnapshot(dataDir2 = getDataDirReadOnly()) {
35503
- const path = join22(dataDir2, "agent-policy.json");
35524
+ const path = join23(dataDir2, "agent-policy.json");
35504
35525
  let descriptor, observed = false;
35505
35526
  try {
35506
- const stat2 = lstatSync17(path);
35527
+ const stat2 = lstatSync18(path);
35507
35528
  observed = true;
35508
35529
  if (!stat2.isFile() || stat2.isSymbolicLink())
35509
35530
  throw refusal();
@@ -35529,7 +35550,7 @@ function readManagedSkillPolicySnapshot(dataDir2 = getDataDirReadOnly()) {
35529
35550
  return { text: text2, value: parseManagedSkillPolicy(text2) };
35530
35551
  } catch (error61) {
35531
35552
  if (error61.code === "ENOENT" && !observed) {
35532
- if (lstatSync17(path, { throwIfNoEntry: false }) === undefined)
35553
+ if (lstatSync18(path, { throwIfNoEntry: false }) === undefined)
35533
35554
  return null;
35534
35555
  }
35535
35556
  if (error61 instanceof SkillSelectionError)
@@ -35655,8 +35676,8 @@ var init_hook_diagnostics = __esm(() => {
35655
35676
 
35656
35677
  // src/lib/agent-sumi.ts
35657
35678
  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";
35679
+ import { accessSync, constants as constants12, existsSync as existsSync8, lstatSync as lstatSync19, realpathSync as realpathSync7, statSync as statSync8 } from "fs";
35680
+ import { delimiter, isAbsolute as isAbsolute16, join as join24, resolve as resolve16 } from "path";
35660
35681
  function recordWithKeys(value, keys) {
35661
35682
  return value !== null && typeof value === "object" && !Array.isArray(value) && Object.keys(value).length === keys.length && keys.every((key2) => Object.hasOwn(value, key2));
35662
35683
  }
@@ -35706,11 +35727,11 @@ function validPathPlan(value, home, cwd) {
35706
35727
  const legacyConfigRoot = value.legacyRoots.config;
35707
35728
  if (typeof configRoot !== "string" || legacyConfigRoot !== null && typeof legacyConfigRoot !== "string")
35708
35729
  return false;
35709
- if (value.configFiles.canonical !== join23(configRoot, "sumi.json") || value.skillRoots.canonical !== join23(configRoot, "skills"))
35730
+ if (value.configFiles.canonical !== join24(configRoot, "sumi.json") || value.skillRoots.canonical !== join24(configRoot, "skills"))
35710
35731
  return false;
35711
35732
  if (legacyConfigRoot === null)
35712
35733
  return value.configFiles.legacy === null && value.skillRoots.legacy === null;
35713
- return value.configFiles.legacy === join23(legacyConfigRoot, "sumi.json") && value.skillRoots.legacy === join23(legacyConfigRoot, "skills");
35734
+ return value.configFiles.legacy === join24(legacyConfigRoot, "sumi.json") && value.skillRoots.legacy === join24(legacyConfigRoot, "skills");
35714
35735
  }
35715
35736
  function sumiPathPlan(home, cwd = process.cwd(), env = process.env) {
35716
35737
  for (const key2 of ["SUMI_CONFIG", "SUMI_CONFIG_CONTENT"])
@@ -35761,7 +35782,7 @@ function selectedConfigDirectory(plan) {
35761
35782
  const canonical9 = plan.roots.config, legacy = plan.legacyRoots.config;
35762
35783
  if (legacy === null)
35763
35784
  return existsSync8(canonical9) ? realpathSync7(canonical9) : canonical9;
35764
- const canonicalStat = lstatSync18(canonical9, { throwIfNoEntry: false }), legacyStat = lstatSync18(legacy, { throwIfNoEntry: false });
35785
+ const canonicalStat = lstatSync19(canonical9, { throwIfNoEntry: false }), legacyStat = lstatSync19(legacy, { throwIfNoEntry: false });
35765
35786
  if (canonicalStat && legacyStat && realpathSync7(canonical9) !== realpathSync7(legacy))
35766
35787
  throw new Error("Sumi config roots conflict; complete native home adoption before Skills integration");
35767
35788
  const selected = canonicalStat ? canonical9 : legacyStat ? legacy : canonical9;
@@ -35776,7 +35797,7 @@ function sumiConfigDirectory(home, env = process.env, cwd = process.cwd()) {
35776
35797
  return selectedConfigDirectory(sumiPathPlan(home, cwd, env));
35777
35798
  }
35778
35799
  function sumiConfigPath(home, cwd = process.cwd(), env = process.env) {
35779
- return join23(sumiConfigDirectory(home, env, cwd), "sumi.json");
35800
+ return join24(sumiConfigDirectory(home, env, cwd), "sumi.json");
35780
35801
  }
35781
35802
  var SUMI_PATH_SELECTORS, SUMI_PATH_KEYS, SUMI_PATH_OUTPUT_LIMIT, SumiPathResolverError;
35782
35803
  var init_agent_sumi = __esm(() => {
@@ -35795,9 +35816,9 @@ var init_agent_sumi = __esm(() => {
35795
35816
  });
35796
35817
 
35797
35818
  // 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";
35819
+ 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
35820
  import { createHash as createHash20 } from "crypto";
35800
- import { dirname as dirname17, isAbsolute as isAbsolute17, resolve as resolve17 } from "path";
35821
+ import { dirname as dirname18, isAbsolute as isAbsolute17, resolve as resolve17 } from "path";
35801
35822
  function need8(value, code) {
35802
35823
  if (!value)
35803
35824
  throw new Error(`CODEX_HOOK_TRUST_${code}`);
@@ -35806,18 +35827,18 @@ function trustedAncestorOwner(uid2) {
35806
35827
  return BigInt(uid2) === 0n || BigInt(uid2) === BigInt(process.getuid());
35807
35828
  }
35808
35829
  function safeParents(file2) {
35809
- for (let p = dirname17(file2);; p = dirname17(p)) {
35810
- const s = lstatSync19(p);
35830
+ for (let p = dirname18(file2);; p = dirname18(p)) {
35831
+ const s = lstatSync20(p);
35811
35832
  need8(s.isDirectory() && !s.isSymbolicLink() && trustedAncestorOwner(s.uid), "UNSAFE_PARENT");
35812
35833
  need8((s.mode & 18) === 0 || s.uid === 0 && (s.mode & 512) !== 0, "UNSAFE_PARENT");
35813
- if (dirname17(p) === p)
35834
+ if (dirname18(p) === p)
35814
35835
  break;
35815
35836
  }
35816
35837
  }
35817
35838
  function snapshot(file2, privateFile = false, options = {}) {
35818
35839
  const readOnlyPackage = options.readOnlyPackage === true && !privateFile;
35819
35840
  safeParents(file2);
35820
- const initial = lstatSync19(file2, { bigint: true });
35841
+ const initial = lstatSync20(file2, { bigint: true });
35821
35842
  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
35843
  need8(initial.size <= 8n * 1024n * 1024n, "FILE_BOUND");
35823
35844
  const fd = openSync15(file2, constants13.O_RDONLY | constants13.O_NOFOLLOW | constants13.O_NONBLOCK);
@@ -35832,7 +35853,7 @@ function snapshot(file2, privateFile = false, options = {}) {
35832
35853
  break;
35833
35854
  length += n2;
35834
35855
  }
35835
- need8(length === Number(before.size) && sameStat(before, fstatSync15(fd, { bigint: true })) && sameStat(before, lstatSync19(file2, { bigint: true })), "INPUT_CHANGED");
35856
+ need8(length === Number(before.size) && sameStat(before, fstatSync15(fd, { bigint: true })) && sameStat(before, lstatSync20(file2, { bigint: true })), "INPUT_CHANGED");
35836
35857
  const content = bytes.subarray(0, length), text2 = new TextDecoder("utf-8", { fatal: true }).decode(content);
35837
35858
  return { file: file2, privateFile, readOnlyPackage, text: text2, bytes: content, stat: before, sha256: createHash20("sha256").update(content).digest("hex") };
35838
35859
  } finally {
@@ -35899,25 +35920,25 @@ var init_runtime_launcher = __esm(() => {
35899
35920
 
35900
35921
  // src/lib/retained-review-artifacts.ts
35901
35922
  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";
35923
+ 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";
35924
+ import { dirname as dirname19, isAbsolute as isAbsolute18, join as join25, resolve as resolve18, sep as sep10 } from "path";
35904
35925
  function keys(value, names) {
35905
35926
  return Boolean(value && typeof value === "object" && !Array.isArray(value) && Object.keys(value).length === names.length && names.every((name) => Object.hasOwn(value, name)));
35906
35927
  }
35907
35928
  function safe4(path) {
35908
35929
  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 });
35930
+ for (let cursor = path;; cursor = dirname19(cursor)) {
35931
+ const stat2 = lstatSync21(cursor, { throwIfNoEntry: false });
35911
35932
  need9(!stat2?.isSymbolicLink());
35912
35933
  if (cursor !== path && stat2)
35913
35934
  need9(stat2.isDirectory());
35914
- if (dirname18(cursor) === cursor)
35935
+ if (dirname19(cursor) === cursor)
35915
35936
  break;
35916
35937
  }
35917
35938
  }
35918
35939
  function readExact(path) {
35919
35940
  safe4(path);
35920
- const before = lstatSync20(path, { throwIfNoEntry: false });
35941
+ const before = lstatSync21(path, { throwIfNoEntry: false });
35921
35942
  need9(before?.isFile() && before.nlink === 1 && before.size <= AGENT_POLICY_LIMITS.discoveryRawSourceBytes && (before.mode & 63) === 0 && (process.getuid === undefined || before.uid === process.getuid()));
35922
35943
  const fd = openSync16(path, constants14.O_RDONLY | constants14.O_NOFOLLOW | constants14.O_NONBLOCK);
35923
35944
  try {
@@ -35931,7 +35952,7 @@ function readExact(path) {
35931
35952
  offset += count;
35932
35953
  }
35933
35954
  need9(readSync10(fd, Buffer.alloc(1), 0, 1, null) === 0);
35934
- const after = fstatSync16(fd), current = lstatSync20(path, { throwIfNoEntry: false });
35955
+ const after = fstatSync16(fd), current = lstatSync21(path, { throwIfNoEntry: false });
35935
35956
  safe4(path);
35936
35957
  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
35958
  const text2 = new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(bytes);
@@ -35948,20 +35969,20 @@ function catalogDigest(text2) {
35948
35969
  } catch {
35949
35970
  return refuse4();
35950
35971
  }
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"));
35972
+ 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
35973
  const skills = projectCodexNativeSkillCatalog({ data: [{ cwd: catalog.cwd, errors: [], skills: catalog.skills }] }, catalog.cwd);
35953
35974
  const plugins = catalog.plugins === undefined ? undefined : projectCodexInstalledPluginEntries(catalog.plugins);
35954
35975
  return sha3(JSON.stringify({ version: catalog.version, cwd: catalog.cwd, skills, ...plugins === undefined ? {} : { plugins } }));
35955
35976
  }
35956
35977
  function retainedArtifactPath(metadata) {
35957
- return join24(metadata.storeRoot, "agent-discovery", "artifacts", metadata.sha256, "catalog.json");
35978
+ return join25(metadata.storeRoot, "agent-discovery", "artifacts", metadata.sha256, "catalog.json");
35958
35979
  }
35959
35980
  function validRetainedArtifact(value) {
35960
35981
  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
35982
  }
35962
35983
  function privateStore(storeRoot) {
35963
35984
  safe4(storeRoot);
35964
- const stat2 = lstatSync20(storeRoot, { throwIfNoEntry: false });
35985
+ const stat2 = lstatSync21(storeRoot, { throwIfNoEntry: false });
35965
35986
  need9(!stat2 || stat2.isDirectory() && (stat2.mode & 18) === 0 && (process.getuid === undefined || stat2.uid === process.getuid()));
35966
35987
  }
35967
35988
  function verifyRetainedReviewArtifact(source, storeRoot) {
@@ -35970,8 +35991,8 @@ function verifyRetainedReviewArtifact(source, storeRoot) {
35970
35991
  privateStore(artifact.storeRoot);
35971
35992
  const text2 = readExact(source.path);
35972
35993
  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);
35994
+ for (let parent = dirname19(source.path);parent !== artifact.storeRoot; parent = dirname19(parent)) {
35995
+ const stat2 = lstatSync21(parent);
35975
35996
  need9(stat2.isDirectory() && (stat2.mode & 63) === 0 && (process.getuid === undefined || stat2.uid === process.getuid()));
35976
35997
  }
35977
35998
  }
@@ -35991,6 +36012,8 @@ var init_retained_review_artifacts = __esm(() => {
35991
36012
  var init_agent_integration = __esm(() => {
35992
36013
  init_sumi_settings_witness();
35993
36014
  init_codex_corpus_write();
36015
+ init_codex_hook_rpc();
36016
+ init_codex_native_config();
35994
36017
  init_codex_plugin_skill_controls();
35995
36018
  init_codex_native_skill_policy();
35996
36019
  init_codex_native_skill_catalog();
@@ -36050,20 +36073,20 @@ var init_skill_aliases = __esm(() => {
36050
36073
  });
36051
36074
 
36052
36075
  // 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";
36076
+ import { existsSync as existsSync9, mkdirSync as mkdirSync7, readFileSync as readFileSync15, writeFileSync as writeFileSync5 } from "fs";
36077
+ import { join as join26 } from "path";
36055
36078
  function getProjectStateDir(targetDir = process.cwd()) {
36056
- return join25(targetDir, SKILLS_PROJECT_DIR);
36079
+ return join26(targetDir, SKILLS_PROJECT_DIR);
36057
36080
  }
36058
36081
  function getProjectConfigPath(targetDir = process.cwd()) {
36059
- return join25(getProjectStateDir(targetDir), PROJECT_CONFIG_FILE);
36082
+ return join26(getProjectStateDir(targetDir), PROJECT_CONFIG_FILE);
36060
36083
  }
36061
36084
  function loadProjectConfig(targetDir = process.cwd()) {
36062
36085
  const path = getProjectConfigPath(targetDir);
36063
36086
  if (!existsSync9(path))
36064
36087
  return null;
36065
36088
  try {
36066
- return normalizeProjectConfig(JSON.parse(readFileSync14(path, "utf-8")));
36089
+ return normalizeProjectConfig(JSON.parse(readFileSync15(path, "utf-8")));
36067
36090
  } catch {
36068
36091
  return null;
36069
36092
  }
@@ -36171,8 +36194,8 @@ var init_project_state = __esm(() => {
36171
36194
  });
36172
36195
 
36173
36196
  // src/lib/installer.ts
36174
- import { existsSync as existsSync10, readFileSync as readFileSync15, rmSync as rmSync2 } from "fs";
36175
- import { join as join26 } from "path";
36197
+ import { existsSync as existsSync10, readFileSync as readFileSync16, rmSync as rmSync2 } from "fs";
36198
+ import { join as join27 } from "path";
36176
36199
  import { homedir as homedir2 } from "os";
36177
36200
  function getSkillPath(name) {
36178
36201
  const skillName = normalizeSkillName(getCanonicalSkillName(name));
@@ -36182,7 +36205,7 @@ function getSkillPath(name) {
36182
36205
  const extensionPath = findExtensionSkillPath(skillName);
36183
36206
  if (extensionPath)
36184
36207
  return extensionPath;
36185
- return join26(getPortableSkillsRoot(), skillName);
36208
+ return join27(getPortableSkillsRoot(), skillName);
36186
36209
  }
36187
36210
  function getCanonicalSkillName(name) {
36188
36211
  return getSkill(name)?.name ?? resolveSkillAlias(normalizeSkillSlug(name));
@@ -36236,11 +36259,11 @@ function getAgentSkillsDir(agent, scope = "global", projectDir) {
36236
36259
  const base = projectDir || process.cwd();
36237
36260
  switch (agent) {
36238
36261
  case "pi":
36239
- return scope === "project" ? join26(base, ".pi", "skills") : join26(homedir2(), ".pi", "agent", "skills");
36262
+ return scope === "project" ? join27(base, ".pi", "skills") : join27(homedir2(), ".pi", "agent", "skills");
36240
36263
  case "opencode":
36241
- return scope === "project" ? join26(base, ".opencode", "skills") : join26(homedir2(), ".config", "opencode", "skills");
36264
+ return scope === "project" ? join27(base, ".opencode", "skills") : join27(homedir2(), ".config", "opencode", "skills");
36242
36265
  default:
36243
- return scope === "project" ? join26(base, `.${agent}`, "skills") : join26(homedir2(), `.${agent}`, "skills");
36266
+ return scope === "project" ? join27(base, `.${agent}`, "skills") : join27(homedir2(), `.${agent}`, "skills");
36244
36267
  }
36245
36268
  }
36246
36269
  function warnMissingDependencies(name, targetDir) {
@@ -36255,11 +36278,11 @@ function warnMissingDependencies(name, targetDir) {
36255
36278
  }
36256
36279
  }
36257
36280
  function readBundledSkillVersion(name) {
36258
- const pkgPath = join26(getSkillPath(name), "package.json");
36281
+ const pkgPath = join27(getSkillPath(name), "package.json");
36259
36282
  if (!existsSync10(pkgPath))
36260
36283
  return "unknown";
36261
36284
  try {
36262
- const pkg = JSON.parse(readFileSync15(pkgPath, "utf-8"));
36285
+ const pkg = JSON.parse(readFileSync16(pkgPath, "utf-8"));
36263
36286
  return pkg.version || "unknown";
36264
36287
  } catch {
36265
36288
  return "unknown";
@@ -36324,16 +36347,16 @@ var init_skill_doc_file = __esm(() => {
36324
36347
  });
36325
36348
 
36326
36349
  // src/lib/skillinfo.ts
36327
- import { existsSync as existsSync11, readFileSync as readFileSync16 } from "fs";
36328
- import { join as join27 } from "path";
36350
+ import { existsSync as existsSync11, readFileSync as readFileSync17 } from "fs";
36351
+ import { join as join28 } from "path";
36329
36352
  function isInstructionSkillDir(skillPath, meta3) {
36330
36353
  if (meta3?.kind === "instruction")
36331
36354
  return true;
36332
- const skillMdPath = join27(skillPath, "SKILL.md");
36355
+ const skillMdPath = join28(skillPath, "SKILL.md");
36333
36356
  if (!existsSync11(skillMdPath))
36334
36357
  return false;
36335
36358
  try {
36336
- return parseSkillFrontmatter(readFileSync16(skillMdPath, "utf-8"))?.kind === "instruction";
36359
+ return parseSkillFrontmatter(readFileSync17(skillMdPath, "utf-8"))?.kind === "instruction";
36337
36360
  } catch {
36338
36361
  return false;
36339
36362
  }
@@ -36343,9 +36366,9 @@ function getSkillDocs(name) {
36343
36366
  if (!existsSync11(skillPath))
36344
36367
  return null;
36345
36368
  return {
36346
- skillMd: readIfExists(join27(skillPath, "SKILL.md")),
36347
- readme: readIfExists(join27(skillPath, "README.md")),
36348
- claudeMd: readIfExists(join27(skillPath, "CLAUDE.md"))
36369
+ skillMd: readIfExists(join28(skillPath, "SKILL.md")),
36370
+ readme: readIfExists(join28(skillPath, "README.md")),
36371
+ claudeMd: readIfExists(join28(skillPath, "CLAUDE.md"))
36349
36372
  };
36350
36373
  }
36351
36374
  function getSkillBestDoc(name, file2) {
@@ -36361,14 +36384,14 @@ function getSkillRequirements(name) {
36361
36384
  return null;
36362
36385
  const texts = [];
36363
36386
  for (const file2 of ["SKILL.md", "README.md", "CLAUDE.md", ".env.example", ".env.local.example"]) {
36364
- const content = readIfExists(join27(skillPath, file2));
36387
+ const content = readIfExists(join28(skillPath, file2));
36365
36388
  if (content)
36366
36389
  texts.push(content);
36367
36390
  }
36368
36391
  const meta3 = getSkill(name);
36369
36392
  let dependencies = {};
36370
36393
  try {
36371
- dependencies = JSON.parse(readFileSync16(join27(skillPath, "package.json"), "utf8")).dependencies || {};
36394
+ dependencies = JSON.parse(readFileSync17(join28(skillPath, "package.json"), "utf8")).dependencies || {};
36372
36395
  } catch {}
36373
36396
  return getSkillRequirementsFromContent(name, texts, dependencies, meta3);
36374
36397
  }
@@ -36430,13 +36453,13 @@ async function runSkill(name, args, options = {}) {
36430
36453
  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
36454
  };
36432
36455
  }
36433
- const pkgPath = join27(skillPath, "package.json");
36456
+ const pkgPath = join28(skillPath, "package.json");
36434
36457
  if (!existsSync11(pkgPath)) {
36435
36458
  return { exitCode: 1, error: `No package.json in skill '${name}'` };
36436
36459
  }
36437
36460
  let entryPoint2;
36438
36461
  try {
36439
- const pkg = JSON.parse(readFileSync16(pkgPath, "utf-8"));
36462
+ const pkg = JSON.parse(readFileSync17(pkgPath, "utf-8"));
36440
36463
  if (pkg.bin) {
36441
36464
  const binValues = Object.values(pkg.bin);
36442
36465
  entryPoint2 = binValues[0];
@@ -36450,12 +36473,12 @@ async function runSkill(name, args, options = {}) {
36450
36473
  } catch {
36451
36474
  return { exitCode: 1, error: `Failed to parse package.json for skill '${name}'` };
36452
36475
  }
36453
- const entryPath = join27(skillPath, entryPoint2);
36476
+ const entryPath = join28(skillPath, entryPoint2);
36454
36477
  if (!existsSync11(entryPath)) {
36455
36478
  return { exitCode: 1, error: `Entry point '${entryPoint2}' not found in skill '${name}'` };
36456
36479
  }
36457
36480
  const env = { ...process.env, ...options.env };
36458
- if (!existsSync11(join27(skillPath, "node_modules")) || hasDependencyPreparationMarker(skillPath)) {
36481
+ if (!existsSync11(join28(skillPath, "node_modules")) || hasDependencyPreparationMarker(skillPath)) {
36459
36482
  const failure = await prepareSkillDependencies(skillPath, env, options.preparationTimeoutMs);
36460
36483
  if (failure)
36461
36484
  return failure;
@@ -36481,7 +36504,7 @@ async function runSkill(name, args, options = {}) {
36481
36504
  function detectProjectSkills(cwd = process.cwd()) {
36482
36505
  let pkg;
36483
36506
  try {
36484
- pkg = JSON.parse(readFileSync16(join27(cwd, "package.json"), "utf8"));
36507
+ pkg = JSON.parse(readFileSync17(join28(cwd, "package.json"), "utf8"));
36485
36508
  } catch {
36486
36509
  return { detected: [], recommended: [] };
36487
36510
  }
@@ -36518,7 +36541,7 @@ function extractEnvVars(text2) {
36518
36541
  function readIfExists(path) {
36519
36542
  try {
36520
36543
  if (existsSync11(path)) {
36521
- return readFileSync16(path, "utf-8");
36544
+ return readFileSync17(path, "utf-8");
36522
36545
  }
36523
36546
  } catch {}
36524
36547
  return null;
@@ -36846,7 +36869,7 @@ var init_selected_manifest = __esm(() => {
36846
36869
  });
36847
36870
 
36848
36871
  // src/lib/plugin-admission.ts
36849
- import { isAbsolute as isAbsolute19, join as join28, resolve as resolve19 } from "path";
36872
+ import { isAbsolute as isAbsolute19, join as join29, resolve as resolve19 } from "path";
36850
36873
  function validatePluginTarget(value) {
36851
36874
  pluginKeys(value, ["schemaVersion", "pluginId", "registrations", "native", "resolver"]);
36852
36875
  pluginNeed(value.schemaVersion === 1, "Invalid plugin admission target");
@@ -37007,12 +37030,12 @@ function pluginResolverCommand(binding) {
37007
37030
  }
37008
37031
  function pluginBindingPath(storeRoot, id) {
37009
37032
  pluginNeed(/^[a-f0-9]{64}$/.test(id), "Invalid plugin binding identifier");
37010
- return join28(storeRoot, "bindings", `${id}.json`);
37033
+ return join29(storeRoot, "bindings", `${id}.json`);
37011
37034
  }
37012
37035
  function pluginReceiptPath(storeRoot, id, digest2) {
37013
37036
  pluginNeed(/^[a-f0-9]{64}$/.test(id), "Invalid plugin binding identifier");
37014
37037
  pluginDigest(digest2);
37015
- return join28(storeRoot, "receipts", id, `${digest2.slice(7)}.json`);
37038
+ return join29(storeRoot, "receipts", id, `${digest2.slice(7)}.json`);
37016
37039
  }
37017
37040
  function readPluginBinding(storeRoot, id) {
37018
37041
  const value = readPluginJson(pluginBindingPath(storeRoot, id));
@@ -37032,7 +37055,7 @@ function readPluginAdmissionReceipt(storeRoot, id, digest2) {
37032
37055
  pluginNeed(receipt.plan.bindingId === id && receipt.plan.planDigest === digest2, "Plugin receipt identity differs from its filename");
37033
37056
  const binding = readPluginBinding(storeRoot, id);
37034
37057
  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");
37058
+ pluginNeed(receipt.materializedPath === join29(storeRoot, "objects", id, digest2.slice(7)), "Plugin receipt points outside its immutable materialization");
37036
37059
  pluginText(receipt.admittedAt, 64);
37037
37060
  pluginNeed(Number.isFinite(Date.parse(receipt.admittedAt)), "Invalid plugin admission time");
37038
37061
  return receipt;
@@ -37049,8 +37072,8 @@ var init_plugin_admission = __esm(() => {
37049
37072
  });
37050
37073
 
37051
37074
  // 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";
37075
+ import { closeSync as closeSync17, constants as constants15, fstatSync as fstatSync17, lstatSync as lstatSync22, openSync as openSync17, opendirSync as opendirSync3, readSync as readSync11 } from "fs";
37076
+ import { basename as basename11, dirname as dirname20, isAbsolute as isAbsolute20, join as join30, resolve as resolve20 } from "path";
37054
37077
  function validateManagedPluginWitnesses(value) {
37055
37078
  pluginNeed(Array.isArray(value) && value.length > 0 && value.length <= PLUGIN_PROJECTION_LIMITS.registrations, "Invalid managed plugin witness collection");
37056
37079
  const seen = new Set;
@@ -37065,15 +37088,15 @@ function validateManagedPluginWitnesses(value) {
37065
37088
  function safe5(path) {
37066
37089
  pluginText(path);
37067
37090
  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))
37091
+ for (let at = path;; at = dirname20(at)) {
37092
+ pluginNeed(!lstatSync22(at, { throwIfNoEntry: false })?.isSymbolicLink(), "Plugin registry path traverses a symlink");
37093
+ if (at === dirname20(at))
37071
37094
  break;
37072
37095
  }
37073
37096
  }
37074
37097
  function readRegistry(path) {
37075
37098
  safe5(path);
37076
- const initial = lstatSync21(path);
37099
+ const initial = lstatSync22(path);
37077
37100
  pluginNeed(initial.isFile() && initial.size <= 1024 * 1024, "Plugin registry is not a bounded regular file");
37078
37101
  const fd = openSync17(path, constants15.O_RDONLY | constants15.O_NOFOLLOW | constants15.O_NONBLOCK);
37079
37102
  try {
@@ -37087,7 +37110,7 @@ function readRegistry(path) {
37087
37110
  break;
37088
37111
  length += count;
37089
37112
  }
37090
- const after = fstatSync17(fd), current = lstatSync21(path);
37113
+ const after = fstatSync17(fd), current = lstatSync22(path);
37091
37114
  safe5(path);
37092
37115
  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
37116
  let value;
@@ -37117,7 +37140,7 @@ function hashManagedPluginRegistry(path, managed) {
37117
37140
  seen.add(target.pluginId);
37118
37141
  const rows = plugins[target.pluginId];
37119
37142
  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);
37143
+ const [name, market] = target.pluginId.split("@"), cacheRoot = join30(dirname20(path), "cache", market, name);
37121
37144
  const scopes = new Set, approvals = new Map, currentFiles = new Map;
37122
37145
  plugins[target.pluginId] = rows.map((row) => {
37123
37146
  pluginNeed(pluginObject(row), "Invalid managed plugin registration");
@@ -37130,10 +37153,10 @@ function hashManagedPluginRegistry(path, managed) {
37130
37153
  pluginText(row.sourceProducerPath);
37131
37154
  pluginText(row.lastUpdated, 64);
37132
37155
  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");
37156
+ 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
37157
  const approval = (producer) => {
37135
37158
  pluginText(producer);
37136
- const digest2 = `sha256:${basename10(producer)}`;
37159
+ const digest2 = `sha256:${basename11(producer)}`;
37137
37160
  const receipt2 = readPluginAdmissionReceipt(witness.storeRoot, witness.bindingId, digest2);
37138
37161
  pluginNeed(receipt2.materializedPath === producer, "Managed producer path is not an approved immutable projection");
37139
37162
  if (!verified.has(producer)) {
@@ -37160,7 +37183,7 @@ function hashManagedPluginRegistry(path, managed) {
37160
37183
  return Object.fromEntries(Object.entries(row).filter(([key2]) => !["version", "installPath", "sourceProducerPath", "previousProducerPaths", "lastUpdated"].includes(key2)));
37161
37184
  });
37162
37185
  safe5(cacheRoot);
37163
- const before = lstatSync21(cacheRoot);
37186
+ const before = lstatSync22(cacheRoot);
37164
37187
  pluginNeed(before.isDirectory(), "Invalid managed plugin cache root");
37165
37188
  const directory = opendirSync3(cacheRoot), names = [];
37166
37189
  try {
@@ -37173,17 +37196,17 @@ function hashManagedPluginRegistry(path, managed) {
37173
37196
  directory.closeSync();
37174
37197
  }
37175
37198
  for (const version2 of names.sort()) {
37176
- const files = pluginFileWitnesses(snapshotPluginTree(join29(cacheRoot, version2), { nativeRuntime: `claude-${target.native.version}` }));
37199
+ const files = pluginFileWitnesses(snapshotPluginTree(join30(cacheRoot, version2), { nativeRuntime: `claude-${target.native.version}` }));
37177
37200
  verifiedBytes += files.reduce((total, file2) => total + file2.size, 0);
37178
37201
  pluginNeed(verifiedBytes <= 256 * 1024 * 1024, "Managed plugin verification exceeds its aggregate byte budget");
37179
37202
  const serialized = JSON.stringify(files);
37180
- const expected = currentFiles.get(join29(cacheRoot, version2));
37203
+ const expected = currentFiles.get(join30(cacheRoot, version2));
37181
37204
  pluginNeed(expected === undefined || serialized === expected, "Current native cache differs from its exact registered producer receipt");
37182
37205
  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
37206
  }
37184
37207
  for (const row of rows)
37185
37208
  pluginNeed(names.includes(row.version), "Managed native plugin installation is missing");
37186
- const after = lstatSync21(cacheRoot);
37209
+ const after = lstatSync22(cacheRoot);
37187
37210
  safe5(cacheRoot);
37188
37211
  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
37212
  }
@@ -37198,8 +37221,8 @@ var init_plugin_discovery = __esm(() => {
37198
37221
 
37199
37222
  // src/lib/claude-marketplace-registry.ts
37200
37223
  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";
37224
+ import { closeSync as closeSync18, constants as constants16, fstatSync as fstatSync18, lstatSync as lstatSync23, openSync as openSync18, readSync as readSync12 } from "fs";
37225
+ import { basename as basename12, dirname as dirname21, isAbsolute as isAbsolute21, resolve as resolve21 } from "path";
37203
37226
  function need10(value, reason2) {
37204
37227
  if (!value)
37205
37228
  throw new Error(`Claude marketplace registry ${reason2}`);
@@ -37209,19 +37232,19 @@ function absolutePath4(value) {
37209
37232
  }
37210
37233
  function parents2(path) {
37211
37234
  const result = [];
37212
- for (let at = dirname20(path);; at = dirname20(at)) {
37213
- const stat2 = lstatSync22(at, { bigint: true });
37235
+ for (let at = dirname21(path);; at = dirname21(at)) {
37236
+ const stat2 = lstatSync23(at, { bigint: true });
37214
37237
  need10(stat2.isDirectory() && !stat2.isSymbolicLink(), "path traverses a symlink or non-directory");
37215
37238
  result.push([at, stat2]);
37216
- if (at === dirname20(at))
37239
+ if (at === dirname21(at))
37217
37240
  return result;
37218
37241
  }
37219
37242
  }
37220
37243
  function readRegistry2(path, budget2) {
37221
37244
  absolutePath4(path);
37222
- need10(basename11(path) === "known_marketplaces.json", "requires known_marketplaces.json");
37245
+ need10(basename12(path) === "known_marketplaces.json", "requires known_marketplaces.json");
37223
37246
  need10(Number.isSafeInteger(budget2.remaining) && budget2.remaining >= 0, "has an invalid byte budget");
37224
- const ancestors2 = parents2(path), initial = lstatSync22(path, { bigint: true });
37247
+ const ancestors2 = parents2(path), initial = lstatSync23(path, { bigint: true });
37225
37248
  need10(initial.isFile() && !initial.isSymbolicLink() && initial.size <= BigInt(CLAUDE_MARKETPLACE_REGISTRY_LIMITS.bytes), "is not a bounded regular file");
37226
37249
  need10(initial.size <= BigInt(budget2.remaining), "exceeds its aggregate byte limit");
37227
37250
  const fd = openSync18(path, constants16.O_RDONLY | constants16.O_NOFOLLOW | constants16.O_NONBLOCK);
@@ -37236,10 +37259,10 @@ function readRegistry2(path, budget2) {
37236
37259
  break;
37237
37260
  length += count;
37238
37261
  }
37239
- const after = fstatSync18(fd, { bigint: true }), current = lstatSync22(path, { bigint: true });
37262
+ const after = fstatSync18(fd, { bigint: true }), current = lstatSync23(path, { bigint: true });
37240
37263
  need10(current.isFile() && sameFile2(opened, after) && sameFile2(after, current) && BigInt(length) === opened.size, "changed during read");
37241
37264
  for (const [ancestor, before] of ancestors2) {
37242
- const now = lstatSync22(ancestor, { bigint: true });
37265
+ const now = lstatSync23(ancestor, { bigint: true });
37243
37266
  need10(now.isDirectory() && before.dev === now.dev && before.ino === now.ino && before.mode === now.mode, "parent changed during read");
37244
37267
  }
37245
37268
  budget2.remaining -= length;
@@ -37426,8 +37449,8 @@ var init_codex_hook_discovery_recovery = __esm(() => {
37426
37449
 
37427
37450
  // src/lib/agent-discovery.ts
37428
37451
  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";
37452
+ import { lstatSync as lstatSync24, readFileSync as readFileSync18, readdirSync as readdirSync9, realpathSync as realpathSync8 } from "fs";
37453
+ 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
37454
  import { isDeepStrictEqual as isDeepStrictEqual5 } from "util";
37432
37455
  function discoveryExecutable(agent) {
37433
37456
  const command = DISCOVERY_RUNTIME_COMMANDS[agent];
@@ -37450,10 +37473,10 @@ function parseConfig(text2, path, toml = false) {
37450
37473
  function safe6(path) {
37451
37474
  if (!isAbsolute22(path) || path.includes("\x00"))
37452
37475
  throw new Error("Expected an absolute native discovery path");
37453
- for (let cursor = path;; cursor = dirname21(cursor)) {
37454
- if (lstatSync23(cursor, { throwIfNoEntry: false })?.isSymbolicLink())
37476
+ for (let cursor = path;; cursor = dirname22(cursor)) {
37477
+ if (lstatSync24(cursor, { throwIfNoEntry: false })?.isSymbolicLink())
37455
37478
  throw new Error(`Refusing symlink native discovery input: ${cursor}`);
37456
- if (dirname21(cursor) === cursor)
37479
+ if (dirname22(cursor) === cursor)
37457
37480
  break;
37458
37481
  }
37459
37482
  }
@@ -37461,19 +37484,19 @@ function read(path, changes) {
37461
37484
  safe6(path);
37462
37485
  if (changes?.has(path))
37463
37486
  return changes.get(path);
37464
- const stat2 = lstatSync23(path, { throwIfNoEntry: false });
37487
+ const stat2 = lstatSync24(path, { throwIfNoEntry: false });
37465
37488
  if (!stat2)
37466
37489
  return null;
37467
37490
  if (!stat2.isFile() || stat2.size > 16 * 1024 * 1024)
37468
37491
  throw new Error(`Unsupported or oversized native discovery input: ${path}`);
37469
- return readFileSync17(path, "utf8");
37492
+ return readFileSync18(path, "utf8");
37470
37493
  }
37471
37494
  function assertReviewedClaudeCacheClosures(home, config2, review, canonical9) {
37472
37495
  const enabledIds = Object.entries(config2.enabledPlugins ?? {}).filter(([, enabled]) => enabled === true).map(([id]) => id);
37473
37496
  if (enabledIds.length === 0)
37474
37497
  return;
37475
- const registryPath = canonical9(join30(home, ".claude/plugins/installed_plugins.json"));
37476
- const cacheAliasRoot = join30(home, ".claude/plugins/cache");
37498
+ const registryPath = canonical9(join31(home, ".claude/plugins/installed_plugins.json"));
37499
+ const cacheAliasRoot = join31(home, ".claude/plugins/cache");
37477
37500
  const cacheRoot = canonical9(cacheAliasRoot);
37478
37501
  const registryText = read(registryPath);
37479
37502
  if (registryText === null)
@@ -37494,7 +37517,7 @@ function assertReviewedClaudeCacheClosures(home, config2, review, canonical9) {
37494
37517
  throw new Error("Reviewed Claude enabled plugin registration requires an object with an installPath string");
37495
37518
  }
37496
37519
  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)) {
37520
+ if (!cachePath(row.installPath) || row.installPath.length > AGENT_POLICY_LIMITS.pathCharacters || row.version !== undefined && (typeof row.version !== "string" || basename13(row.installPath) !== row.version)) {
37498
37521
  throw new Error("Reviewed Claude discovery has a malformed active cache registration");
37499
37522
  }
37500
37523
  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 +37538,11 @@ function assertReviewedClaudeCacheClosures(home, config2, review, canonical9) {
37515
37538
  };
37516
37539
  for (const root of activeRoots) {
37517
37540
  safe6(root);
37518
- const rootStat = lstatSync23(root, { throwIfNoEntry: false });
37541
+ const rootStat = lstatSync24(root, { throwIfNoEntry: false });
37519
37542
  if (!rootStat?.isDirectory() || realpathSync8(root) !== root)
37520
37543
  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 });
37544
+ const manifestPath = join31(root, ".claude-plugin/plugin.json");
37545
+ const manifestStat = lstatSync24(manifestPath, { throwIfNoEntry: false });
37523
37546
  let manifest;
37524
37547
  if (manifestStat) {
37525
37548
  if (!manifestStat.isFile())
@@ -37534,8 +37557,8 @@ function assertReviewedClaudeCacheClosures(home, config2, review, canonical9) {
37534
37557
  } 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
37558
  throw new Error("Reviewed Claude active cache plugin manifest absence requires a path-bytes witness");
37536
37559
  }
37537
- const roots = new Set([join30(root, "skills")]);
37538
- if (lstatSync23(join30(root, "SKILL.md"), { throwIfNoEntry: false })?.isFile())
37560
+ const roots = new Set([join31(root, "skills")]);
37561
+ if (lstatSync24(join31(root, "SKILL.md"), { throwIfNoEntry: false })?.isFile())
37539
37562
  roots.add(root);
37540
37563
  const declared = manifest?.skills === undefined ? ["./skills"] : typeof manifest.skills === "string" ? [manifest.skills] : manifest.skills;
37541
37564
  if (!Array.isArray(declared) || declared.some((path) => typeof path !== "string"))
@@ -37544,13 +37567,13 @@ function assertReviewedClaudeCacheClosures(home, config2, review, canonical9) {
37544
37567
  const path = resolve22(root, value);
37545
37568
  if (path !== root && !path.startsWith(root + sep11))
37546
37569
  throw new Error("Reviewed Claude active cache plugin skill path escapes its root");
37547
- roots.add(path.endsWith(`${sep11}SKILL.md`) ? dirname21(path) : path);
37570
+ roots.add(path.endsWith(`${sep11}SKILL.md`) ? dirname22(path) : path);
37548
37571
  }
37549
37572
  for (const skillRoot of roots)
37550
37573
  if (!review.roots.includes(skillRoot))
37551
37574
  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 });
37575
+ const hooksPath = join31(root, "hooks/hooks.json");
37576
+ const hooksStat = lstatSync24(hooksPath, { throwIfNoEntry: false });
37554
37577
  if (hooksStat) {
37555
37578
  if (!hooksStat.isFile())
37556
37579
  throw new Error("Reviewed Claude plugin hook manifest is unsupported");
@@ -37688,18 +37711,18 @@ function absentCodexSkillRoots(binding, tolerance) {
37688
37711
  return [];
37689
37712
  if (binding.agent !== "codex" || !Array.isArray(controls) || controls.length > 4096)
37690
37713
  throw new Error("Invalid disabled Codex discovery proof");
37691
- if (binding.method !== "reviewed" || controls.every((control) => lstatSync23(control.pluginParent, { throwIfNoEntry: false })))
37714
+ if (binding.method !== "reviewed" || controls.every((control) => lstatSync24(control.pluginParent, { throwIfNoEntry: false })))
37692
37715
  return [];
37693
- const cache = dirname21(dirname21(controls[0].pluginParent)), config2 = join30(dirname21(dirname21(cache)), "config.toml");
37716
+ const cache = dirname22(dirname22(controls[0].pluginParent)), config2 = join31(dirname22(dirname22(cache)), "config.toml");
37694
37717
  const source = binding.sources.find((source2) => source2.path === config2 && source2.sha256 !== null && source2.format === undefined && source2.fields === undefined);
37695
37718
  if (!source || !codexConfigWitnessCurrent(source, tolerance))
37696
37719
  throw new Error("Missing current disabled Codex configuration witness");
37697
37720
  const rules = Bun.TOML.parse(read(config2)).skills?.config ?? [];
37698
37721
  return [...new Set(controls.map((control) => control.pluginParent))].filter((parent) => !codexDirectHookSelects(cache, parent) && absentDisabledCodexPluginParent(cache, parent, controls, rules));
37699
37722
  }
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"));
37723
+ function codexDirectHookSelects(cache, root, configPath = join31(dirname22(dirname22(cache)), "config.toml")) {
37724
+ const codex = dirname22(configPath), config2 = Bun.TOML.parse(read(configPath) ?? "");
37725
+ const hooks = read(join31(codex, "hooks.json"));
37703
37726
  if (hooks !== null)
37704
37727
  hashNativeJsonControls(hooks);
37705
37728
  return JSON.stringify(config2.hooks ?? {}).includes(root) || hooks !== null && JSON.stringify(JSON.parse(hooks)).includes(root);
@@ -37711,7 +37734,7 @@ function retiredCodexRoots(binding, tolerance) {
37711
37734
  const controls = binding.codexDisabledPluginSkills;
37712
37735
  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
37736
  throw new Error("Invalid retired Codex materialization proof");
37714
- const cache = dirname21(dirname21(controls[0].pluginParent)), config2 = join30(dirname21(dirname21(cache)), "config.toml");
37737
+ const cache = dirname22(dirname22(controls[0].pluginParent)), config2 = join31(dirname22(dirname22(cache)), "config.toml");
37715
37738
  const source = binding.sources.find((source2) => source2.path === config2 && source2.sha256 !== null && source2.format === undefined && source2.fields === undefined);
37716
37739
  if (!source || !codexConfigWitnessCurrent(source, tolerance))
37717
37740
  throw new Error("Missing current retired Codex configuration witness");
@@ -37719,7 +37742,7 @@ function retiredCodexRoots(binding, tolerance) {
37719
37742
  if ((proof.parents ?? []).some((parent) => codexDirectHookSelects(cache, parent) || !reviewedDisabledCodexPluginParent(cache, parent, controls, rules)) || !reviewedCodexPluginCapabilitiesUnchanged(cache, controls, (path) => read(path), rules))
37720
37743
  throw new Error("Retired Codex parent capabilities changed");
37721
37744
  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));
37745
+ 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
37746
  if (!manifest || codexDirectHookSelects(cache, root) || !reviewedRetiredCodexRoot(cache, root, controls, rules, (path) => read(path), true))
37724
37747
  throw new Error("Retired Codex materialization changed");
37725
37748
  }
@@ -37730,7 +37753,7 @@ function retainableAbsentWitness(source) {
37730
37753
  return null;
37731
37754
  if ([undefined, "bytes"].includes(source.hashMode))
37732
37755
  return "bytes";
37733
- if (source.hashMode === "claude-plugin-manifest-v1" && source.sha256 !== null && source.path.endsWith(join30(sep11, ".claude-plugin", "plugin.json")))
37756
+ if (source.hashMode === "claude-plugin-manifest-v1" && source.sha256 !== null && source.path.endsWith(join31(sep11, ".claude-plugin", "plugin.json")))
37734
37757
  return "claude-plugin-manifest-v1";
37735
37758
  if (source.hashMode === CLAUDE_ORPHAN_MARKER_MODE && source.sha256 !== null && isClaudePluginCacheOrphanMarker(source.path))
37736
37759
  return CLAUDE_ORPHAN_MARKER_MODE;
@@ -37755,11 +37778,11 @@ function absentRetiredClaudeRoots(binding) {
37755
37778
  const cache = source.path.slice(0, at + marker.length - 1), parts = source.path.slice(at + marker.length).split(sep11);
37756
37779
  if (parts.length < 4 || parts.slice(0, 3).some((part) => !part || part === "." || part === ".."))
37757
37780
  continue;
37758
- const root = join30(cache, ...parts.slice(0, 3));
37781
+ const root = join31(cache, ...parts.slice(0, 3));
37759
37782
  safe6(root);
37760
- if (lstatSync23(root, { throwIfNoEntry: false }))
37783
+ if (lstatSync24(root, { throwIfNoEntry: false }))
37761
37784
  continue;
37762
- const claude = dirname21(dirname21(cache)), settings = join30(claude, "settings.json"), registry2 = join30(claude, "plugins/installed_plugins.json");
37785
+ const claude = dirname22(dirname22(cache)), settings = join31(claude, "settings.json"), registry2 = join31(claude, "plugins/installed_plugins.json");
37763
37786
  const full = (path) => binding.sources.find((item) => item.path === path && item.sha256 !== null && item.format === undefined && item.fields === undefined);
37764
37787
  const configSource = full(settings), registrySource = full(registry2);
37765
37788
  if (!configSource || !registrySource || projected(configSource) !== configSource.sha256 || projected(registrySource) !== registrySource.sha256)
@@ -37802,9 +37825,9 @@ function absentRetiredClaudeRoots(binding) {
37802
37825
  if (!targetValid || !targetScopes.has("user\x00"))
37803
37826
  continue;
37804
37827
  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)
37828
+ if (typeof active !== "string" || rows[0]?.version !== basename13(active) || dirname22(active) !== dirname22(root) || active === root || !lstatSync24(active, { throwIfNoEntry: false })?.isDirectory() || realpathSync8(active) !== active)
37806
37829
  continue;
37807
- const activeManifest = full(join30(active, ".claude-plugin/plugin.json"));
37830
+ const activeManifest = full(join31(active, ".claude-plugin/plugin.json"));
37808
37831
  if (!activeManifest || projected(activeManifest) !== activeManifest.sha256)
37809
37832
  continue;
37810
37833
  result.add(root);
@@ -37815,10 +37838,10 @@ function codexSemanticCacheSourceRole(source, cacheRoot, parents3, hookParents =
37815
37838
  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
37839
  return false;
37817
37840
  const parts = relative7(cacheRoot, source.path).split(sep11);
37818
- if (parts.length < 3 || !parents3.includes(join30(cacheRoot, parts[0], parts[1])))
37841
+ if (parts.length < 3 || !parents3.includes(join31(cacheRoot, parts[0], parts[1])))
37819
37842
  return false;
37820
37843
  const tail = parts.slice(3).join("/");
37821
- const parent = join30(cacheRoot, parts[0], parts[1]);
37844
+ const parent = join31(cacheRoot, parts[0], parts[1]);
37822
37845
  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
37846
  }
37824
37847
  function codexSemanticCacheDirectoryRole(path, cacheRoot) {
@@ -37827,9 +37850,9 @@ function codexSemanticCacheDirectoryRole(path, cacheRoot) {
37827
37850
  function assertCodexSemanticCacheHookSafety(cacheRoot, parents3, configPath, hookRootAlias = null) {
37828
37851
  const selectionRoots = [cacheRoot, ...parents3];
37829
37852
  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)
37853
+ 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
37854
  throw new Error("Reviewed semantic cache hook alias changed");
37832
- selectionRoots.push(...selectionRoots.map((root) => join30(hookRootAlias.alias, relative7(hookRootAlias.target, root))));
37855
+ selectionRoots.push(...selectionRoots.map((root) => join31(hookRootAlias.alias, relative7(hookRootAlias.target, root))));
37833
37856
  }
37834
37857
  selectionRoots.push("plugins/cache");
37835
37858
  if (selectionRoots.some((parent) => codexDirectHookSelects(cacheRoot, parent, configPath)))
@@ -37849,7 +37872,7 @@ function verifyCodexSemanticCacheDiscovery(binding, reviewedRootAliases) {
37849
37872
  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
37873
  throw new Error("Invalid Codex semantic cache discovery proof");
37851
37874
  const cacheRoot = proof.witness.cacheRoot;
37852
- if (controls.some((control) => dirname21(dirname21(control.pluginParent)) !== cacheRoot))
37875
+ if (controls.some((control) => dirname22(dirname22(control.pluginParent)) !== cacheRoot))
37853
37876
  throw new Error("Codex semantic cache names another enrolled cache");
37854
37877
  const reviewedHookParents = proof.reviewedHookParents ?? [];
37855
37878
  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 +37888,7 @@ function verifyCodexSemanticCacheDiscovery(binding, reviewedRootAliases) {
37865
37888
  if (!directories.length || !isDeepStrictEqual5(sources, proof.supersededSources) || !isDeepStrictEqual5(directories, proof.supersededDirectories))
37866
37889
  throw new Error("Codex semantic cache provenance changed");
37867
37890
  const configPath = proof.configPath;
37868
- if (!isAbsolute22(configPath) || resolve22(configPath) !== configPath || basename12(configPath) !== "config.toml" || /[\x00-\x1f\x7f]/.test(configPath))
37891
+ if (!isAbsolute22(configPath) || resolve22(configPath) !== configPath || basename13(configPath) !== "config.toml" || /[\x00-\x1f\x7f]/.test(configPath))
37869
37892
  throw new Error("Invalid semantic cache configuration source");
37870
37893
  const configSource = binding.sources.find((source) => source.path === configPath && source.sha256 !== null && source.format === undefined && source.fields === undefined);
37871
37894
  if (!configSource || projected(configSource) !== configSource.sha256)
@@ -37898,7 +37921,7 @@ function verifyAgentDiscovery(binding, codexRecovery, reviewedRootAliases, witne
37898
37921
  const projection = binding.codexRetiredMaterializations.directories.filter((directory) => !semanticDirectory(directory.path));
37899
37922
  if (projection.length !== ordinary.length || projection.some((item, index) => item.path !== ordinary[index]?.path))
37900
37923
  throw new Error("Missing retired Codex directory projection");
37901
- const omitted = [...retiredRoots, ...(binding.codexRetiredMaterializations.parents ?? []).filter((parent) => !lstatSync23(parent, { throwIfNoEntry: false }))];
37924
+ const omitted = [...retiredRoots, ...(binding.codexRetiredMaterializations.parents ?? []).filter((parent) => !lstatSync24(parent, { throwIfNoEntry: false }))];
37902
37925
  if (projection.every((item) => Array.isArray(item.entries)))
37903
37926
  verifyDiscoveryDirectoryProjection(projection, omitted, witnessTolerance);
37904
37927
  else {
@@ -37915,7 +37938,7 @@ function verifyAgentDiscovery(binding, codexRecovery, reviewedRootAliases, witne
37915
37938
  verifyDiscoveryDirectories(ordinary, [], witnessTolerance);
37916
37939
  verifyDiscoveryDirectories(projected2, installationRoots, witnessTolerance);
37917
37940
  }
37918
- const absentRoots = [...absentCodexSkillRoots(binding, witnessTolerance), ...absentRetiredClaudeRoots(binding), ...retiredRoots.filter((root) => !lstatSync23(root, { throwIfNoEntry: false }))];
37941
+ const absentRoots = [...absentCodexSkillRoots(binding, witnessTolerance), ...absentRetiredClaudeRoots(binding), ...retiredRoots.filter((root) => !lstatSync24(root, { throwIfNoEntry: false }))];
37919
37942
  const budget2 = discoveryByteBudget();
37920
37943
  for (const source of binding.sources) {
37921
37944
  assertMarketplaceBinding(binding, source);
@@ -37953,12 +37976,12 @@ function verifyAgentDiscovery(binding, codexRecovery, reviewedRootAliases, witne
37953
37976
  safe6(root);
37954
37977
  for (const root of absentRoots) {
37955
37978
  safe6(root);
37956
- if (lstatSync23(root, { throwIfNoEntry: false }))
37979
+ if (lstatSync24(root, { throwIfNoEntry: false }))
37957
37980
  throw new Error("Retired native materialization changed during discovery verification");
37958
37981
  }
37959
37982
  }
37960
37983
  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}`);
37984
+ 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
37985
  }
37963
37986
  function retainedAbsentClaudeRoot(absentRoots, source) {
37964
37987
  return claudeControlSource(source) ? undefined : retainedAbsentRoot(absentRoots, source);
@@ -37969,13 +37992,13 @@ function codexInstallationRoots(binding) {
37969
37992
  return [];
37970
37993
  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
37994
  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)));
37995
+ const cache = dirname22(dirname22(proof.plugins[0].pluginParent));
37996
+ const config2 = join31(dirname22(dirname22(cache)), "config.toml"), home = dirname22(dirname22(dirname22(cache)));
37974
37997
  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)))))
37998
+ const nativeRoots = NATIVE_SKILL_ROOTS.filter(([agent]) => agent === "codex").map(([, path]) => join31(home, path));
37999
+ 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
38000
  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)))
38001
+ 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
38002
  throw new Error("Missing native installation input source witness");
37980
38003
  return reviewedCodexPluginSourceRoots(cache, proof.plugins, (path) => {
37981
38004
  const text2 = read(path);
@@ -37991,13 +38014,13 @@ function assertMarketplaceBinding(binding, source) {
37991
38014
  throw new Error("Provider executable witnesses require explicit reviewed Codex V6");
37992
38015
  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
38016
  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"))))
38017
+ 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
38018
  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"))
38019
+ if (source.hashMode === "sumi-settings-v1" && (binding.agent !== "sumi" || binding.method !== "reviewed" || basename13(source.path) !== "sumi.json"))
37997
38020
  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"))
38021
+ 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
38022
  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"))
38023
+ 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
38024
  throw new Error("Claude settings witnesses require explicit reviewed Claude configuration");
38002
38025
  if ((source.hashMode === "claude-marketplace-registry" || source.hashMode === "claude-marketplace-registry-v2") && (binding.agent !== "claude" || binding.method !== "reviewed"))
38003
38026
  throw new Error("Claude marketplace witnesses require explicit reviewed Claude discovery");
@@ -38005,11 +38028,11 @@ function assertMarketplaceBinding(binding, source) {
38005
38028
  throw new Error("Claude marketplace entry witnesses require explicit reviewed Claude discovery of one named entry");
38006
38029
  }
38007
38030
  function hashReviewedExecutable(path, budget2) {
38008
- const before = lstatSync23(path, { bigint: true });
38031
+ const before = lstatSync24(path, { bigint: true });
38009
38032
  if (before.size < 0n || before.size > BigInt(budget2.remaining))
38010
38033
  throw new Error("Discovery aggregate executable byte limit exceeded");
38011
38034
  const digest3 = pluginExecutableDigest(path).slice(7);
38012
- const after = lstatSync23(path, { bigint: true });
38035
+ const after = lstatSync24(path, { bigint: true });
38013
38036
  for (const key2 of ["dev", "ino", "size", "mode", "uid", "gid", "nlink", "mtimeNs", "ctimeNs"]) {
38014
38037
  if (before[key2] !== after[key2])
38015
38038
  throw new Error("Discovery executable changed during budgeted capture");
@@ -38020,7 +38043,7 @@ function hashReviewedExecutable(path, budget2) {
38020
38043
  function agentDiscoveryConfigPath(home, agent) {
38021
38044
  if (agent === "sumi")
38022
38045
  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"}`);
38046
+ 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
38047
  }
38025
38048
  function resolveAgentDiscovery(options) {
38026
38049
  const canonical9 = options.canonical ?? resolve22, home = resolve22(options.home), agent = options.agent;
@@ -38044,42 +38067,42 @@ function resolveAgentDiscovery(options) {
38044
38067
  const review = options.reviewed?.agents.find((item) => item.agent === agent);
38045
38068
  if (agent === "sumi") {
38046
38069
  const directory = sumiConfigDirectory(home);
38047
- if (witness(join30(directory, "sumi.jsonc")) !== null)
38070
+ if (witness(join31(directory, "sumi.jsonc")) !== null)
38048
38071
  unresolved("JSONC configuration requires a supported format adapter");
38049
- for (const root of [directory, join30(home, ".claude"), join30(home, ".agents")])
38072
+ for (const root of [directory, join31(home, ".claude"), join31(home, ".agents")])
38050
38073
  for (const name of ["skill", "skills"])
38051
- roots.add(canonical9(join30(root, name)));
38074
+ roots.add(canonical9(join31(root, name)));
38052
38075
  if (config2.skills !== undefined && (!Array.isArray(config2.skills) || config2.skills.some((path) => typeof path !== "string")))
38053
38076
  unresolved("skills must be a string array");
38054
38077
  for (const value of config2.skills ?? []) {
38055
38078
  if (typeof value !== "string" || /[\0$]/.test(value) || !value || !(isAbsolute22(value) || value.startsWith("~/")))
38056
38079
  unresolved("remote or relative skill sources need a dedicated discovery adapter");
38057
- roots.add(canonical9(value.startsWith("~/") ? join30(home, value.slice(2)) : value));
38080
+ roots.add(canonical9(value.startsWith("~/") ? join31(home, value.slice(2)) : value));
38058
38081
  }
38059
38082
  for (const key2 of ["plugin", "plugins"])
38060
38083
  if (config2[key2] !== undefined && !Array.isArray(config2[key2]))
38061
38084
  unresolved(`${key2} must be an array`);
38062
- const plugins = [join30(directory, "plugin"), join30(directory, "plugins")];
38085
+ const plugins = [join31(directory, "plugin"), join31(directory, "plugins")];
38063
38086
  for (const path of plugins) {
38064
38087
  safe6(path);
38065
- if (lstatSync23(path, { throwIfNoEntry: false })?.isDirectory())
38066
- for (const name of readdirSync8(path).sort()) {
38088
+ if (lstatSync24(path, { throwIfNoEntry: false })?.isDirectory())
38089
+ for (const name of readdirSync9(path).sort()) {
38067
38090
  if (name === "skills-cli.js" && path === plugins[1])
38068
38091
  continue;
38069
- const target = join30(path, name);
38070
- if (!lstatSync23(target).isFile())
38092
+ const target = join31(path, name);
38093
+ if (!lstatSync24(target).isFile())
38071
38094
  unresolved("local plugin packages need a dedicated discovery adapter");
38072
38095
  witness(target);
38073
38096
  }
38074
38097
  }
38075
38098
  for (const root of roots) {
38076
38099
  safe6(root);
38077
- if (lstatSync23(root, { throwIfNoEntry: false })?.isDirectory() && readdirSync8(root).some((name) => name.endsWith(".md")))
38100
+ if (lstatSync24(root, { throwIfNoEntry: false })?.isDirectory() && readdirSync9(root).some((name) => name.endsWith(".md")))
38078
38101
  unresolved("flat markdown skills require a dedicated native migration adapter");
38079
38102
  }
38080
38103
  }
38081
38104
  if (agent === "hermes") {
38082
- const profile = witness(join30(home, ".hermes/active_profile"));
38105
+ const profile = witness(join31(home, ".hermes/active_profile"));
38083
38106
  if (profile?.trim() && profile.trim() !== "default")
38084
38107
  unresolved("a non-default profile is active");
38085
38108
  const declared = config2.skills?.external_dirs ?? [], paths = typeof declared === "string" ? [declared] : declared;
@@ -38093,7 +38116,7 @@ function resolveAgentDiscovery(options) {
38093
38116
  continue;
38094
38117
  if (normalized.startsWith("~") && normalized !== "~" && !normalized.startsWith("~/"))
38095
38118
  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);
38119
+ const path = normalized === "~" ? home : normalized.startsWith("~/") ? join31(home, normalized.slice(2)) : resolve22(home, ".hermes", normalized);
38097
38120
  safe6(path);
38098
38121
  roots.add(path);
38099
38122
  }
@@ -38102,24 +38125,24 @@ function resolveAgentDiscovery(options) {
38102
38125
  const executable = options.executable === undefined ? discoveryExecutable(agent) : options.executable;
38103
38126
  if (executable) {
38104
38127
  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);
38128
+ for (let directory = dirname22(executable.target), depth = 0;depth < 8; directory = dirname22(directory), depth++) {
38129
+ const path = join31(directory, "package.json"), raw = read(path);
38107
38130
  if (raw !== null && parseConfig(raw, path).name === "@google/gemini-cli") {
38108
38131
  packageRoot = directory;
38109
38132
  witness(path);
38110
38133
  break;
38111
38134
  }
38112
- if (dirname21(directory) === directory)
38135
+ if (dirname22(directory) === directory)
38113
38136
  break;
38114
38137
  }
38115
38138
  if (!packageRoot)
38116
38139
  unresolved("installed Gemini package layout is not recognized");
38117
- const builtinRoot = join30(packageRoot, "bundle/builtin");
38140
+ const builtinRoot = join31(packageRoot, "bundle/builtin");
38118
38141
  safe6(builtinRoot);
38119
- if (!lstatSync23(builtinRoot, { throwIfNoEntry: false })?.isDirectory())
38142
+ if (!lstatSync24(builtinRoot, { throwIfNoEntry: false })?.isDirectory())
38120
38143
  unresolved("installed Gemini builtin root is missing");
38121
- for (const name of readdirSync8(builtinRoot).sort()) {
38122
- const text2 = witness(join30(builtinRoot, name, "SKILL.md"));
38144
+ for (const name of readdirSync9(builtinRoot).sort()) {
38145
+ const text2 = witness(join31(builtinRoot, name, "SKILL.md"));
38123
38146
  const match = text2?.match(/^---\r?\n[\s\S]*?^name:\s*([a-z0-9][a-z0-9-]*)\s*$/m);
38124
38147
  if (!match?.[1] || builtinNames.includes(match[1]))
38125
38148
  unresolved("installed Gemini builtin name is missing or ambiguous");
@@ -38165,10 +38188,10 @@ function resolveAgentDiscovery(options) {
38165
38188
  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
38189
  return { path: source.path, hashMode: CLAUDE_ORPHAN_MARKER_MODE, sha256: hashClaudePluginCacheOrphanMarker(source.path) };
38167
38190
  }
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")))
38191
+ 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
38192
  return source;
38170
- const pluginRoot = dirname21(dirname21(source.path)), hooksPath = join30(pluginRoot, "hooks/hooks.json");
38171
- const hookStat = lstatSync23(hooksPath, { throwIfNoEntry: false });
38193
+ const pluginRoot = dirname22(dirname22(source.path)), hooksPath = join31(pluginRoot, "hooks/hooks.json");
38194
+ const hookStat = lstatSync24(hooksPath, { throwIfNoEntry: false });
38172
38195
  const text2 = read(source.path);
38173
38196
  if (text2 === null)
38174
38197
  throw new Error("Reviewed Claude plugin manifest is missing");
@@ -38196,7 +38219,7 @@ function resolveAgentDiscovery(options) {
38196
38219
  assertReviewedClaudeCacheClosures(home, config2, review, canonical9);
38197
38220
  for (const root of absentRoots) {
38198
38221
  safe6(root);
38199
- if (lstatSync23(root, { throwIfNoEntry: false }))
38222
+ if (lstatSync24(root, { throwIfNoEntry: false }))
38200
38223
  throw new Error("Retired native materialization changed during discovery review");
38201
38224
  }
38202
38225
  const combined = [...reviewedSources, ...reviewedSourcesWithManifestProjection];
@@ -38206,39 +38229,39 @@ function resolveAgentDiscovery(options) {
38206
38229
  function plugin(root) {
38207
38230
  root = canonical9(root);
38208
38231
  safe6(root);
38209
- const manifestPath = join30(root, agent === "claude" ? ".claude-plugin/plugin.json" : ".codex-plugin/plugin.json");
38232
+ const manifestPath = join31(root, agent === "claude" ? ".claude-plugin/plugin.json" : ".codex-plugin/plugin.json");
38210
38233
  const raw = witness(manifestPath, undefined, undefined, agent === "claude" ? "claude-plugin-manifest-v1" : undefined);
38211
38234
  if (raw === null)
38212
38235
  unresolved("plugin manifest missing");
38213
38236
  const manifest = parseConfig(raw, manifestPath);
38214
- const hooks = witness(join30(root, "hooks/hooks.json"));
38237
+ const hooks = witness(join31(root, "hooks/hooks.json"));
38215
38238
  if (manifest.hooks !== undefined || hooks !== null)
38216
38239
  unresolved("plugin hooks require a separate no-skill-injection review");
38217
- const commands = join30(root, "commands");
38240
+ const commands = join31(root, "commands");
38218
38241
  safe6(commands);
38219
- if (agent === "claude" && (manifest.commands !== undefined || lstatSync23(commands, { throwIfNoEntry: false })?.isDirectory() && readdirSync8(commands).length))
38242
+ if (agent === "claude" && (manifest.commands !== undefined || lstatSync24(commands, { throwIfNoEntry: false })?.isDirectory() && readdirSync9(commands).length))
38220
38243
  unresolved("legacy command discovery requires retirement or a dedicated format adapter");
38221
- const rootSkill = witness(join30(root, "SKILL.md"));
38244
+ const rootSkill = witness(join31(root, "SKILL.md"));
38222
38245
  if (rootSkill !== null)
38223
38246
  roots.add(root);
38224
38247
  const declared = manifest.skills === undefined ? ["./skills"] : typeof manifest.skills === "string" ? [manifest.skills] : manifest.skills;
38225
38248
  if (!Array.isArray(declared) || declared.some((path) => typeof path !== "string"))
38226
38249
  unresolved("unsupported plugin skill paths");
38227
38250
  if (agent === "claude")
38228
- roots.add(join30(root, "skills"));
38251
+ roots.add(join31(root, "skills"));
38229
38252
  for (const value of declared) {
38230
38253
  const path = resolve22(root, value);
38231
38254
  if (path !== root && !path.startsWith(root + sep11))
38232
38255
  unresolved("plugin skill path escapes its root");
38233
- roots.add(path.endsWith(`${sep11}SKILL.md`) ? dirname21(path) : path);
38256
+ roots.add(path.endsWith(`${sep11}SKILL.md`) ? dirname22(path) : path);
38234
38257
  }
38235
38258
  }
38236
38259
  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"));
38260
+ const registrations = witness(join31(home, ".claude/plugins/installed_plugins.json"));
38261
+ const installed = registrations === null ? {} : parseConfig(registrations, join31(home, ".claude/plugins/installed_plugins.json")).plugins;
38262
+ const commands = canonical9(join31(home, ".claude/commands"));
38240
38263
  safe6(commands);
38241
- if (lstatSync23(commands, { throwIfNoEntry: false })?.isDirectory() && readdirSync8(commands).length)
38264
+ if (lstatSync24(commands, { throwIfNoEntry: false })?.isDirectory() && readdirSync9(commands).length)
38242
38265
  unresolved("legacy home command discovery requires a dedicated format adapter");
38243
38266
  for (const [id, enabled] of Object.entries(config2.enabledPlugins ?? {})) {
38244
38267
  if (enabled === false)
@@ -38260,16 +38283,16 @@ function resolveAgentDiscovery(options) {
38260
38283
  const market = config2.marketplaces?.[marketplace] ?? (marketplace === "personal" ? { source_type: "local", source: home } : undefined);
38261
38284
  if (split < 1 || market?.source_type !== "local" || typeof market.source !== "string" || !isAbsolute22(market.source))
38262
38285
  unresolved("enabled plugin marketplace is not an explicit local source");
38263
- const catalogText = witness(join30(market.source, ".agents/plugins/marketplace.json"));
38286
+ const catalogText = witness(join31(market.source, ".agents/plugins/marketplace.json"));
38264
38287
  if (catalogText === null)
38265
38288
  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) : [];
38289
+ const catalog = parseConfig(catalogText, join31(market.source, ".agents/plugins/marketplace.json")), matches = Array.isArray(catalog.plugins) ? catalog.plugins.filter((item) => item.name === name) : [];
38267
38290
  if (matches.length !== 1 || matches[0]?.source?.source !== "local" || typeof matches[0]?.source?.path !== "string")
38268
38291
  unresolved("plugin catalog source is missing or ambiguous");
38269
38292
  plugin(resolve22(market.source, matches[0].source.path));
38270
38293
  }
38271
38294
  } else if (agent === "opencode") {
38272
- if (witness(join30(home, ".config/opencode/opencode.jsonc")) !== null || witness(join30(home, ".config/opencode/config.json")) !== null)
38295
+ if (witness(join31(home, ".config/opencode/opencode.jsonc")) !== null || witness(join31(home, ".config/opencode/config.json")) !== null)
38273
38296
  unresolved("additional config layers require review");
38274
38297
  if ((config2.plugin?.length ?? 0) > 0 || config2.skills?.urls?.length)
38275
38298
  unresolved("external plugin or remote skill source");
@@ -38278,17 +38301,17 @@ function resolveAgentDiscovery(options) {
38278
38301
  unresolved("relative or malformed added skill root");
38279
38302
  roots.add(path);
38280
38303
  }
38281
- const localPlugins = join30(home, ".config/opencode/plugins");
38304
+ const localPlugins = join31(home, ".config/opencode/plugins");
38282
38305
  safe6(localPlugins);
38283
- if (lstatSync23(localPlugins, { throwIfNoEntry: false }) && readdirSync8(localPlugins).some((name) => name !== "skills-cli.js"))
38306
+ if (lstatSync24(localPlugins, { throwIfNoEntry: false }) && readdirSync9(localPlugins).some((name) => name !== "skills-cli.js"))
38284
38307
  unresolved("additional local plugin hooks require review");
38285
38308
  } 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))
38309
+ 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
38310
  unresolved("external or foreign local plugins require review");
38288
38311
  } else if (agent === "hermes") {
38289
- for (const directory of [join30(home, ".hermes/plugins"), join30(home, ".hermes/hermes-agent")]) {
38312
+ for (const directory of [join31(home, ".hermes/plugins"), join31(home, ".hermes/hermes-agent")]) {
38290
38313
  safe6(directory);
38291
- if (lstatSync23(directory, { throwIfNoEntry: false }))
38314
+ if (lstatSync24(directory, { throwIfNoEntry: false }))
38292
38315
  unresolved("installed runtime/plugin discovery requires reviewed source bindings");
38293
38316
  }
38294
38317
  if (Bun.which("hermes") || Object.keys(config2.plugins ?? {}).length)
@@ -38296,24 +38319,24 @@ function resolveAgentDiscovery(options) {
38296
38319
  } else if (agent === "gemini") {
38297
38320
  if (Object.keys(config2.extensions ?? {}).length || config2.skills?.paths?.length)
38298
38321
  unresolved("custom extension or skill paths");
38299
- const directory = join30(home, ".gemini/extensions");
38322
+ const directory = join31(home, ".gemini/extensions");
38300
38323
  safe6(directory);
38301
- if (lstatSync23(directory, { throwIfNoEntry: false }))
38302
- for (const name of readdirSync8(directory)) {
38303
- const root = join30(directory, name);
38324
+ if (lstatSync24(directory, { throwIfNoEntry: false }))
38325
+ for (const name of readdirSync9(directory)) {
38326
+ const root = join31(directory, name);
38304
38327
  safe6(root);
38305
- if (!lstatSync23(root)?.isDirectory())
38328
+ if (!lstatSync24(root)?.isDirectory())
38306
38329
  continue;
38307
- const raw = witness(join30(root, "gemini-extension.json"));
38330
+ const raw = witness(join31(root, "gemini-extension.json"));
38308
38331
  if (raw === null)
38309
38332
  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)
38333
+ const manifest = parseConfig(raw, join31(root, "gemini-extension.json"));
38334
+ if (manifest.hooks !== undefined || witness(join31(root, "hooks/hooks.json")) !== null || witness(join31(root, ".gemini-extension-install.json")) !== null)
38312
38335
  unresolved("extension hooks or linked registration require review");
38313
- roots.add(join30(root, "skills"));
38336
+ roots.add(join31(root, "skills"));
38314
38337
  }
38315
38338
  }
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))) } : {} };
38339
+ 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
38340
  }
38318
38341
  var DISCOVERY_RUNTIME_COMMANDS, realpathOrNull = (path) => {
38319
38342
  try {
@@ -38358,9 +38381,9 @@ var init_agent_discovery = __esm(() => {
38358
38381
  });
38359
38382
 
38360
38383
  // src/lib/authoring-path.ts
38361
- import { lstatSync as lstatSync24, realpathSync as realpathSync9 } from "fs";
38384
+ import { lstatSync as lstatSync25, realpathSync as realpathSync9 } from "fs";
38362
38385
  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";
38386
+ import { basename as basename14, dirname as dirname23, join as join32, resolve as resolve23, sep as sep12 } from "path";
38364
38387
  function pathParts(path) {
38365
38388
  return resolve23(path).split(sep12).filter(Boolean);
38366
38389
  }
@@ -38378,9 +38401,9 @@ function nativeRootMatch(path) {
38378
38401
  function physicalPath(path) {
38379
38402
  let cursor = resolve23(path);
38380
38403
  const suffix = [];
38381
- while (!lstatSync24(cursor, { throwIfNoEntry: false })) {
38382
- suffix.unshift(basename13(cursor));
38383
- const parent = dirname22(cursor);
38404
+ while (!lstatSync25(cursor, { throwIfNoEntry: false })) {
38405
+ suffix.unshift(basename14(cursor));
38406
+ const parent = dirname23(cursor);
38384
38407
  if (parent === cursor)
38385
38408
  return resolve23(path);
38386
38409
  cursor = parent;
@@ -38391,7 +38414,7 @@ function contains(root, path) {
38391
38414
  return path === root || path.startsWith(root + sep12);
38392
38415
  }
38393
38416
  function configuredRoots(home, explicitHome) {
38394
- const homeData = join31(home, ".hasna", "skills");
38417
+ const homeData = join32(home, ".hasna", "skills");
38395
38418
  const homePolicy = readManagedSkillPolicySnapshot(homeData);
38396
38419
  const configuredPolicy = !explicitHome && resolve23(getDataDirReadOnly()) !== resolve23(homeData) ? readManagedSkillPolicySnapshot(getDataDirReadOnly()) : null;
38397
38420
  const policy = homePolicy ?? configuredPolicy;
@@ -38422,8 +38445,8 @@ function configuredRoots(home, explicitHome) {
38422
38445
  admitBinding(binding);
38423
38446
  continue;
38424
38447
  }
38425
- const nativeHome = join31(home, agent === "opencode" ? ".config/opencode" : `.${agent}`);
38426
- if (!lstatSync24(nativeHome, { throwIfNoEntry: false }))
38448
+ const nativeHome = join32(home, agent === "opencode" ? ".config/opencode" : `.${agent}`);
38449
+ if (!lstatSync25(nativeHome, { throwIfNoEntry: false }))
38427
38450
  continue;
38428
38451
  roots.push(...resolveAgentDiscovery({ home, agent, canonical: physicalPath }).roots);
38429
38452
  }
@@ -38437,8 +38460,8 @@ function assertPortableAuthoringPath(path, options = {}) {
38437
38460
  const candidates = [lexical, physical];
38438
38461
  let native = candidates.map(nativeRootMatch).find(Boolean);
38439
38462
  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"));
38463
+ const defaults = NATIVE_DISCOVERY_ROOTS.map((parts) => join32(home, ...parts));
38464
+ defaults.push(join32(home, ".codex/plugins/cache"), join32(home, ".claude/plugins/cache"), join32(home, ".claude/plugins/synced"), join32(home, ".gemini/extensions"));
38442
38465
  for (const root of defaults) {
38443
38466
  if (candidates.some((candidate) => contains(resolve23(root), candidate) || contains(physicalPath(root), candidate)))
38444
38467
  native ??= root;
@@ -38467,29 +38490,29 @@ import {
38467
38490
  existsSync as existsSync12,
38468
38491
  mkdirSync as mkdirSync8,
38469
38492
  mkdtempSync,
38470
- readdirSync as readdirSync9,
38493
+ readdirSync as readdirSync10,
38471
38494
  realpathSync as realpathSync10,
38472
38495
  renameSync as renameSync3,
38473
38496
  rmSync as rmSync3,
38474
38497
  statSync as statSync9,
38475
38498
  writeFileSync as writeFileSync6
38476
38499
  } 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";
38500
+ 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
38501
  function getPortableSkillsRoot(options = {}) {
38479
38502
  return resolvePortableSkillsRoot(options, true);
38480
38503
  }
38481
38504
  function resolvePortableSkillsRoot(options, migrate) {
38482
38505
  if (options.rootDir)
38483
38506
  return options.rootDir;
38484
- const appDir = options.homeDir ? join32(options.homeDir, ".hasna", "skills") : migrate ? getDataDir() : getDataDirReadOnly();
38485
- const cache = join32(appDir, SKILLS_CACHE_DIRNAME);
38507
+ const appDir = options.homeDir ? join33(options.homeDir, ".hasna", "skills") : migrate ? getDataDir() : getDataDirReadOnly();
38508
+ const cache = join33(appDir, SKILLS_CACHE_DIRNAME);
38486
38509
  if (isOwnerLayoutMigrated(appDir) && safeIsDirectory(cache))
38487
38510
  return cache;
38488
- const installed = join32(appDir, INSTALLED_SKILLS_DIRNAME);
38511
+ const installed = join33(appDir, INSTALLED_SKILLS_DIRNAME);
38489
38512
  return installed;
38490
38513
  }
38491
38514
  function getPortableSkillPath(name, options = {}) {
38492
- return join32(getPortableSkillsRoot(options), normalizePortableSkillName(name));
38515
+ return join33(getPortableSkillsRoot(options), normalizePortableSkillName(name));
38493
38516
  }
38494
38517
  function findPortableSkill(name, options = {}) {
38495
38518
  let normalized;
@@ -38512,10 +38535,10 @@ function listPortableSkills(options = {}) {
38512
38535
  if (!safeIsDirectory(root))
38513
38536
  return [];
38514
38537
  const skills = [];
38515
- for (const entry of readdirSync9(root).sort()) {
38538
+ for (const entry of readdirSync10(root).sort()) {
38516
38539
  if (entry.startsWith("."))
38517
38540
  continue;
38518
- const path = join32(root, entry);
38541
+ const path = join33(root, entry);
38519
38542
  if (!safeIsDirectory(path))
38520
38543
  continue;
38521
38544
  try {
@@ -38548,9 +38571,9 @@ function isOfficialSkillName(name) {
38548
38571
  function scaffoldPortableSkill(name, options = {}) {
38549
38572
  const skillName = normalizeNewPortableSkillName(name);
38550
38573
  const readOnlyRoot = resolvePortableSkillsRoot(options, false);
38551
- assertPortableAuthoringPath(join32(readOnlyRoot, skillName), options);
38574
+ assertPortableAuthoringPath(join33(readOnlyRoot, skillName), options);
38552
38575
  const root = getPortableSkillsRoot(options);
38553
- const skillPath = join32(root, skillName);
38576
+ const skillPath = join33(root, skillName);
38554
38577
  assertPortableAuthoringPath(skillPath, options);
38555
38578
  if (existsSync12(skillPath)) {
38556
38579
  if (!options.overwrite)
@@ -38572,10 +38595,10 @@ function physicalImportPath(path) {
38572
38595
  let ancestor = resolve24(path);
38573
38596
  const suffix = [];
38574
38597
  while (!existsSync12(ancestor)) {
38575
- suffix.unshift(basename14(ancestor));
38576
- ancestor = dirname23(ancestor);
38598
+ suffix.unshift(basename15(ancestor));
38599
+ ancestor = dirname24(ancestor);
38577
38600
  }
38578
- return join32(realpathSync10(ancestor), ...suffix);
38601
+ return join33(realpathSync10(ancestor), ...suffix);
38579
38602
  }
38580
38603
  function assertDisjointImportPaths(source, destination) {
38581
38604
  const sourcePath = realpathSync10(source);
@@ -38597,15 +38620,15 @@ function portPortableSkill(sourcePath, options = {}) {
38597
38620
  const explicitName = options.name != null;
38598
38621
  const skillName = normalizeNewPortableSkillName(options.name ?? inferred.name);
38599
38622
  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.`;
38623
+ const sourceSlug = safeNormalizeName(basename15(absoluteSource));
38624
+ 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
38625
  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
38626
  }
38604
- const readOnlyDestination = join32(resolvePortableSkillsRoot(options, false), skillName);
38627
+ const readOnlyDestination = join33(resolvePortableSkillsRoot(options, false), skillName);
38605
38628
  assertPortableAuthoringPath(readOnlyDestination, options);
38606
38629
  assertDisjointImportPaths(absoluteSource, readOnlyDestination);
38607
38630
  const root = getPortableSkillsRoot(options);
38608
- const destination = join32(root, skillName);
38631
+ const destination = join33(root, skillName);
38609
38632
  assertPortableAuthoringPath(destination, options);
38610
38633
  assertDisjointImportPaths(absoluteSource, destination);
38611
38634
  if (existsSync12(destination)) {
@@ -38613,7 +38636,7 @@ function portPortableSkill(sourcePath, options = {}) {
38613
38636
  throw new Error(`Skill '${skillName}' already exists at ${destination}`);
38614
38637
  rmSync3(destination, { recursive: true, force: true });
38615
38638
  }
38616
- mkdirSync8(dirname23(destination), { recursive: true });
38639
+ mkdirSync8(dirname24(destination), { recursive: true });
38617
38640
  copySkillDirectory(absoluteSource, destination);
38618
38641
  const base = {
38619
38642
  ...inferred,
@@ -38632,18 +38655,29 @@ function safeNormalizeName(name) {
38632
38655
  }
38633
38656
  function validatePortableSkillDirectory(name, skillPath) {
38634
38657
  const normalizedName = normalizePortableSkillName(name);
38635
- const base = validateSkillDirectory(normalizedName, skillPath);
38658
+ let manifest;
38659
+ let manifestError;
38660
+ if (existsSync12(skillPath)) {
38661
+ try {
38662
+ manifest = readPortableSkillManifest(skillPath, normalizedName);
38663
+ } catch (error61) {
38664
+ manifestError = error61;
38665
+ }
38666
+ }
38667
+ const base = validateSkillDirectory(normalizedName, skillPath, undefined, { kind: manifest?.kind });
38636
38668
  const issues = [...base.issues];
38637
38669
  const warnings = [...base.warnings];
38638
- let manifest;
38639
38670
  if (existsSync12(skillPath)) {
38640
- const skillJsonPath = join32(skillPath, "skill.json");
38641
- const skillMdPath = join32(skillPath, "SKILL.md");
38671
+ const skillJsonPath = join33(skillPath, "skill.json");
38672
+ const skillMdPath = join33(skillPath, "SKILL.md");
38642
38673
  if (!existsSync12(skillJsonPath) && !existsSync12(skillMdPath)) {
38643
38674
  add3(issues, "portable.manifest_missing", "Missing portable manifest: expected SKILL.md frontmatter and/or skill.json");
38644
38675
  }
38645
38676
  try {
38646
- manifest = readPortableSkillManifest(skillPath, normalizedName);
38677
+ if (manifestError)
38678
+ throw manifestError;
38679
+ if (!manifest)
38680
+ throw new Error("Portable manifest could not be read");
38647
38681
  const isInstruction = manifest.kind === "instruction";
38648
38682
  if (manifest.name !== normalizedName) {
38649
38683
  add3(issues, "portable.name_mismatch", `Portable manifest name '${manifest.name}' does not match '${normalizedName}'`);
@@ -38658,27 +38692,11 @@ function validatePortableSkillDirectory(name, skillPath) {
38658
38692
  add3(issues, "portable.version_missing", "Portable manifest missing version");
38659
38693
  }
38660
38694
  const contractIssues = validatePortableManifestContract(manifest, {
38661
- strict: existsSync12(join32(skillPath, "skill.json")),
38695
+ strict: existsSync12(join33(skillPath, "skill.json")),
38662
38696
  skillPath
38663
38697
  });
38664
38698
  for (const issue2 of contractIssues)
38665
38699
  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
38700
  if (!isInstruction && (!Array.isArray(manifest.inputs) || manifest.inputs.length === 0)) {
38683
38701
  add3(issues, "portable.inputs_missing", "Portable manifest must declare inputs");
38684
38702
  }
@@ -38698,7 +38716,7 @@ function validatePortableSkillDirectory(name, skillPath) {
38698
38716
  add3(issues, "portable.command_entry_unsafe", `Command '${command.name}' entry '${command.entry}' must stay inside the skill directory`);
38699
38717
  continue;
38700
38718
  }
38701
- const entryPath = join32(skillPath, command.entry);
38719
+ const entryPath = join33(skillPath, command.entry);
38702
38720
  if (!existsSync12(entryPath))
38703
38721
  add3(issues, "portable.command_entry_missing", `Command '${command.name}' entry '${command.entry}' is missing`);
38704
38722
  else if (statSync9(entryPath).isDirectory())
@@ -38709,7 +38727,7 @@ function validatePortableSkillDirectory(name, skillPath) {
38709
38727
  } catch (error61) {
38710
38728
  add3(issues, "portable.manifest_invalid", error61.message);
38711
38729
  }
38712
- if (manifest?.kind !== "instruction" && !existsSync12(join32(skillPath, "AGENTS.md"))) {
38730
+ if (manifest?.kind !== "instruction" && !existsSync12(join33(skillPath, "AGENTS.md"))) {
38713
38731
  add3(issues, "portable.agents_missing", "Missing AGENTS.md with build-out instructions for coding agents");
38714
38732
  }
38715
38733
  }
@@ -38847,8 +38865,8 @@ var init_registry_types = __esm(() => {
38847
38865
  });
38848
38866
 
38849
38867
  // src/lib/registry.ts
38850
- import { existsSync as existsSync13, readFileSync as readFileSync18, readdirSync as readdirSync10 } from "fs";
38851
- import { join as join33 } from "path";
38868
+ import { existsSync as existsSync13, readFileSync as readFileSync19, readdirSync as readdirSync11 } from "fs";
38869
+ import { join as join34 } from "path";
38852
38870
  function parseSkillMdFrontmatter(content) {
38853
38871
  const match = content.match(/^---\n([\s\S]*?)\n---/);
38854
38872
  if (!match)
@@ -38885,16 +38903,16 @@ function discoverSkillsInDir(dir, source = "custom") {
38885
38903
  return [];
38886
38904
  const result = [];
38887
38905
  try {
38888
- const entries = readdirSync10(dir, { withFileTypes: true });
38906
+ const entries = readdirSync11(dir, { withFileTypes: true });
38889
38907
  for (const entry of entries) {
38890
38908
  if (!entry.isDirectory())
38891
38909
  continue;
38892
- const skillMdPath = join33(dir, entry.name, "SKILL.md");
38910
+ const skillMdPath = join34(dir, entry.name, "SKILL.md");
38893
38911
  if (!existsSync13(skillMdPath))
38894
38912
  continue;
38895
38913
  let content;
38896
38914
  try {
38897
- content = readFileSync18(skillMdPath, "utf-8");
38915
+ content = readFileSync19(skillMdPath, "utf-8");
38898
38916
  } catch {
38899
38917
  continue;
38900
38918
  }
@@ -38909,7 +38927,7 @@ function discoverSkillsInDir(dir, source = "custom") {
38909
38927
  category: fm.category || "Development Tools",
38910
38928
  tags: fm.tags || [],
38911
38929
  ...fm.kind ? { kind: fm.kind } : {},
38912
- ...isHostedMetadataSkillDir(join33(dir, entry.name)) ? { serverOwned: true } : {},
38930
+ ...isHostedMetadataSkillDir(join34(dir, entry.name)) ? { serverOwned: true } : {},
38913
38931
  source
38914
38932
  });
38915
38933
  }
@@ -38921,17 +38939,17 @@ function findExtensionSkillPath(name) {
38921
38939
  if (!config2.extensionsDir || !existsSync13(config2.extensionsDir))
38922
38940
  return null;
38923
38941
  try {
38924
- const entries = readdirSync10(config2.extensionsDir, { withFileTypes: true });
38942
+ const entries = readdirSync11(config2.extensionsDir, { withFileTypes: true });
38925
38943
  for (const entry of entries) {
38926
38944
  if (!entry.isDirectory())
38927
38945
  continue;
38928
- const skillDir = join33(config2.extensionsDir, entry.name);
38929
- const skillMdPath = join33(skillDir, "SKILL.md");
38946
+ const skillDir = join34(config2.extensionsDir, entry.name);
38947
+ const skillMdPath = join34(skillDir, "SKILL.md");
38930
38948
  if (!existsSync13(skillMdPath))
38931
38949
  continue;
38932
38950
  let content;
38933
38951
  try {
38934
- content = readFileSync18(skillMdPath, "utf-8");
38952
+ content = readFileSync19(skillMdPath, "utf-8");
38935
38953
  } catch {
38936
38954
  continue;
38937
38955
  }
@@ -40143,14 +40161,14 @@ var init_remote_workspace_leave = __esm(() => {
40143
40161
  });
40144
40162
 
40145
40163
  // 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";
40164
+ 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";
40165
+ import { basename as basename16, dirname as dirname25, join as join35 } from "path";
40148
40166
  function getAuthFilePath(env = process.env) {
40149
40167
  return skillsCredentialFilePath(env);
40150
40168
  }
40151
40169
  function getIdentityFilePath(env = process.env) {
40152
40170
  const file2 = skillsCredentialFilePath(env);
40153
- return join34(dirname24(file2), basename15(file2).replace(/^credentials/, "identity") + ".json");
40171
+ return join35(dirname25(file2), basename16(file2).replace(/^credentials/, "identity") + ".json");
40154
40172
  }
40155
40173
  function getApiUrl(action, env = process.env, options = {}) {
40156
40174
  return requireSkillsApiOrigin(action, env, options);
@@ -40485,6 +40503,130 @@ var init_remote_permissions = __esm(() => {
40485
40503
  };
40486
40504
  });
40487
40505
 
40506
+ // src/lib/revision.ts
40507
+ import { createHash as createHash26 } from "crypto";
40508
+ function revisionIdOf(content) {
40509
+ const canonicalContent = {
40510
+ slug: content.slug,
40511
+ displayName: content.displayName,
40512
+ description: content.description,
40513
+ category: content.category,
40514
+ tags: content.tags,
40515
+ source: content.source,
40516
+ kind: content.kind,
40517
+ version: content.version ?? null,
40518
+ skillMd: content.skillMd ?? null,
40519
+ bundleSha256: content.bundleSha256 ?? null,
40520
+ bundleByteSize: content.bundleByteSize ?? null
40521
+ };
40522
+ if (content.lifecycle === "archived" || content.archiveReason !== undefined || content.replacementSlug !== undefined) {
40523
+ canonicalContent.lifecycle = content.lifecycle ?? "active";
40524
+ canonicalContent.archiveReason = content.archiveReason ?? null;
40525
+ canonicalContent.replacementSlug = content.replacementSlug ?? null;
40526
+ }
40527
+ const canonical9 = JSON.stringify(canonicalContent);
40528
+ return createHash26("sha256").update(canonical9).digest("hex");
40529
+ }
40530
+ var REVISION_ID_PATTERN;
40531
+ var init_revision = __esm(() => {
40532
+ REVISION_ID_PATTERN = /^[0-9a-f]{64}$/;
40533
+ });
40534
+
40535
+ // src/lib/skill-metadata-update.ts
40536
+ function metadataPatch(value) {
40537
+ if (!object7(value))
40538
+ throw new SkillMetadataUpdateError("INVALID_METADATA_PATCH");
40539
+ const keys2 = Object.keys(value);
40540
+ if (!keys2.length || keys2.some((key2) => !["category", "tags"].includes(key2)))
40541
+ throw new SkillMetadataUpdateError("INVALID_METADATA_PATCH");
40542
+ const copy = {};
40543
+ if (Object.hasOwn(value, "category"))
40544
+ copy.category = value.category;
40545
+ if (Object.hasOwn(value, "tags")) {
40546
+ const tags = value.tags;
40547
+ copy.tags = Array.isArray(tags) ? Array.from(tags) : tags;
40548
+ }
40549
+ if (Object.hasOwn(copy, "category") && !text3(copy.category))
40550
+ throw new SkillMetadataUpdateError("INVALID_METADATA_PATCH");
40551
+ 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))
40552
+ throw new SkillMetadataUpdateError("INVALID_METADATA_PATCH");
40553
+ return copy;
40554
+ }
40555
+ function metadataSnapshot(value, etag) {
40556
+ 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}"`)
40557
+ throw new SkillMetadataUpdateError("INVALID_METADATA_SNAPSHOT");
40558
+ const content = {
40559
+ slug: value.slug,
40560
+ displayName: value.displayName,
40561
+ description: value.description,
40562
+ category: value.category,
40563
+ tags: [...value.tags],
40564
+ source: value.publishedSource,
40565
+ kind: value.kind
40566
+ };
40567
+ for (const key2 of ["version", "skillMd", "bundleSha256", "archiveReason", "replacementSlug"]) {
40568
+ if (value[key2] !== undefined) {
40569
+ if (typeof value[key2] !== "string")
40570
+ throw new SkillMetadataUpdateError("INVALID_METADATA_SNAPSHOT");
40571
+ content[key2] = value[key2];
40572
+ }
40573
+ }
40574
+ if (value.bundleByteSize !== undefined) {
40575
+ if (!Number.isSafeInteger(value.bundleByteSize) || value.bundleByteSize < 0)
40576
+ throw new SkillMetadataUpdateError("INVALID_METADATA_SNAPSHOT");
40577
+ content.bundleByteSize = value.bundleByteSize;
40578
+ }
40579
+ if (value.lifecycle !== undefined) {
40580
+ if (value.lifecycle !== "active" && value.lifecycle !== "archived")
40581
+ throw new SkillMetadataUpdateError("INVALID_METADATA_SNAPSHOT");
40582
+ content.lifecycle = value.lifecycle;
40583
+ }
40584
+ if (revisionIdOf(content) !== value.revisionId)
40585
+ throw new SkillMetadataUpdateError("INVALID_METADATA_SNAPSHOT");
40586
+ return { content, revisionId: value.revisionId };
40587
+ }
40588
+ function metadataPlan(value) {
40589
+ 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))
40590
+ throw new SkillMetadataUpdateError("INVALID_METADATA_PLAN");
40591
+ const before = metadataSnapshot({ ...value.before, publishedSource: value.before.source, revisionId: value.expectedRevisionId }, `"${value.expectedRevisionId}"`).content;
40592
+ let original;
40593
+ try {
40594
+ original = JSON.parse(value.originalDocument);
40595
+ } catch {
40596
+ throw new SkillMetadataUpdateError("INVALID_METADATA_PLAN");
40597
+ }
40598
+ const preserved = metadataSnapshot(original, `"${value.expectedRevisionId}"`);
40599
+ if (preserved.revisionId !== value.expectedRevisionId)
40600
+ throw new SkillMetadataUpdateError("INVALID_METADATA_PLAN");
40601
+ return {
40602
+ schemaVersion: 1,
40603
+ authority: value.authority,
40604
+ organizationId: value.organizationId,
40605
+ expectedRevisionId: value.expectedRevisionId,
40606
+ originalDocument: value.originalDocument,
40607
+ before,
40608
+ patch: metadataPatch(value.patch)
40609
+ };
40610
+ }
40611
+ 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);
40612
+ var init_skill_metadata_update = __esm(() => {
40613
+ init_revision();
40614
+ SkillMetadataUpdateError = class SkillMetadataUpdateError extends Error {
40615
+ code;
40616
+ constructor(code) {
40617
+ super({
40618
+ METADATA_AUTH_REQUIRED: "Metadata updates require a signed-in Skills connection; use skills login.",
40619
+ INVALID_METADATA_PATCH: "Metadata patch accepts only category (a nonempty string) and tags (an array of unique nonempty strings).",
40620
+ INVALID_METADATA_SNAPSHOT: "The current skill must carry a matching quoted revision ETag and complete verifiable metadata, body and bundle identity.",
40621
+ INVALID_METADATA_PLAN: "The saved metadata plan must name its original revision, authority, organization, complete original content and category/tags-only patch.",
40622
+ METADATA_REVISION_CONFLICT: "The skill revision changed after preview; inspect it and prepare a new plan.",
40623
+ METADATA_UPDATE_UNCONFIRMED: "Metadata update could not be confirmed by authoritative readback; inspect the current revision before preparing another write."
40624
+ }[code]);
40625
+ this.code = code;
40626
+ }
40627
+ };
40628
+ });
40629
+
40488
40630
  // src/lib/remote-client.ts
40489
40631
  var exports_remote_client = {};
40490
40632
  __export(exports_remote_client, {
@@ -40562,6 +40704,89 @@ class RemoteSkillsClient {
40562
40704
  return null;
40563
40705
  return res.json();
40564
40706
  }
40707
+ async metadataOrganization() {
40708
+ const identity4 = await this.getIdentity();
40709
+ const organization2 = identity4.organization;
40710
+ if (typeof organization2?.id !== "string" || !organization2.id)
40711
+ throw new SkillMetadataUpdateError("INVALID_METADATA_SNAPSHOT");
40712
+ return organization2.id;
40713
+ }
40714
+ async readMetadataSnapshot(slug2) {
40715
+ const response = await this.request(`/api/v1/skills/${encodeURIComponent(slug2)}`);
40716
+ if (!response.ok)
40717
+ throw new RemoteRequestError("/api/v1/skills/:slug", response.status);
40718
+ const bytes = await readBoundedResponse(response, 2 * 1024 * 1024);
40719
+ const originalDocument = new TextDecoder("utf-8", { fatal: true }).decode(bytes);
40720
+ let value;
40721
+ try {
40722
+ value = JSON.parse(originalDocument);
40723
+ } catch {
40724
+ throw new SkillMetadataUpdateError("INVALID_METADATA_SNAPSHOT");
40725
+ }
40726
+ const snapshot2 = metadataSnapshot(value, response.headers.get("etag"));
40727
+ if (snapshot2.content.slug !== slug2)
40728
+ throw new SkillMetadataUpdateError("INVALID_METADATA_SNAPSHOT");
40729
+ return { ...snapshot2, originalDocument };
40730
+ }
40731
+ async prepareSkillMetadataUpdate(slug2, patch) {
40732
+ const captured = metadataPatch(patch);
40733
+ const organizationId = await this.metadataOrganization();
40734
+ const snapshot2 = await this.readMetadataSnapshot(slug2);
40735
+ return metadataPlan({
40736
+ schemaVersion: 1,
40737
+ authority: this.apiUrl,
40738
+ organizationId,
40739
+ expectedRevisionId: snapshot2.revisionId,
40740
+ originalDocument: snapshot2.originalDocument,
40741
+ before: snapshot2.content,
40742
+ patch: captured
40743
+ });
40744
+ }
40745
+ async applySkillMetadataUpdate(input2) {
40746
+ const plan = metadataPlan(input2);
40747
+ if (plan.authority !== this.apiUrl || await this.metadataOrganization() !== plan.organizationId)
40748
+ throw new SkillMetadataUpdateError("INVALID_METADATA_PLAN");
40749
+ const access = await this.getCapabilities({ refresh: true });
40750
+ if (access.permissions?.publish !== true)
40751
+ throw new RemoteSkillsPermissionError("publish");
40752
+ const current = await this.readMetadataSnapshot(plan.before.slug);
40753
+ if (current.revisionId !== plan.expectedRevisionId)
40754
+ throw new SkillMetadataUpdateError("METADATA_REVISION_CONFLICT");
40755
+ const expected = revisionIdOf({ ...plan.before, ...plan.patch });
40756
+ if (expected === current.revisionId)
40757
+ return { status: "unchanged", revisionId: expected };
40758
+ let uncertain = false;
40759
+ try {
40760
+ const response = await this.request(`/api/v1/skills/${encodeURIComponent(plan.before.slug)}`, {
40761
+ method: "PATCH",
40762
+ headers: { "If-Match": `"${plan.expectedRevisionId}"` },
40763
+ body: JSON.stringify(plan.patch)
40764
+ });
40765
+ if (!response.ok && response.status < 500)
40766
+ throw new RemoteRequestError("/api/v1/skills/:slug", response.status);
40767
+ if (!response.ok)
40768
+ uncertain = true;
40769
+ else {
40770
+ const bytes = await readBoundedResponse(response, 2 * 1024 * 1024);
40771
+ const written = metadataSnapshot(JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(bytes)), response.headers.get("etag"));
40772
+ if (written.revisionId !== expected)
40773
+ throw new SkillMetadataUpdateError("METADATA_UPDATE_UNCONFIRMED");
40774
+ }
40775
+ } catch (error61) {
40776
+ if (error61 instanceof RemoteRequestError && error61.status < 500)
40777
+ throw error61;
40778
+ uncertain = true;
40779
+ }
40780
+ let verified;
40781
+ try {
40782
+ verified = await this.readMetadataSnapshot(plan.before.slug);
40783
+ } catch {
40784
+ throw new SkillMetadataUpdateError("METADATA_UPDATE_UNCONFIRMED");
40785
+ }
40786
+ if (verified.revisionId !== expected)
40787
+ throw new SkillMetadataUpdateError("METADATA_UPDATE_UNCONFIRMED");
40788
+ return { status: uncertain ? "reconciled" : "applied", revisionId: expected };
40789
+ }
40565
40790
  async getSkillStatus(slug2) {
40566
40791
  const res = await this.request(`/api/v1/skills/${encodeURIComponent(slug2)}`, { method: "GET" });
40567
40792
  let body = null;
@@ -41432,6 +41657,8 @@ var init_remote_client = __esm(() => {
41432
41657
  init_remote_credit_checkout();
41433
41658
  init_remote_quote_errors();
41434
41659
  init_remote_permissions();
41660
+ init_skill_metadata_update();
41661
+ init_revision();
41435
41662
  RemoteRouteUnsupportedError = class RemoteRouteUnsupportedError extends Error {
41436
41663
  path;
41437
41664
  status;
@@ -41619,7 +41846,7 @@ var init_remote_invitation_recovery = __esm(() => {
41619
41846
  });
41620
41847
 
41621
41848
  // src/lib/remote-private-publications.ts
41622
- import { createHash as createHash26 } from "crypto";
41849
+ import { createHash as createHash27 } from "crypto";
41623
41850
  function checkedPrivateSkillCreate(value) {
41624
41851
  const refuse5 = (field3, accepted) => {
41625
41852
  throw new PrivatePublicationError("INVALID_SKILL_CREATE_INPUT", `Invalid ${field3}. ${accepted}`);
@@ -41657,7 +41884,7 @@ function checkedPublicationView(value, skillId, intentId, declaration) {
41657
41884
  return invalid4();
41658
41885
  return Object.freeze({ ...value });
41659
41886
  }
41660
- async function boundedJson(url2, init, token, mutation, budget3 = 15000, signal, create = false) {
41887
+ async function boundedJson(url2, init, token, mutation, budget3 = 15000, signal, create = false, readBinding) {
41661
41888
  const controller = new AbortController;
41662
41889
  let reader;
41663
41890
  let response;
@@ -41673,8 +41900,18 @@ async function boundedJson(url2, init, token, mutation, budget3 = 15000, signal,
41673
41900
  redirect: "error",
41674
41901
  credentials: "omit",
41675
41902
  signal: controller.signal,
41676
- headers: { "Content-Type": "application/json", Authorization: `Bearer ${token}` }
41903
+ headers: {
41904
+ "Content-Type": "application/json",
41905
+ Authorization: `Bearer ${token}`,
41906
+ ...readBinding ? {
41907
+ "x-skills-user-id": readBinding.userId,
41908
+ "x-skills-workspace-id": readBinding.organizationId,
41909
+ "x-skills-membership-id": readBinding.membershipId
41910
+ } : {}
41911
+ }
41677
41912
  });
41913
+ if (readBinding && response.ok && response.status !== 200)
41914
+ return invalid4();
41678
41915
  const length = response.headers.get("content-length");
41679
41916
  if (length !== null && (!/^\d+$/.test(length) || Number(length) > 65536))
41680
41917
  return invalid4();
@@ -41742,6 +41979,81 @@ async function boundedJson(url2, init, token, mutation, budget3 = 15000, signal,
41742
41979
  response?.body?.cancel().catch(() => {});
41743
41980
  }
41744
41981
  }
41982
+ function historyDate(value) {
41983
+ if (typeof value !== "string")
41984
+ return false;
41985
+ const parts = /^(\d{4})-(\d{2})-(\d{2})(T| )(\d{2}):(\d{2}):(\d{2})(?:\.(\d{1,9}))?(Z|[+-](\d{2})(?::(\d{2}))?)$/.exec(value);
41986
+ if (!parts)
41987
+ return false;
41988
+ const [, y, m, d, separator, h, minute, second, fraction, zone, offsetHour, offsetMinute] = parts;
41989
+ if (separator === " " ? zone === "Z" || (fraction?.length ?? 0) > 6 : zone !== "Z" && offsetMinute === undefined)
41990
+ return false;
41991
+ const year = Number(y), month = Number(m), day = Number(d);
41992
+ const leap = year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0);
41993
+ const days = [31, leap ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
41994
+ return year > 0 && month >= 1 && month <= 12 && day >= 1 && day <= days[month - 1] && Number(h) <= 23 && Number(minute) <= 59 && Number(second) <= 59 && (zone === "Z" || Number(offsetHour) <= 23 && Number(offsetMinute ?? 0) <= 59);
41995
+ }
41996
+ function privateHistory(value, organizationId, skillId, limit, cursor2) {
41997
+ if (!record10(value) || value.organizationId !== organizationId || value.skillId !== skillId || typeof value.slug !== "string" || !/^[a-z0-9-]+$/.test(value.slug) || !(value.currentVersion === null || historyText(value.currentVersion)) || !(value.currentVersionId === null || publicationUuid(value.currentVersionId)) || value.currentVersion === null !== (value.currentVersionId === null) || !(value.nextCursor === null || publicationUuid(value.nextCursor)) || !Array.isArray(value.versions) || value.versions.length > limit)
41998
+ return historyResponse();
41999
+ const seen = new Set;
42000
+ let previous = cursor2;
42001
+ const versions2 = value.versions.map((row) => {
42002
+ if (!record10(row) || !publicationUuid(row.id) || seen.has(row.id) || previous !== undefined && row.id >= previous || !historyText(row.version) || !(row.releasedAt === null || historyDate(row.releasedAt)) || !historyDate(row.createdAt) || row.id === value.currentVersionId !== (row.version === value.currentVersion))
42003
+ return historyResponse();
42004
+ seen.add(row.id);
42005
+ previous = row.id;
42006
+ return Object.freeze({ id: row.id, version: row.version, releasedAt: row.releasedAt, createdAt: row.createdAt });
42007
+ });
42008
+ if (value.nextCursor !== null && (!versions2.length || value.nextCursor !== versions2.at(-1).id))
42009
+ return historyResponse();
42010
+ return Object.freeze({
42011
+ organizationId,
42012
+ skillId,
42013
+ slug: value.slug,
42014
+ currentVersion: value.currentVersion,
42015
+ currentVersionId: value.currentVersionId,
42016
+ versions: Object.freeze(versions2),
42017
+ nextCursor: value.nextCursor
42018
+ });
42019
+ }
42020
+
42021
+ class RemotePrivateSkillHistoryClient {
42022
+ apiOrigin;
42023
+ organizationId;
42024
+ userId;
42025
+ membershipId;
42026
+ #token;
42027
+ constructor(apiUrl, session) {
42028
+ const checked = parseWorkspaceSession(session, { userId: session?.user?.id, membershipId: session?.user?.membershipId });
42029
+ this.apiOrigin = normalizeSkillsApiOrigin(apiUrl);
42030
+ this.#token = checked.token;
42031
+ this.organizationId = checked.organization.id;
42032
+ this.userId = checked.user.id;
42033
+ this.membershipId = checked.user.membershipId;
42034
+ Object.freeze(this);
42035
+ }
42036
+ async listVersions(skillId, options = {}) {
42037
+ if (!publicationUuid(skillId) || options.limit !== undefined && (!Number.isSafeInteger(options.limit) || options.limit < 1 || options.limit > 50) || options.cursor !== undefined && !publicationUuid(options.cursor) || options.timeoutMs !== undefined && (!Number.isSafeInteger(options.timeoutMs) || options.timeoutMs < 1 || options.timeoutMs > 15000))
42038
+ return historyInput();
42039
+ const limit = options.limit ?? 20, cursor2 = options.cursor;
42040
+ const query = new URLSearchParams;
42041
+ if (options.limit !== undefined)
42042
+ query.set("limit", String(limit));
42043
+ if (cursor2 !== undefined)
42044
+ query.set("cursor", cursor2);
42045
+ const path = `/api/v1/skills/${skillId}/versions${query.size ? `?${query}` : ""}`;
42046
+ let value;
42047
+ try {
42048
+ value = await boundedJson(skillsApiRequestUrl(this.apiOrigin, path), { method: "GET" }, this.#token, false, options.timeoutMs, options.signal, false, this);
42049
+ } catch (error61) {
42050
+ if (error61 instanceof PrivatePublicationError && error61.code === "INVALID_PUBLICATION_RESPONSE")
42051
+ return historyResponse();
42052
+ throw new PrivatePublicationError("PRIVATE_HISTORY_UNAVAILABLE", "Unable to read private version history. Check the selected server, current membership and fresh sign-in; no skill or credential was changed.", false, error61 instanceof PrivatePublicationError ? error61.status : undefined);
42053
+ }
42054
+ return privateHistory(value, this.organizationId, skillId, limit, cursor2);
42055
+ }
42056
+ }
41745
42057
 
41746
42058
  class RemotePrivatePublicationsClient {
41747
42059
  apiOrigin;
@@ -41915,7 +42227,11 @@ var PRIVATE_PUBLICATION_MAX_BYTES, skillCreateFailures, failures2, PrivatePublic
41915
42227
  throw new PrivatePublicationError("INVALID_PUBLICATION_INPUT", "Invalid publication input or recovery data.");
41916
42228
  }, invalid4 = () => {
41917
42229
  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");
42230
+ }, 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"), historyInput = () => {
42231
+ throw new PrivatePublicationError("INVALID_PRIVATE_HISTORY_INPUT", "Provide a private skill UUID, limit from 1 to 50, and an optional UUID cursor; timeoutMs must be from 1 to 15000.");
42232
+ }, historyResponse = () => {
42233
+ throw new PrivatePublicationError("INVALID_PRIVATE_HISTORY_RESPONSE", "The server returned invalid private version history.");
42234
+ }, historyText = (value) => typeof value === "string" && value.length > 0 && value.length <= 128 && !/[\p{Cc}\p{Cs}\u2028\u2029]/u.test(value);
41919
42235
  var init_remote_private_publications = __esm(() => {
41920
42236
  init_fleet_credentials();
41921
42237
  init_remote_workspace_selection();
@@ -41986,8 +42302,8 @@ async function requestAuthApi(instance, path, options) {
41986
42302
  apiUrl: safeUrl
41987
42303
  });
41988
42304
  }
41989
- const text3 = await res.text();
41990
- const body = text3 ? parseJsonBody(text3) : {};
42305
+ const text4 = await res.text();
42306
+ const body = text4 ? parseJsonBody(text4) : {};
41991
42307
  if (!res.ok) {
41992
42308
  const record11 = isRecord6(body) ? body : {};
41993
42309
  const detail = typeof record11.detail === "string" ? record11.detail : undefined;
@@ -42003,15 +42319,15 @@ async function requestAuthApi(instance, path, options) {
42003
42319
  }
42004
42320
  return body;
42005
42321
  }
42006
- function parseJsonBody(text3) {
42322
+ function parseJsonBody(text4) {
42007
42323
  try {
42008
- return JSON.parse(text3);
42324
+ return JSON.parse(text4);
42009
42325
  } catch {
42010
- return { detail: condenseErrorBody(text3) };
42326
+ return { detail: condenseErrorBody(text4) };
42011
42327
  }
42012
42328
  }
42013
- function condenseErrorBody(text3) {
42014
- const stripped = /<[a-z!/]/i.test(text3) ? text3.replace(/<(script|style)[\s\S]*?<\/\1>/gi, " ").replace(/<[^>]*>/g, " ") : text3;
42329
+ function condenseErrorBody(text4) {
42330
+ const stripped = /<[a-z!/]/i.test(text4) ? text4.replace(/<(script|style)[\s\S]*?<\/\1>/gi, " ").replace(/<[^>]*>/g, " ") : text4;
42015
42331
  const collapsed = stripped.replace(/\s+/g, " ").trim();
42016
42332
  if (collapsed.length <= MAX_ERROR_DETAIL_LENGTH)
42017
42333
  return collapsed;
@@ -42030,6 +42346,10 @@ class RemoteSkillsAuthClient {
42030
42346
  const origin = this.apiOrigin, captured = workspaceContext(context);
42031
42347
  return new RemotePrivatePublicationsClient(origin, await this.switchWorkspace(email4, code, captured));
42032
42348
  }
42349
+ async openPrivateSkillHistory(email4, code, context) {
42350
+ const origin = this.apiOrigin, captured = workspaceContext(context);
42351
+ return new RemotePrivateSkillHistoryClient(origin, await this.switchWorkspace(email4, code, captured));
42352
+ }
42033
42353
  requestInvitationEmailChallenge(input2) {
42034
42354
  return requestInvitationEmail(this.apiOrigin, "challenge", input2);
42035
42355
  }
@@ -42202,10 +42522,10 @@ var init_remote_auth = __esm(() => {
42202
42522
  });
42203
42523
 
42204
42524
  // 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";
42525
+ 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
42526
  function stat2(path) {
42207
42527
  try {
42208
- return lstatSync25(path);
42528
+ return lstatSync26(path);
42209
42529
  } catch (error61) {
42210
42530
  if (error61.code === "ENOENT")
42211
42531
  return null;
@@ -42220,18 +42540,18 @@ function safeText(file2) {
42220
42540
  const s = fstatSync19(fd);
42221
42541
  if (!s.isFile() || s.size > 65536 || ![256, 384].includes(s.mode & 4095) || process.getuid && s.uid !== process.getuid())
42222
42542
  return fail("The selected profile must use bounded owner-only regular files.");
42223
- return readFileSync20(fd, "utf8");
42543
+ return readFileSync21(fd, "utf8");
42224
42544
  } finally {
42225
42545
  closeSync19(fd);
42226
42546
  }
42227
42547
  }
42228
42548
  function checkIdentityMetadata(file2, identity4) {
42229
- const text3 = safeText(file2);
42230
- if (text3 === null)
42549
+ const text4 = safeText(file2);
42550
+ if (text4 === null)
42231
42551
  return;
42232
42552
  let value;
42233
42553
  try {
42234
- value = JSON.parse(text3);
42554
+ value = JSON.parse(text4);
42235
42555
  } catch {
42236
42556
  return fail("The profile identity metadata is invalid. Sign in again before managing this workspace.");
42237
42557
  }
@@ -42434,8 +42754,8 @@ var init_recurring_customer = __esm(() => {
42434
42754
  });
42435
42755
 
42436
42756
  // 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";
42757
+ 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";
42758
+ import { dirname as dirname26, isAbsolute as isAbsolute24, join as join36, resolve as resolve25 } from "path";
42439
42759
  import { randomUUID as randomUUID3 } from "crypto";
42440
42760
 
42441
42761
  class RecoveryOwner {
@@ -42445,12 +42765,12 @@ class RecoveryOwner {
42445
42765
  this.directory = directory;
42446
42766
  if (!isAbsolute24(directory) || resolve25(directory) !== directory || realpathSync11(directory) !== directory)
42447
42767
  invalid5();
42448
- for (let path = directory;; path = dirname25(path)) {
42449
- const stat3 = lstatSync26(path);
42768
+ for (let path = directory;; path = dirname26(path)) {
42769
+ const stat3 = lstatSync27(path);
42450
42770
  if (!stat3.isDirectory() || stat3.isSymbolicLink())
42451
42771
  invalid5();
42452
42772
  this.parents.push({ path, dev: stat3.dev, ino: stat3.ino });
42453
- if (path === dirname25(path))
42773
+ if (path === dirname26(path))
42454
42774
  break;
42455
42775
  }
42456
42776
  this.assert();
@@ -42459,17 +42779,17 @@ class RecoveryOwner {
42459
42779
  if (realpathSync11(this.directory) !== this.directory)
42460
42780
  invalid5();
42461
42781
  for (const prior of this.parents) {
42462
- const now = lstatSync26(prior.path);
42782
+ const now = lstatSync27(prior.path);
42463
42783
  if (!now.isDirectory() || now.isSymbolicLink() || now.dev !== prior.dev || now.ino !== prior.ino)
42464
42784
  invalid5();
42465
42785
  }
42466
- const own2 = lstatSync26(this.directory);
42786
+ const own2 = lstatSync27(this.directory);
42467
42787
  if ((own2.mode & 511) !== 448 || (own2.mode & 3584) !== 0 || process.getuid && own2.uid !== process.getuid())
42468
42788
  invalid5();
42469
42789
  }
42470
42790
  read(name) {
42471
42791
  this.assert();
42472
- const fd = openSync20(join35(this.directory, name), constants18.O_RDONLY | constants18.O_NOFOLLOW | constants18.O_NONBLOCK);
42792
+ const fd = openSync20(join36(this.directory, name), constants18.O_RDONLY | constants18.O_NOFOLLOW | constants18.O_NONBLOCK);
42473
42793
  try {
42474
42794
  const before = fstatSync20(fd);
42475
42795
  if (!before.isFile() || before.nlink !== 1 || (before.mode & 4095) !== 384 || before.size < 1 || before.size > 8192 || process.getuid && before.uid !== process.getuid())
@@ -42482,7 +42802,7 @@ class RecoveryOwner {
42482
42802
  break;
42483
42803
  size += n2;
42484
42804
  }
42485
- const after = fstatSync20(fd), path = lstatSync26(join35(this.directory, name));
42805
+ const after = fstatSync20(fd), path = lstatSync27(join36(this.directory, name));
42486
42806
  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
42807
  invalid5();
42488
42808
  this.assert();
@@ -42495,7 +42815,7 @@ class RecoveryOwner {
42495
42815
  this.assert();
42496
42816
  const bytes = canonicalJson2(value, 8192) + `
42497
42817
  `;
42498
- const fd = openSync20(join35(this.directory, name), constants18.O_WRONLY | constants18.O_CREAT | constants18.O_EXCL | constants18.O_NOFOLLOW, 384);
42818
+ const fd = openSync20(join36(this.directory, name), constants18.O_WRONLY | constants18.O_CREAT | constants18.O_EXCL | constants18.O_NOFOLLOW, 384);
42499
42819
  try {
42500
42820
  writeFileSync9(fd, bytes);
42501
42821
  fsyncSync5(fd);
@@ -42522,14 +42842,14 @@ class RecoveryOwner {
42522
42842
  if (this.read("state.json") !== expected)
42523
42843
  invalid5();
42524
42844
  this.assert();
42525
- renameSync6(join35(this.directory, name), join35(this.directory, "state.json"));
42845
+ renameSync6(join36(this.directory, name), join36(this.directory, "state.json"));
42526
42846
  this.sync();
42527
42847
  }
42528
42848
  async locked(action) {
42529
42849
  this.assert();
42530
42850
  let fd;
42531
42851
  try {
42532
- fd = openSync20(join35(this.directory, "operation.lock"), constants18.O_WRONLY | constants18.O_CREAT | constants18.O_EXCL | constants18.O_NOFOLLOW, 384);
42852
+ fd = openSync20(join36(this.directory, "operation.lock"), constants18.O_WRONLY | constants18.O_CREAT | constants18.O_EXCL | constants18.O_NOFOLLOW, 384);
42533
42853
  } catch {
42534
42854
  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
42855
  }
@@ -42542,10 +42862,10 @@ class RecoveryOwner {
42542
42862
  } finally {
42543
42863
  closeSync20(fd);
42544
42864
  this.assert();
42545
- const now = lstatSync26(join35(this.directory, "operation.lock"));
42865
+ const now = lstatSync27(join36(this.directory, "operation.lock"));
42546
42866
  if (owner2.dev !== now.dev || owner2.ino !== now.ino || !now.isFile() || now.isSymbolicLink())
42547
42867
  invalid5();
42548
- unlinkSync5(join35(this.directory, "operation.lock"));
42868
+ unlinkSync5(join36(this.directory, "operation.lock"));
42549
42869
  this.sync();
42550
42870
  }
42551
42871
  }
@@ -42578,7 +42898,7 @@ function base(customer, organizationId) {
42578
42898
  };
42579
42899
  }
42580
42900
  function create(directory, intent) {
42581
- if (!isAbsolute24(directory) || resolve25(directory) !== directory || realpathSync11(dirname25(directory)) !== dirname25(directory))
42901
+ if (!isAbsolute24(directory) || resolve25(directory) !== directory || realpathSync11(dirname26(directory)) !== dirname26(directory))
42582
42902
  invalid5();
42583
42903
  mkdirSync11(directory, { mode: 448 });
42584
42904
  const owner2 = new RecoveryOwner(directory), checked = intentSchema.parse(intent), intentSha256 = canonicalJsonSha256(checked);
@@ -44315,17 +44635,17 @@ var init_tool_primitives = __esm(() => {
44315
44635
 
44316
44636
  // src/lib/compact-output.ts
44317
44637
  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()}...`;
44638
+ const text4 = String(value ?? "").replace(/\s+/g, " ").trim();
44639
+ if (text4.length <= maxChars)
44640
+ return text4;
44641
+ return `${text4.slice(0, Math.max(0, maxChars - 3)).trimEnd()}...`;
44322
44642
  }
44323
44643
  function previewText(value, maxChars = DEFAULT_PREVIEW_CHARS) {
44324
- const text3 = String(value ?? "");
44644
+ const text4 = String(value ?? "");
44325
44645
  return {
44326
- text: text3.length > maxChars ? `${text3.slice(0, Math.max(0, maxChars - 3))}...` : text3,
44327
- length: text3.length,
44328
- truncated: text3.length > maxChars
44646
+ text: text4.length > maxChars ? `${text4.slice(0, Math.max(0, maxChars - 3))}...` : text4,
44647
+ length: text4.length,
44648
+ truncated: text4.length > maxChars
44329
44649
  };
44330
44650
  }
44331
44651
  function parsePageLimit(value, fallback, options = {}) {
@@ -44675,21 +44995,21 @@ var init_credential_state = __esm(() => {
44675
44995
  });
44676
44996
 
44677
44997
  // 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";
44998
+ import { createHash as createHash28, randomBytes } from "crypto";
44999
+ import { existsSync as existsSync15, mkdirSync as mkdirSync12, readFileSync as readFileSync22, readdirSync as readdirSync12, statSync as statSync11, writeFileSync as writeFileSync10 } from "fs";
45000
+ import { extname, join as join37, relative as relative9 } from "path";
44681
45001
  function createSkillRun(params, targetDir = process.cwd()) {
44682
45002
  const now = new Date;
44683
45003
  const id = createRunId(now);
44684
45004
  const day = now.toISOString().slice(0, 10);
44685
45005
  const skillName = normalizeSkillName(params.skill);
44686
45006
  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);
45007
+ const runDir = join37(root, "runs", day, id);
45008
+ const logsDir = join37(runDir, "logs");
45009
+ const exportDir = join37(root, "exports", skillName, id);
44690
45010
  mkdirSync12(logsDir, { recursive: true });
44691
45011
  mkdirSync12(exportDir, { recursive: true });
44692
- mkdirSync12(join36(root, "tmp"), { recursive: true });
45012
+ mkdirSync12(join37(root, "tmp"), { recursive: true });
44693
45013
  const record11 = {
44694
45014
  id,
44695
45015
  skill: skillName,
@@ -44741,22 +45061,22 @@ function updateSkillRun(context2, patch) {
44741
45061
  return context2.record;
44742
45062
  }
44743
45063
  function writeRunLogs(context2, stdout = "", stderr = "") {
44744
- writeFileSync10(join36(context2.logsDir, "stdout.log"), stdout);
44745
- writeFileSync10(join36(context2.logsDir, "stderr.log"), stderr);
45064
+ writeFileSync10(join37(context2.logsDir, "stdout.log"), stdout);
45065
+ writeFileSync10(join37(context2.logsDir, "stderr.log"), stderr);
44746
45066
  }
44747
45067
  function appendRunEvent(context2, event, data = {}) {
44748
45068
  const line = JSON.stringify({ ts: new Date().toISOString(), event, ...data }) + `
44749
45069
  `;
44750
- const path = join36(context2.runDir, "events.ndjson");
44751
- const previous = existsSync15(path) ? readFileSync21(path, "utf-8") : "";
45070
+ const path = join37(context2.runDir, "events.ndjson");
45071
+ const previous = existsSync15(path) ? readFileSync22(path, "utf-8") : "";
44752
45072
  writeFileSync10(path, previous + line);
44753
45073
  }
44754
45074
  function findSkillRun(runId, targetDir = process.cwd()) {
44755
- const runsRoot = join36(getProjectStateDir(targetDir), "runs");
45075
+ const runsRoot = join37(getProjectStateDir(targetDir), "runs");
44756
45076
  if (!existsSync15(runsRoot))
44757
45077
  return null;
44758
- for (const day of readdirSync11(runsRoot)) {
44759
- const record11 = readRunRecord(join36(runsRoot, day, runId));
45078
+ for (const day of readdirSync12(runsRoot)) {
45079
+ const record11 = readRunRecord(join37(runsRoot, day, runId));
44760
45080
  if (record11)
44761
45081
  return record11;
44762
45082
  }
@@ -44773,11 +45093,11 @@ function skillRunEnv(context2) {
44773
45093
  };
44774
45094
  }
44775
45095
  function writeRunRecord(context2) {
44776
- writeFileSync10(join36(context2.runDir, "run.json"), JSON.stringify(context2.record, null, 2) + `
45096
+ writeFileSync10(join37(context2.runDir, "run.json"), JSON.stringify(context2.record, null, 2) + `
44777
45097
  `);
44778
45098
  }
44779
45099
  function writeArtifactsManifest(context2, artifacts) {
44780
- writeFileSync10(join36(context2.runDir, "artifacts.json"), JSON.stringify({ runId: context2.record.id, artifacts }, null, 2) + `
45100
+ writeFileSync10(join37(context2.runDir, "artifacts.json"), JSON.stringify({ runId: context2.record.id, artifacts }, null, 2) + `
44781
45101
  `);
44782
45102
  }
44783
45103
  function collectRunArtifacts(context2) {
@@ -44786,30 +45106,30 @@ function collectRunArtifacts(context2) {
44786
45106
  const artifacts = [];
44787
45107
  for (const path of walkFiles(context2.exportDir)) {
44788
45108
  const stat3 = statSync11(path);
44789
- const bytes = readFileSync21(path);
45109
+ const bytes = readFileSync22(path);
44790
45110
  artifacts.push({
44791
45111
  path: toProjectRelative(context2.targetDir, path),
44792
45112
  mime: mimeForPath(path),
44793
- sha256: createHash27("sha256").update(bytes).digest("hex"),
45113
+ sha256: createHash28("sha256").update(bytes).digest("hex"),
44794
45114
  sizeBytes: stat3.size
44795
45115
  });
44796
45116
  }
44797
45117
  return artifacts.sort((a, b) => a.path.localeCompare(b.path));
44798
45118
  }
44799
45119
  function readRunRecord(runDir) {
44800
- const path = join36(runDir, "run.json");
45120
+ const path = join37(runDir, "run.json");
44801
45121
  if (!existsSync15(path))
44802
45122
  return null;
44803
45123
  try {
44804
- return JSON.parse(readFileSync21(path, "utf-8"));
45124
+ return JSON.parse(readFileSync22(path, "utf-8"));
44805
45125
  } catch {
44806
45126
  return null;
44807
45127
  }
44808
45128
  }
44809
45129
  function walkFiles(dir) {
44810
45130
  const files = [];
44811
- for (const entry of readdirSync11(dir)) {
44812
- const full = join36(dir, entry);
45131
+ for (const entry of readdirSync12(dir)) {
45132
+ const full = join37(dir, entry);
44813
45133
  if (statSync11(full).isDirectory())
44814
45134
  files.push(...walkFiles(full));
44815
45135
  else
@@ -45062,11 +45382,11 @@ var init_cloud_executions = __esm(() => {
45062
45382
  // node_modules/@hasna/secrets/dist/sdk.js
45063
45383
  import { isIP as isIP2 } from "net";
45064
45384
  import { spawnSync as spawnSync5 } from "child_process";
45065
- import { closeSync as closeSync21, fstatSync as fstatSync21, openSync as openSync21, readFileSync as readFileSync22 } from "fs";
45385
+ import { closeSync as closeSync21, fstatSync as fstatSync21, openSync as openSync21, readFileSync as readFileSync23 } from "fs";
45066
45386
  import { O_NOFOLLOW as O_NOFOLLOW3, O_NONBLOCK as O_NONBLOCK3, O_RDONLY as O_RDONLY3 } from "constants";
45067
45387
  import { createRequire as createRequire2 } from "module";
45068
45388
  import { hostname as osHostname2 } from "os";
45069
- import { isAbsolute as isAbsolute26, join as join37 } from "path";
45389
+ import { isAbsolute as isAbsolute26, join as join38 } from "path";
45070
45390
  import { createRequire as createRequire22 } from "module";
45071
45391
  function envToken2(name) {
45072
45392
  return name.toUpperCase().replace(/-/g, "_");
@@ -45097,14 +45417,14 @@ function hasnaHomeDir2(env) {
45097
45417
  if (override)
45098
45418
  return override;
45099
45419
  const home = homeDir2(env);
45100
- return home ? join37(home, HASNA_HOME_DIR2) : null;
45420
+ return home ? join38(home, HASNA_HOME_DIR2) : null;
45101
45421
  }
45102
45422
  function appConfigDir2(name, env) {
45103
45423
  const configRoot = absoluteOverride2(env, HASNA_CONFIG_HOME_ENV_KEY2);
45104
45424
  if (configRoot)
45105
- return join37(configRoot, name);
45425
+ return join38(configRoot, name);
45106
45426
  const root = hasnaHomeDir2(env);
45107
- return root ? join37(root, name, CONFIG_SUBDIR2) : null;
45427
+ return root ? join38(root, name, CONFIG_SUBDIR2) : null;
45108
45428
  }
45109
45429
  function credentialDiskSourceList2(name, env, profile = null) {
45110
45430
  if (!SAFE_APP_SLUG2.test(name))
@@ -45113,7 +45433,7 @@ function credentialDiskSourceList2(name, env, profile = null) {
45113
45433
  if (!directory2)
45114
45434
  return [];
45115
45435
  const file2 = profile ? `${CREDENTIALS_FILE2}-${profile}` : CREDENTIALS_FILE2;
45116
- return [{ path: join37(directory2, file2), tier: "disk" }];
45436
+ return [{ path: join38(directory2, file2), tier: "disk" }];
45117
45437
  }
45118
45438
  function credentialDiskSources2(name, env) {
45119
45439
  return credentialDiskSourceList2(name, env, null).map((s) => s.path);
@@ -45121,10 +45441,10 @@ function credentialDiskSources2(name, env) {
45121
45441
  function profileDiskSources2(name, env, profile) {
45122
45442
  return credentialDiskSourceList2(name, env, profile).map((s) => s.path);
45123
45443
  }
45124
- function parseEnvFile2(text3) {
45444
+ function parseEnvFile2(text4) {
45125
45445
  const values = new Map;
45126
45446
  const unusable = new Set;
45127
- for (const rawLine of text3.split(/\r?\n/)) {
45447
+ for (const rawLine of text4.split(/\r?\n/)) {
45128
45448
  const line = rawLine.trim();
45129
45449
  if (line.length === 0 || line.startsWith("#"))
45130
45450
  continue;
@@ -45188,7 +45508,7 @@ function readAppConfigFile2(path) {
45188
45508
  unsafe("the file is not owned by the current user");
45189
45509
  if (before.size > MAX_CREDENTIAL_FILE_BYTES2)
45190
45510
  unsafe("the file exceeds the size limit");
45191
- const bytes = readFileSync22(fd);
45511
+ const bytes = readFileSync23(fd);
45192
45512
  const after = fstatSync21(fd);
45193
45513
  if (!configFileReadsCoherent2(before, after)) {
45194
45514
  unsafe("the file changed while being read");
@@ -45364,8 +45684,8 @@ function keychainAccount2(env, options) {
45364
45684
  const user = env.USER?.trim();
45365
45685
  return user || null;
45366
45686
  }
45367
- function keychainFailureHint2(text3) {
45368
- const line = text3.split(/\r?\n/).find((entry) => entry.trim().length > 0)?.trim() ?? "";
45687
+ function keychainFailureHint2(text4) {
45688
+ const line = text4.split(/\r?\n/).find((entry) => entry.trim().length > 0)?.trim() ?? "";
45369
45689
  const clean = line.replace(/[\u0000-\u001f\u007f]/g, "").slice(0, 200);
45370
45690
  return clean ? `: ${clean}` : "";
45371
45691
  }
@@ -45943,12 +46263,12 @@ function createHasnaHttpTransportInternal(options, requestBindingProvider) {
45943
46263
  await response.body?.cancel();
45944
46264
  } catch {}
45945
46265
  } else {
45946
- const text3 = await response.text();
45947
- if (text3.length > 0) {
46266
+ const text4 = await response.text();
46267
+ if (text4.length > 0) {
45948
46268
  try {
45949
- parsed = JSON.parse(text3);
46269
+ parsed = JSON.parse(text4);
45950
46270
  } catch {
45951
- parsed = text3;
46271
+ parsed = text4;
45952
46272
  }
45953
46273
  }
45954
46274
  }
@@ -46051,13 +46371,13 @@ class SecretsClient {
46051
46371
  headers,
46052
46372
  redirect: "manual"
46053
46373
  });
46054
- const text3 = await response.text();
46374
+ const text4 = await response.text();
46055
46375
  let body = undefined;
46056
- if (text3) {
46376
+ if (text4) {
46057
46377
  try {
46058
- body = JSON.parse(text3);
46378
+ body = JSON.parse(text4);
46059
46379
  } catch {
46060
- body = text3;
46380
+ body = text4;
46061
46381
  }
46062
46382
  }
46063
46383
  if (!response.ok) {
@@ -46459,7 +46779,7 @@ async function resolveSelectedSecrets(bindings, createClient = createSecretsClie
46459
46779
  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
46780
  }
46461
46781
  }
46462
- function redactExecutionSecrets(text3, env) {
46782
+ function redactExecutionSecrets(text4, env) {
46463
46783
  const values = new Set(Object.values(env).flatMap((value) => {
46464
46784
  let encoded = "";
46465
46785
  try {
@@ -46468,8 +46788,8 @@ function redactExecutionSecrets(text3, env) {
46468
46788
  return [value, JSON.stringify(value).slice(1, -1), Buffer.from(value).toString("base64"), encoded];
46469
46789
  }));
46470
46790
  for (const value of [...values].filter(Boolean).sort((a, b) => b.length - a.length))
46471
- text3 = text3.split(value).join("[REDACTED]");
46472
- return text3;
46791
+ text4 = text4.split(value).join("[REDACTED]");
46792
+ return text4;
46473
46793
  }
46474
46794
  var init_execution_secrets = __esm(() => {
46475
46795
  init_sdk();
@@ -46608,10 +46928,10 @@ __export(exports_selected_run, {
46608
46928
  executeSelectedLocal: () => executeSelectedLocal,
46609
46929
  declaredOperation: () => declaredOperation
46610
46930
  });
46611
- import { createHash as createHash28 } from "crypto";
46931
+ import { createHash as createHash29 } from "crypto";
46612
46932
  import { spawn as spawn2 } from "child_process";
46613
46933
  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";
46934
+ import { dirname as dirname27, join as join39, resolve as resolve26 } from "path";
46615
46935
  import { tmpdir, hostname as stationHostname2 } from "os";
46616
46936
  async function resolveSelectedRun(spec, profileId, options = {}) {
46617
46937
  const context2 = await resolveSelectionContext(profileId, options);
@@ -46734,7 +47054,7 @@ async function executeSelectedLocal(selected, options = {}) {
46734
47054
  throw new SkillSelectionError("INVALID_SECRET_BINDINGS", "Explicit environment values must be bounded strings without NUL bytes.");
46735
47055
  secretEnv[name] = value;
46736
47056
  }
46737
- const runDirectory = mkdtempSync3(join38(tmpdir(), "skills-execution-"));
47057
+ const runDirectory = mkdtempSync3(join39(tmpdir(), "skills-execution-"));
46738
47058
  const paths = new SkillEntryPaths;
46739
47059
  for (const entry of entries) {
46740
47060
  paths.add(entry.path, 100, () => {
@@ -46742,8 +47062,8 @@ async function executeSelectedLocal(selected, options = {}) {
46742
47062
  }, () => {
46743
47063
  throw new SkillSelectionError("INVALID_BUNDLE_PATH", "The execution bundle path exceeds its limit.");
46744
47064
  });
46745
- const destination = join38(runDirectory, entry.path);
46746
- mkdirSync13(dirname26(destination), { recursive: true, mode: 448 });
47065
+ const destination = join39(runDirectory, entry.path);
47066
+ mkdirSync13(dirname27(destination), { recursive: true, mode: 448 });
46747
47067
  writeFileSync11(destination, entry.bytes, { flag: "wx", mode: entry.mode & 511 });
46748
47068
  }
46749
47069
  env.SKILLS_INPUT_JSON = input2;
@@ -46770,7 +47090,7 @@ async function executeSelectedLocal(selected, options = {}) {
46770
47090
  }
46771
47091
  if (bindings)
46772
47092
  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);
47093
+ const result = await subprocess([executable, ...runtimeName === "bun" ? ["--no-env-file"] : [], join39(runDirectory, declaredEntry), ...args], runDirectory, { ...env, ...secretEnv }, input2, timeoutMs);
46774
47094
  result.stdout = redactExecutionSecrets(result.stdout, secretEnv);
46775
47095
  result.stderr = redactExecutionSecrets(result.stderr, secretEnv);
46776
47096
  const receipt = {
@@ -46778,13 +47098,13 @@ async function executeSelectedLocal(selected, options = {}) {
46778
47098
  target: "local",
46779
47099
  runtime: runtimeName,
46780
47100
  entrypoint: declaredEntry,
46781
- inputDigest: `sha256:${createHash28("sha256").update(input2).digest("hex")}`,
47101
+ inputDigest: `sha256:${createHash29("sha256").update(input2).digest("hex")}`,
46782
47102
  runDirectory,
46783
47103
  ...executionGrant ? { executionGrant } : {},
46784
47104
  ...bindings ? { secretBinding: { schema: bindings.schema, selection: bindings.selection, consumer: bindings.consumer, secretsAuthority: bindings.secretsAuthority, bindings: bindings.bindings } } : {},
46785
47105
  ...result
46786
47106
  };
46787
- writeFileSync11(join38(runDirectory, ".execution-receipt.json"), JSON.stringify({ ...receipt, stdout: undefined, stderr: undefined }), { mode: 384 });
47107
+ writeFileSync11(join39(runDirectory, ".execution-receipt.json"), JSON.stringify({ ...receipt, stdout: undefined, stderr: undefined }), { mode: 384 });
46788
47108
  return receipt;
46789
47109
  }
46790
47110
  async function subprocess(command, cwd, env, input2, timeoutMs) {
@@ -46973,8 +47293,8 @@ var init_blog_article = __esm(() => {
46973
47293
  });
46974
47294
 
46975
47295
  // 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";
47296
+ import { existsSync as existsSync16, readdirSync as readdirSync13, statSync as statSync12 } from "fs";
47297
+ import { join as join40 } from "path";
46978
47298
  function registerOperationTools(server) {
46979
47299
  server.registerTool("cloud_skill_eligibility", {
46980
47300
  title: "Cloud Skill Eligibility",
@@ -47455,8 +47775,8 @@ function registerOperationTools(server) {
47455
47775
  let skillCount = 0;
47456
47776
  if (exists) {
47457
47777
  try {
47458
- skillCount = readdirSync12(agentSkillsPath).filter((f) => {
47459
- const full = join39(agentSkillsPath, f);
47778
+ skillCount = readdirSync13(agentSkillsPath).filter((f) => {
47779
+ const full = join40(agentSkillsPath, f);
47460
47780
  return !f.startsWith(".") && statSync12(full).isDirectory();
47461
47781
  }).length;
47462
47782
  } catch {}
@@ -47524,14 +47844,14 @@ var init_operation_tools = __esm(() => {
47524
47844
 
47525
47845
  // src/lib/feedback.ts
47526
47846
  import { appendFileSync, existsSync as existsSync17, mkdirSync as mkdirSync14 } from "fs";
47527
- import { dirname as dirname27, join as join40 } from "path";
47847
+ import { dirname as dirname28, join as join41 } from "path";
47528
47848
  import { Database } from "bun:sqlite";
47529
47849
  function getFeedbackDbPath() {
47530
- return join40(getDataDir(), "skills.db");
47850
+ return join41(getDataDir(), "skills.db");
47531
47851
  }
47532
47852
  function getFeedbackDb() {
47533
47853
  const dbPath = getFeedbackDbPath();
47534
- const dir = dirname27(dbPath);
47854
+ const dir = dirname28(dbPath);
47535
47855
  if (!existsSync17(dir))
47536
47856
  mkdirSync14(dir, { recursive: true });
47537
47857
  const db = new Database(dbPath);
@@ -47559,8 +47879,8 @@ function saveFeedback(input2) {
47559
47879
  throw new Error("Feedback message is required");
47560
47880
  const category = input2.category ?? "general";
47561
47881
  if (isApiMode()) {
47562
- const path = join40(getDataDir(), "feedback.jsonl");
47563
- const dir = dirname27(path);
47882
+ const path = join41(getDataDir(), "feedback.jsonl");
47883
+ const dir = dirname28(path);
47564
47884
  if (!existsSync17(dir))
47565
47885
  mkdirSync14(dir, { recursive: true });
47566
47886
  appendFileSync(path, JSON.stringify({ message, category, email: input2.email ?? null, agent: input2.agent ?? null, version: input2.version ?? null, createdAt: new Date().toISOString() }) + `
@@ -47723,23 +48043,23 @@ var init_resource_meta_tools = __esm(() => {
47723
48043
  });
47724
48044
 
47725
48045
  // 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";
48046
+ import { existsSync as existsSync18, readFileSync as readFileSync24, writeFileSync as writeFileSync12, mkdirSync as mkdirSync15 } from "fs";
48047
+ import { join as join42 } from "path";
47728
48048
  function getSchedulesPath(targetDir = process.cwd()) {
47729
- return join41(targetDir, ".skills", "schedules.json");
48049
+ return join42(targetDir, ".skills", "schedules.json");
47730
48050
  }
47731
48051
  function loadSchedules(targetDir = process.cwd()) {
47732
48052
  const path = getSchedulesPath(targetDir);
47733
48053
  if (existsSync18(path)) {
47734
48054
  try {
47735
- return JSON.parse(readFileSync23(path, "utf-8"));
48055
+ return JSON.parse(readFileSync24(path, "utf-8"));
47736
48056
  } catch {}
47737
48057
  }
47738
48058
  return { version: 1, schedules: [] };
47739
48059
  }
47740
48060
  function saveSchedules(data, targetDir = process.cwd()) {
47741
48061
  const path = getSchedulesPath(targetDir);
47742
- const dir = join41(targetDir, ".skills");
48062
+ const dir = join42(targetDir, ".skills");
47743
48063
  if (!existsSync18(dir))
47744
48064
  mkdirSync15(dir, { recursive: true });
47745
48065
  writeFileSync12(path, JSON.stringify(data, null, 2));
@@ -48011,16 +48331,16 @@ var init_schedule_tools = __esm(() => {
48011
48331
  });
48012
48332
 
48013
48333
  // src/lib/native-storage.ts
48014
- import { createHash as createHash29, createHmac } from "crypto";
48334
+ import { createHash as createHash30, createHmac } from "crypto";
48015
48335
  import {
48016
48336
  existsSync as existsSync19,
48017
48337
  mkdirSync as mkdirSync16,
48018
- readFileSync as readFileSync24,
48019
- readdirSync as readdirSync13,
48338
+ readFileSync as readFileSync25,
48339
+ readdirSync as readdirSync14,
48020
48340
  statSync as statSync13,
48021
48341
  writeFileSync as writeFileSync13
48022
48342
  } from "fs";
48023
- import { dirname as dirname28, join as join42, normalize as normalize5, relative as relative10, sep as sep14 } from "path";
48343
+ import { dirname as dirname29, join as join43, normalize as normalize5, relative as relative10, sep as sep14 } from "path";
48024
48344
  function resolveSkillsNativeStorageConfig(env = process.env) {
48025
48345
  assertNoRetiredModeEnvVars(env, {
48026
48346
  app: SKILLS_ENV_NAMESPACE,
@@ -48061,7 +48381,7 @@ function getSkillsNativeStorageStatus(options = {}) {
48061
48381
  local: {
48062
48382
  dataDir: getDataDir(),
48063
48383
  projectStateDir: getProjectStateDir(targetDir),
48064
- feedbackDbPath: join42(getDataDir(), "skills.db")
48384
+ feedbackDbPath: join43(getDataDir(), "skills.db")
48065
48385
  },
48066
48386
  remote: {
48067
48387
  databaseConfigured: Boolean(config2.databaseUrl),
@@ -48083,12 +48403,12 @@ function exportSkillsLocalSnapshot(targetDir = process.cwd(), options = {}) {
48083
48403
  const files = [];
48084
48404
  if (existsSync19(projectStateDir)) {
48085
48405
  for (const filePath of walkFiles2(projectStateDir)) {
48086
- const bytes = readFileSync24(filePath);
48406
+ const bytes = readFileSync25(filePath);
48087
48407
  const relativePath = toPosix(relative10(targetDir, filePath));
48088
48408
  files.push({
48089
48409
  path: relativePath,
48090
48410
  sizeBytes: bytes.byteLength,
48091
- sha256: createHash29("sha256").update(bytes).digest("hex"),
48411
+ sha256: createHash30("sha256").update(bytes).digest("hex"),
48092
48412
  ...options.includeFileContents ? { contentBase64: Buffer.from(bytes).toString("base64") } : {}
48093
48413
  });
48094
48414
  }
@@ -48141,8 +48461,8 @@ function parsePositiveInteger(value) {
48141
48461
  }
48142
48462
  function walkFiles2(dir) {
48143
48463
  const files = [];
48144
- for (const entry of readdirSync13(dir)) {
48145
- const full = join42(dir, entry);
48464
+ for (const entry of readdirSync14(dir)) {
48465
+ const full = join43(dir, entry);
48146
48466
  const stats = statSync13(full);
48147
48467
  if (stats.isDirectory())
48148
48468
  files.push(...walkFiles2(full));
@@ -48360,7 +48680,7 @@ var init_remote_invitation_tools = __esm(() => {
48360
48680
  });
48361
48681
 
48362
48682
  // src/lib/private-publication-customer.ts
48363
- function preparePrivatePublicationSession(requested) {
48683
+ function preparePrivateSession(requested, action, open2) {
48364
48684
  const selectors = [
48365
48685
  "HASNA_PROFILE",
48366
48686
  "HASNA_HOME",
@@ -48374,7 +48694,7 @@ function preparePrivatePublicationSession(requested) {
48374
48694
  "SKILLS_API_KEY"
48375
48695
  ];
48376
48696
  const before = new Map(selectors.map((key2) => [key2, process.env[key2]]));
48377
- const profile = selectedSkillsProfile(process.env), pending = prepareProfileWorkspace("Manage private publications");
48697
+ const profile = selectedSkillsProfile(process.env), pending = prepareProfileWorkspace(action);
48378
48698
  const captured = requested ? { ...requested } : undefined;
48379
48699
  const unchanged3 = () => {
48380
48700
  if (selectors.some((key2) => process.env[key2] !== before.get(key2)) || selectedSkillsProfile(process.env) !== profile)
@@ -48388,12 +48708,15 @@ function preparePrivatePublicationSession(requested) {
48388
48708
  throw new PrivatePublicationError("PUBLICATION_CONTEXT_REQUIRED", "Provide the observed user and membership IDs, or select an enrolled workspace profile.");
48389
48709
  unchanged3();
48390
48710
  target.unchanged();
48391
- const client = await new RemoteSkillsAuthClient(target.origin).openPrivatePublications(email5, code2, context2);
48711
+ const client = await open2(new RemoteSkillsAuthClient(target.origin), email5, code2, context2);
48392
48712
  unchanged3();
48393
48713
  target.unchanged();
48394
48714
  return client;
48395
48715
  } };
48396
48716
  }
48717
+ function preparePrivatePublicationSession(requested) {
48718
+ return preparePrivateSession(requested, "Manage private publications", (auth, email5, code2, context2) => auth.openPrivatePublications(email5, code2, context2));
48719
+ }
48397
48720
  async function privatePublicationSession(email5, code2, requested) {
48398
48721
  return preparePrivatePublicationSession(requested).verify(email5, code2);
48399
48722
  }
@@ -48408,20 +48731,20 @@ var init_private_publication_customer = __esm(() => {
48408
48731
  });
48409
48732
 
48410
48733
  // 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";
48734
+ 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";
48735
+ import { dirname as dirname30, isAbsolute as isAbsolute27, join as join44, resolve as resolve27 } from "path";
48413
48736
  import { randomUUID as randomUUID4 } from "crypto";
48414
48737
  function safeDirectory(directory2) {
48415
48738
  if (!isAbsolute27(directory2) || directory2 !== resolve27(directory2) || realpathSync14(directory2) !== directory2)
48416
48739
  return fail2();
48417
- for (let path = directory2;; path = dirname29(path)) {
48418
- const stat3 = lstatSync27(path);
48740
+ for (let path = directory2;; path = dirname30(path)) {
48741
+ const stat3 = lstatSync28(path);
48419
48742
  if (!stat3.isDirectory() || stat3.isSymbolicLink())
48420
48743
  return fail2();
48421
- if (path === dirname29(path))
48744
+ if (path === dirname30(path))
48422
48745
  break;
48423
48746
  }
48424
- const own2 = lstatSync27(directory2);
48747
+ const own2 = lstatSync28(directory2);
48425
48748
  if ((own2.mode & 63) !== 0 || process.getuid && own2.uid !== process.getuid())
48426
48749
  return fail2();
48427
48750
  return { dev: own2.dev, ino: own2.ino };
@@ -48432,7 +48755,7 @@ function unchangedDirectory(directory2, identity4) {
48432
48755
  return fail2();
48433
48756
  }
48434
48757
  function readOwned(directory2, name, max) {
48435
- const identity4 = safeDirectory(directory2), file2 = join43(directory2, name);
48758
+ const identity4 = safeDirectory(directory2), file2 = join44(directory2, name);
48436
48759
  const fd = openSync23(file2, constants20.O_RDONLY | constants20.O_NOFOLLOW);
48437
48760
  try {
48438
48761
  const stat3 = fstatSync23(fd);
@@ -48456,7 +48779,7 @@ function readOwned(directory2, name, max) {
48456
48779
  }
48457
48780
  }
48458
48781
  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);
48782
+ const fd = openSync23(join44(directory2, name), constants20.O_WRONLY | constants20.O_CREAT | constants20.O_EXCL | constants20.O_NOFOLLOW, 384);
48460
48783
  try {
48461
48784
  writeFileSync14(fd, bytes);
48462
48785
  fsyncSync6(fd);
@@ -48469,7 +48792,7 @@ function save(directory2, value) {
48469
48792
  writeOwned(directory2, temporary, JSON.stringify(value) + `
48470
48793
  `);
48471
48794
  unchangedDirectory(directory2, identity4);
48472
- renameSync7(join43(directory2, temporary), join43(directory2, "receipt.json"));
48795
+ renameSync7(join44(directory2, temporary), join44(directory2, "receipt.json"));
48473
48796
  const fd = openSync23(directory2, constants20.O_RDONLY | constants20.O_NOFOLLOW);
48474
48797
  try {
48475
48798
  fsyncSync6(fd);
@@ -48482,7 +48805,7 @@ function bind(client, receipt) {
48482
48805
  throw new PrivatePublicationError("PUBLICATION_IDENTITY_CHANGED", "The fresh session does not match the recovery directory's server, account and membership.");
48483
48806
  }
48484
48807
  async function locked(directory2, action) {
48485
- const identity4 = safeDirectory(directory2), file2 = join43(directory2, "operation.lock");
48808
+ const identity4 = safeDirectory(directory2), file2 = join44(directory2, "operation.lock");
48486
48809
  let fd;
48487
48810
  try {
48488
48811
  fd = openSync23(file2, constants20.O_WRONLY | constants20.O_CREAT | constants20.O_EXCL | constants20.O_NOFOLLOW, 384);
@@ -48498,7 +48821,7 @@ async function locked(directory2, action) {
48498
48821
  } finally {
48499
48822
  closeSync23(fd);
48500
48823
  unchangedDirectory(directory2, identity4);
48501
- const now = lstatSync27(file2);
48824
+ const now = lstatSync28(file2);
48502
48825
  if (now.dev !== lock.dev || now.ino !== lock.ino || !now.isFile() || now.isSymbolicLink())
48503
48826
  fail2();
48504
48827
  unlinkSync6(file2);
@@ -48550,11 +48873,11 @@ async function preparePrivatePublication(client, sourceDirectory, recoveryDirect
48550
48873
  phase: "prepared",
48551
48874
  intent: null
48552
48875
  };
48553
- if (!isAbsolute27(recoveryDirectory) || resolve27(recoveryDirectory) !== recoveryDirectory || realpathSync14(dirname29(recoveryDirectory)) !== dirname29(recoveryDirectory))
48876
+ if (!isAbsolute27(recoveryDirectory) || resolve27(recoveryDirectory) !== recoveryDirectory || realpathSync14(dirname30(recoveryDirectory)) !== dirname30(recoveryDirectory))
48554
48877
  return fail2();
48555
48878
  mkdirSync17(recoveryDirectory, { mode: 448 });
48556
48879
  safeDirectory(recoveryDirectory);
48557
- const parent = openSync23(dirname29(recoveryDirectory), constants20.O_RDONLY | constants20.O_NOFOLLOW);
48880
+ const parent = openSync23(dirname30(recoveryDirectory), constants20.O_RDONLY | constants20.O_NOFOLLOW);
48558
48881
  try {
48559
48882
  fsyncSync6(parent);
48560
48883
  } finally {
@@ -49005,13 +49328,13 @@ function legacyInputSchema(rest) {
49005
49328
  function jsonSchema(schema, io) {
49006
49329
  if (schema === undefined || schema === null)
49007
49330
  return;
49008
- const object7 = isRawShape(schema) ? exports_external.object(schema) : schema;
49009
- const def = object7._zod?.def;
49331
+ const object8 = isRawShape(schema) ? exports_external.object(schema) : schema;
49332
+ const def = object8._zod?.def;
49010
49333
  if (!def)
49011
49334
  throw new Error("Skills MCP tool schemas must be built with this package's zod 4");
49012
49335
  if (def.type !== "object" && def.shape === undefined)
49013
49336
  return;
49014
- return exports_external.toJSONSchema(object7, { target: "draft-7", io });
49337
+ return exports_external.toJSONSchema(object8, { target: "draft-7", io });
49015
49338
  }
49016
49339
  var EMPTY_OBJECT_JSON_SCHEMA;
49017
49340
  var init_package_tool_list = __esm(() => {