@hasna/skills 0.10.18 → 0.10.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/bin/index.js CHANGED
@@ -36868,7 +36868,7 @@ var package_default;
36868
36868
  var init_package = __esm(() => {
36869
36869
  package_default = {
36870
36870
  name: "@hasna/skills",
36871
- version: "0.10.18",
36871
+ version: "0.10.20",
36872
36872
  description: "Skills library for AI coding agents",
36873
36873
  type: "module",
36874
36874
  bin: {
@@ -51052,6 +51052,59 @@ function projectCodexNativeSkillCatalog(response, cwd2) {
51052
51052
  return { name: value.name, path: value.path, enabled: value.enabled, pluginId: value.pluginId ?? null };
51053
51053
  });
51054
51054
  }
51055
+ function projectCodexInstalledPlugins(response) {
51056
+ if (!object4(response) || !Array.isArray(response.marketplaces) || !Array.isArray(response.marketplaceLoadErrors) || response.marketplaceLoadErrors.length !== 0 || response.marketplaces.length > MAX_SKILLS)
51057
+ refuse();
51058
+ const plugins = [];
51059
+ for (const marketplace of response.marketplaces) {
51060
+ if (!object4(marketplace) || !scalar(marketplace.name, MAX_NAME_BYTES) || !Array.isArray(marketplace.plugins) || marketplace.plugins.length > MAX_SKILLS)
51061
+ refuse();
51062
+ for (const value of marketplace.plugins) {
51063
+ if (!object4(value) || !scalar(value.id, MAX_PLUGIN_ID_BYTES) || !scalar(value.name, MAX_NAME_BYTES) || value.id !== `${value.name}@${marketplace.name}`)
51064
+ refuse();
51065
+ plugins.push({ ...value, marketplace: marketplace.name });
51066
+ }
51067
+ }
51068
+ return projectCodexInstalledPluginEntries(plugins);
51069
+ }
51070
+ function projectCodexInstalledPluginEntries(value) {
51071
+ if (!Array.isArray(value) || value.length > MAX_SKILLS)
51072
+ refuse();
51073
+ const ids = new Set;
51074
+ return value.map((item) => {
51075
+ if (!object4(item) || !scalar(item.id, MAX_PLUGIN_ID_BYTES) || !scalar(item.name, MAX_NAME_BYTES) || typeof item.installed !== "boolean" || typeof item.enabled !== "boolean" || item.localVersion !== null && !scalar(item.localVersion, MAX_NAME_BYTES))
51076
+ refuse();
51077
+ const at2 = item.id.lastIndexOf("@");
51078
+ if (at2 < 1 || item.id.slice(0, at2) !== item.name || at2 === item.id.length - 1 || ids.has(item.id))
51079
+ refuse();
51080
+ ids.add(item.id);
51081
+ return { id: item.id, name: item.name, installed: item.installed, enabled: item.enabled, localVersion: item.localVersion ?? null };
51082
+ });
51083
+ }
51084
+ async function captureCodexNativeSkillCatalog(options, connect = connectCodexHookRpc) {
51085
+ if (!absolutePath2(options.cwd) || !absolutePath2(options.home))
51086
+ refuse();
51087
+ const rpc = await connect({
51088
+ command: options.command,
51089
+ home: options.home,
51090
+ ...options.codexHome === undefined ? {} : { codexHome: options.codexHome },
51091
+ ...options.timeoutMs === undefined ? {} : { timeoutMs: options.timeoutMs }
51092
+ });
51093
+ try {
51094
+ if (!SUPPORTED_NAME_CONTROL_VERSIONS.has(rpc.version))
51095
+ throw new Error("CODEX_NATIVE_SKILL_CATALOG_UNSUPPORTED_VERSION");
51096
+ const response = await rpc.request("skills/list", { cwds: [options.cwd], forceReload: true });
51097
+ const installed = await rpc.request("plugin/installed", { cwds: [options.cwd] });
51098
+ return {
51099
+ version: rpc.version,
51100
+ cwd: options.cwd,
51101
+ skills: projectCodexNativeSkillCatalog(response, options.cwd),
51102
+ plugins: projectCodexInstalledPlugins(installed)
51103
+ };
51104
+ } finally {
51105
+ await rpc.close();
51106
+ }
51107
+ }
51055
51108
  function canonicalPath(path) {
51056
51109
  try {
51057
51110
  return realpathSync4(path);
@@ -51089,14 +51142,14 @@ function isCodexNativeSkillDisabled(skill, rules) {
51089
51142
  }
51090
51143
  return disabled;
51091
51144
  }
51092
- var MAX_SKILLS = 4096, MAX_NAME_BYTES = 1024, MAX_PATH_BYTES = 16384, SUPPORTED_NAME_CONTROL_VERSIONS, object4 = (value) => value !== null && typeof value === "object" && !Array.isArray(value), scalar = (value, max2) => typeof value === "string" && value.length > 0 && value.trim() === value && Buffer.byteLength(value, "utf8") <= max2 && !/[\u0000-\u001f\u007f]/u.test(value), absolutePath2 = (value) => scalar(value, MAX_PATH_BYTES) && isAbsolute10(value);
51145
+ var MAX_SKILLS = 4096, MAX_NAME_BYTES = 1024, MAX_PATH_BYTES = 16384, MAX_PLUGIN_ID_BYTES = 1024, SUPPORTED_NAME_CONTROL_VERSIONS, object4 = (value) => value !== null && typeof value === "object" && !Array.isArray(value), scalar = (value, max2) => typeof value === "string" && value.length > 0 && value.trim() === value && Buffer.byteLength(value, "utf8") <= max2 && !/[\u0000-\u001f\u007f]/u.test(value), absolutePath2 = (value) => scalar(value, MAX_PATH_BYTES) && isAbsolute10(value);
51093
51146
  var init_codex_native_skill_catalog = __esm(() => {
51094
51147
  init_codex_hook_rpc();
51095
51148
  SUPPORTED_NAME_CONTROL_VERSIONS = new Set(["codex-cli 0.159.2"]);
51096
51149
  });
51097
51150
 
51098
51151
  // src/lib/codex-plugin-skill-controls.ts
51099
- import { dirname as dirname10, join as join18, resolve as resolve10, sep as sep4 } from "path";
51152
+ import { basename as basename5, dirname as dirname10, join as join18, relative as relative4, resolve as resolve10, sep as sep4 } from "path";
51100
51153
  import { lstatSync as lstatSync12, readdirSync as readdirSync6, readlinkSync as readlinkSync3, realpathSync as realpathSync5 } from "fs";
51101
51154
  function refuse2() {
51102
51155
  throw new Error("CODEX_NATIVE_SKILL_IDENTITY_UNSUPPORTED: review native plugin names and hook controls");
@@ -51136,6 +51189,9 @@ function rootControls(root, read2) {
51136
51189
  }
51137
51190
  if (!manifest || typeof manifest !== "object" || Array.isArray(manifest) || !identifier2(manifest.name))
51138
51191
  refuse2();
51192
+ const cacheVersion = basename5(root), declaredVersion = manifest.version === undefined ? "" : typeof manifest.version === "string" ? manifest.version.trim() : null;
51193
+ if (declaredVersion === null || (declaredVersion ? declaredVersion !== cacheVersion : cacheVersion !== CODEX_DEFAULT_AGENT_PLUGIN_VERSION))
51194
+ refuse2();
51139
51195
  if (manifest.hooks !== undefined || manifest.mcpServers !== undefined || manifest.commands !== undefined || manifest.apps !== undefined && manifest.apps !== "./.app.json" || ["hooks", ".mcp.json"].some((path) => lstatSync12(join18(root, path), { throwIfNoEntry: false })))
51140
51196
  refuse2();
51141
51197
  const app = join18(root, ".app.json"), present = lstatSync12(app, { throwIfNoEntry: false });
@@ -51212,22 +51268,48 @@ function reviewedCodexPluginCapabilitiesUnchanged(cache3, controls, read2) {
51212
51268
  return false;
51213
51269
  }
51214
51270
  }
51215
- function reviewCodexPluginSkillControls(catalog, documents, cache3, cwd2, read2) {
51271
+ function reviewCodexPluginSkillControls(catalog, documents, cache3, cwd2, read2, rules) {
51216
51272
  if (catalog?.version !== "codex-cli 0.159.2" || catalog.cwd !== cwd2)
51217
51273
  refuse2();
51218
51274
  const skills = projectCodexNativeSkillCatalog({ data: [{ cwd: cwd2, errors: [], skills: catalog.skills }] }, cwd2);
51219
51275
  const allowed = new Set(documents), result2 = [];
51220
- for (const skill of skills) {
51221
- if (!allowed.has(skill.path) || !skill.path.startsWith(cache3 + sep4))
51276
+ let installedPlugins;
51277
+ try {
51278
+ installedPlugins = projectCodexInstalledPluginEntries(catalog.plugins ?? []);
51279
+ } catch {
51280
+ refuse2();
51281
+ }
51282
+ const candidates = catalog.plugins === undefined ? skills.map((skill) => skill.path).filter((path) => allowed.has(path)) : allowed;
51283
+ for (const document3 of candidates) {
51284
+ if (!document3.startsWith(cache3 + sep4))
51222
51285
  continue;
51223
- if (skills.filter((other) => other.name === skill.name).length !== 1)
51286
+ const parsed = identity4(document3, cache3, read2);
51287
+ if (parsed.name === "skills-cli" || parsed.name.endsWith(":skills-cli"))
51288
+ refuse2();
51289
+ const cacheParts = relative4(cache3, parsed.pluginParent).split(sep4);
51290
+ if (cacheParts.length !== 2 || cacheParts.some((part) => !identifier2(part)))
51224
51291
  refuse2();
51225
- if (!skill.pluginId || skill.name === "skills-cli" || skill.name.endsWith(":skills-cli"))
51292
+ const [marketplace, pluginName] = cacheParts;
51293
+ if (pluginName !== parsed.namespace)
51226
51294
  refuse2();
51227
- const parsed = identity4(skill.path, cache3, read2);
51228
- if (parsed.name !== skill.name)
51295
+ const expectedPluginId = `${pluginName}@${marketplace}`;
51296
+ const listed = skills.filter((skill) => skill.path === document3);
51297
+ if (listed.length > 1)
51229
51298
  refuse2();
51230
- result2.push({ ...parsed, pluginId: skill.pluginId });
51299
+ if (listed.length === 1) {
51300
+ if (listed[0].name !== parsed.name || listed[0].pluginId !== expectedPluginId)
51301
+ refuse2();
51302
+ } else {
51303
+ const installed = installedPlugins.filter((plugin) => plugin.id === expectedPluginId && plugin.name === pluginName);
51304
+ if (installed.length !== 1 || !installed[0].installed || !installed[0].enabled || !installed[0].localVersion)
51305
+ refuse2();
51306
+ if (installed[0].localVersion !== basename5(dirname10(dirname10(dirname10(document3)))))
51307
+ continue;
51308
+ const exactPathDeny = Array.isArray(rules) && rules.some((rule) => rule?.path === document3 && rule?.enabled === false);
51309
+ if (!exactPathDeny || !isCodexNativeSkillDisabled({ name: parsed.name, path: document3, pluginId: expectedPluginId, enabled: true }, rules))
51310
+ refuse2();
51311
+ }
51312
+ result2.push({ ...parsed, pluginId: expectedPluginId });
51231
51313
  }
51232
51314
  if (!result2.length || new Set(result2.map((item) => item.name)).size !== result2.length)
51233
51315
  refuse2();
@@ -51261,7 +51343,7 @@ enabled = false
51261
51343
  }
51262
51344
  return text2;
51263
51345
  }
51264
- var identifier2 = (v) => typeof v === "string" && /^[A-Za-z0-9_-]{1,64}$/.test(v);
51346
+ var identifier2 = (v) => typeof v === "string" && /^[A-Za-z0-9_-]{1,64}$/.test(v), CODEX_DEFAULT_AGENT_PLUGIN_VERSION = "1.0.0";
51265
51347
  var init_codex_plugin_skill_controls = __esm(() => {
51266
51348
  init_claude_settings_witness();
51267
51349
  init_codex_native_skill_catalog();
@@ -51776,7 +51858,7 @@ var init_agent_codex = __esm(() => {
51776
51858
  // src/lib/agent-integration.ts
51777
51859
  import { createHash as createHash11, randomUUID as randomUUID5 } from "crypto";
51778
51860
  import { existsSync as existsSync12, lstatSync as lstatSync15, statSync as statSync8, mkdirSync as mkdirSync5, readFileSync as readFileSync13, readdirSync as readdirSync8, opendirSync as opendirSync3, readlinkSync as readlinkSync4, realpathSync as realpathSync6, renameSync as renameSync2, rmdirSync as rmdirSync2, writeFileSync as writeFileSync4, unlinkSync as unlinkSync3, chmodSync, openSync as openSync8, closeSync as closeSync8, fsyncSync as fsyncSync2, fstatSync as fstatSync8, readSync as readSync6, constants as constants8, linkSync } from "fs";
51779
- import { dirname as dirname11, join as join21, resolve as resolve11, relative as relative4, isAbsolute as isAbsolute11, sep as sep5 } from "path";
51861
+ import { dirname as dirname11, join as join21, resolve as resolve11, relative as relative5, isAbsolute as isAbsolute11, sep as sep5 } from "path";
51780
51862
  import { homedir as homedir3 } from "os";
51781
51863
  function assertSafePath(path) {
51782
51864
  let cursor = resolve11(path);
@@ -51800,7 +51882,7 @@ function readRootAlias(home, agent) {
51800
51882
  const targetStat = lstatSync15(targetPath, { throwIfNoEntry: false });
51801
51883
  if (!targetStat?.isDirectory())
51802
51884
  throw new Error(`Agent root alias must target an existing directory: ${alias}`);
51803
- const target = realpathSync6(targetPath), inside = relative4(realHome, target);
51885
+ const target = realpathSync6(targetPath), inside = relative5(realHome, target);
51804
51886
  if (!inside || inside === ".." || inside.startsWith(`..${sep5}`) || isAbsolute11(inside))
51805
51887
  throw new Error(`Agent root alias target must be inside the real home: ${alias}`);
51806
51888
  return { agent, home: realHome, alias, target, link: link2, aliasIdentity: `${stat.dev}:${stat.ino}:${stat.ctimeNs}`, targetIdentity: `${targetStat.dev}:${targetStat.ino}` };
@@ -51818,7 +51900,7 @@ function rootAliases(home, allowed = false) {
51818
51900
  }
51819
51901
  function canonicalAgentPath(path, aliases) {
51820
51902
  const absolute = resolve11(path), binding = aliases.find((item) => absolute === item.alias || absolute.startsWith(item.alias + sep5));
51821
- return binding ? join21(binding.target, relative4(binding.alias, absolute)) : absolute;
51903
+ return binding ? join21(binding.target, relative5(binding.alias, absolute)) : absolute;
51822
51904
  }
51823
51905
  function disabledCodexSkillPaths(config, aliases) {
51824
51906
  const skills = config.skills;
@@ -51889,7 +51971,7 @@ function treeHash(root) {
51889
51971
  const stat = lstatSync15(path);
51890
51972
  if (stat.isSymbolicLink())
51891
51973
  throw new Error(`Refusing symlink in skill: ${path}`);
51892
- const rel = relative4(root, path);
51974
+ const rel = relative5(root, path);
51893
51975
  if (stat.isDirectory()) {
51894
51976
  hash2.update(`d\x00${rel}\x00`);
51895
51977
  for (const name of readdirSync8(path).sort())
@@ -51940,7 +52022,7 @@ function parseNativeMigrationTargetManifest(input) {
51940
52022
  assertSafePath(projectRoot);
51941
52023
  if (isAbsolute11(item.path) || item.path.includes("\\") || item.path.length === 0 || item.path.includes("\x00"))
51942
52024
  throw new Error(`Native migration target path must be normalized and project-relative: ${item.path}`);
51943
- const resolved = resolve11(projectRoot, item.path), normalized = relative4(projectRoot, resolved);
52025
+ const resolved = resolve11(projectRoot, item.path), normalized = relative5(projectRoot, resolved);
51944
52026
  if (!normalized || normalized === ".." || normalized.startsWith(`..${sep5}`) || isAbsolute11(normalized) || normalized !== item.path)
51945
52027
  throw new Error(`Native migration target path escapes or is not normalized: ${item.path}`);
51946
52028
  if (!/^[0-9a-f]{64}$/.test(item.treeSha256))
@@ -51962,7 +52044,7 @@ function selectNativeMigrationTargets(inventory, manifest) {
51962
52044
  const identities = new Set;
51963
52045
  const selected = [];
51964
52046
  for (const target of manifest.targets) {
51965
- const projectRoot = resolve11(target.projectRoot), normalized = relative4(projectRoot, resolve11(projectRoot, target.path));
52047
+ const projectRoot = resolve11(target.projectRoot), normalized = relative5(projectRoot, resolve11(projectRoot, target.path));
51966
52048
  if (!isAbsolute11(target.projectRoot) || projectRoot !== target.projectRoot || !existsSync12(projectRoot) || !lstatSync15(projectRoot).isDirectory())
51967
52049
  throw new Error(`Native migration target project root must be an existing absolute directory: ${target.projectRoot}`);
51968
52050
  assertSafePath(projectRoot);
@@ -52317,7 +52399,7 @@ function planAgentIntegration(options) {
52317
52399
  const bytes = readNativeBytes(path, 1024 * 1024);
52318
52400
  observedNativeSources.push({ path, sha256: sha2(bytes) });
52319
52401
  return new TextDecoder("utf-8", { fatal: true }).decode(bytes);
52320
- }) : policy.bridge?.codexPluginSkills ?? [];
52402
+ }, codexConfig.skills?.config ?? []) : policy.bridge?.codexPluginSkills ?? [];
52321
52403
  const changes = [];
52322
52404
  for (const agent of [...new Set(options.agents)]) {
52323
52405
  if (!INTEGRATION_AGENTS.includes(agent))
@@ -52395,7 +52477,7 @@ function planAgentIntegration(options) {
52395
52477
  profiles: Object.fromEntries([...new Set([...priorAgents, ...options.agents])].sort().map((agent) => [agent, bindings.get(agent)?.profileId ?? policy.bridge?.profiles?.[agent] ?? policy.profileId])),
52396
52478
  disabledBuiltins: options.agents.includes("codex") ? nativeSkills.filter((entry) => entry.agent === "codex" && entry.vendor && entry.path.startsWith(canonicalAgentPath(join21(home, ".codex", "skills", ".system"), aliases) + sep5)).map((entry) => ({ path: entry.path, hash: entry.hash })) : policy.bridge?.disabledBuiltins ?? [],
52397
52479
  rootAliases: aliases,
52398
- ...codexPluginSkills.length ? { codexPluginSkills, codexPluginSkillReview: options.codexNativeCatalog ? { version: options.codexNativeCatalog.version, cwd: options.codexNativeCatalog.cwd, catalogSha256: sha2(JSON.stringify({ version: options.codexNativeCatalog.version, cwd: options.codexNativeCatalog.cwd, skills: projectCodexNativeSkillCatalog({ data: [{ cwd: options.codexNativeCatalog.cwd, errors: [], skills: options.codexNativeCatalog.skills }] }, options.codexNativeCatalog.cwd) })), configSha256: changes.find((change) => change.path === canonicalAgentPath(join21(home, ".codex/config.toml"), aliases))?.before === null ? null : sha2(readOptional(canonicalAgentPath(join21(home, ".codex/config.toml"), aliases)) ?? "") } : policy.bridge?.codexPluginSkillReview } : {},
52480
+ ...codexPluginSkills.length ? { codexPluginSkills, codexPluginSkillReview: options.codexNativeCatalog ? { version: options.codexNativeCatalog.version, cwd: options.codexNativeCatalog.cwd, catalogSha256: sha2(JSON.stringify({ version: options.codexNativeCatalog.version, cwd: options.codexNativeCatalog.cwd, skills: projectCodexNativeSkillCatalog({ data: [{ cwd: options.codexNativeCatalog.cwd, errors: [], skills: options.codexNativeCatalog.skills }] }, options.codexNativeCatalog.cwd), ...options.codexNativeCatalog.plugins === undefined ? {} : { plugins: projectCodexInstalledPluginEntries(options.codexNativeCatalog.plugins) } })), configSha256: changes.find((change) => change.path === canonicalAgentPath(join21(home, ".codex/config.toml"), aliases))?.before === null ? null : sha2(readOptional(canonicalAgentPath(join21(home, ".codex/config.toml"), aliases)) ?? "") } : policy.bridge?.codexPluginSkillReview } : {},
52399
52481
  discovery: { ...policy.bridge?.discovery, ...Object.fromEntries(discoveryAfter.map((binding) => [binding.agent, binding])) }
52400
52482
  } };
52401
52483
  const serializedPolicy = serializeManagedSkillPolicy(nextPolicy);
@@ -53033,7 +53115,7 @@ import {
53033
53115
  writeFileSync as writeFileSync6
53034
53116
  } from "fs";
53035
53117
  import { homedir as homedir4 } from "os";
53036
- import { basename as basename5, dirname as dirname12, join as join25 } from "path";
53118
+ import { basename as basename6, dirname as dirname12, join as join25 } from "path";
53037
53119
  function isSkillsOwnershipMarker(marker) {
53038
53120
  return typeof marker === "object" && marker !== null && Object.hasOwn(marker, "managedBy") && marker.managedBy === SYNC_MARKER_MANAGED_BY;
53039
53121
  }
@@ -53267,7 +53349,7 @@ function writeManagedSkillDir(dir, skillMd, options) {
53267
53349
  return { action, path: skillMdPath };
53268
53350
  const parentDir = dirname12(dir);
53269
53351
  mkdirSync7(parentDir, { recursive: true });
53270
- const transactionDir = mkdtempSync(join25(parentDir, `.hasna-skills-write-${basename5(dir)}-`));
53352
+ const transactionDir = mkdtempSync(join25(parentDir, `.hasna-skills-write-${basename6(dir)}-`));
53271
53353
  const candidateDir = join25(transactionDir, "candidate");
53272
53354
  const backupDir = join25(transactionDir, "backup");
53273
53355
  const candidateSkillMdPath = join25(candidateDir, "SKILL.md");
@@ -54780,7 +54862,7 @@ function directoryNames(path) {
54780
54862
  function snapshotPluginTree(root, options = {}) {
54781
54863
  const chain = ancestors(root), entries = [], files = [], directories = [];
54782
54864
  let bytes = 0, visited = 0;
54783
- const visit2 = (directory, relative5) => {
54865
+ const visit2 = (directory, relative6) => {
54784
54866
  const before2 = stat(directory);
54785
54867
  pluginNeed(before2 && before2.isDirectory() && !before2.isSymbolicLink(), "Plugin tree must contain real directories");
54786
54868
  const names = directoryNames(directory);
@@ -54788,18 +54870,18 @@ function snapshotPluginTree(root, options = {}) {
54788
54870
  directories.push({ path: directory, stat: before2, names });
54789
54871
  for (const name of names) {
54790
54872
  pluginNeed(++visited <= PLUGIN_PROJECTION_LIMITS.files * 50, "Plugin tree membership exceeds its limit");
54791
- const path = relative5 ? `${relative5}/${name}` : name;
54873
+ const path = relative6 ? `${relative6}/${name}` : name;
54792
54874
  pluginNeed(new TextEncoder().encode(path).byteLength <= 100 && !/[\\:\x00-\x1f\x7f]/u.test(path), "Plugin entry path exceeds its limit or is unsafe");
54793
54875
  const absolute = join29(directory, name), entryStat = stat(absolute);
54794
54876
  pluginNeed(entryStat, "Plugin tree member disappeared");
54795
- if (relative5 === "" && name === ".orphaned_at" && (options.nativeRuntime === "claude-2.1.274" || options.nativeRuntime === "claude-2.1.276")) {
54877
+ if (relative6 === "" && name === ".orphaned_at" && (options.nativeRuntime === "claude-2.1.274" || options.nativeRuntime === "claude-2.1.276")) {
54796
54878
  const bytes2 = readBytes(absolute, 32, "native-pin");
54797
54879
  pluginNeed(/^[1-9][0-9]{12}$/.test(new TextDecoder().decode(bytes2)), "Malformed native orphan timestamp");
54798
54880
  same3(entryStat, stat(absolute));
54799
54881
  files.push({ path: absolute, stat: entryStat });
54800
54882
  continue;
54801
54883
  }
54802
- if (relative5 === "" && name === ".in_use" && (options.nativeRuntime === "claude-2.1.274" || options.nativeRuntime === "claude-2.1.276")) {
54884
+ if (relative6 === "" && name === ".in_use" && (options.nativeRuntime === "claude-2.1.274" || options.nativeRuntime === "claude-2.1.276")) {
54803
54885
  pluginNeed(entryStat.isDirectory() && !entryStat.isSymbolicLink(), "Native plugin pins require a real directory");
54804
54886
  owner(entryStat);
54805
54887
  const pins = directoryNames(absolute);
@@ -55421,7 +55503,7 @@ var init_plugin_admission = __esm(() => {
55421
55503
 
55422
55504
  // src/lib/plugin-discovery.ts
55423
55505
  import { closeSync as closeSync10, constants as constants10, fstatSync as fstatSync10, lstatSync as lstatSync18, openSync as openSync10, opendirSync as opendirSync5, readSync as readSync8 } from "fs";
55424
- import { basename as basename6, dirname as dirname14, isAbsolute as isAbsolute14, join as join31, resolve as resolve14 } from "path";
55506
+ import { basename as basename7, dirname as dirname14, isAbsolute as isAbsolute14, join as join31, resolve as resolve14 } from "path";
55425
55507
  function validateManagedPluginWitnesses(value) {
55426
55508
  pluginNeed(Array.isArray(value) && value.length > 0 && value.length <= PLUGIN_PROJECTION_LIMITS.registrations, "Invalid managed plugin witness collection");
55427
55509
  const seen = new Set;
@@ -55504,7 +55586,7 @@ function hashManagedPluginRegistry(path, managed) {
55504
55586
  pluginNeed(/^(?:[A-Za-z0-9][A-Za-z0-9._+-]*-)?[a-f0-9]{12}$/.test(row.version) && row.installPath === join31(cacheRoot, row.version), "Managed plugin cache path or version is outside its registration");
55505
55587
  const approval = (producer) => {
55506
55588
  pluginText(producer);
55507
- const digest = `sha256:${basename6(producer)}`;
55589
+ const digest = `sha256:${basename7(producer)}`;
55508
55590
  const receipt2 = readPluginAdmissionReceipt(witness.storeRoot, witness.bindingId, digest);
55509
55591
  pluginNeed(receipt2.materializedPath === producer, "Managed producer path is not an approved immutable projection");
55510
55592
  if (!verified.has(producer)) {
@@ -55570,7 +55652,7 @@ var init_plugin_discovery = __esm(() => {
55570
55652
  // src/lib/claude-marketplace-registry.ts
55571
55653
  import { createHash as createHash14 } from "crypto";
55572
55654
  import { closeSync as closeSync11, constants as constants11, fstatSync as fstatSync11, lstatSync as lstatSync19, openSync as openSync11, readSync as readSync9 } from "fs";
55573
- import { basename as basename7, dirname as dirname15, isAbsolute as isAbsolute15, resolve as resolve15 } from "path";
55655
+ import { basename as basename8, dirname as dirname15, isAbsolute as isAbsolute15, resolve as resolve15 } from "path";
55574
55656
  function need4(value, reason) {
55575
55657
  if (!value)
55576
55658
  throw new Error(`Claude marketplace registry ${reason}`);
@@ -55590,7 +55672,7 @@ function parents2(path) {
55590
55672
  }
55591
55673
  function readRegistry2(path, budget) {
55592
55674
  absolutePath3(path);
55593
- need4(basename7(path) === "known_marketplaces.json", "requires known_marketplaces.json");
55675
+ need4(basename8(path) === "known_marketplaces.json", "requires known_marketplaces.json");
55594
55676
  need4(Number.isSafeInteger(budget.remaining) && budget.remaining >= 0, "has an invalid byte budget");
55595
55677
  const ancestors2 = parents2(path), initial2 = lstatSync19(path, { bigint: true });
55596
55678
  need4(initial2.isFile() && !initial2.isSymbolicLink() && initial2.size <= BigInt(CLAUDE_MARKETPLACE_REGISTRY_LIMITS.bytes), "is not a bounded regular file");
@@ -56088,7 +56170,7 @@ var init_codex_hook_discovery_recovery = __esm(() => {
56088
56170
  // src/lib/agent-discovery.ts
56089
56171
  import { createHash as createHash17 } from "crypto";
56090
56172
  import { lstatSync as lstatSync21, readFileSync as readFileSync18, readdirSync as readdirSync11, realpathSync as realpathSync7 } from "fs";
56091
- import { basename as basename8, dirname as dirname17, isAbsolute as isAbsolute17, join as join32, resolve as resolve16, sep as sep6 } from "path";
56173
+ import { basename as basename9, dirname as dirname17, isAbsolute as isAbsolute17, join as join32, resolve as resolve16, sep as sep6 } from "path";
56092
56174
  import { isDeepStrictEqual as isDeepStrictEqual7 } from "util";
56093
56175
  function parseConfig(text3, path, toml = false) {
56094
56176
  try {
@@ -56198,9 +56280,9 @@ function verifyAgentDiscovery(binding, codexRecovery) {
56198
56280
  safe4(root2);
56199
56281
  }
56200
56282
  function assertMarketplaceBinding(binding, source) {
56201
- if (source.hashMode === "codex-settings-v1" && (binding.agent !== "codex" || binding.method !== "reviewed" || basename8(source.path) !== "config.toml"))
56283
+ if (source.hashMode === "codex-settings-v1" && (binding.agent !== "codex" || binding.method !== "reviewed" || basename9(source.path) !== "config.toml"))
56202
56284
  throw new Error("Codex settings witnesses require explicit reviewed Codex configuration");
56203
- if ((source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || source.hashMode === "claude-settings-v3") && (binding.agent !== "claude" || binding.method !== "reviewed" || basename8(source.path) !== "settings.json"))
56285
+ if ((source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || source.hashMode === "claude-settings-v3") && (binding.agent !== "claude" || binding.method !== "reviewed" || basename9(source.path) !== "settings.json"))
56204
56286
  throw new Error("Claude settings witnesses require explicit reviewed Claude configuration");
56205
56287
  if ((source.hashMode === "claude-marketplace-registry" || source.hashMode === "claude-marketplace-registry-v2") && (binding.agent !== "claude" || binding.method !== "reviewed"))
56206
56288
  throw new Error("Claude marketplace witnesses require explicit reviewed Claude discovery");
@@ -56483,7 +56565,7 @@ var init_agent_discovery = __esm(() => {
56483
56565
  // src/lib/authoring-path.ts
56484
56566
  import { lstatSync as lstatSync22, realpathSync as realpathSync8 } from "fs";
56485
56567
  import { homedir as homedir7 } from "os";
56486
- import { basename as basename9, dirname as dirname18, join as join33, resolve as resolve17, sep as sep7 } from "path";
56568
+ import { basename as basename10, dirname as dirname18, join as join33, resolve as resolve17, sep as sep7 } from "path";
56487
56569
  function pathParts(path) {
56488
56570
  return resolve17(path).split(sep7).filter(Boolean);
56489
56571
  }
@@ -56502,7 +56584,7 @@ function physicalPath(path) {
56502
56584
  let cursor = resolve17(path);
56503
56585
  const suffix = [];
56504
56586
  while (!lstatSync22(cursor, { throwIfNoEntry: false })) {
56505
- suffix.unshift(basename9(cursor));
56587
+ suffix.unshift(basename10(cursor));
56506
56588
  const parent = dirname18(cursor);
56507
56589
  if (parent === cursor)
56508
56590
  return resolve17(path);
@@ -56597,7 +56679,7 @@ import {
56597
56679
  statSync as statSync11,
56598
56680
  writeFileSync as writeFileSync9
56599
56681
  } from "fs";
56600
- import { basename as basename10, dirname as dirname19, isAbsolute as isAbsolute18, join as join34, normalize as normalize3, relative as relative5, resolve as resolve18, sep as sep8 } from "path";
56682
+ import { basename as basename11, dirname as dirname19, isAbsolute as isAbsolute18, join as join34, normalize as normalize3, relative as relative6, resolve as resolve18, sep as sep8 } from "path";
56601
56683
  function getPortableSkillsRoot(options = {}) {
56602
56684
  return resolvePortableSkillsRoot(options, true);
56603
56685
  }
@@ -56745,7 +56827,7 @@ function physicalImportPath(path) {
56745
56827
  let ancestor = resolve18(path);
56746
56828
  const suffix = [];
56747
56829
  while (!existsSync18(ancestor)) {
56748
- suffix.unshift(basename10(ancestor));
56830
+ suffix.unshift(basename11(ancestor));
56749
56831
  ancestor = dirname19(ancestor);
56750
56832
  }
56751
56833
  return join34(realpathSync9(ancestor), ...suffix);
@@ -56754,7 +56836,7 @@ function assertDisjointImportPaths(source, destination) {
56754
56836
  const sourcePath = realpathSync9(source);
56755
56837
  const destinationPath = physicalImportPath(destination);
56756
56838
  const contains2 = (parent, child) => {
56757
- const path = relative5(parent, child);
56839
+ const path = relative6(parent, child);
56758
56840
  return path === "" || !isAbsolute18(path) && path !== ".." && !path.startsWith(`..${sep8}`);
56759
56841
  };
56760
56842
  if (contains2(sourcePath, destinationPath) || contains2(destinationPath, sourcePath)) {
@@ -56770,8 +56852,8 @@ function portPortableSkill(sourcePath, options = {}) {
56770
56852
  const explicitName = options.name != null;
56771
56853
  const skillName = normalizeNewPortableSkillName(options.name ?? inferred.name);
56772
56854
  if (isOfficialSkillName(skillName) && !options.allowShadow) {
56773
- const sourceSlug = safeNormalizeName(basename10(absoluteSource));
56774
- const via = explicitName ? `Name '${skillName}' matches a bundled official skill.` : `Inferred name '${skillName}'${sourceSlug && sourceSlug !== skillName ? ` (from source folder '${basename10(absoluteSource)}')` : ""} matches a bundled official skill.`;
56855
+ const sourceSlug = safeNormalizeName(basename11(absoluteSource));
56856
+ const via = explicitName ? `Name '${skillName}' matches a bundled official skill.` : `Inferred name '${skillName}'${sourceSlug && sourceSlug !== skillName ? ` (from source folder '${basename11(absoluteSource)}')` : ""} matches a bundled official skill.`;
56775
56857
  throw new Error(`${via} Importing it would shadow the official '${skillName}'. ` + `Pass --name to choose a different name, or --allow-shadow to override deliberately.`);
56776
56858
  }
56777
56859
  const readOnlyDestination = join34(resolvePortableSkillsRoot(options, false), skillName);
@@ -58980,13 +59062,13 @@ var require_cli_spinners = __commonJS((exports, module) => {
58980
59062
 
58981
59063
  // src/lib/auth-store.ts
58982
59064
  import { chmodSync as chmodSync2, existsSync as existsSync20, mkdirSync as mkdirSync11, readFileSync as readFileSync20, renameSync as renameSync7, statSync as statSync12, unlinkSync as unlinkSync5, writeFileSync as writeFileSync10 } from "fs";
58983
- import { basename as basename11, dirname as dirname20, join as join36 } from "path";
59065
+ import { basename as basename12, dirname as dirname20, join as join36 } from "path";
58984
59066
  function getAuthFilePath(env3 = process.env) {
58985
59067
  return skillsCredentialFilePath(env3);
58986
59068
  }
58987
59069
  function getIdentityFilePath(env3 = process.env) {
58988
59070
  const file = skillsCredentialFilePath(env3);
58989
- return join36(dirname20(file), basename11(file).replace(/^credentials/, "identity") + ".json");
59071
+ return join36(dirname20(file), basename12(file).replace(/^credentials/, "identity") + ".json");
58990
59072
  }
58991
59073
  function getAuthIdentity(env3 = process.env) {
58992
59074
  return readIdentity(env3);
@@ -81010,7 +81092,7 @@ var init_remote_auth = __esm(() => {
81010
81092
  // src/lib/sign-in.ts
81011
81093
  import { createHash as createHash20 } from "crypto";
81012
81094
  import { chmodSync as chmodSync3, mkdirSync as mkdirSync12, readFileSync as readFileSync21, readdirSync as readdirSync14, renameSync as renameSync8, unlinkSync as unlinkSync6, writeFileSync as writeFileSync11 } from "fs";
81013
- import { basename as basename12, dirname as dirname21, join as join37 } from "path";
81095
+ import { basename as basename13, dirname as dirname21, join as join37 } from "path";
81014
81096
  function isRecord6(value) {
81015
81097
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
81016
81098
  }
@@ -81155,7 +81237,7 @@ async function pollDeviceAuthorization(input2) {
81155
81237
  }
81156
81238
  function pendingDeviceSignInStem(env3) {
81157
81239
  const file2 = skillsCredentialFilePath(env3);
81158
- return { dir: dirname21(file2), stem: basename12(file2).replace(/^credentials/, "device-login") };
81240
+ return { dir: dirname21(file2), stem: basename13(file2).replace(/^credentials/, "device-login") };
81159
81241
  }
81160
81242
  function pendingDeviceSignInPath(origin, env3 = process.env) {
81161
81243
  const { dir, stem } = pendingDeviceSignInStem(env3);
@@ -82340,9 +82422,9 @@ async function buildSkillContext(input2, options = {}) {
82340
82422
  if (prompt.length > 128 * 1024 || (input2.paths?.length ?? 0) > 100 || (input2.skills?.length ?? 0) > 100) {
82341
82423
  throw new SkillSelectionError("CONTEXT_INPUT_TOO_LARGE", "The Skills context input exceeds its size limit.");
82342
82424
  }
82343
- const maxChars = options.maxChars ?? 8000;
82425
+ const maxChars = options.maxChars;
82344
82426
  const maxSkills = options.maxSkills ?? 3;
82345
- if (!Number.isInteger(maxChars) || maxChars < 512 || maxChars > 64000 || !Number.isInteger(maxSkills) || maxSkills < 1 || maxSkills > 20) {
82427
+ if (maxChars !== undefined && (!Number.isInteger(maxChars) || maxChars < 512 || maxChars > 64000) || !Number.isInteger(maxSkills) || maxSkills < 1 || maxSkills > 20) {
82346
82428
  throw new SkillSelectionError("INVALID_CONTEXT_BUDGET", "Context limits must be 512\u201364000 characters and 1\u201320 skills.");
82347
82429
  }
82348
82430
  const profileId = input2.profileId ?? "default";
@@ -82399,7 +82481,7 @@ async function buildSkillContext(input2, options = {}) {
82399
82481
  const { content } = readSelectedDocument(entries);
82400
82482
  const section = `Skill ${selection.slug}@${selection.version} (${selection.bundleDigest}; ${reason})
82401
82483
  ${content}`;
82402
- if (chars + section.length + (sections.length ? 2 : 0) > maxChars) {
82484
+ if (maxChars !== undefined && chars + section.length + (sections.length ? 2 : 0) > maxChars) {
82403
82485
  omitted.push({ slug: selection.slug, version: selection.version, reason: "context-budget", loadCommand });
82404
82486
  continue;
82405
82487
  }
@@ -82655,7 +82737,7 @@ Preserved original receipt: ${result2.archivePath}` : `Planned one session recon
82655
82737
  reportContextError(error61, options.json);
82656
82738
  }
82657
82739
  });
82658
- parent.command("context [prompt]").description("Select bounded, versioned skill context for this prompt without running skills").option("--stdin", "Read native hook JSON or a prompt from stdin", false).option("--selection-profile <id>", "Selection profile (separate from the credential --profile)").option("--cached", "Use only an explicitly selected verified cache, at most 24 hours old", false).option("--auto-reconcile-safe", "For managed hooks, archive and renew an expired session only when all loaded selections are unchanged", false).option("--session <id>", "Keep the same skill versions across this session").option("--restore", "Re-emit loaded session context after compaction or resume", false).option("--max-chars <count>", "Maximum injected characters", "8000").option("--max-skills <count>", "Maximum loaded skills", "3").option("--json", "Return context and selection receipts as JSON", false).action(async (prompt, options) => {
82740
+ parent.command("context [prompt]").description("Select bounded, versioned skill context for this prompt without running skills").option("--stdin", "Read native hook JSON or a prompt from stdin", false).option("--selection-profile <id>", "Selection profile (separate from the credential --profile)").option("--cached", "Use only an explicitly selected verified cache, at most 24 hours old", false).option("--auto-reconcile-safe", "For managed hooks, archive and renew an expired session only when all loaded selections are unchanged", false).option("--session <id>", "Keep the same skill versions across this session").option("--restore", "Re-emit loaded session context after compaction or resume", false).option("--max-chars <count>", "Optional maximum injected characters").option("--max-skills <count>", "Maximum loaded skills", "3").option("--json", "Return context and selection receipts as JSON", false).action(async (prompt, options) => {
82659
82741
  try {
82660
82742
  if (options.autoReconcileSafe && !options.cached)
82661
82743
  throw new SkillSelectionError("INVALID_CONTEXT_INPUT", "--auto-reconcile-safe requires --cached.");
@@ -82664,7 +82746,7 @@ Preserved original receipt: ${result2.archivePath}` : `Planned one session recon
82664
82746
  input2.cwd ??= process.cwd();
82665
82747
  input2.sessionId = options.session ?? input2.sessionId;
82666
82748
  input2.restore ||= options.restore;
82667
- const resolverOptions = { ...contextResolverOptions(options), maxChars: Number(options.maxChars), maxSkills: Number(options.maxSkills) };
82749
+ const resolverOptions = { ...contextResolverOptions(options), ...options.maxChars === undefined ? {} : { maxChars: Number(options.maxChars) }, maxSkills: Number(options.maxSkills) };
82668
82750
  let result2;
82669
82751
  try {
82670
82752
  result2 = await buildSkillContext(input2, resolverOptions);
@@ -91520,7 +91602,7 @@ var init_runs = __esm(() => {
91520
91602
  // src/lib/run-state.ts
91521
91603
  import { createHash as createHash25, randomBytes } from "crypto";
91522
91604
  import { existsSync as existsSync27, mkdirSync as mkdirSync16, readFileSync as readFileSync32, readdirSync as readdirSync18, statSync as statSync16, writeFileSync as writeFileSync16 } from "fs";
91523
- import { extname, join as join46, relative as relative6 } from "path";
91605
+ import { extname, join as join46, relative as relative7 } from "path";
91524
91606
  function createSkillRun(params, targetDir = process.cwd()) {
91525
91607
  const now3 = new Date;
91526
91608
  const id2 = createRunId(now3);
@@ -91686,7 +91768,7 @@ function createRunId(now3) {
91686
91768
  return `run_${now3.getTime().toString(36)}_${randomBytes(4).toString("hex")}`;
91687
91769
  }
91688
91770
  function toProjectRelative(targetDir, path) {
91689
- const rel = relative6(targetDir, path).split(/[\\/]/).join("/");
91771
+ const rel = relative7(targetDir, path).split(/[\\/]/).join("/");
91690
91772
  return rel.startsWith(".") ? rel : `./${rel}`;
91691
91773
  }
91692
91774
  function mimeForPath(path) {
@@ -98982,49 +99064,49 @@ var require_fast_uri = __commonJS((exports, module) => {
98982
99064
  schemelessOptions.skipEscape = true;
98983
99065
  return serialize(resolved, schemelessOptions);
98984
99066
  }
98985
- function resolveComponent(base2, relative7, options, skipNormalization) {
99067
+ function resolveComponent(base2, relative8, options, skipNormalization) {
98986
99068
  const target = {};
98987
99069
  if (!skipNormalization) {
98988
99070
  base2 = parse12(serialize(base2, options), options);
98989
- relative7 = parse12(serialize(relative7, options), options);
99071
+ relative8 = parse12(serialize(relative8, options), options);
98990
99072
  }
98991
99073
  options = options || {};
98992
- if (!options.tolerant && relative7.scheme) {
98993
- target.scheme = relative7.scheme;
98994
- target.userinfo = relative7.userinfo;
98995
- target.host = relative7.host;
98996
- target.port = relative7.port;
98997
- target.path = removeDotSegments(relative7.path || "");
98998
- target.query = relative7.query;
99074
+ if (!options.tolerant && relative8.scheme) {
99075
+ target.scheme = relative8.scheme;
99076
+ target.userinfo = relative8.userinfo;
99077
+ target.host = relative8.host;
99078
+ target.port = relative8.port;
99079
+ target.path = removeDotSegments(relative8.path || "");
99080
+ target.query = relative8.query;
98999
99081
  } else {
99000
- if (relative7.userinfo !== undefined || relative7.host !== undefined || relative7.port !== undefined) {
99001
- target.userinfo = relative7.userinfo;
99002
- target.host = relative7.host;
99003
- target.port = relative7.port;
99004
- target.path = removeDotSegments(relative7.path || "");
99005
- target.query = relative7.query;
99082
+ if (relative8.userinfo !== undefined || relative8.host !== undefined || relative8.port !== undefined) {
99083
+ target.userinfo = relative8.userinfo;
99084
+ target.host = relative8.host;
99085
+ target.port = relative8.port;
99086
+ target.path = removeDotSegments(relative8.path || "");
99087
+ target.query = relative8.query;
99006
99088
  } else {
99007
- if (!relative7.path) {
99089
+ if (!relative8.path) {
99008
99090
  target.path = base2.path;
99009
- if (relative7.query !== undefined) {
99010
- target.query = relative7.query;
99091
+ if (relative8.query !== undefined) {
99092
+ target.query = relative8.query;
99011
99093
  } else {
99012
99094
  target.query = base2.query;
99013
99095
  }
99014
99096
  } else {
99015
- if (relative7.path[0] === "/") {
99016
- target.path = removeDotSegments(relative7.path);
99097
+ if (relative8.path[0] === "/") {
99098
+ target.path = removeDotSegments(relative8.path);
99017
99099
  } else {
99018
99100
  if ((base2.userinfo !== undefined || base2.host !== undefined || base2.port !== undefined) && !base2.path) {
99019
- target.path = "/" + relative7.path;
99101
+ target.path = "/" + relative8.path;
99020
99102
  } else if (!base2.path) {
99021
- target.path = relative7.path;
99103
+ target.path = relative8.path;
99022
99104
  } else {
99023
- target.path = base2.path.slice(0, base2.path.lastIndexOf("/") + 1) + relative7.path;
99105
+ target.path = base2.path.slice(0, base2.path.lastIndexOf("/") + 1) + relative8.path;
99024
99106
  }
99025
99107
  target.path = removeDotSegments(target.path);
99026
99108
  }
99027
- target.query = relative7.query;
99109
+ target.query = relative8.query;
99028
99110
  }
99029
99111
  target.userinfo = base2.userinfo;
99030
99112
  target.host = base2.host;
@@ -99032,7 +99114,7 @@ var require_fast_uri = __commonJS((exports, module) => {
99032
99114
  }
99033
99115
  target.scheme = base2.scheme;
99034
99116
  }
99035
- target.fragment = relative7.fragment;
99117
+ target.fragment = relative8.fragment;
99036
99118
  return target;
99037
99119
  }
99038
99120
  function equal(uriA, uriB, options) {
@@ -106912,7 +106994,7 @@ import {
106912
106994
  statSync as statSync18,
106913
106995
  writeFileSync as writeFileSync20
106914
106996
  } from "fs";
106915
- import { dirname as dirname27, join as join52, normalize as normalize4, relative as relative7, sep as sep9 } from "path";
106997
+ import { dirname as dirname27, join as join52, normalize as normalize4, relative as relative8, sep as sep9 } from "path";
106916
106998
  function resolveSkillsNativeStorageConfig(env3 = process.env) {
106917
106999
  assertNoRetiredModeEnvVars(env3, {
106918
107000
  app: SKILLS_ENV_NAMESPACE,
@@ -106976,7 +107058,7 @@ function exportSkillsLocalSnapshot(targetDir = process.cwd(), options = {}) {
106976
107058
  if (existsSync31(projectStateDir)) {
106977
107059
  for (const filePath of walkFiles2(projectStateDir)) {
106978
107060
  const bytes = readFileSync35(filePath);
106979
- const relativePath = toPosix(relative7(targetDir, filePath));
107061
+ const relativePath = toPosix(relative8(targetDir, filePath));
106980
107062
  files.push({
106981
107063
  path: relativePath,
106982
107064
  sizeBytes: bytes.byteLength,
@@ -108179,7 +108261,7 @@ import {
108179
108261
  symlinkSync,
108180
108262
  writeFileSync as writeFileSync23
108181
108263
  } from "fs";
108182
- import { basename as basename13, delimiter, dirname as dirname30, isAbsolute as isAbsolute24, join as join55, relative as relative8, resolve as resolve23, sep as sep10 } from "path";
108264
+ import { basename as basename14, delimiter, dirname as dirname30, isAbsolute as isAbsolute24, join as join55, relative as relative9, resolve as resolve23, sep as sep10 } from "path";
108183
108265
  function object9(value, code2) {
108184
108266
  if (!value || typeof value !== "object" || Array.isArray(value))
108185
108267
  throw new Error(code2);
@@ -108189,7 +108271,7 @@ function hash5(bytes) {
108189
108271
  return createHash27("sha256").update(bytes).digest("hex");
108190
108272
  }
108191
108273
  function isWithin(parent, child) {
108192
- const rel = relative8(parent, child);
108274
+ const rel = relative9(parent, child);
108193
108275
  return rel === "" || !rel.startsWith(`..${sep10}`) && rel !== ".." && !isAbsolute24(rel);
108194
108276
  }
108195
108277
  function entryExists(path) {
@@ -108284,7 +108366,7 @@ function resolveRuntimeLayout(homeInput, pathInput) {
108284
108366
  assertNoSymlinkAncestors(currentPackageRoot);
108285
108367
  if (!isWithin(runtimeRoot, currentPackageRoot))
108286
108368
  throw new Error("ACTIVE_RUNTIME_OUTSIDE_COPYFILE_ROOT");
108287
- const relativePackage = relative8(runtimeRoot, currentPackageRoot).split(sep10);
108369
+ const relativePackage = relative9(runtimeRoot, currentPackageRoot).split(sep10);
108288
108370
  if (relativePackage.length !== 4 || relativePackage[1] !== "node_modules" || relativePackage[2] !== "@hasna" || relativePackage[3] !== "skills") {
108289
108371
  throw new Error("ACTIVE_RUNTIME_LAYOUT_UNSUPPORTED");
108290
108372
  }
@@ -108838,7 +108920,7 @@ function inspectAliasPackageChain(home, aliasPath, oldLinkTarget, oldTarget, bin
108838
108920
  function validateAliasSource(home, name, actual) {
108839
108921
  const packageRoot = dirname30(dirname30(actual));
108840
108922
  const roots = [join55(home, ".hasna", "skills", "runtime"), join55(home, ".bun", "install"), join55(home, ".local", "lib", "node_modules")];
108841
- if (basename13(packageRoot) !== "skills" || basename13(dirname30(packageRoot)) !== "@hasna" || !roots.some((root2) => isWithin(root2, packageRoot))) {
108923
+ if (basename14(packageRoot) !== "skills" || basename14(dirname30(packageRoot)) !== "@hasna" || !roots.some((root2) => isWithin(root2, packageRoot))) {
108842
108924
  throw new Error("ALIAS_SOURCE_ROOT_UNSUPPORTED");
108843
108925
  }
108844
108926
  assertOwnedSafePath(packageRoot, home);
@@ -108916,8 +108998,8 @@ function adoptCopyfileAliases(options = {}) {
108916
108998
  for (const item of aliases) {
108917
108999
  if (readlinkSync5(item.path) !== item.oldLinkTarget || realpathSync14(item.path) !== item.oldTarget)
108918
109000
  throw new Error("ALIAS_CHANGED_BEFORE_SWITCH");
108919
- inspectAliasPackageChain(home, item.path, item.oldLinkTarget, item.oldTarget, layout.bin[basename13(item.path)], item.chain, true);
108920
- const source = validateAliasSource(home, basename13(item.path), item.oldTarget);
109001
+ inspectAliasPackageChain(home, item.path, item.oldLinkTarget, item.oldTarget, layout.bin[basename14(item.path)], item.chain, true);
109002
+ const source = validateAliasSource(home, basename14(item.path), item.oldTarget);
108921
109003
  if (source.version !== item.oldVersion || source.binarySha256 !== item.oldBinarySha256)
108922
109004
  throw new Error("ALIAS_SOURCE_DRIFT");
108923
109005
  receipt.state = "switching";
@@ -108926,11 +109008,11 @@ function adoptCopyfileAliases(options = {}) {
108926
109008
  replaceLink(item.path, item.newTarget, item.backupPath, item.oldLinkTarget, item.oldTarget);
108927
109009
  if (realpathSync14(item.path) !== item.newTarget || realpathSync14(item.backupPath) !== item.oldTarget)
108928
109010
  throw new Error("ALIAS_SWITCH_READBACK_MISMATCH");
108929
- inspectAliasPackageChain(home, item.path, item.oldLinkTarget, item.oldTarget, layout.bin[basename13(item.path)], item.chain, true);
109011
+ inspectAliasPackageChain(home, item.path, item.oldLinkTarget, item.oldTarget, layout.bin[basename14(item.path)], item.chain, true);
108930
109012
  options.onAliasSwitched?.(item.path);
108931
109013
  }
108932
109014
  for (const item of aliases) {
108933
- inspectAliasPackageChain(home, item.path, item.oldLinkTarget, item.oldTarget, layout.bin[basename13(item.path)], item.chain, true);
109015
+ inspectAliasPackageChain(home, item.path, item.oldLinkTarget, item.oldTarget, layout.bin[basename14(item.path)], item.chain, true);
108934
109016
  if (readlinkSync5(item.backupPath) !== item.oldLinkTarget || realpathSync14(item.backupPath) !== item.oldTarget)
108935
109017
  throw new Error("ALIAS_BACKUP_DRIFT");
108936
109018
  }
@@ -108943,16 +109025,16 @@ function adoptCopyfileAliases(options = {}) {
108943
109025
  for (const item of [...aliases].reverse()) {
108944
109026
  try {
108945
109027
  if (!entryExists(item.backupPath)) {
108946
- inspectAliasPackageChain(home, item.path, item.oldLinkTarget, item.oldTarget, layout.bin[basename13(item.path)], item.chain, true);
108947
- const source2 = validateAliasSource(home, basename13(item.path), item.oldTarget);
109028
+ inspectAliasPackageChain(home, item.path, item.oldLinkTarget, item.oldTarget, layout.bin[basename14(item.path)], item.chain, true);
109029
+ const source2 = validateAliasSource(home, basename14(item.path), item.oldTarget);
108948
109030
  if (!entryExists(item.path) || readlinkSync5(item.path) !== item.oldLinkTarget || realpathSync14(item.path) !== item.oldTarget || source2.version !== item.oldVersion || source2.binarySha256 !== item.oldBinarySha256)
108949
109031
  failed = true;
108950
109032
  continue;
108951
109033
  }
108952
109034
  if (readlinkSync5(item.backupPath) !== item.oldLinkTarget || realpathSync14(item.backupPath) !== item.oldTarget)
108953
109035
  throw new Error("ALIAS_BACKUP_DRIFT");
108954
- inspectAliasPackageChain(home, item.path, item.oldLinkTarget, item.oldTarget, layout.bin[basename13(item.path)], item.chain, true);
108955
- const source = validateAliasSource(home, basename13(item.path), item.oldTarget);
109036
+ inspectAliasPackageChain(home, item.path, item.oldLinkTarget, item.oldTarget, layout.bin[basename14(item.path)], item.chain, true);
109037
+ const source = validateAliasSource(home, basename14(item.path), item.oldTarget);
108956
109038
  if (source.version !== item.oldVersion || source.binarySha256 !== item.oldBinarySha256)
108957
109039
  throw new Error("ALIAS_SOURCE_DRIFT");
108958
109040
  if (realpathSync14(item.path) === item.oldTarget && readlinkSync5(item.path) === item.oldLinkTarget)
@@ -109005,7 +109087,7 @@ function rollbackCopyfileAliases(receiptId, options = {}) {
109005
109087
  throw new Error("ALIAS_RECEIPT_BINDING_INVALID");
109006
109088
  const seen = new Set;
109007
109089
  for (const item of receipt.aliases) {
109008
- const name = basename13(item.path), target = layout.bin[name];
109090
+ const name = basename14(item.path), target = layout.bin[name];
109009
109091
  if (!target || seen.has(item.path) || !aliasDirs(home).includes(dirname30(item.path)) || item.newTarget !== join55(layout.currentPackageRoot, target) || item.backupPath !== `${item.path}.skills-alias-prev-${receiptId}` || item.chain !== undefined && (!item.chain || typeof item.chain !== "object" || typeof item.chain.packageLinkPath !== "string" || typeof item.chain.packageLinkTarget !== "string")) {
109010
109092
  throw new Error("ALIAS_RECEIPT_LAUNCHER_INVALID");
109011
109093
  }
@@ -109054,7 +109136,7 @@ function rollbackCopyfileAliases(receiptId, options = {}) {
109054
109136
  restored++;
109055
109137
  }
109056
109138
  for (const item of receipt.aliases) {
109057
- inspectAliasPackageChain(home, item.path, item.oldLinkTarget, item.oldTarget, layout.bin[basename13(item.path)], item.chain, true);
109139
+ inspectAliasPackageChain(home, item.path, item.oldLinkTarget, item.oldTarget, layout.bin[basename14(item.path)], item.chain, true);
109058
109140
  }
109059
109141
  receipt.state = "rolled-back";
109060
109142
  persistAliasReceipt(receiptPath, receipt);
@@ -109087,7 +109169,7 @@ async function updateCopyfileRuntime(version2, options = {}) {
109087
109169
  const releaseLock = acquireRuntimeLock(layout.runtimeRoot);
109088
109170
  const stagePath = join55(layout.runtimeRoot, `.stage-${version2}-${id2}`);
109089
109171
  const finalPath = join55(layout.runtimeRoot, `${version2}-copyfile`);
109090
- const launchers = layout.launchers.map((item) => ({ ...item, newTarget: join55(finalPath, "node_modules", "@hasna", "skills", layout.bin[basename13(item.path)]) }));
109172
+ const launchers = layout.launchers.map((item) => ({ ...item, newTarget: join55(finalPath, "node_modules", "@hasna", "skills", layout.bin[basename14(item.path)]) }));
109091
109173
  let switched = [];
109092
109174
  let moved = false;
109093
109175
  try {
@@ -109270,7 +109352,7 @@ function rollbackCopyfileRuntime(receiptId, options = {}) {
109270
109352
  const switched = [];
109271
109353
  const seen = new Set;
109272
109354
  for (const item of receipt.launchers) {
109273
- const bin = oldBins[basename13(item.path)];
109355
+ const bin = oldBins[basename14(item.path)];
109274
109356
  if (!bin || !isAbsolute24(item.path) || seen.has(item.path) || item.oldTarget !== join55(receipt.currentPackageRoot, bin) || item.newTarget !== join55(receipt.targetPackageRoot, bin) || !/^.+\.skills-prev-[0-9a-f-]{36}$/.test(item.backupPath) || !item.backupPath.startsWith(`${item.path}.skills-prev-`) || typeof item.oldLinkTarget !== "string" || resolve23(dirname30(item.path), item.oldLinkTarget) !== item.oldTarget)
109275
109357
  throw new Error("RECEIPT_LAUNCHER_BINDING_INVALID");
109276
109358
  assertNoSymlinkAncestors(dirname30(item.path));
@@ -109340,7 +109422,7 @@ __export(exports_runtime, {
109340
109422
  });
109341
109423
  import { createHash as createHash28, randomUUID as randomUUID10 } from "crypto";
109342
109424
  import { lstatSync as lstatSync29, mkdirSync as mkdirSync25, readFileSync as readFileSync38, realpathSync as realpathSync15, writeFileSync as writeFileSync24 } from "fs";
109343
- import { basename as basename14, isAbsolute as isAbsolute25, join as join56 } from "path";
109425
+ import { basename as basename15, isAbsolute as isAbsolute25, join as join56 } from "path";
109344
109426
  import { createInterface } from "readline";
109345
109427
  function registerRuntime(parent) {
109346
109428
  parent.command("run").argument("<skill>", "Skill name").argument("[args...]", "Arguments to pass to the skill; use -- to end Skills options").allowUnknownOption(true).passThroughOptions(true).option("--json", "Output result as JSON", false).option("--remote", "Run on the configured server, using its catalog and quote", false).option("--target <target>", "Execution target: local or cloud").option("--secret-bindings <path>", "Reviewed, exact-selection local execution vault bindings (JSON file)").option("--secret-bindings-template", "Print a scoped bindings template without resolving secrets or running the skill", false).option("--input <json>", "Structured cloud execution input").option("--skill-version <version>", "Exact selected skill version").option("--selection-profile <id>", "Selected Skills profile").option("--session <id>", "Pinned Skills session").option("--cached", "Use the explicit verified selected cache", false).option("--yes", "Approve the server's quoted credit cost for this run", false).option("--idempotency-key <key>", "Reuse this key when retrying the same remote submission").option("--file <path>", "Attach a local input file to a remote run (repeatable)", (value, prior) => [...prior, value], []).option("--wait", "Poll remote runs until a terminal status", false).option("--poll-interval-ms <ms>", "Remote polling interval in milliseconds", "1000").option("--poll-timeout-ms <ms>", "Maximum time to wait for a remote run", "300000").description("Run a skill directly").action(async (name, args2, options, command) => {
@@ -109853,7 +109935,7 @@ async function handleRun(name, args2, options, separatorBeforeSkill) {
109853
109935
  const info = lstatSync29(path);
109854
109936
  if (!info.isFile() || info.size > 20 * 1024 * 1024)
109855
109937
  throw new Error("Input must be a regular file no larger than 20 MiB");
109856
- return { name: basename14(path), bytes: new Uint8Array(readFileSync38(path)) };
109938
+ return { name: basename15(path), bytes: new Uint8Array(readFileSync38(path)) };
109857
109939
  });
109858
109940
  describeRemoteFiles(inputFiles);
109859
109941
  client2 = new RemoteSkillsClient(routing.apiKey, routing.apiOrigin);
@@ -111030,7 +111112,7 @@ import {
111030
111112
  statSync as statSync20,
111031
111113
  writeFileSync as writeFileSync25
111032
111114
  } from "fs";
111033
- import { dirname as dirname32, isAbsolute as isAbsolute26, relative as relative9, resolve as resolve24, sep as sep12 } from "path";
111115
+ import { dirname as dirname32, isAbsolute as isAbsolute26, relative as relative10, resolve as resolve24, sep as sep12 } from "path";
111034
111116
  function validateStationId(stationId) {
111035
111117
  if (!/^[a-z0-9-]+$/.test(stationId)) {
111036
111118
  throw new StationSnapshotError("INVALID_STATION", `station id must be a slug, got: ${stationId}`);
@@ -111135,7 +111217,7 @@ function writeStationSnapshot(options) {
111135
111217
  const untouched = [];
111136
111218
  for (const plan of plans) {
111137
111219
  const destination = resolve24(repoRoot, plan.destination);
111138
- const destinationRelative = relative9(repoRoot, destination);
111220
+ const destinationRelative = relative10(repoRoot, destination);
111139
111221
  if (destinationRelative.startsWith("..") || destinationRelative.startsWith(sep12) || isAbsolute26(destinationRelative)) {
111140
111222
  throw new StationSnapshotError("DESTINATION_ESCAPE", `destination escapes repo root: ${plan.destination}`);
111141
111223
  }
@@ -112194,7 +112276,9 @@ var exports_agent_integration = {};
112194
112276
  __export(exports_agent_integration, {
112195
112277
  registerAgentIntegration: () => registerAgentIntegration
112196
112278
  });
112197
- import { readFileSync as readFileSync41 } from "fs";
112279
+ import { existsSync as existsSync35, lstatSync as lstatSync32, readFileSync as readFileSync41, writeFileSync as writeFileSync26 } from "fs";
112280
+ import { createHash as createHash31 } from "crypto";
112281
+ import { homedir as homedir13 } from "os";
112198
112282
  import { isAbsolute as isAbsolute29 } from "path";
112199
112283
  function pinnedHookProfile(input3, configuredProfile) {
112200
112284
  try {
@@ -112261,6 +112345,45 @@ function agents(value) {
112261
112345
  }
112262
112346
  function registerAgentIntegration(parent) {
112263
112347
  const hook = parent.command("hook").description("Load selected Skills context through agent lifecycle hooks");
112348
+ hook.command("native-catalog").requiredOption("--cwd <path>", "Absolute project directory observed by native Codex skills/list").requiredOption("--output <file>", "New private file for the projected native catalog").option("--codex-command <path>", "Installed Codex executable used by the native client", "codex").option("--json", "Output bounded capture metadata as JSON", false).description("Capture a reviewed Codex native skill catalog for exact hook enrollment").action(async (options) => {
112349
+ try {
112350
+ if (!isAbsolute29(options.cwd) || !isAbsolute29(options.output))
112351
+ throw new Error("CODEX_NATIVE_SKILL_CATALOG_ABSOLUTE_PATH_REQUIRED");
112352
+ if (existsSync35(options.output))
112353
+ throw new Error("CODEX_NATIVE_SKILL_CATALOG_OUTPUT_EXISTS");
112354
+ const catalog = await captureCodexNativeSkillCatalog({
112355
+ command: options.codexCommand,
112356
+ home: homedir13(),
112357
+ ...process.env.CODEX_HOME === undefined ? {} : { codexHome: process.env.CODEX_HOME },
112358
+ cwd: options.cwd
112359
+ });
112360
+ const bytes = JSON.stringify(catalog, null, 2) + `
112361
+ `;
112362
+ try {
112363
+ writeFileSync26(options.output, bytes, { flag: "wx", mode: 384 });
112364
+ } catch (error61) {
112365
+ if (error61 && typeof error61 === "object" && "code" in error61 && error61.code === "EEXIST")
112366
+ throw new Error("CODEX_NATIVE_SKILL_CATALOG_OUTPUT_EXISTS");
112367
+ throw error61;
112368
+ }
112369
+ const written = lstatSync32(options.output);
112370
+ if (!written.isFile() || written.isSymbolicLink() || (written.mode & 63) !== 0 || readFileSync41(options.output, "utf8") !== bytes)
112371
+ throw new Error("CODEX_NATIVE_SKILL_CATALOG_READBACK_FAILED");
112372
+ const receipt = {
112373
+ version: catalog.version,
112374
+ cwd: catalog.cwd,
112375
+ skillCount: catalog.skills.length,
112376
+ output: options.output,
112377
+ bytes: Buffer.byteLength(bytes),
112378
+ sha256: createHash31("sha256").update(bytes).digest("hex")
112379
+ };
112380
+ await writeCliOutput(options.json ? JSON.stringify(receipt) : `Captured ${receipt.skillCount} native Codex skill(s) in ${receipt.output}.`);
112381
+ } catch (error61) {
112382
+ const message = error61 instanceof Error && /^[A-Z][A-Z0-9_]{2,120}$/.test(error61.message) ? error61.message : "CODEX_NATIVE_SKILL_CATALOG_CAPTURE_FAILED";
112383
+ console.error(message);
112384
+ process.exitCode = 1;
112385
+ }
112386
+ });
112264
112387
  hook.command("witness").requiredOption("--kind <kind>", "claude-settings-v3, claude-settings-v2, codex-settings-v1 or claude-marketplace-registry-v2").requiredOption("--path <path>", "Canonical absolute path to the reviewed settings or registry file").option("--json", "Output the discovery witness as JSON", false).description("Capture an explicit versioned review witness without installing it").action(async (options) => {
112265
112388
  const capture2 = options.kind === "codex-settings-v1" ? captureCodexSettings : options.kind === "claude-settings-v3" ? captureClaudeSettingsV3 : options.kind === "claude-settings-v2" ? captureClaudeSettingsV2 : options.kind === "claude-marketplace-registry-v2" ? captureClaudeMarketplaceRegistryV2 : null;
112266
112389
  if (!capture2)
@@ -112283,7 +112406,7 @@ function registerAgentIntegration(parent) {
112283
112406
  hook.command("agents").option("--json", "Output the adapter capability inventory", false).description("Show maintained native adapters and explicit coverage limits").action(async () => {
112284
112407
  await writeCliOutput(JSON.stringify({ agents: INTEGRATION_AGENTS.map((agent) => ({ agent, bridge: true, ...AGENT_ADAPTERS[agent] })), inventoryOnly: ["codewith", "windsurf", "pi", "amp", "cline", "roo", "copilot"], limitations: ["Cursor prompt hooks gate submission; selected context is injected at session start only.", "Native discovery checks cover known home roots and current project ancestors. External plugin hook injection and arbitrary added directories require separate review.", "Hermes injects selected prompt context, but native pre_llm_call fails open. Exact native hook trust, bundled reseeding opt-out, native payload retirement and a supervised pre-tool guard are required. Child failures block explicitly; native host/supervisor death is not a universal fail-closed guarantee.", "Restart agents and use their normal hook trust controls after installation."] }, null, 2));
112285
112408
  });
112286
- hook.command("install").option("--agent <agent>", `Agent to configure: ${INTEGRATION_AGENTS.join(", ")}, all`, "all").option("--command <path>", "Skills executable used by the hook (preserves existing binding; new agents use skills)").option("--selection-profile <id>", "Selection profile (preserves existing binding; new agents use default)").option("--include-vendor", "Retained for compatibility; vendor system skills are always inventoried and disabled", false).option("--discovery-inputs <file>", "Advanced reviewed active plugin roots and source hashes for unsupported registrations").option("--codex-native-catalog <file>", "Reviewed native0.159.2 skills/list receipt for exact qualified plugin-name disables").option("--reviewed-cache-alias <path>", "Exact skill-containing vendor cache alias reviewed for this hook plan").option("--allow-root-aliases", "Allow home .claude/.codex aliases to existing directories within this home", false).option("--apply", "Apply the plan, preserving prior configuration in private backups", false).option("--json", "Output a receipt as JSON", false).description("Plan or install one Skills CLI bridge plus native prompt hooks").action(async (options) => {
112409
+ hook.command("install").option("--agent <agent>", `Agent to configure: ${INTEGRATION_AGENTS.join(", ")}, all`, "all").option("--command <path>", "Skills executable used by the hook (preserves existing binding; new agents use skills)").option("--selection-profile <id>", "Selection profile (preserves existing binding; new agents use default)").option("--include-vendor", "Retained for compatibility; vendor system skills are always inventoried and disabled", false).option("--discovery-inputs <file>", "Advanced reviewed active plugin roots and source hashes for unsupported registrations").option("--codex-native-catalog <file>", "Reviewed Codex 0.159.2 skill and installed-plugin receipt for exact qualified-name disables").option("--reviewed-cache-alias <path>", "Exact skill-containing vendor cache alias reviewed for this hook plan").option("--allow-root-aliases", "Allow home .claude/.codex aliases to existing directories within this home", false).option("--apply", "Apply the plan, preserving prior configuration in private backups", false).option("--json", "Output a receipt as JSON", false).description("Plan or install one Skills CLI bridge plus native prompt hooks").action(async (options) => {
112287
112410
  try {
112288
112411
  const discoveryInputs = options.discoveryInputs ? JSON.parse(readFileSync41(options.discoveryInputs, "utf8")) : undefined;
112289
112412
  const plan = planAgentIntegration({ projectDir: process.cwd(), agents: agents(options.agent), command: options.command, profileId: options.selectionProfile, includeVendor: options.includeVendor, discoveryInputs, allowRootAliases: options.allowRootAliases, reviewedCacheAlias: options.reviewedCacheAlias, codexNativeCatalog: options.codexNativeCatalog ? JSON.parse(readFileSync41(options.codexNativeCatalog, "utf8")) : undefined });
@@ -112492,6 +112615,7 @@ var init_agent_integration2 = __esm(() => {
112492
112615
  init_claude_settings_witness();
112493
112616
  init_codex_settings_witness();
112494
112617
  init_claude_marketplace_registry();
112618
+ init_codex_native_skill_catalog();
112495
112619
  RECOVERABLE_CONTEXT_CACHE_ERRORS = new Set(["CACHED_PROFILE_EXPIRED", "CACHED_PROFILE_MISSING", "CACHED_BUNDLE_MISSING"]);
112496
112620
  });
112497
112621
 
@@ -112630,7 +112754,7 @@ var exports_profiles = {};
112630
112754
  __export(exports_profiles, {
112631
112755
  registerProfiles: () => registerProfiles
112632
112756
  });
112633
- import { closeSync as closeSync21, constants as constants20, fstatSync as fstatSync21, openSync as openSync21, readSync as readSync17, writeFileSync as writeFileSync26 } from "fs";
112757
+ import { closeSync as closeSync21, constants as constants20, fstatSync as fstatSync21, openSync as openSync21, readSync as readSync17, writeFileSync as writeFileSync27 } from "fs";
112634
112758
  function readProfileInput(path) {
112635
112759
  const fd = openSync21(path, constants20.O_RDONLY | constants20.O_NONBLOCK);
112636
112760
  try {
@@ -112658,7 +112782,7 @@ function registerProfiles(parent) {
112658
112782
  try {
112659
112783
  const profile = await readSkillProfile(id3), text4 = JSON.stringify(profile, null, 2);
112660
112784
  if (options.save)
112661
- writeFileSync26(options.save, JSON.stringify(profile), { mode: 384, flag: "wx" });
112785
+ writeFileSync27(options.save, JSON.stringify(profile), { mode: 384, flag: "wx" });
112662
112786
  await writeCliOutput(options.json ? text4 : `${profile.id} at ${profile.revision}: ${profile.selections.map((skill) => `${skill.slug}@${skill.version}`).join(", ")}`);
112663
112787
  } catch (error61) {
112664
112788
  console.error(error61.message);
@@ -112705,7 +112829,7 @@ import {
112705
112829
  fstatSync as fstatSync23,
112706
112830
  openSync as openSync23,
112707
112831
  readSync as readSync18,
112708
- writeFileSync as writeFileSync27
112832
+ writeFileSync as writeFileSync28
112709
112833
  } from "fs";
112710
112834
  function readInput(path) {
112711
112835
  const fd = openSync23(path, constants21.O_RDONLY | constants21.O_NONBLOCK);
@@ -112738,7 +112862,7 @@ function registerGrants(parent) {
112738
112862
  try {
112739
112863
  const policy = await readExecutionGrantPolicy(profile, options.revision);
112740
112864
  if (options.save)
112741
- writeFileSync27(options.save, JSON.stringify(policy, null, 2), {
112865
+ writeFileSync28(options.save, JSON.stringify(policy, null, 2), {
112742
112866
  mode: 384,
112743
112867
  flag: "wx"
112744
112868
  });
@@ -112765,14 +112889,14 @@ var init_grants = __esm(() => {
112765
112889
  });
112766
112890
 
112767
112891
  // src/lib/station-hydrate.ts
112768
- import { createHash as createHash31 } from "crypto";
112892
+ import { createHash as createHash32 } from "crypto";
112769
112893
  import {
112770
112894
  copyFileSync as copyFileSync3,
112771
112895
  mkdirSync as mkdirSync28,
112772
112896
  readdirSync as readdirSync24,
112773
112897
  readFileSync as readFileSync42,
112774
112898
  statSync as statSync22,
112775
- writeFileSync as writeFileSync28
112899
+ writeFileSync as writeFileSync29
112776
112900
  } from "fs";
112777
112901
  import { dirname as dirname35, join as join61, resolve as resolve26, sep as sep13 } from "path";
112778
112902
  function fail5(code2, message, detail = []) {
@@ -112968,7 +113092,7 @@ function skillSha256(skill) {
112968
113092
  return sha256File(skill.files[0].winner.fullPath);
112969
113093
  }
112970
113094
  const joined = skill.files.map((file2) => sha256File(file2.winner.fullPath));
112971
- return createHash31("sha256").update(joined.sort().join(`
113095
+ return createHash32("sha256").update(joined.sort().join(`
112972
113096
  `)).digest("hex");
112973
113097
  }
112974
113098
  function writeStationHydration(options) {
@@ -113050,7 +113174,7 @@ function writeStationHydration(options) {
113050
113174
  };
113051
113175
  const hydrationManifestPath = join61(dirname35(cacheRoot), `hydration-${options.stationId}.json`);
113052
113176
  mkdirSync28(dirname35(hydrationManifestPath), { recursive: true });
113053
- writeFileSync28(hydrationManifestPath, `${JSON.stringify(hydration, null, 2)}
113177
+ writeFileSync29(hydrationManifestPath, `${JSON.stringify(hydration, null, 2)}
113054
113178
  `);
113055
113179
  return {
113056
113180
  ...base3,
@@ -113125,10 +113249,10 @@ var init_hydrate = __esm(() => {
113125
113249
  });
113126
113250
 
113127
113251
  // src/lib/prepare-skill.ts
113128
- import { createHash as createHash32, randomUUID as randomUUID12 } from "crypto";
113129
- import { chmodSync as chmodSync5, existsSync as existsSync35, lstatSync as lstatSync32, mkdirSync as mkdirSync29, mkdtempSync as mkdtempSync6, readFileSync as readFileSync43, readdirSync as readdirSync25, renameSync as renameSync14, rmSync as rmSync9, writeFileSync as writeFileSync29 } from "fs";
113252
+ import { createHash as createHash33, randomUUID as randomUUID12 } from "crypto";
113253
+ import { chmodSync as chmodSync5, existsSync as existsSync36, lstatSync as lstatSync33, mkdirSync as mkdirSync29, mkdtempSync as mkdtempSync6, readFileSync as readFileSync43, readdirSync as readdirSync25, renameSync as renameSync14, rmSync as rmSync9, writeFileSync as writeFileSync30 } from "fs";
113130
113254
  import { tmpdir as tmpdir2 } from "os";
113131
- import { dirname as dirname36, isAbsolute as isAbsolute30, join as join62, relative as relative10, resolve as resolve27, sep as sep14 } from "path";
113255
+ import { dirname as dirname36, isAbsolute as isAbsolute30, join as join62, relative as relative11, resolve as resolve27, sep as sep14 } from "path";
113132
113256
  function prepareSkill(name, options) {
113133
113257
  const normalized = normalizePortableSkillName(name);
113134
113258
  if (!new RegExp(SEMVER_PATTERN).test(options.version))
@@ -113175,10 +113299,10 @@ function prepareSkill(name, options) {
113175
113299
  for (const file2 of before2.files) {
113176
113300
  const destination = join62(staging, file2.path);
113177
113301
  mkdirSync29(dirname36(destination), { recursive: true });
113178
- writeFileSync29(destination, file2.bytes, { mode: file2.mode });
113302
+ writeFileSync30(destination, file2.bytes, { mode: file2.mode });
113179
113303
  }
113180
113304
  const stagedManifest = join62(staging, "skill.json");
113181
- writeFileSync29(stagedManifest, `${JSON.stringify(candidate2, null, 2)}
113305
+ writeFileSync30(stagedManifest, `${JSON.stringify(candidate2, null, 2)}
113182
113306
  `);
113183
113307
  const contentHash = computeContentHash(staging);
113184
113308
  const changed3 = options.version !== previousVersion || kind !== manifest.kind || contentHash !== provenance?.content_hash;
@@ -113188,7 +113312,7 @@ function prepareSkill(name, options) {
113188
113312
  candidate2.provenance.content_hash = contentHash;
113189
113313
  const candidateBytes = `${JSON.stringify(candidate2, null, 2)}
113190
113314
  `;
113191
- writeFileSync29(stagedManifest, candidateBytes);
113315
+ writeFileSync30(stagedManifest, candidateBytes);
113192
113316
  validateRawCandidate(candidate2);
113193
113317
  validateRuntimeEntrypoint(candidate2, staging);
113194
113318
  const validation = validatePortableSkillDirectory(normalized, staging);
@@ -113202,7 +113326,7 @@ ${validation.issues.map((issue2) => `${issue2.code}: ${issue2.message}`).join(`
113202
113326
  if (changed3 && !options.dryRun) {
113203
113327
  const temporary = join62(path, `.skill-prepare-${randomUUID12()}.tmp`);
113204
113328
  try {
113205
- writeFileSync29(temporary, candidateBytes, { flag: "wx", mode: manifestFile.mode });
113329
+ writeFileSync30(temporary, candidateBytes, { flag: "wx", mode: manifestFile.mode });
113206
113330
  chmodSync5(temporary, manifestFile.mode);
113207
113331
  renameSync14(temporary, join62(path, "skill.json"));
113208
113332
  } finally {
@@ -113234,8 +113358,8 @@ function validateRuntimeEntrypoint(candidate2, root2) {
113234
113358
  const entry = candidate2.runtime.entrypoint;
113235
113359
  if (typeof entry !== "string")
113236
113360
  return;
113237
- const target = resolve27(root2, entry), rel = relative10(root2, target);
113238
- if (isAbsolute30(entry) || /^[a-zA-Z]:/.test(entry) || entry.includes("\\") || !rel || rel === ".." || rel.startsWith(`..${sep14}`) || isAbsolute30(rel) || !existsSync35(target) || !lstatSync32(target).isFile()) {
113361
+ const target = resolve27(root2, entry), rel = relative11(root2, target);
113362
+ if (isAbsolute30(entry) || /^[a-zA-Z]:/.test(entry) || entry.includes("\\") || !rel || rel === ".." || rel.startsWith(`..${sep14}`) || isAbsolute30(rel) || !existsSync36(target) || !lstatSync33(target).isFile()) {
113239
113363
  throw new Error("Executable runtime.entrypoint must name an existing regular file inside the skill directory.");
113240
113364
  }
113241
113365
  }
@@ -113320,20 +113444,20 @@ function compareVersions(left, right) {
113320
113444
  return 0;
113321
113445
  }
113322
113446
  function snapshot2(root2) {
113323
- const rootStat = lstatSync32(root2);
113447
+ const rootStat = lstatSync33(root2);
113324
113448
  if (rootStat.isSymbolicLink() || !rootStat.isDirectory())
113325
113449
  throw new Error("Skill root must be a real directory, not a symlink.");
113326
113450
  const files = [], directories = [];
113327
- const hash6 = createHash32("sha256").update(`${rootStat.dev}:${rootStat.ino}\x00`);
113451
+ const hash6 = createHash33("sha256").update(`${rootStat.dev}:${rootStat.ino}\x00`);
113328
113452
  let count = 0, bytes = 0;
113329
- const walk2 = (relative11) => {
113330
- for (const name of readdirSync25(join62(root2, relative11)).sort()) {
113331
- if (IGNORED.has(name.toLowerCase()) || !relative11 && ROOT_IGNORED.has(name.toLowerCase()))
113453
+ const walk2 = (relative12) => {
113454
+ for (const name of readdirSync25(join62(root2, relative12)).sort()) {
113455
+ if (IGNORED.has(name.toLowerCase()) || !relative12 && ROOT_IGNORED.has(name.toLowerCase()))
113332
113456
  continue;
113333
- const path = relative11 ? `${relative11}/${name}` : name;
113457
+ const path = relative12 ? `${relative12}/${name}` : name;
113334
113458
  if (++count > 20000)
113335
113459
  throw new Error("Skill exceeds the preparation entry limit (20000).");
113336
- const absolute = join62(root2, path), stat3 = lstatSync32(absolute);
113460
+ const absolute = join62(root2, path), stat3 = lstatSync33(absolute);
113337
113461
  if (stat3.isSymbolicLink())
113338
113462
  throw new Error(`Skill contains a symlink: ${path}. No files were changed.`);
113339
113463
  if (stat3.isDirectory() && name === "node_modules")
@@ -113748,8 +113872,8 @@ var init_schedule = __esm(() => {
113748
113872
  });
113749
113873
 
113750
113874
  // src/lib/registry-sync.ts
113751
- import { mkdirSync as mkdirSync30, writeFileSync as writeFileSync30 } from "fs";
113752
- import { dirname as dirname37, relative as relative11 } from "path";
113875
+ import { mkdirSync as mkdirSync30, writeFileSync as writeFileSync31 } from "fs";
113876
+ import { dirname as dirname37, relative as relative12 } from "path";
113753
113877
  function createRegistrySyncArtifact(options = {}) {
113754
113878
  const profile = options.profile ?? "all";
113755
113879
  const includeDocs = options.includeDocs ?? true;
@@ -113761,7 +113885,7 @@ function createRegistrySyncArtifact(options = {}) {
113761
113885
  const registry2 = [...loadRegistryProfile(profile)].sort((a, b) => a.name.localeCompare(b.name));
113762
113886
  const skills = registry2.map((skill) => {
113763
113887
  const skillPath = getSkillPath(skill.name);
113764
- const directory2 = relative11(process.cwd(), skillPath) || skillPath;
113888
+ const directory2 = relative12(process.cwd(), skillPath) || skillPath;
113765
113889
  const validation = includeValidation ? validateSkillDirectory(skill.name, skillPath, skill) : undefined;
113766
113890
  const docs = includeDocs ? buildDocs(skill.name) : undefined;
113767
113891
  return {
@@ -113807,7 +113931,7 @@ function createRegistrySyncArtifact(options = {}) {
113807
113931
  }
113808
113932
  function writeRegistrySyncArtifact(path, artifact) {
113809
113933
  mkdirSync30(dirname37(path), { recursive: true });
113810
- writeFileSync30(path, `${JSON.stringify(artifact, null, 2)}
113934
+ writeFileSync31(path, `${JSON.stringify(artifact, null, 2)}
113811
113935
  `);
113812
113936
  }
113813
113937
  function buildDocs(name) {
@@ -113826,8 +113950,8 @@ var init_registry_sync = __esm(() => {
113826
113950
  });
113827
113951
 
113828
113952
  // src/lib/review-export.ts
113829
- import { constants as constants22, closeSync as closeSync25, existsSync as existsSync36, fstatSync as fstatSync25, fsyncSync as fsyncSync7, lstatSync as lstatSync33, openSync as openSync25, realpathSync as realpathSync18, statSync as statSync23, writeFileSync as writeFileSync31 } from "fs";
113830
- import { basename as basename15, dirname as dirname38, isAbsolute as isAbsolute31, join as join63, parse as parse12, resolve as resolve28, sep as sep15 } from "path";
113953
+ import { constants as constants22, closeSync as closeSync25, existsSync as existsSync37, fstatSync as fstatSync25, fsyncSync as fsyncSync7, lstatSync as lstatSync34, openSync as openSync25, realpathSync as realpathSync18, statSync as statSync23, writeFileSync as writeFileSync32 } from "fs";
113954
+ import { basename as basename16, dirname as dirname38, isAbsolute as isAbsolute31, join as join63, parse as parse12, resolve as resolve28, sep as sep15 } from "path";
113831
113955
  function exactVersion(spec) {
113832
113956
  const at2 = spec.indexOf("@");
113833
113957
  const slug2 = spec.slice(0, at2);
@@ -113838,11 +113962,11 @@ function exactVersion(spec) {
113838
113962
  return { slug: slug2, version: version2 };
113839
113963
  }
113840
113964
  function assertPrivateDestination(output2) {
113841
- if (!isAbsolute31(output2) || resolve28(output2) !== output2 || !basename15(output2).endsWith(".tar.gz")) {
113965
+ if (!isAbsolute31(output2) || resolve28(output2) !== output2 || !basename16(output2).endsWith(".tar.gz")) {
113842
113966
  throw new Error("Review output must be an absolute, normalized .tar.gz path.");
113843
113967
  }
113844
113968
  const parent = dirname38(output2);
113845
- if (realpathSync18(parent) !== parent || lstatSync33(parent).isSymbolicLink()) {
113969
+ if (realpathSync18(parent) !== parent || lstatSync34(parent).isSymbolicLink()) {
113846
113970
  throw new Error("Review output parent must be a real directory, not a symlink.");
113847
113971
  }
113848
113972
  const parentStat = statSync23(parent);
@@ -113854,7 +113978,7 @@ function assertPrivateDestination(output2) {
113854
113978
  throw new Error("Review output cannot be placed in agent-native discovery or Skills installation paths.");
113855
113979
  }
113856
113980
  for (let current = parent;; current = dirname38(current)) {
113857
- if (existsSync36(join63(current, ".git"))) {
113981
+ if (existsSync37(join63(current, ".git"))) {
113858
113982
  throw new Error("Review output cannot be placed inside a Git worktree.");
113859
113983
  }
113860
113984
  if (current === parse12(current).root)
@@ -113865,7 +113989,7 @@ function assertPrivateDestination(output2) {
113865
113989
  async function exportSkillVersionForReview(spec, output2, client2) {
113866
113990
  const { slug: slug2, version: version2 } = exactVersion(spec);
113867
113991
  const target = assertPrivateDestination(output2);
113868
- if (existsSync36(target))
113992
+ if (existsSync37(target))
113869
113993
  throw new Error("Review output already exists; choose a new filename.");
113870
113994
  const metadata = await client2.getSkillVersion(slug2, version2);
113871
113995
  if (!metadata)
@@ -113892,7 +114016,7 @@ async function exportSkillVersionForReview(spec, output2, client2) {
113892
114016
  }
113893
114017
  const fd = openSync25(target, constants22.O_WRONLY | constants22.O_CREAT | constants22.O_EXCL | constants22.O_NOFOLLOW, 384);
113894
114018
  try {
113895
- writeFileSync31(fd, bytes);
114019
+ writeFileSync32(fd, bytes);
113896
114020
  fsyncSync7(fd);
113897
114021
  if (fstatSync25(fd).size !== bytes.byteLength)
113898
114022
  throw new Error("Incomplete review output write.");
@@ -114139,7 +114263,7 @@ __export(exports_publish, {
114139
114263
  PushSkillError: () => PushSkillError
114140
114264
  });
114141
114265
  import { execFileSync as execFileSync2 } from "child_process";
114142
- import { existsSync as existsSync37, readFileSync as readFileSync44 } from "fs";
114266
+ import { existsSync as existsSync38, readFileSync as readFileSync44 } from "fs";
114143
114267
  import { hostname as hostname5 } from "os";
114144
114268
  import { join as join64 } from "path";
114145
114269
  function registerPublish(parent) {
@@ -114194,7 +114318,7 @@ async function pushSkill(name, options = {}) {
114194
114318
  await verifyPackedCanonicalHash(skill.name, packed);
114195
114319
  const versionManifest = buildVersionManifest(skill.path, packed);
114196
114320
  const skillMdPath = join64(skill.path, "SKILL.md");
114197
- const skillMd = existsSync37(skillMdPath) ? readFileSync44(skillMdPath, "utf-8") : undefined;
114321
+ const skillMd = existsSync38(skillMdPath) ? readFileSync44(skillMdPath, "utf-8") : undefined;
114198
114322
  const base3 = {
114199
114323
  slug: skill.name,
114200
114324
  path: skill.path,
@@ -115913,7 +116037,7 @@ var init_storage2 = __esm(() => {
115913
116037
  });
115914
116038
 
115915
116039
  // src/lib/registry-reconcile.ts
115916
- import { existsSync as existsSync38, readFileSync as readFileSync45, statSync as statSync24, writeFileSync as writeFileSync32 } from "fs";
116040
+ import { existsSync as existsSync39, readFileSync as readFileSync45, statSync as statSync24, writeFileSync as writeFileSync33 } from "fs";
115917
116041
  import { join as join65 } from "path";
115918
116042
  function isDirectory2(path) {
115919
116043
  try {
@@ -115930,7 +116054,7 @@ function migrationNeeded(options) {
115930
116054
  }
115931
116055
  function readBaseline(skillDir) {
115932
116056
  const markerPath = join65(skillDir, PULL_MARKER_FILE);
115933
- if (!existsSync38(markerPath))
116057
+ if (!existsSync39(markerPath))
115934
116058
  return;
115935
116059
  try {
115936
116060
  const marker = JSON.parse(readFileSync45(markerPath, "utf-8"));
@@ -115946,7 +116070,7 @@ function readBaseline(skillDir) {
115946
116070
  }
115947
116071
  function readCursor(root2) {
115948
116072
  const path = join65(root2, SYNC_CURSOR_FILE);
115949
- if (!existsSync38(path))
116073
+ if (!existsSync39(path))
115950
116074
  return { runCount: 0 };
115951
116075
  try {
115952
116076
  const cursor2 = JSON.parse(readFileSync45(path, "utf-8"));
@@ -115977,7 +116101,7 @@ function remoteRowToSkill(record11) {
115977
116101
  }
115978
116102
  function recheckLocalSide(plannedLocal, localDir, ops = {
115979
116103
  pack: (dir) => packSkillBundle(dir).sha256,
115980
- exists: existsSync38
116104
+ exists: existsSync39
115981
116105
  }) {
115982
116106
  let localNow;
115983
116107
  try {
@@ -116228,7 +116352,7 @@ async function reconcileRegistry(options = {}) {
116228
116352
  runCount: readCursor(root2).runCount + 1,
116229
116353
  summary
116230
116354
  };
116231
- writeFileSync32(join65(root2, SYNC_CURSOR_FILE), `${JSON.stringify(cursor2, null, 2)}
116355
+ writeFileSync33(join65(root2, SYNC_CURSOR_FILE), `${JSON.stringify(cursor2, null, 2)}
116232
116356
  `);
116233
116357
  return {
116234
116358
  corpusRoot: root2,