@hasna/skills 0.10.60 → 0.10.61

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
@@ -36888,7 +36888,7 @@ var package_default;
36888
36888
  var init_package = __esm(() => {
36889
36889
  package_default = {
36890
36890
  name: "@hasna/skills",
36891
- version: "0.10.60",
36891
+ version: "0.10.61",
36892
36892
  description: "Skills library for AI coding agents",
36893
36893
  type: "module",
36894
36894
  bin: {
@@ -36925,6 +36925,7 @@ var init_package = __esm(() => {
36925
36925
  "!dist/test-preload.d.ts",
36926
36926
  "!dist/platform",
36927
36927
  "bin/",
36928
+ "native/kernel-lock-acl-darwin",
36928
36929
  "migrations/",
36929
36930
  "docs/skill-standard.md",
36930
36931
  "docs/plugin-admission.md",
@@ -36938,8 +36939,8 @@ var init_package = __esm(() => {
36938
36939
  types: "./dist/index.d.ts",
36939
36940
  scripts: {
36940
36941
  clean: "rm -rf bin/ dist/",
36941
- build: "bun run clean && bun build --external @hasna/contracts/kernel-lock ./src/cli/index.tsx --outdir ./bin --target bun && bun build --external @hasna/contracts/kernel-lock ./src/mcp/index.ts --outfile ./bin/mcp.js --target bun && bun build --external @hasna/contracts/kernel-lock ./src/server/index.ts --outfile ./bin/server.js --target bun && bun build --external @hasna/contracts/kernel-lock ./src/server/worker.ts --outfile ./bin/worker.js --target bun && bun build --external @hasna/contracts/kernel-lock ./src/server/migrate.ts --outfile ./bin/migrate.js --target bun && bun build --external @hasna/contracts/kernel-lock ./src/server/maintenance.ts --outfile ./bin/maintenance.js --target bun && bun build --external @hasna/contracts/kernel-lock ./src/index.ts ./src/storage.ts ./src/sdk/index.ts ./src/admin-contract.ts --outdir ./dist --target bun && tsc --emitDeclarationOnly --declaration --outDir dist",
36942
- "build:js": "rm -rf dist && bun build --external @hasna/contracts/kernel-lock ./src/index.ts ./src/storage.ts ./src/sdk/index.ts ./src/admin-contract.ts --outdir ./dist --target bun && tsc --emitDeclarationOnly --declaration --outDir dist",
36942
+ build: "bun run clean && bun build --external @hasna/contracts/kernel-lock ./src/cli/index.tsx --outdir ./bin --target bun && bun build --external @modelcontextprotocol/sdk ./src/mcp/index.ts --outfile ./bin/mcp.js --target bun && bun build --external @hasna/contracts/kernel-lock ./src/server/index.ts --outfile ./bin/server.js --target bun && bun build --external @hasna/contracts/kernel-lock ./src/server/worker.ts --outfile ./bin/worker.js --target bun && bun build --external @hasna/contracts/kernel-lock ./src/server/migrate.ts --outfile ./bin/migrate.js --target bun && bun build --external @hasna/contracts/kernel-lock ./src/server/maintenance.ts --outfile ./bin/maintenance.js --target bun && bun build ./src/index.ts ./src/storage.ts ./src/sdk/index.ts ./src/admin-contract.ts --outdir ./dist --target bun && tsc --emitDeclarationOnly --declaration --outDir dist && bun scripts/stage-kernel-lock-assets.ts",
36943
+ "build:js": "rm -rf dist && bun build ./src/index.ts ./src/storage.ts ./src/sdk/index.ts ./src/admin-contract.ts --outdir ./dist --target bun && tsc --emitDeclarationOnly --declaration --outDir dist && bun scripts/stage-kernel-lock-assets.ts",
36943
36944
  test: "bun test --timeout 30000",
36944
36945
  dev: "bun run ./src/cli/index.tsx",
36945
36946
  "dev:watch": "bun --watch run ./src/cli/index.tsx",
@@ -39899,7 +39900,7 @@ var init_agent_adapters = __esm(() => {
39899
39900
  codex: { root: ".codex/skills", config: ".codex/hooks.json", events: ["UserPromptSubmit", "SessionStart", "SubagentStart"], promptContext: true },
39900
39901
  gemini: { root: ".gemini/skills", config: ".gemini/settings.json", events: ["BeforeAgent", "SessionStart"], promptContext: true },
39901
39902
  opencode: { root: ".config/opencode/skills", config: ".config/opencode/opencode.json", events: ["chat.message"], promptContext: true },
39902
- sumi: { root: ".hasna-internal/sumi/config/skills", config: ".hasna-internal/sumi/config/sumi.json", events: ["prompt", "context"], promptContext: true },
39903
+ sumi: { root: null, config: null, events: ["prompt", "context"], promptContext: true },
39903
39904
  hermes: { root: ".hermes/skills", config: ".hermes/config.yaml", events: ["pre_llm_call", "pre_tool_call"], promptContext: true, promptFailureMode: "open", toolFailureMode: "supervised-child-errors-block", requiresNativeTrust: true },
39904
39905
  cursor: { root: ".cursor/skills", config: ".cursor/hooks.json", events: ["beforeSubmitPrompt", "sessionStart"], promptContext: false }
39905
39906
  };
@@ -54091,37 +54092,136 @@ var init_agent_codex = __esm(() => {
54091
54092
  });
54092
54093
 
54093
54094
  // src/lib/agent-sumi.ts
54094
- import { existsSync as existsSync12, lstatSync as lstatSync18, realpathSync as realpathSync8 } from "fs";
54095
- import { join as join27, resolve as resolve15 } from "path";
54096
- function sumiConfigDirectory(home, env3 = process.env) {
54095
+ import { spawnSync as spawnSync3 } from "child_process";
54096
+ import { accessSync as accessSync2, constants as constants11, existsSync as existsSync12, lstatSync as lstatSync18, realpathSync as realpathSync8, statSync as statSync9 } from "fs";
54097
+ import { delimiter as delimiter2, isAbsolute as isAbsolute15, join as join27, resolve as resolve15 } from "path";
54098
+ function recordWithKeys(value, keys2) {
54099
+ return value !== null && typeof value === "object" && !Array.isArray(value) && Object.keys(value).length === keys2.length && keys2.every((key) => Object.hasOwn(value, key));
54100
+ }
54101
+ function absolutePath3(value) {
54102
+ return typeof value === "string" && value.length > 0 && value.length <= 32768 && !/[\x00-\x1f\x7f]/.test(value) && isAbsolute15(value) && resolve15(value) === value;
54103
+ }
54104
+ function absoluteInput(value) {
54105
+ return value.length > 0 && value.length <= 32768 && !/[\x00-\x1f\x7f]/.test(value) && isAbsolute15(value);
54106
+ }
54107
+ function resolveSumiPathsCommand(pathValue) {
54108
+ if (!pathValue)
54109
+ return null;
54110
+ for (const directory of pathValue.split(delimiter2)) {
54111
+ if (!directory || /[\x00-\x1f\x7f]/.test(directory))
54112
+ continue;
54113
+ const candidate = resolve15(directory, "sumi-paths");
54114
+ try {
54115
+ accessSync2(candidate, constants11.X_OK);
54116
+ if (statSync9(candidate).isFile())
54117
+ return candidate;
54118
+ } catch {}
54119
+ }
54120
+ return null;
54121
+ }
54122
+ function validPathPlan(value, home, cwd2) {
54123
+ if (!recordWithKeys(value, ["schemaVersion", "kind", "home", "cwd", "roots", "legacyRoots", "configFiles", "skillRoots"]))
54124
+ return false;
54125
+ if (value.schemaVersion !== 1 || value.kind !== "sumi-paths" || value.home !== resolve15(home) || value.cwd !== resolve15(cwd2))
54126
+ return false;
54127
+ if (!recordWithKeys(value.roots, SUMI_PATH_KEYS) || !recordWithKeys(value.legacyRoots, SUMI_PATH_KEYS))
54128
+ return false;
54129
+ for (const key of SUMI_PATH_KEYS) {
54130
+ if (!absolutePath3(value.roots[key]))
54131
+ return false;
54132
+ if (value.legacyRoots[key] !== null && !absolutePath3(value.legacyRoots[key]))
54133
+ return false;
54134
+ }
54135
+ if (!recordWithKeys(value.configFiles, ["canonical", "legacy"]) || !recordWithKeys(value.skillRoots, ["canonical", "legacy"]))
54136
+ return false;
54137
+ if (!absolutePath3(value.configFiles.canonical) || !absolutePath3(value.skillRoots.canonical))
54138
+ return false;
54139
+ if (value.configFiles.legacy !== null && !absolutePath3(value.configFiles.legacy))
54140
+ return false;
54141
+ if (value.skillRoots.legacy !== null && !absolutePath3(value.skillRoots.legacy))
54142
+ return false;
54143
+ const configRoot = value.roots.config;
54144
+ const legacyConfigRoot = value.legacyRoots.config;
54145
+ if (typeof configRoot !== "string" || legacyConfigRoot !== null && typeof legacyConfigRoot !== "string")
54146
+ return false;
54147
+ if (value.configFiles.canonical !== join27(configRoot, "sumi.json") || value.skillRoots.canonical !== join27(configRoot, "skills"))
54148
+ return false;
54149
+ if (legacyConfigRoot === null)
54150
+ return value.configFiles.legacy === null && value.skillRoots.legacy === null;
54151
+ return value.configFiles.legacy === join27(legacyConfigRoot, "sumi.json") && value.skillRoots.legacy === join27(legacyConfigRoot, "skills");
54152
+ }
54153
+ function sumiPathPlan(home, cwd2 = process.cwd(), env3 = process.env) {
54097
54154
  for (const key of ["SUMI_CONFIG", "SUMI_CONFIG_CONTENT"])
54098
54155
  if (env3[key] !== undefined)
54099
- throw new Error(`Sumi ${key} requires a dedicated discovery adapter; unset it before Skills integration`);
54100
- const selected = (key) => env3[key]?.trim() ? env3[key] : undefined;
54101
- const expand = (value) => resolve15(value === "~" ? home : value.startsWith("~/") ? join27(home, value.slice(2)) : value);
54102
- const explicit = selected("SUMI_CONFIG_DIR");
54103
- const xdg = selected("XDG_CONFIG_HOME");
54104
- const custom = selected("SUMI_HOME");
54105
- const canonical7 = explicit ? expand(explicit) : xdg ? join27(expand(xdg), "sumi") : join27(custom ? expand(custom) : join27(home, ".hasna-internal/sumi"), "config");
54106
- if (explicit || xdg || custom)
54107
- return canonical7;
54108
- const legacy = join27(home, ".config/sumi");
54109
- const a = lstatSync18(canonical7, { throwIfNoEntry: false }), b = lstatSync18(legacy, { throwIfNoEntry: false });
54110
- if (a && b && realpathSync8(canonical7) !== realpathSync8(legacy))
54156
+ throw new SumiPathResolverError("SUMI_PATH_CONFIG_UNSUPPORTED");
54157
+ if (!absoluteInput(home) || !absoluteInput(cwd2))
54158
+ throw new SumiPathResolverError("SUMI_PATH_INPUT_REFUSED");
54159
+ const runtimePath = process.env.PATH ?? "";
54160
+ const executable2 = resolveSumiPathsCommand(runtimePath);
54161
+ if (!executable2 || !isAbsolute15(executable2))
54162
+ throw new SumiPathResolverError("SUMI_PATH_RESOLVER_UNAVAILABLE");
54163
+ const childEnv = { PATH: runtimePath };
54164
+ for (const key of SUMI_PATH_SELECTORS)
54165
+ if (env3[key] !== undefined)
54166
+ childEnv[key] = env3[key];
54167
+ let child2;
54168
+ try {
54169
+ child2 = spawnSync3(executable2, ["--json", "--home", resolve15(home), "--cwd", resolve15(cwd2)], {
54170
+ cwd: resolve15(cwd2),
54171
+ env: childEnv,
54172
+ encoding: "buffer",
54173
+ timeout: 3000,
54174
+ maxBuffer: SUMI_PATH_OUTPUT_LIMIT,
54175
+ shell: false
54176
+ });
54177
+ } catch {
54178
+ throw new SumiPathResolverError("SUMI_PATH_RESOLVER_UNAVAILABLE");
54179
+ }
54180
+ const stdoutBytes = child2.stdout === null ? 0 : Buffer.byteLength(child2.stdout);
54181
+ const stderrBytes = child2.stderr === null ? 0 : Buffer.byteLength(child2.stderr);
54182
+ if (child2.error || child2.signal || !child2.stdout || stdoutBytes > SUMI_PATH_OUTPUT_LIMIT || stderrBytes > 0) {
54183
+ throw new SumiPathResolverError("SUMI_PATH_RESOLVER_UNAVAILABLE");
54184
+ }
54185
+ let result2;
54186
+ try {
54187
+ result2 = JSON.parse(child2.stdout.toString("utf8"));
54188
+ } catch {
54189
+ throw new SumiPathResolverError("SUMI_PATH_RESOLVER_INVALID_RESPONSE");
54190
+ }
54191
+ if (recordWithKeys(result2, ["schemaVersion", "kind", "code"]) && result2.schemaVersion === 1 && result2.kind === "sumi-paths-error" && (result2.code === "SUMI_PATH_INPUT_REFUSED" || result2.code === "SUMI_PATH_CONFIG_UNSUPPORTED") && child2.status === 2) {
54192
+ throw new SumiPathResolverError(result2.code);
54193
+ }
54194
+ if (child2.status !== 0 || !validPathPlan(result2, home, cwd2))
54195
+ throw new SumiPathResolverError("SUMI_PATH_RESOLVER_INVALID_RESPONSE");
54196
+ return result2;
54197
+ }
54198
+ function selectedConfigDirectory(plan) {
54199
+ const canonical7 = plan.roots.config, legacy = plan.legacyRoots.config;
54200
+ if (legacy === null)
54201
+ return existsSync12(canonical7) ? realpathSync8(canonical7) : canonical7;
54202
+ const canonicalStat = lstatSync18(canonical7, { throwIfNoEntry: false }), legacyStat = lstatSync18(legacy, { throwIfNoEntry: false });
54203
+ if (canonicalStat && legacyStat && realpathSync8(canonical7) !== realpathSync8(legacy))
54111
54204
  throw new Error("Sumi config roots conflict; complete native home adoption before Skills integration");
54112
- const path = a ? canonical7 : b ? legacy : canonical7;
54113
- if (!existsSync12(path))
54114
- return path;
54115
- const physical = realpathSync8(path);
54116
- if ((a?.isSymbolicLink() || b?.isSymbolicLink()) && ![canonical7, legacy].includes(physical))
54205
+ const selected = canonicalStat ? canonical7 : legacyStat ? legacy : canonical7;
54206
+ if (!existsSync12(selected))
54207
+ return selected;
54208
+ const physical = realpathSync8(selected);
54209
+ if ((canonicalStat?.isSymbolicLink() || legacyStat?.isSymbolicLink()) && ![canonical7, legacy].includes(physical))
54117
54210
  throw new Error("Sumi config alias must resolve to its canonical or legacy root");
54118
54211
  return physical;
54119
54212
  }
54120
- function sumiBridgeRoot(home) {
54121
- return join27(sumiConfigDirectory(home), "skills");
54213
+ function sumiConfigDirectory(home, env3 = process.env, cwd2 = process.cwd()) {
54214
+ return selectedConfigDirectory(sumiPathPlan(home, cwd2, env3));
54215
+ }
54216
+ function sumiSkillRoots(home, cwd2 = process.cwd(), env3 = process.env) {
54217
+ const plan = sumiPathPlan(home, cwd2, env3);
54218
+ return [join27(selectedConfigDirectory(plan), "skills")];
54122
54219
  }
54123
- function sumiConfigPath(home) {
54124
- return join27(sumiConfigDirectory(home), "sumi.json");
54220
+ function sumiBridgeRoot(home, cwd2 = process.cwd(), env3 = process.env) {
54221
+ return sumiSkillRoots(home, cwd2, env3)[0];
54222
+ }
54223
+ function sumiConfigPath(home, cwd2 = process.cwd(), env3 = process.env) {
54224
+ return join27(sumiConfigDirectory(home, env3, cwd2), "sumi.json");
54125
54225
  }
54126
54226
  function renderSumiPlugin(command, profile) {
54127
54227
  return renderSumiPluginVersion(command, profile, false);
@@ -54207,8 +54307,19 @@ export default {
54207
54307
  };
54208
54308
  `;
54209
54309
  }
54210
- var SUMI_SKILL_PERMISSIONS;
54310
+ var SUMI_PATH_SELECTORS, SUMI_PATH_KEYS, SUMI_PATH_OUTPUT_LIMIT, SumiPathResolverError, SUMI_SKILL_PERMISSIONS;
54211
54311
  var init_agent_sumi = __esm(() => {
54312
+ SUMI_PATH_SELECTORS = ["SUMI_HOME", "SUMI_CONFIG_DIR", "XDG_DATA_HOME", "XDG_CACHE_HOME", "XDG_CONFIG_HOME", "XDG_STATE_HOME"];
54313
+ SUMI_PATH_KEYS = ["data", "cache", "config", "state"];
54314
+ SUMI_PATH_OUTPUT_LIMIT = 128 * 1024;
54315
+ SumiPathResolverError = class SumiPathResolverError extends Error {
54316
+ code;
54317
+ constructor(code) {
54318
+ super(`Sumi path discovery refused (${code})`);
54319
+ this.code = code;
54320
+ this.name = "SumiPathResolverError";
54321
+ }
54322
+ };
54212
54323
  SUMI_SKILL_PERMISSIONS = [
54213
54324
  { action: "skill", resource: "*", effect: "deny" },
54214
54325
  { action: "skill", resource: "skills-cli", effect: "allow" }
@@ -54216,9 +54327,9 @@ var init_agent_sumi = __esm(() => {
54216
54327
  });
54217
54328
 
54218
54329
  // src/lib/codex-hook-trust-files.ts
54219
- import { closeSync as closeSync10, constants as constants11, fstatSync as fstatSync10, fsyncSync as fsyncSync3, lstatSync as lstatSync19, openSync as openSync10, readlinkSync as readlinkSync5, readSync as readSync8, writeFileSync as writeFileSync5 } from "fs";
54330
+ import { closeSync as closeSync10, constants as constants12, fstatSync as fstatSync10, fsyncSync as fsyncSync3, lstatSync as lstatSync19, openSync as openSync10, readlinkSync as readlinkSync5, readSync as readSync8, writeFileSync as writeFileSync5 } from "fs";
54220
54331
  import { createHash as createHash18 } from "crypto";
54221
- import { dirname as dirname15, isAbsolute as isAbsolute15, resolve as resolve16 } from "path";
54332
+ import { dirname as dirname15, isAbsolute as isAbsolute16, resolve as resolve16 } from "path";
54222
54333
  function need6(value, code) {
54223
54334
  if (!value)
54224
54335
  throw new Error(`CODEX_HOOK_TRUST_${code}`);
@@ -54238,7 +54349,7 @@ function safeParents(file) {
54238
54349
  function directAliasTarget(link2) {
54239
54350
  const text2 = readlinkSync5(link2), parts = text2.split("/");
54240
54351
  let first = 0;
54241
- if (isAbsolute15(text2))
54352
+ if (isAbsolute16(text2))
54242
54353
  first = 1;
54243
54354
  else
54244
54355
  while (parts[first] === "..")
@@ -54254,7 +54365,7 @@ function snapshot(file, privateFile = false, options = {}) {
54254
54365
  const initial2 = lstatSync19(file, { bigint: true });
54255
54366
  need6(initial2.isFile() && initial2.uid === BigInt(process.getuid()) && (initial2.nlink === 1n || readOnlyPackage && initial2.nlink > 1n) && (initial2.mode & 0o022n) === 0n && (!privateFile || (initial2.mode & 0o777n) === 0o600n), "UNSAFE_FILE");
54256
54367
  need6(initial2.size <= 8n * 1024n * 1024n, "FILE_BOUND");
54257
- const fd = openSync10(file, constants11.O_RDONLY | constants11.O_NOFOLLOW | constants11.O_NONBLOCK);
54368
+ const fd = openSync10(file, constants12.O_RDONLY | constants12.O_NOFOLLOW | constants12.O_NONBLOCK);
54258
54369
  try {
54259
54370
  const before2 = fstatSync10(fd, { bigint: true });
54260
54371
  need6(sameStat(initial2, before2), "INPUT_CHANGED");
@@ -54279,7 +54390,7 @@ function unchanged2(before2) {
54279
54390
  }
54280
54391
  function save(file, content) {
54281
54392
  safeParents(file);
54282
- const fd = openSync10(file, constants11.O_WRONLY | constants11.O_CREAT | constants11.O_EXCL | constants11.O_NOFOLLOW, 384);
54393
+ const fd = openSync10(file, constants12.O_WRONLY | constants12.O_CREAT | constants12.O_EXCL | constants12.O_NOFOLLOW, 384);
54283
54394
  try {
54284
54395
  writeFileSync5(fd, content);
54285
54396
  fsyncSync3(fd);
@@ -54290,35 +54401,152 @@ function save(file, content) {
54290
54401
  var sameStat = (a, b) => ["dev", "ino", "uid", "nlink", "mode", "size", "mtimeNs", "ctimeNs"].every((key) => a[key] === b[key]);
54291
54402
  var init_codex_hook_trust_files = () => {};
54292
54403
 
54404
+ // src/server/launcher-environment-policy.ts
54405
+ function renderLegacyPinnedLauncher(binding) {
54406
+ const names = LEGACY_ENV_NAMES.join(" ");
54407
+ const prefixes = LEGACY_ENV_PREFIXES.join("|");
54408
+ return [
54409
+ "#!/bin/sh -p",
54410
+ `# ${LEGACY_PINNED_LAUNCHER_SCHEMA}`,
54411
+ "# Written by `skills self-update`; rewrite it with `skills self-update`, do not edit by hand.",
54412
+ "# Runs the exact Skills entry below under one exact Bun from one trusted directory with",
54413
+ "# no working-directory configuration (no bunfig.toml, no .env, no macros, no auto-install)",
54414
+ "# and only the environment names allowed here. Everything else, BUN_* and NODE_OPTIONS",
54415
+ "# included, never reaches the runtime. The CLI returns to the caller's directory itself.",
54416
+ "# `-p` keeps the caller's exported functions and shell options out of this shell.",
54417
+ "set -eu",
54418
+ `${LAUNCH_CWD_VARIABLE2}=$(pwd -P 2>/dev/null || :)`,
54419
+ `export ${LAUNCH_CWD_VARIABLE2}`,
54420
+ `set -- '${binding.runtime}' ${PINNED_LAUNCHER_BUN_FLAGS.join(" ")} '--cwd=${binding.cwd}' '${binding.entry}' "$@"`,
54421
+ "hasna_skills_env=$(LC_ALL=C /usr/bin/awk 'BEGIN {",
54422
+ ` n = split("${names}", exact, " ")`,
54423
+ " for (i = 1; i <= n; i++) allow[exact[i]] = 1",
54424
+ " for (name in ENVIRON) {",
54425
+ " if (name !~ /^[A-Za-z_][A-Za-z0-9_]*$/) continue",
54426
+ ` if (name == "LC_ALL" || (!(name in allow) && name !~ /^(${prefixes})_/)) continue`,
54427
+ ' value = ENVIRON[name]; quoted = ""',
54428
+ ' while ((k = index(value, "\\047")) > 0) { quoted = quoted substr(value, 1, k - 1) "\\047\\\\\\047\\047"; value = substr(value, k + 1) }',
54429
+ ' printf "\\047%s=%s\\047 ", name, quoted value',
54430
+ " }",
54431
+ "}')",
54432
+ 'eval "set -- $hasna_skills_env \\"\\$@\\""',
54433
+ 'if [ "${LC_ALL+x}" = x ]; then set -- "LC_ALL=$LC_ALL" "$@"; fi',
54434
+ 'exec /usr/bin/env -i "$@"',
54435
+ ""
54436
+ ].join(`
54437
+ `);
54438
+ }
54439
+ function isStorageLocatorEnvironmentName(name) {
54440
+ return storageLocators.has(name);
54441
+ }
54442
+ var LEGACY_PINNED_LAUNCHER_SCHEMA = "hasna-skills-pinned-launcher-v1", LAUNCH_CWD_VARIABLE2 = "HASNA_SKILLS_LAUNCH_CWD", PINNED_LAUNCHER_BUN_FLAGS, LEGACY_ENV_NAMES, LEGACY_ENV_PREFIXES, SERVER_LAUNCHER_ENV_NAMES, STORAGE_LOCATOR_ENV_NAMES, storageLocators, CLIENT_LAUNCHER_STORAGE_DENY_AWK = ` if (name == "DATABASE_URL" || name == "HASNA_SKILLS_DATABASE_URL" || name == "SKILLS_DATABASE_URL") continue`;
54443
+ var init_launcher_environment_policy = __esm(() => {
54444
+ PINNED_LAUNCHER_BUN_FLAGS = ["--config=/dev/null", "--no-env-file", "--no-macros", "--no-install"];
54445
+ LEGACY_ENV_NAMES = [
54446
+ "HOME",
54447
+ "PATH",
54448
+ "TMPDIR",
54449
+ "TERM",
54450
+ "TERM_PROGRAM",
54451
+ "TERM_PROGRAM_VERSION",
54452
+ "COLORTERM",
54453
+ "LANG",
54454
+ "USER",
54455
+ "LOGNAME",
54456
+ "SHELL",
54457
+ "TZ",
54458
+ "NO_COLOR",
54459
+ "FORCE_COLOR",
54460
+ "CI",
54461
+ "COLUMNS",
54462
+ "LINES",
54463
+ "EDITOR",
54464
+ "VISUAL",
54465
+ "PAGER",
54466
+ "SSH_AUTH_SOCK",
54467
+ "DATABASE_URL",
54468
+ "TERMINAL_CWD",
54469
+ "CODEX_HOME",
54470
+ "HERMES_HOME",
54471
+ "HERMES_ENABLE_PROJECT_PLUGINS",
54472
+ "HOST",
54473
+ "PORT",
54474
+ "NODE_ENV",
54475
+ "AGENT_ID",
54476
+ "ECS_CONTAINER_METADATA_URI_V4"
54477
+ ];
54478
+ LEGACY_ENV_PREFIXES = ["HASNA", "SKILLS", "SKILL", "MCP", "XDG", "LC", "AWS"];
54479
+ SERVER_LAUNCHER_ENV_NAMES = ["DATABASE_URL"];
54480
+ STORAGE_LOCATOR_ENV_NAMES = ["DATABASE_URL", "HASNA_SKILLS_DATABASE_URL", "SKILLS_DATABASE_URL"];
54481
+ storageLocators = new Set(STORAGE_LOCATOR_ENV_NAMES);
54482
+ });
54483
+
54293
54484
  // src/cli/commands/runtime-launcher.ts
54294
54485
  import { createHash as createHash19 } from "crypto";
54295
- import { closeSync as closeSync11, constants as constants12, fchmodSync, fstatSync as fstatSync11, fsyncSync as fsyncSync4, lstatSync as lstatSync20, openSync as openSync11, readFileSync as readFileSync15, readlinkSync as readlinkSync6, realpathSync as realpathSync9, symlinkSync, writeSync as writeSync2 } from "fs";
54296
- import { isAbsolute as isAbsolute16 } from "path";
54297
- function pinnedLauncherEnvironment(env3) {
54486
+ import { closeSync as closeSync11, constants as constants13, fchmodSync, fstatSync as fstatSync11, fsyncSync as fsyncSync4, lstatSync as lstatSync20, openSync as openSync11, readFileSync as readFileSync15, readlinkSync as readlinkSync6, realpathSync as realpathSync9, symlinkSync, writeSync as writeSync2 } from "fs";
54487
+ import { isAbsolute as isAbsolute17 } from "path";
54488
+ function pinnedLauncherEnvironment(env3, profile = "client") {
54489
+ assertLauncherProfile(profile);
54298
54490
  const result2 = {};
54299
- for (const [name, value] of Object.entries(env3)) {
54300
- if (value === undefined || !ENV_NAME.test(name) || !ENV_EXACT.has(name) && !ENV_PREFIX.test(name))
54491
+ for (const name of Object.keys(env3)) {
54492
+ if (!ENV_NAME.test(name))
54493
+ continue;
54494
+ const storageLocator = isStorageLocatorEnvironmentName(name);
54495
+ if (storageLocator && profile === "client")
54301
54496
  continue;
54302
- result2[name] = value;
54497
+ if (!storageLocator && !ENV_EXACT.has(name) && !ENV_PREFIX.test(name))
54498
+ continue;
54499
+ const value = env3[name];
54500
+ if (value !== undefined)
54501
+ result2[name] = value;
54303
54502
  }
54304
54503
  return result2;
54305
54504
  }
54505
+ function assertLauncherProfile(profile) {
54506
+ if (profile !== "client" && profile !== "server")
54507
+ throw new Error("LAUNCHER_PROFILE_INVALID");
54508
+ }
54509
+ function launcherProfileForBin(name, entry) {
54510
+ const bins = {
54511
+ skills: ["bin/index.js", "client"],
54512
+ "skills-mcp": ["bin/mcp.js", "client"],
54513
+ "skills-serve": ["bin/server.js", "server"],
54514
+ "skills-server": ["bin/server.js", "server"],
54515
+ "skills-worker": ["bin/worker.js", "server"],
54516
+ "skills-maintenance": ["bin/maintenance.js", "server"],
54517
+ "skills-migrate": ["bin/migrate.js", "server"]
54518
+ };
54519
+ const contract = bins[name];
54520
+ if (!contract || entry !== contract[0])
54521
+ throw new Error("LAUNCHER_BIN_CONTRACT_INVALID");
54522
+ return contract[1];
54523
+ }
54306
54524
  function sha2562(bytes) {
54307
54525
  return createHash19("sha256").update(bytes).digest("hex");
54308
54526
  }
54309
54527
  function assertLauncherPath(value, code) {
54310
- if (typeof value !== "string" || !isAbsolute16(value) || /['\x00-\x1f\x7f]/.test(value))
54528
+ if (typeof value !== "string" || !isAbsolute17(value) || /['\x00-\x1f\x7f]/.test(value))
54311
54529
  throw new Error(code);
54312
54530
  }
54313
54531
  function renderPinnedLauncher(binding) {
54314
54532
  assertLauncherPath(binding.runtime, "LAUNCHER_RUNTIME_PATH_INVALID");
54315
54533
  assertLauncherPath(binding.cwd, "LAUNCHER_CWD_PATH_INVALID");
54316
54534
  assertLauncherPath(binding.entry, "LAUNCHER_ENTRY_PATH_INVALID");
54317
- const names = PINNED_LAUNCHER_ENV_NAMES.join(" ");
54535
+ if (binding.format === "v1") {
54536
+ if (binding.profile !== undefined)
54537
+ throw new Error("LAUNCHER_PROFILE_INVALID");
54538
+ return renderLegacyPinnedLauncher(binding);
54539
+ }
54540
+ if (binding.format !== undefined && binding.format !== "v2")
54541
+ throw new Error("LAUNCHER_FORMAT_INVALID");
54542
+ const profile = binding.profile === undefined ? "client" : binding.profile;
54543
+ assertLauncherProfile(profile);
54544
+ const names = [...PINNED_LAUNCHER_ENV_NAMES, ...profile === "server" ? SERVER_LAUNCHER_ENV_NAMES : []].join(" ");
54318
54545
  const prefixes = PINNED_LAUNCHER_ENV_PREFIXES.join("|");
54319
54546
  return [
54320
54547
  "#!/bin/sh -p",
54321
54548
  `# ${PINNED_LAUNCHER_SCHEMA}`,
54549
+ `# environment-profile: ${profile}`,
54322
54550
  "# Written by `skills self-update`; rewrite it with `skills self-update`, do not edit by hand.",
54323
54551
  "# Runs the exact Skills entry below under one exact Bun from one trusted directory with",
54324
54552
  "# no working-directory configuration (no bunfig.toml, no .env, no macros, no auto-install)",
@@ -54326,15 +54554,16 @@ function renderPinnedLauncher(binding) {
54326
54554
  "# included, never reaches the runtime. The CLI returns to the caller's directory itself.",
54327
54555
  "# `-p` keeps the caller's exported functions and shell options out of this shell.",
54328
54556
  "set -eu",
54329
- `${LAUNCH_CWD_VARIABLE2}=$(pwd -P 2>/dev/null || :)`,
54330
- `export ${LAUNCH_CWD_VARIABLE2}`,
54331
- `set -- '${binding.runtime}' ${PINNED_LAUNCHER_BUN_FLAGS.join(" ")} '--cwd=${binding.cwd}' '${binding.entry}' "$@"`,
54557
+ `${LAUNCH_CWD_VARIABLE3}=$(pwd -P 2>/dev/null || :)`,
54558
+ `export ${LAUNCH_CWD_VARIABLE3}`,
54559
+ `set -- '${binding.runtime}' ${PINNED_LAUNCHER_BUN_FLAGS2.join(" ")} '--cwd=${binding.cwd}' '${binding.entry}' "$@"`,
54332
54560
  "hasna_skills_env=$(LC_ALL=C /usr/bin/awk 'BEGIN {",
54333
54561
  ` n = split("${names}", exact, " ")`,
54334
54562
  " for (i = 1; i <= n; i++) allow[exact[i]] = 1",
54335
54563
  " for (name in ENVIRON) {",
54336
54564
  " if (name !~ /^[A-Za-z_][A-Za-z0-9_]*$/) continue",
54337
54565
  ` if (name == "LC_ALL" || (!(name in allow) && name !~ /^(${prefixes})_/)) continue`,
54566
+ ...profile === "client" ? [CLIENT_LAUNCHER_STORAGE_DENY_AWK] : [],
54338
54567
  ' value = ENVIRON[name]; quoted = ""',
54339
54568
  ' while ((k = index(value, "\\047")) > 0) { quoted = quoted substr(value, 1, k - 1) "\\047\\\\\\047\\047"; value = substr(value, k + 1) }',
54340
54569
  ' printf "\\047%s=%s\\047 ", name, quoted value',
@@ -54351,7 +54580,19 @@ function parsePinnedLauncher(text2) {
54351
54580
  const match = COMMAND_LINE.exec(text2);
54352
54581
  if (!match)
54353
54582
  return null;
54354
- const binding = { runtime: match[1], cwd: match[2], entry: match[3] };
54583
+ let metadata;
54584
+ if (text2.split(`
54585
+ `)[1] === `# ${LEGACY_PINNED_LAUNCHER_SCHEMA}`)
54586
+ metadata = { format: "v1" };
54587
+ else if (text2.split(`
54588
+ `)[1] === `# ${PINNED_LAUNCHER_SCHEMA}`) {
54589
+ const profile = /^# environment-profile: (client|server)$/m.exec(text2)?.[1];
54590
+ if (!profile)
54591
+ return null;
54592
+ metadata = { format: "v2", profile };
54593
+ } else
54594
+ return null;
54595
+ const binding = { runtime: match[1], cwd: match[2], entry: match[3], ...metadata };
54355
54596
  try {
54356
54597
  if (renderPinnedLauncher(binding) !== text2)
54357
54598
  return null;
@@ -54398,7 +54639,7 @@ function inspectLauncher(path) {
54398
54639
  const binding = parsePinnedLauncher(text2);
54399
54640
  if (!binding)
54400
54641
  return { kind: "foreign" };
54401
- return { kind: "pinned", runtime: binding.runtime, cwd: binding.cwd, target: binding.entry, sha256: sha2562(text2), text: text2 };
54642
+ return { kind: "pinned", format: binding.format, profile: binding.profile, runtime: binding.runtime, cwd: binding.cwd, target: binding.entry, sha256: sha2562(text2), text: text2 };
54402
54643
  }
54403
54644
  function launcherTarget(path) {
54404
54645
  const inspected = inspectLauncher(path);
@@ -54415,17 +54656,22 @@ function launcherIs(path, state) {
54415
54656
  }
54416
54657
  if (state.shape === "symlink")
54417
54658
  return inspected.kind === "symlink" && inspected.linkTarget === state.linkTarget && inspected.target === state.target;
54418
- return inspected.kind === "pinned" && inspected.sha256 === state.sha256 && inspected.runtime === state.runtime && inspected.cwd === state.cwd && inspected.target === state.target;
54659
+ return inspected.kind === "pinned" && inspected.sha256 === state.sha256 && inspected.runtime === state.runtime && inspected.cwd === state.cwd && inspected.target === state.target && inspected.format === (state.format ?? "v1") && inspected.profile === state.profile;
54419
54660
  }
54420
54661
  function pinnedLauncherText(state) {
54421
- const text2 = renderPinnedLauncher({ runtime: state.runtime, cwd: state.cwd, entry: state.target });
54662
+ if (state.format === "v2")
54663
+ assertLauncherProfile(state.profile);
54664
+ const text2 = renderPinnedLauncher({ runtime: state.runtime, cwd: state.cwd, entry: state.target, format: state.format === undefined ? "v1" : state.format, profile: state.profile });
54422
54665
  if (sha2562(text2) !== state.sha256)
54423
54666
  throw new Error("LAUNCHER_TEXT_DIGEST_MISMATCH");
54424
54667
  return text2;
54425
54668
  }
54426
- function pinnedLauncherState(runtime, cwd2, target) {
54427
- const text2 = renderPinnedLauncher({ runtime, cwd: cwd2, entry: target });
54428
- return { shape: "pinned", runtime, cwd: cwd2, target, sha256: sha2562(text2) };
54669
+ function pinnedLauncherState(runtime, cwd2, target, metadata = { format: "v2", profile: "client" }) {
54670
+ const format = metadata.format === undefined ? "v1" : metadata.format, profile = metadata.profile;
54671
+ if (format === "v2")
54672
+ assertLauncherProfile(profile);
54673
+ const text2 = renderPinnedLauncher({ runtime, cwd: cwd2, entry: target, format, profile });
54674
+ return { shape: "pinned", runtime, cwd: cwd2, target, sha256: sha2562(text2), format, ...profile ? { profile } : {} };
54429
54675
  }
54430
54676
  function materializeLauncher(path, state) {
54431
54677
  if (state.shape === "symlink") {
@@ -54435,7 +54681,7 @@ function materializeLauncher(path, state) {
54435
54681
  return;
54436
54682
  }
54437
54683
  const text2 = pinnedLauncherText(state);
54438
- const fd = openSync11(path, constants12.O_WRONLY | constants12.O_CREAT | constants12.O_EXCL | constants12.O_NOFOLLOW, 493);
54684
+ const fd = openSync11(path, constants13.O_WRONLY | constants13.O_CREAT | constants13.O_EXCL | constants13.O_NOFOLLOW, 493);
54439
54685
  try {
54440
54686
  const bytes = Buffer.from(text2, "utf8");
54441
54687
  let written = 0;
@@ -54491,9 +54737,10 @@ function assertPinnedLauncherShell() {
54491
54737
  if (probe.exitCode !== 0)
54492
54738
  throw new Error("LAUNCHER_SHELL_UNSUPPORTED");
54493
54739
  }
54494
- var PINNED_LAUNCHER_SCHEMA = "hasna-skills-pinned-launcher-v1", LAUNCH_CWD_VARIABLE2 = "HASNA_SKILLS_LAUNCH_CWD", PINNED_LAUNCHER_BUN_FLAGS, PINNED_LAUNCHER_ENV_NAMES, PINNED_LAUNCHER_ENV_PREFIXES, ENV_NAME, ENV_PREFIX, ENV_EXACT, COMMAND_LINE, PINNED_LAUNCHER_MAX_BYTES;
54740
+ var PINNED_LAUNCHER_SCHEMA = "hasna-skills-pinned-launcher-v2", LAUNCH_CWD_VARIABLE3 = "HASNA_SKILLS_LAUNCH_CWD", PINNED_LAUNCHER_BUN_FLAGS2, PINNED_LAUNCHER_ENV_NAMES, PINNED_LAUNCHER_ENV_PREFIXES, ENV_NAME, ENV_PREFIX, ENV_EXACT, COMMAND_LINE, PINNED_LAUNCHER_MAX_BYTES;
54495
54741
  var init_runtime_launcher = __esm(() => {
54496
- PINNED_LAUNCHER_BUN_FLAGS = ["--config=/dev/null", "--no-env-file", "--no-macros", "--no-install"];
54742
+ init_launcher_environment_policy();
54743
+ PINNED_LAUNCHER_BUN_FLAGS2 = ["--config=/dev/null", "--no-env-file", "--no-macros", "--no-install"];
54497
54744
  PINNED_LAUNCHER_ENV_NAMES = [
54498
54745
  "HOME",
54499
54746
  "PATH",
@@ -54516,7 +54763,6 @@ var init_runtime_launcher = __esm(() => {
54516
54763
  "VISUAL",
54517
54764
  "PAGER",
54518
54765
  "SSH_AUTH_SOCK",
54519
- "DATABASE_URL",
54520
54766
  "TERMINAL_CWD",
54521
54767
  "CODEX_HOME",
54522
54768
  "HERMES_HOME",
@@ -54531,16 +54777,32 @@ var init_runtime_launcher = __esm(() => {
54531
54777
  ENV_NAME = /^[A-Za-z_][A-Za-z0-9_]*$/;
54532
54778
  ENV_PREFIX = new RegExp(`^(${PINNED_LAUNCHER_ENV_PREFIXES.join("|")})_`);
54533
54779
  ENV_EXACT = new Set(PINNED_LAUNCHER_ENV_NAMES);
54534
- COMMAND_LINE = new RegExp(`^set -- '([^']+)' ${PINNED_LAUNCHER_BUN_FLAGS.join(" ")} '--cwd=([^']+)' '([^']+)' "\\$@"$`, "m");
54780
+ COMMAND_LINE = new RegExp(`^set -- '([^']+)' ${PINNED_LAUNCHER_BUN_FLAGS2.join(" ")} '--cwd=([^']+)' '([^']+)' "\\$@"$`, "m");
54535
54781
  PINNED_LAUNCHER_MAX_BYTES = 16 * 1024;
54536
54782
  });
54537
54783
 
54538
54784
  // src/lib/agent-integration.ts
54539
54785
  import { createHash as createHash20, randomUUID as randomUUID6 } from "crypto";
54540
54786
  import { isDeepStrictEqual as isDeepStrictEqual7 } from "util";
54541
- import { existsSync as existsSync13, lstatSync as lstatSync21, statSync as statSync9, mkdirSync as mkdirSync6, readFileSync as readFileSync16, readdirSync as readdirSync8, opendirSync as opendirSync3, readlinkSync as readlinkSync7, realpathSync as realpathSync10, renameSync as renameSync3, rmdirSync as rmdirSync2, writeFileSync as writeFileSync6, unlinkSync as unlinkSync4, chmodSync, openSync as openSync12, closeSync as closeSync12, fsyncSync as fsyncSync5, fstatSync as fstatSync12, readSync as readSync9, constants as constants13, linkSync as linkSync2 } from "fs";
54542
- import { dirname as dirname16, join as join28, resolve as resolve17, relative as relative6, isAbsolute as isAbsolute17, sep as sep7 } from "path";
54787
+ import { existsSync as existsSync13, lstatSync as lstatSync21, statSync as statSync10, mkdirSync as mkdirSync6, readFileSync as readFileSync16, readdirSync as readdirSync8, opendirSync as opendirSync3, readlinkSync as readlinkSync7, realpathSync as realpathSync10, renameSync as renameSync3, rmdirSync as rmdirSync2, writeFileSync as writeFileSync6, unlinkSync as unlinkSync4, chmodSync, openSync as openSync12, closeSync as closeSync12, fsyncSync as fsyncSync5, fstatSync as fstatSync12, readSync as readSync9, constants as constants14, linkSync as linkSync2 } from "fs";
54788
+ import { dirname as dirname16, join as join28, resolve as resolve17, relative as relative6, isAbsolute as isAbsolute18, sep as sep7 } from "path";
54543
54789
  import { homedir as homedir3 } from "os";
54790
+ function nativeAgentRoot(home, agent, cwd2 = process.cwd()) {
54791
+ if (agent === "sumi")
54792
+ return sumiBridgeRoot(home, cwd2);
54793
+ const root = AGENT_ADAPTERS[agent].root;
54794
+ if (typeof root !== "string")
54795
+ throw new Error(`Native skill root is unavailable for ${agent}`);
54796
+ return join28(home, root);
54797
+ }
54798
+ function nativeAgentConfig(home, agent, cwd2 = process.cwd()) {
54799
+ if (agent === "sumi")
54800
+ return sumiConfigPath(home, cwd2);
54801
+ const config = AGENT_ADAPTERS[agent].config;
54802
+ if (typeof config !== "string")
54803
+ throw new Error(`Native configuration path is unavailable for ${agent}`);
54804
+ return join28(home, config);
54805
+ }
54544
54806
  function hasTrustedDarwinAcl(fd, allowDenyOnly = false) {
54545
54807
  try {
54546
54808
  const { dlopen, read: read2, ptr } = __require("bun:ffi");
@@ -54603,7 +54865,7 @@ function isSystemRootAlias(path) {
54603
54865
  throw new Error("Writable system alias directory");
54604
54866
  } else if ((stat.mode & 0o1000n) === 0n)
54605
54867
  throw new Error("Unprotected system temporary directory");
54606
- const fd = openSync12(directory, constants13.O_RDONLY | constants13.O_DIRECTORY | constants13.O_NOFOLLOW);
54868
+ const fd = openSync12(directory, constants14.O_RDONLY | constants14.O_DIRECTORY | constants14.O_NOFOLLOW);
54607
54869
  try {
54608
54870
  if (directoryIdentity(fstatSync12(fd, { bigint: true })) !== directoryIdentity(stat) || !hasTrustedDarwinAcl(fd) || directoryIdentity(fstatSync12(fd, { bigint: true })) !== directoryIdentity(stat))
54609
54871
  throw new Error("Unverified system alias directory ACL");
@@ -54648,7 +54910,7 @@ function readRootAlias(home, agent) {
54648
54910
  if (!targetStat?.isDirectory())
54649
54911
  throw new Error(`Agent root alias must target an existing directory: ${alias}`);
54650
54912
  const target = realpathSync10(targetPath), inside = relative6(realHome, target);
54651
- if (!inside || inside === ".." || inside.startsWith(`..${sep7}`) || isAbsolute17(inside))
54913
+ if (!inside || inside === ".." || inside.startsWith(`..${sep7}`) || isAbsolute18(inside))
54652
54914
  throw new Error(`Agent root alias target must be inside the real home: ${alias}`);
54653
54915
  return { agent, home: realHome, alias, target, link: link2, aliasIdentity: `${stat.dev}:${stat.ino}:${stat.ctimeNs}`, targetIdentity: `${targetStat.dev}:${targetStat.ino}` };
54654
54916
  }
@@ -54674,13 +54936,13 @@ function disabledCodexSkillPaths(config, aliases) {
54674
54936
  const rows = skills.config;
54675
54937
  if (!Array.isArray(rows))
54676
54938
  return [];
54677
- if (rows.some((entry) => !entry || typeof entry !== "object" || Array.isArray(entry) || typeof entry.enabled !== "boolean" || entry.path !== undefined === (entry.name !== undefined) || entry.path !== undefined && (typeof entry.path !== "string" || !isAbsolute17(entry.path)) || entry.name !== undefined && (typeof entry.name !== "string" || !entry.name.trim())))
54939
+ if (rows.some((entry) => !entry || typeof entry !== "object" || Array.isArray(entry) || typeof entry.enabled !== "boolean" || entry.path !== undefined === (entry.name !== undefined) || entry.path !== undefined && (typeof entry.path !== "string" || !isAbsolute18(entry.path)) || entry.name !== undefined && (typeof entry.name !== "string" || !entry.name.trim())))
54678
54940
  return [];
54679
54941
  if (rows.some((entry) => entry.name !== undefined && entry.enabled !== false))
54680
54942
  return [];
54681
54943
  const settings = new Map;
54682
54944
  for (const entry of rows) {
54683
- if (typeof entry.path !== "string" || !isAbsolute17(entry.path))
54945
+ if (typeof entry.path !== "string" || !isAbsolute18(entry.path))
54684
54946
  continue;
54685
54947
  let document3;
54686
54948
  try {
@@ -54712,7 +54974,7 @@ function readNativeBytes(path, maximum = 64 * 1024 * 1024) {
54712
54974
  const before2 = lstatSync21(path);
54713
54975
  if (!before2.isFile() || before2.size > maximum)
54714
54976
  throw new Error("Unsupported or oversized native skill file");
54715
- const descriptor = openSync12(path, constants13.O_RDONLY | constants13.O_NOFOLLOW | constants13.O_NONBLOCK);
54977
+ const descriptor = openSync12(path, constants14.O_RDONLY | constants14.O_NOFOLLOW | constants14.O_NONBLOCK);
54716
54978
  try {
54717
54979
  const opened = fstatSync12(descriptor);
54718
54980
  if (!opened.isFile() || opened.dev !== before2.dev || opened.ino !== before2.ino || opened.size !== before2.size)
@@ -54785,16 +55047,16 @@ function parseNativeMigrationTargetManifest(input) {
54785
55047
  throw new Error("Invalid native migration target fields");
54786
55048
  if (!ROOTS.some(([agent]) => agent === item.agent))
54787
55049
  throw new Error(`Unsupported native migration target agent: ${item.agent}`);
54788
- if (!isAbsolute17(item.projectRoot) || resolve17(item.projectRoot) !== item.projectRoot)
55050
+ if (!isAbsolute18(item.projectRoot) || resolve17(item.projectRoot) !== item.projectRoot)
54789
55051
  throw new Error(`Native migration target project root must be an existing absolute directory: ${item.projectRoot}`);
54790
55052
  const projectRoot = canonicalSystemPath(item.projectRoot);
54791
55053
  if (!existsSync13(projectRoot) || !lstatSync21(projectRoot).isDirectory())
54792
55054
  throw new Error(`Native migration target project root must be an existing absolute directory: ${item.projectRoot}`);
54793
55055
  assertSafePath(projectRoot);
54794
- if (isAbsolute17(item.path) || item.path.includes("\\") || item.path.length === 0 || item.path.includes("\x00"))
55056
+ if (isAbsolute18(item.path) || item.path.includes("\\") || item.path.length === 0 || item.path.includes("\x00"))
54795
55057
  throw new Error(`Native migration target path must be normalized and project-relative: ${item.path}`);
54796
55058
  const resolved = resolve17(projectRoot, item.path), normalized = relative6(projectRoot, resolved);
54797
- if (!normalized || normalized === ".." || normalized.startsWith(`..${sep7}`) || isAbsolute17(normalized) || normalized !== item.path)
55059
+ if (!normalized || normalized === ".." || normalized.startsWith(`..${sep7}`) || isAbsolute18(normalized) || normalized !== item.path)
54798
55060
  throw new Error(`Native migration target path escapes or is not normalized: ${item.path}`);
54799
55061
  if (!/^[0-9a-f]{64}$/.test(item.treeSha256))
54800
55062
  throw new Error(`Invalid native migration tree digest for ${item.path}`);
@@ -54815,13 +55077,13 @@ function selectNativeMigrationTargets(inventory, manifest) {
54815
55077
  const identities = new Set;
54816
55078
  const selected = [];
54817
55079
  for (const target of manifest.targets) {
54818
- if (!isAbsolute17(target.projectRoot) || resolve17(target.projectRoot) !== target.projectRoot)
55080
+ if (!isAbsolute18(target.projectRoot) || resolve17(target.projectRoot) !== target.projectRoot)
54819
55081
  throw new Error(`Native migration target project root must be an existing absolute directory: ${target.projectRoot}`);
54820
55082
  const projectRoot = canonicalSystemPath(target.projectRoot), normalized = relative6(projectRoot, resolve17(projectRoot, target.path));
54821
55083
  if (!existsSync13(projectRoot) || !lstatSync21(projectRoot).isDirectory())
54822
55084
  throw new Error(`Native migration target project root must be an existing absolute directory: ${target.projectRoot}`);
54823
55085
  assertSafePath(projectRoot);
54824
- if (isAbsolute17(target.path) || target.path.includes("\\") || target.path.includes("\x00") || !normalized || normalized === ".." || normalized.startsWith(`..${sep7}`) || normalized !== target.path || !/^[0-9a-f]{64}$/.test(target.treeSha256))
55086
+ if (isAbsolute18(target.path) || target.path.includes("\\") || target.path.includes("\x00") || !normalized || normalized === ".." || normalized.startsWith(`..${sep7}`) || normalized !== target.path || !/^[0-9a-f]{64}$/.test(target.treeSha256))
54825
55087
  throw new Error(`Invalid native migration target: ${target.path}`);
54826
55088
  const identity6 = `${target.agent}\x00${canonicalSystemPath(projectRoot)}\x00${normalized}`;
54827
55089
  if (identities.has(identity6))
@@ -54864,25 +55126,32 @@ function isCodexSkillDiscoveryInput(path) {
54864
55126
  }
54865
55127
  function inventoryNativeSkills(home = homedir3(), options = {}) {
54866
55128
  home = canonicalSystemPath(home);
54867
- if (options.reviewedCacheAlias !== undefined && (!options.includeVendor || !isAbsolute17(options.reviewedCacheAlias) || resolve17(options.reviewedCacheAlias) !== options.reviewedCacheAlias))
55129
+ if (options.reviewedCacheAlias !== undefined && (!options.includeVendor || !isAbsolute18(options.reviewedCacheAlias) || resolve17(options.reviewedCacheAlias) !== options.reviewedCacheAlias))
54868
55130
  throw new Error("A reviewed cache alias requires vendor inventory and an exact absolute path");
54869
- if (options.disabledVendorPaths?.some((path) => !isAbsolute17(path) || resolve17(path) !== path))
55131
+ if (options.disabledVendorPaths?.some((path) => !isAbsolute18(path) || resolve17(path) !== path))
54870
55132
  throw new Error("Disabled vendor paths must be exact absolute paths");
54871
55133
  const reviewedCacheAlias = options.reviewedCacheAlias === undefined ? undefined : canonicalSystemPath(options.reviewedCacheAlias);
54872
55134
  const disabledVendorPaths = new Set((options.disabledVendorPaths ?? []).map(canonicalSystemPath));
54873
55135
  const aliases = rootAliases(home, options.allowRootAliases);
54874
55136
  const selectedAgents = options.agents ? new Set(options.agents) : undefined;
54875
55137
  const includesAgent = (agent) => !selectedAgents || selectedAgents.has(agent);
54876
- const rootDefinitions = selectedAgents ? ROOTS.filter(([agent, path]) => selectedAgents.has(agent) || selectedAgents.has("hermes") && agent === "codex" && path === ".agents/skills") : ROOTS;
55138
+ const rootDefinitions = selectedAgents ? ROOTS.filter(([agent, path]) => agent !== "sumi" && selectedAgents.has(agent) || selectedAgents.has("hermes") && agent === "codex" && path === ".agents/skills") : ROOTS.filter(([agent]) => agent !== "sumi");
54877
55139
  const roots = rootDefinitions.map(([agent, path]) => [agent, canonicalAgentPath(join28(home, path), aliases)]);
54878
- const bridgePaths = Object.entries(AGENT_ADAPTERS).filter(([agent]) => agent !== "sumi" || includesAgent("sumi")).map(([agent, adapter]) => canonicalAgentPath(join28(agent === "sumi" ? sumiBridgeRoot(home) : join28(home, adapter.root), CLI_BRIDGE_NAME), aliases));
55140
+ const includesSumi = !selectedAgents || selectedAgents.has("sumi");
55141
+ if (includesSumi)
55142
+ for (const path of sumiSkillRoots(home))
55143
+ roots.push(["sumi", canonicalAgentPath(path, aliases)]);
55144
+ const bridgePaths = Object.entries(AGENT_ADAPTERS).filter(([agent]) => agent !== "sumi" || includesSumi).map(([agent]) => canonicalAgentPath(join28(nativeAgentRoot(home, agent), CLI_BRIDGE_NAME), aliases));
54879
55145
  for (const project of projectAncestorDirectories([...options.projectDirs ?? [], ...options.projectDir ? [options.projectDir] : []])) {
54880
55146
  for (const [agent, path] of rootDefinitions)
54881
55147
  roots.push([agent, canonicalAgentPath(join28(project, path), aliases)]);
54882
- if (selectedAgents?.has("sumi"))
55148
+ if (selectedAgents?.has("sumi")) {
55149
+ for (const path of sumiSkillRoots(home, project))
55150
+ roots.push(["sumi", canonicalAgentPath(path, aliases)]);
54883
55151
  for (const directory of [".claude", ".agents"])
54884
55152
  for (const name of ["skill", "skills"])
54885
55153
  roots.push(["sumi", canonicalAgentPath(join28(project, directory, name), aliases)]);
55154
+ }
54886
55155
  }
54887
55156
  const installationInputs = options.codexInstallationInputRoots ?? [];
54888
55157
  if (installationInputs.some((input) => resolve17(input) !== input || realpathSync10(input) !== input || roots.some(([agent, path]) => agent === "codex" && (path === input || path.startsWith(input + sep7) || input.startsWith(path + sep7)))))
@@ -54900,7 +55169,7 @@ function inventoryNativeSkills(home = homedir3(), options = {}) {
54900
55169
  let reviewedCacheAliasFound = false;
54901
55170
  function verifiedSiblingCacheAlias(agent, path, parent) {
54902
55171
  const link2 = readlinkSync7(path), lexicalTarget = resolve17(parent, link2);
54903
- if (isAbsolute17(link2) ? link2 !== lexicalTarget : dirname16(link2) !== ".")
55172
+ if (isAbsolute18(link2) ? link2 !== lexicalTarget : dirname16(link2) !== ".")
54904
55173
  return false;
54905
55174
  const target = canonicalSystemPath(lexicalTarget);
54906
55175
  if (dirname16(target) !== parent)
@@ -54980,7 +55249,7 @@ function inventoryNativeSkills(home = homedir3(), options = {}) {
54980
55249
  continue;
54981
55250
  const child2 = join28(path, name);
54982
55251
  if (isVendor && lstatSync21(child2, { throwIfNoEntry: false })?.isSymbolicLink()) {
54983
- const target = statSync9(child2, { throwIfNoEntry: false });
55252
+ const target = statSync10(child2, { throwIfNoEntry: false });
54984
55253
  if (target?.isFile() || pluginCache && target?.isDirectory() && verifiedSiblingCacheAlias(agent, child2, path)) {
54985
55254
  scan.entries++;
54986
55255
  continue;
@@ -55244,8 +55513,7 @@ function planAgentIntegration(options) {
55244
55513
  if (!INTEGRATION_AGENTS.includes(agent))
55245
55514
  throw new Error(`Unsupported agent: ${agent}`);
55246
55515
  const { command, profileId: profileId2 } = bindings.get(agent);
55247
- const adapter = AGENT_ADAPTERS[agent];
55248
- const bridgePath = canonicalAgentPath(join28(agent === "sumi" ? sumiBridgeRoot(home) : join28(home, adapter.root), CLI_BRIDGE_NAME), aliases);
55516
+ const bridgePath = canonicalAgentPath(join28(nativeAgentRoot(home, agent, options.projectDir ?? process.cwd()), CLI_BRIDGE_NAME), aliases);
55249
55517
  assertSafePath(bridgePath);
55250
55518
  if (existsSync13(bridgePath) && !isOwnedCliBridge(bridgePath, [bridgePath]))
55251
55519
  throw new Error(`Refusing to overwrite an unrecognized or modified Skills bridge: ${bridgePath}`);
@@ -55254,7 +55522,7 @@ function planAgentIntegration(options) {
55254
55522
  if (before3 !== after3)
55255
55523
  changes.push({ path: path2, before: before3, after: after3 });
55256
55524
  }
55257
- const path = canonicalAgentPath(agent === "sumi" ? sumiConfigPath(home) : join28(home, adapter.config), aliases);
55525
+ const path = canonicalAgentPath(nativeAgentConfig(home, agent, options.projectDir ?? process.cwd()), aliases);
55258
55526
  const before2 = readOptional(path);
55259
55527
  if (agent === "hermes") {
55260
55528
  const supervisorPath = join28(dataDir3, "agent-hooks", "hermes.js"), supervisorBefore = readOptional(supervisorPath), supervisorAfter = renderHermesSupervisor(command, profileId2);
@@ -55279,7 +55547,7 @@ function planAgentIntegration(options) {
55279
55547
  if (config.permissions !== undefined && (!Array.isArray(config.permissions) || config.permissions.some((rule) => !rule || typeof rule.action !== "string" || typeof rule.resource !== "string" || !["allow", "deny", "ask"].includes(rule.effect))))
55280
55548
  throw new Error("Expected Sumi native permission rules");
55281
55549
  config.permissions = [...(config.permissions ?? []).filter((rule) => rule.action !== "skill"), ...SUMI_SKILL_PERMISSIONS];
55282
- const pluginPath = join28(sumiConfigDirectory(home), "plugins", "skills-cli.js"), pluginBefore = readOptional(pluginPath);
55550
+ const pluginPath = join28(sumiConfigDirectory(home, process.env, options.projectDir ?? process.cwd()), "plugins", "skills-cli.js"), pluginBefore = readOptional(pluginPath);
55283
55551
  const pluginAfter = renderSumiPlugin(command, profileId2);
55284
55552
  const priorCommand = policy.bridge?.commands?.sumi, priorProfile = policy.bridge?.profiles?.sumi ?? policy.profileId;
55285
55553
  if (pluginBefore !== null && pluginBefore !== pluginAfter && !(typeof priorCommand === "string" && typeof priorProfile === "string" && isManagedSumiPlugin(pluginBefore, priorCommand, priorProfile)))
@@ -55370,7 +55638,7 @@ function projectedHookAcl(path, observed) {
55370
55638
  if (process.platform !== "darwin")
55371
55639
  return;
55372
55640
  const identity6 = observed.isDirectory() ? (stat) => `${stat.dev}:${stat.ino}:${stat.uid}:${stat.mode}` : (stat) => `${stat.dev}:${stat.ino}:${stat.ctimeNs}:${stat.uid}:${stat.mode}:${stat.nlink}:${stat.size}:${stat.mtimeNs}`;
55373
- const fd = openSync12(path, constants13.O_RDONLY | constants13.O_NOFOLLOW | constants13.O_NONBLOCK | (observed.isDirectory() ? constants13.O_DIRECTORY : 0));
55641
+ const fd = openSync12(path, constants14.O_RDONLY | constants14.O_NOFOLLOW | constants14.O_NONBLOCK | (observed.isDirectory() ? constants14.O_DIRECTORY : 0));
55374
55642
  try {
55375
55643
  if (identity6(fstatSync12(fd, { bigint: true })) !== identity6(observed) || !hasTrustedDarwinAcl(fd, true) || identity6(fstatSync12(fd, { bigint: true })) !== identity6(observed) || identity6(lstatSync21(path, { bigint: true })) !== identity6(observed))
55376
55644
  hookProjectionRefusal("EXECUTABLE_UNVERIFIED");
@@ -55380,7 +55648,7 @@ function projectedHookAcl(path, observed) {
55380
55648
  }
55381
55649
  function projectedHookExecutable(command, expectedResolved) {
55382
55650
  try {
55383
- if (!isAbsolute17(command) || /[\0\r\n]/.test(command) || resolve17(command) !== command)
55651
+ if (!isAbsolute18(command) || /[\0\r\n]/.test(command) || resolve17(command) !== command)
55384
55652
  hookProjectionRefusal("EXECUTABLE_UNVERIFIED");
55385
55653
  command = canonicalSystemPath(command);
55386
55654
  const parents2 = (file = command) => {
@@ -55600,7 +55868,7 @@ function planAgentSettingsWitnessUpgrade(options) {
55600
55868
  const binding = policy.bridge?.discovery?.[options.agent];
55601
55869
  if (!binding || binding.agent !== options.agent || binding.method !== "reviewed")
55602
55870
  throw new Error("Settings witness upgrade requires an existing reviewed native binding");
55603
- const configPath = canonicalAgentPath(options.agent === "sumi" ? sumiConfigPath(home) : join28(home, options.agent === "claude" ? ".claude/settings.json" : ".codex/config.toml"), aliases);
55871
+ const configPath = canonicalAgentPath(options.agent === "sumi" ? nativeAgentConfig(home, "sumi", options.projectDir ?? process.cwd()) : join28(home, options.agent === "claude" ? ".claude/settings.json" : ".codex/config.toml"), aliases);
55604
55872
  const settings = readOptional(configPath);
55605
55873
  if (settings === null || sha3(settings) !== options.expectedSettingsSha256)
55606
55874
  throw new Error("Native settings preimage changed");
@@ -55778,7 +56046,7 @@ function applyAgentIntegrationUnlocked(plan, options = {}, assertCurrent) {
55778
56046
  }
55779
56047
  function syncArchiveDirectory(path) {
55780
56048
  assertSafePath(path);
55781
- const descriptor = openSync12(path, constants13.O_RDONLY | constants13.O_DIRECTORY | constants13.O_NOFOLLOW | constants13.O_NONBLOCK);
56049
+ const descriptor = openSync12(path, constants14.O_RDONLY | constants14.O_DIRECTORY | constants14.O_NOFOLLOW | constants14.O_NONBLOCK);
55782
56050
  try {
55783
56051
  fsyncSync5(descriptor);
55784
56052
  } finally {
@@ -55790,7 +56058,7 @@ function writeArchiveJournal(path, value) {
55790
56058
  const temporary = `${path}.skills-${randomUUID6()}`;
55791
56059
  let descriptor;
55792
56060
  try {
55793
- descriptor = openSync12(temporary, constants13.O_WRONLY | constants13.O_CREAT | constants13.O_EXCL | constants13.O_NOFOLLOW, 384);
56061
+ descriptor = openSync12(temporary, constants14.O_WRONLY | constants14.O_CREAT | constants14.O_EXCL | constants14.O_NOFOLLOW, 384);
55794
56062
  writeFileSync6(descriptor, `${JSON.stringify(value)}
55795
56063
  `);
55796
56064
  fsyncSync5(descriptor);
@@ -55824,7 +56092,7 @@ function archiveNativeSkillsUnlocked(inventory, options, assertCurrent) {
55824
56092
  recheckRootAliases(aliases);
55825
56093
  for (const entry of inventory.filter((entry2) => entry2.bridge)) {
55826
56094
  const adapter = AGENT_ADAPTERS[entry.agent];
55827
- const expected = adapter && entry.bridgeHome ? canonicalAgentPath(join28(entry.agent === "sumi" ? sumiBridgeRoot(entry.bridgeHome) : join28(entry.bridgeHome, adapter.root), CLI_BRIDGE_NAME), aliases) : undefined;
56095
+ const expected = adapter && entry.bridgeHome ? canonicalAgentPath(join28(nativeAgentRoot(entry.bridgeHome, entry.agent), CLI_BRIDGE_NAME), aliases) : undefined;
55828
56096
  if (!expected || treeHash(entry.path) !== entry.hash || !isOwnedCliBridge(entry.path, [expected]))
55829
56097
  throw new Error(`Skills bridge changed after planning: ${entry.path}`);
55830
56098
  }
@@ -55948,7 +56216,7 @@ function isInertCodexPluginCacheCopy(entry, cache3, allowedHostPaths, read2) {
55948
56216
  return false;
55949
56217
  const document3 = join28(entry.path, "SKILL.md");
55950
56218
  const inside = relative6(cache3, entry.path);
55951
- if (!inside || isAbsolute17(inside) || inside.split(sep7).some((segment) => segment === ".."))
56219
+ if (!inside || isAbsolute18(inside) || inside.split(sep7).some((segment) => segment === ".."))
55952
56220
  return false;
55953
56221
  assertSafePath(entry.path);
55954
56222
  if (!lstatSync21(cache3).isDirectory() || !lstatSync21(entry.path).isDirectory() || !lstatSync21(document3).isFile())
@@ -55980,14 +56248,14 @@ function assertManagedAgentBridgeWithDiscovery(agent, options = {}, provenDiscov
55980
56248
  if (!Array.isArray(aliases))
55981
56249
  throw new Error("NATIVE_SKILL_DRIFT: invalid root alias binding");
55982
56250
  recheckRootAliases(aliases);
55983
- const expected = canonicalAgentPath(join28(agent === "sumi" ? sumiBridgeRoot(home) : join28(home, AGENT_ADAPTERS[agent].root), CLI_BRIDGE_NAME), aliases);
56251
+ const expected = canonicalAgentPath(join28(nativeAgentRoot(home, agent, options.projectDir ?? process.cwd()), CLI_BRIDGE_NAME), aliases);
55984
56252
  if (!isOwnedCliBridge(expected, [expected]))
55985
56253
  throw new Error("NATIVE_SKILL_DRIFT: the native Skills bridge is missing or modified; repair it before continuing");
55986
56254
  const roots = projectAncestorDirectories([options.projectDir ?? process.cwd(), ...options.projectDirs ?? [], ...agent === "hermes" && process.env.TERMINAL_CWD ? [process.cwd()] : []]);
55987
56255
  const visible = (entry) => entry.agent === agent || ["codex", "gemini", "opencode", "hermes", "sumi"].includes(agent) && entry.path.includes(`${sep7}.agents${sep7}skills${sep7}`) || ["opencode", "sumi"].includes(agent) && entry.agent === "claude";
55988
56256
  const discovery = provenDiscovery ?? binding.discovery?.[agent];
55989
56257
  assertProjectDiscovery(agent, [...roots], home, (path) => canonicalAgentPath(path, aliases), discovery);
55990
- const configPath = canonicalAgentPath(agent === "sumi" ? sumiConfigPath(home) : join28(home, AGENT_ADAPTERS[agent].config), aliases), config = agent === "hermes" ? parseHermesConfig(readOptional(configPath)) : jsonObject(readOptional(configPath), configPath);
56258
+ const configPath = canonicalAgentPath(nativeAgentConfig(home, agent, options.projectDir ?? process.cwd()), aliases), config = agent === "hermes" ? parseHermesConfig(readOptional(configPath)) : jsonObject(readOptional(configPath), configPath);
55991
56259
  const command = binding.commands?.[agent], profile = binding.profiles?.[agent];
55992
56260
  if (typeof command !== "string" || typeof profile !== "string")
55993
56261
  throw new Error("NATIVE_SKILL_DRIFT: the native hook command/profile binding is missing");
@@ -55999,7 +56267,7 @@ function assertManagedAgentBridgeWithDiscovery(agent, options = {}, provenDiscov
55999
56267
  throw new Error("NATIVE_SKILL_DRIFT: Hermes supervisor binding changed; run skills hook install");
56000
56268
  assertHermesProtection(home, config, command, profile, supervisor);
56001
56269
  } else if (agent === "sumi") {
56002
- if (JSON.stringify(config.permissions?.filter((rule) => rule.action === "skill")) !== JSON.stringify(SUMI_SKILL_PERMISSIONS) || !isManagedSumiPlugin(readOptional(join28(sumiConfigDirectory(home), "plugins", "skills-cli.js")), command, profile))
56270
+ if (JSON.stringify(config.permissions?.filter((rule) => rule.action === "skill")) !== JSON.stringify(SUMI_SKILL_PERMISSIONS) || !isManagedSumiPlugin(readOptional(join28(sumiConfigDirectory(home, process.env, options.projectDir ?? process.cwd()), "plugins", "skills-cli.js")), command, profile))
56003
56271
  throw new Error("NATIVE_SKILL_DRIFT: Sumi bridge protection changed; run skills hook install");
56004
56272
  } else if (agent === "opencode") {
56005
56273
  if (JSON.stringify(config.permission?.skill) !== JSON.stringify({ "*": "deny", [CLI_BRIDGE_NAME]: "allow" }) || readOptional(join28(home, ".config", "opencode", "plugins", "skills-cli.js")) !== renderOpenCodePlugin(command, profile))
@@ -56105,7 +56373,7 @@ function assertManagedAgentBridgeWithDiscovery(agent, options = {}, provenDiscov
56105
56373
  return escaped.length > 768 ? `${escaped.slice(0, 384)}...${escaped.slice(-381)}` : escaped;
56106
56374
  });
56107
56375
  const remaining = unexpected.length - paths.length;
56108
- throw new Error(`NATIVE_SKILL_DRIFT: ${unexpected.length} unexpected native skill copies were found: ${paths.join(", ")}${remaining ? `; ${remaining} more` : ""}. Review skills migrate native --project <working-directory> --include-unmanaged --include-vendor --json before continuing; it inventories that directory and its ancestors. Use --apply after reviewing the archive plan.${adapterRefusal ? ` Native policy adapter refused: ${adapterRefusal}` : ""}`);
56376
+ throw new Error(`NATIVE_SKILL_DRIFT: ${unexpected.length} unexpected native skill copies were found: ${paths.join(", ")}${remaining ? `; ${remaining} more` : ""}. Review skills migrate native --agent ${agent} --project <working-directory> --include-unmanaged --include-vendor --json before continuing; it inventories that directory and its ancestors. Use --apply after reviewing the archive plan.${adapterRefusal ? ` Native policy adapter refused: ${adapterRefusal}` : ""}`);
56109
56377
  }
56110
56378
  recheckRootAliases(aliases);
56111
56379
  }
@@ -56170,7 +56438,7 @@ var init_agent_integration = __esm(() => {
56170
56438
  });
56171
56439
 
56172
56440
  // src/lib/home-migration.ts
56173
- import { existsSync as existsSync14, mkdirSync as mkdirSync7, readdirSync as readdirSync9, renameSync as renameSync4, rmSync, statSync as statSync10, writeFileSync as writeFileSync7 } from "fs";
56441
+ import { existsSync as existsSync14, mkdirSync as mkdirSync7, readdirSync as readdirSync9, renameSync as renameSync4, rmSync, statSync as statSync11, writeFileSync as writeFileSync7 } from "fs";
56174
56442
  import { join as join29 } from "path";
56175
56443
  function layoutMigrationRecordPath(appDir) {
56176
56444
  return join29(appDir, SKILLS_CACHE_DIRNAME, LAYOUT_MIGRATION_RECORD);
@@ -56183,7 +56451,7 @@ function migrationAppDir(homeDir2) {
56183
56451
  }
56184
56452
  function looksLikeSkillDirectory(path) {
56185
56453
  try {
56186
- if (!statSync10(path).isDirectory())
56454
+ if (!statSync11(path).isDirectory())
56187
56455
  return false;
56188
56456
  } catch {
56189
56457
  return false;
@@ -56315,7 +56583,7 @@ import {
56315
56583
  readdirSync as readdirSync10,
56316
56584
  renameSync as renameSync5,
56317
56585
  rmSync as rmSync2,
56318
- statSync as statSync11,
56586
+ statSync as statSync12,
56319
56587
  writeFileSync as writeFileSync8
56320
56588
  } from "fs";
56321
56589
  import { homedir as homedir4 } from "os";
@@ -56432,7 +56700,7 @@ function containsSkillDirectories(path) {
56432
56700
  }
56433
56701
  function isDirectory(path) {
56434
56702
  try {
56435
- return statSync11(path).isDirectory();
56703
+ return statSync12(path).isDirectory();
56436
56704
  } catch {
56437
56705
  return false;
56438
56706
  }
@@ -57962,8 +58230,8 @@ var init_plugin_projection = __esm(() => {
57962
58230
 
57963
58231
  // src/lib/plugin-projection-store.ts
57964
58232
  import { createHash as createHash22, randomUUID as randomUUID7 } from "crypto";
57965
- import { constants as constants14, closeSync as closeSync13, fchmodSync as fchmodSync2, fstatSync as fstatSync13, fsyncSync as fsyncSync6, linkSync as linkSync3, lstatSync as lstatSync23, mkdirSync as mkdirSync10, openSync as openSync13, opendirSync as opendirSync4, readSync as readSync10, renameSync as renameSync6, rmdirSync as rmdirSync3, rmSync as rmSync4, unlinkSync as unlinkSync5, writeSync as writeSync3 } from "fs";
57966
- import { dirname as dirname18, isAbsolute as isAbsolute18, join as join34, parse as parse6, resolve as resolve18 } from "path";
58233
+ import { constants as constants15, closeSync as closeSync13, fchmodSync as fchmodSync2, fstatSync as fstatSync13, fsyncSync as fsyncSync6, linkSync as linkSync3, lstatSync as lstatSync23, mkdirSync as mkdirSync10, openSync as openSync13, opendirSync as opendirSync4, readSync as readSync10, renameSync as renameSync6, rmdirSync as rmdirSync3, rmSync as rmSync4, unlinkSync as unlinkSync5, writeSync as writeSync3 } from "fs";
58234
+ import { dirname as dirname18, isAbsolute as isAbsolute19, join as join34, parse as parse6, resolve as resolve18 } from "path";
57967
58235
  function stat(path) {
57968
58236
  try {
57969
58237
  return lstatSync23(path, { bigint: true });
@@ -57974,7 +58242,7 @@ function stat(path) {
57974
58242
  }
57975
58243
  }
57976
58244
  function canonical7(path) {
57977
- pluginNeed(typeof path === "string" && path.length <= 8192 && isAbsolute18(path) && resolve18(path) === path && !/[\x00-\x1f\x7f]/.test(path), "Plugin storage paths must be canonical absolute paths");
58245
+ pluginNeed(typeof path === "string" && path.length <= 8192 && isAbsolute19(path) && resolve18(path) === path && !/[\x00-\x1f\x7f]/.test(path), "Plugin storage paths must be canonical absolute paths");
57978
58246
  }
57979
58247
  function owner(stats, system = false) {
57980
58248
  const current = uid();
@@ -58324,8 +58592,8 @@ function pluginExecutableDigest(path) {
58324
58592
  var READ_FLAGS, WRITE_FLAGS, uid = () => typeof process.getuid === "function" ? BigInt(process.getuid()) : undefined, missing = (error) => Boolean(error && typeof error === "object" && "code" in error && error.code === "ENOENT");
58325
58593
  var init_plugin_projection_store = __esm(() => {
58326
58594
  init_plugin_projection();
58327
- READ_FLAGS = constants14.O_RDONLY | constants14.O_NOFOLLOW | constants14.O_NONBLOCK;
58328
- WRITE_FLAGS = constants14.O_WRONLY | constants14.O_CREAT | constants14.O_EXCL | constants14.O_NOFOLLOW | constants14.O_NONBLOCK;
58595
+ READ_FLAGS = constants15.O_RDONLY | constants15.O_NOFOLLOW | constants15.O_NONBLOCK;
58596
+ WRITE_FLAGS = constants15.O_WRONLY | constants15.O_CREAT | constants15.O_EXCL | constants15.O_NOFOLLOW | constants15.O_NONBLOCK;
58329
58597
  });
58330
58598
 
58331
58599
  // src/lib/selected-manifest.ts
@@ -58356,7 +58624,7 @@ var init_selected_manifest = __esm(() => {
58356
58624
 
58357
58625
  // src/lib/plugin-admission.ts
58358
58626
  import { homedir as homedir6 } from "os";
58359
- import { isAbsolute as isAbsolute19, join as join35, resolve as resolve19 } from "path";
58627
+ import { isAbsolute as isAbsolute20, join as join35, resolve as resolve19 } from "path";
58360
58628
  function pluginAdmissionRoot() {
58361
58629
  return join35(homedir6(), ".hasna", "skills", "plugin-admission");
58362
58630
  }
@@ -58369,7 +58637,7 @@ function validatePluginTarget(value) {
58369
58637
  for (const registration of value.registrations) {
58370
58638
  pluginKeys(registration, ["scope", "projectPath"]);
58371
58639
  pluginNeed(registration.scope === "user" || registration.scope === "project", "Unsupported plugin registration scope");
58372
- pluginNeed(registration.scope === "user" ? registration.projectPath === null : typeof registration.projectPath === "string" && isAbsolute19(registration.projectPath) && resolve19(registration.projectPath) === registration.projectPath, "Plugin scope requires its exact project path");
58640
+ pluginNeed(registration.scope === "user" ? registration.projectPath === null : typeof registration.projectPath === "string" && isAbsolute20(registration.projectPath) && resolve19(registration.projectPath) === registration.projectPath, "Plugin scope requires its exact project path");
58373
58641
  const key = JSON.stringify([registration.scope, registration.projectPath]);
58374
58642
  pluginNeed(!scopes.has(key), "Duplicate plugin registration scope");
58375
58643
  scopes.add(key);
@@ -58377,7 +58645,7 @@ function validatePluginTarget(value) {
58377
58645
  for (const key of ["native", "resolver"]) {
58378
58646
  pluginKeys(value[key], key === "native" ? ["version", "executable", "digest"] : ["executable", "digest"]);
58379
58647
  pluginText(value[key].executable);
58380
- pluginNeed(isAbsolute19(value[key].executable) && resolve19(value[key].executable) === value[key].executable, "Plugin executable must have a canonical absolute path");
58648
+ pluginNeed(isAbsolute20(value[key].executable) && resolve19(value[key].executable) === value[key].executable, "Plugin executable must have a canonical absolute path");
58381
58649
  pluginDigest(value[key].digest);
58382
58650
  }
58383
58651
  pluginNeed(["2.1.274", "2.1.276"].includes(value.native.version), "Plugin admission requires a certified Claude command-source runtime (2.1.274 or 2.1.276)");
@@ -58527,7 +58795,7 @@ function pluginResolverCommand(binding) {
58527
58795
  }
58528
58796
  function root(options) {
58529
58797
  const path = options.storeRoot ?? pluginAdmissionRoot();
58530
- pluginNeed(isAbsolute19(path) && resolve19(path) === path, "Invalid plugin admission store root");
58798
+ pluginNeed(isAbsolute20(path) && resolve19(path) === path, "Invalid plugin admission store root");
58531
58799
  return path;
58532
58800
  }
58533
58801
  function pluginBindingPath(storeRoot, id) {
@@ -58734,8 +59002,8 @@ var init_plugin_admission = __esm(() => {
58734
59002
  });
58735
59003
 
58736
59004
  // src/lib/plugin-discovery.ts
58737
- import { closeSync as closeSync14, constants as constants15, fstatSync as fstatSync14, lstatSync as lstatSync24, openSync as openSync14, opendirSync as opendirSync5, readSync as readSync11 } from "fs";
58738
- import { basename as basename10, dirname as dirname19, isAbsolute as isAbsolute20, join as join36, resolve as resolve20 } from "path";
59005
+ import { closeSync as closeSync14, constants as constants16, fstatSync as fstatSync14, lstatSync as lstatSync24, openSync as openSync14, opendirSync as opendirSync5, readSync as readSync11 } from "fs";
59006
+ import { basename as basename10, dirname as dirname19, isAbsolute as isAbsolute21, join as join36, resolve as resolve20 } from "path";
58739
59007
  function validateManagedPluginWitnesses(value) {
58740
59008
  pluginNeed(Array.isArray(value) && value.length > 0 && value.length <= PLUGIN_PROJECTION_LIMITS.registrations, "Invalid managed plugin witness collection");
58741
59009
  const seen = new Set;
@@ -58744,12 +59012,12 @@ function validateManagedPluginWitnesses(value) {
58744
59012
  pluginNeed(typeof item.bindingId === "string" && /^[a-f0-9]{64}$/.test(item.bindingId) && !seen.has(item.bindingId), "Invalid or duplicate managed plugin witness");
58745
59013
  seen.add(item.bindingId);
58746
59014
  pluginText(item.storeRoot);
58747
- pluginNeed(isAbsolute20(item.storeRoot) && resolve20(item.storeRoot) === item.storeRoot, "Invalid plugin receipt store path");
59015
+ pluginNeed(isAbsolute21(item.storeRoot) && resolve20(item.storeRoot) === item.storeRoot, "Invalid plugin receipt store path");
58748
59016
  }
58749
59017
  }
58750
59018
  function safe3(path) {
58751
59019
  pluginText(path);
58752
- pluginNeed(isAbsolute20(path) && resolve20(path) === path, "Invalid plugin registry path");
59020
+ pluginNeed(isAbsolute21(path) && resolve20(path) === path, "Invalid plugin registry path");
58753
59021
  for (let at2 = path;; at2 = dirname19(at2)) {
58754
59022
  pluginNeed(!lstatSync24(at2, { throwIfNoEntry: false })?.isSymbolicLink(), "Plugin registry path traverses a symlink");
58755
59023
  if (at2 === dirname19(at2))
@@ -58760,7 +59028,7 @@ function readRegistry(path) {
58760
59028
  safe3(path);
58761
59029
  const initial2 = lstatSync24(path);
58762
59030
  pluginNeed(initial2.isFile() && initial2.size <= 1024 * 1024, "Plugin registry is not a bounded regular file");
58763
- const fd = openSync14(path, constants15.O_RDONLY | constants15.O_NOFOLLOW | constants15.O_NONBLOCK);
59031
+ const fd = openSync14(path, constants16.O_RDONLY | constants16.O_NOFOLLOW | constants16.O_NONBLOCK);
58764
59032
  try {
58765
59033
  const opened = fstatSync14(fd);
58766
59034
  pluginNeed(opened.isFile() && opened.ino === initial2.ino && opened.dev === initial2.dev, "Plugin registry changed during open");
@@ -58886,14 +59154,14 @@ var init_plugin_discovery = __esm(() => {
58886
59154
 
58887
59155
  // src/lib/claude-marketplace-registry.ts
58888
59156
  import { createHash as createHash23 } from "crypto";
58889
- import { closeSync as closeSync15, constants as constants16, fstatSync as fstatSync15, lstatSync as lstatSync25, openSync as openSync15, readSync as readSync12 } from "fs";
58890
- import { basename as basename11, dirname as dirname20, isAbsolute as isAbsolute21, resolve as resolve21 } from "path";
59157
+ import { closeSync as closeSync15, constants as constants17, fstatSync as fstatSync15, lstatSync as lstatSync25, openSync as openSync15, readSync as readSync12 } from "fs";
59158
+ import { basename as basename11, dirname as dirname20, isAbsolute as isAbsolute22, resolve as resolve21 } from "path";
58891
59159
  function need7(value, reason2) {
58892
59160
  if (!value)
58893
59161
  throw new Error(`Claude marketplace registry ${reason2}`);
58894
59162
  }
58895
- function absolutePath3(value) {
58896
- need7(typeof value === "string" && value.length > 0 && value.length <= CLAUDE_MARKETPLACE_REGISTRY_LIMITS.pathCharacters && !/[\x00-\x1f\x7f]/.test(value) && isAbsolute21(value) && resolve21(value) === value, "requires a normalized absolute path");
59163
+ function absolutePath4(value) {
59164
+ need7(typeof value === "string" && value.length > 0 && value.length <= CLAUDE_MARKETPLACE_REGISTRY_LIMITS.pathCharacters && !/[\x00-\x1f\x7f]/.test(value) && isAbsolute22(value) && resolve21(value) === value, "requires a normalized absolute path");
58897
59165
  }
58898
59166
  function parents2(path) {
58899
59167
  const result2 = [];
@@ -58906,13 +59174,13 @@ function parents2(path) {
58906
59174
  }
58907
59175
  }
58908
59176
  function readRegistry2(path, budget2) {
58909
- absolutePath3(path);
59177
+ absolutePath4(path);
58910
59178
  need7(basename11(path) === "known_marketplaces.json", "requires known_marketplaces.json");
58911
59179
  need7(Number.isSafeInteger(budget2.remaining) && budget2.remaining >= 0, "has an invalid byte budget");
58912
59180
  const ancestors2 = parents2(path), initial2 = lstatSync25(path, { bigint: true });
58913
59181
  need7(initial2.isFile() && !initial2.isSymbolicLink() && initial2.size <= BigInt(CLAUDE_MARKETPLACE_REGISTRY_LIMITS.bytes), "is not a bounded regular file");
58914
59182
  need7(initial2.size <= BigInt(budget2.remaining), "exceeds its aggregate byte limit");
58915
- const fd = openSync15(path, constants16.O_RDONLY | constants16.O_NOFOLLOW | constants16.O_NONBLOCK);
59183
+ const fd = openSync15(path, constants17.O_RDONLY | constants17.O_NOFOLLOW | constants17.O_NONBLOCK);
58916
59184
  try {
58917
59185
  const opened = fstatSync15(fd, { bigint: true });
58918
59186
  need7(opened.isFile() && sameFile2(initial2, opened), "changed during open");
@@ -59039,8 +59307,8 @@ function normalizeRow(row, version = 1) {
59039
59307
  return;
59040
59308
  const sourceLocation = textField(field2(source, location));
59041
59309
  if (type.value === "directory")
59042
- absolutePath3(sourceLocation);
59043
- absolutePath3(textField(field2(row, "installLocation")));
59310
+ absolutePath4(sourceLocation);
59311
+ absolutePath4(textField(field2(row, "installLocation")));
59044
59312
  const updated = textField(field2(row, "lastUpdated"));
59045
59313
  need7(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/.test(updated), "contains an invalid recognized update timestamp");
59046
59314
  const millis = Date.parse(updated);
@@ -59201,7 +59469,7 @@ var fail3 = () => new Error('CODEX_HOOK_TRUST_UNSUPPORTED_LAYOUT: preserve and c
59201
59469
  var init_codex_hook_trust_layout = () => {};
59202
59470
 
59203
59471
  // src/lib/codex-hook-additions-review.ts
59204
- import { isAbsolute as isAbsolute22 } from "path";
59472
+ import { isAbsolute as isAbsolute23 } from "path";
59205
59473
  import { isDeepStrictEqual as isDeepStrictEqual9 } from "util";
59206
59474
  function exactKeys2(value, keys2) {
59207
59475
  need6(value && typeof value === "object" && !Array.isArray(value) && isDeepStrictEqual9(Object.keys(value).sort(), [...keys2].sort()), "RECONCILE_ADDITIONS_REVIEW_SCHEMA");
@@ -59215,7 +59483,7 @@ function readReviewedAdditionTrustStates(proof, before2, current, journalHooks)
59215
59483
  return captured.states;
59216
59484
  }
59217
59485
  function reviewNativeHookAdditions(options) {
59218
- need6(isAbsolute22(options.path), "RECONCILE_ADDITIONS_REVIEW_PATH");
59486
+ need6(isAbsolute23(options.path), "RECONCILE_ADDITIONS_REVIEW_PATH");
59219
59487
  const reviewFile = snapshot(options.path, true), review = JSON.parse(reviewFile.text);
59220
59488
  exactKeys2(review, ["version", "kind", "reason", "producerEvidence", "journalIntentSha256", "policySha256", "configCurrentSha256", "hooksCurrentSha256", "producerBefore", "additions"]);
59221
59489
  need6((review.version === 1 || review.version === 2) && review.kind === "native-hook-additions" && text2(review.reason) && text2(review.producerEvidence), "RECONCILE_ADDITIONS_REVIEW_SCHEMA");
@@ -59223,7 +59491,7 @@ function reviewNativeHookAdditions(options) {
59223
59491
  need6(hash2(review[name]) && review[name] === expected, "RECONCILE_ADDITIONS_REVIEW_CHANGED");
59224
59492
  exactKeys2(review.producerBefore, ["configPath", "configSha256", "hooksPath", "hooksSha256"]);
59225
59493
  const before2 = review.producerBefore;
59226
- need6(isAbsolute22(before2.configPath) && isAbsolute22(before2.hooksPath) && hash2(before2.configSha256) && hash2(before2.hooksSha256), "RECONCILE_ADDITIONS_PRODUCER_PREIMAGE");
59494
+ need6(isAbsolute23(before2.configPath) && isAbsolute23(before2.hooksPath) && hash2(before2.configSha256) && hash2(before2.hooksSha256), "RECONCILE_ADDITIONS_PRODUCER_PREIMAGE");
59227
59495
  const producerConfig = snapshot(before2.configPath, true), producerHooks = snapshot(before2.hooksPath, true);
59228
59496
  need6(producerConfig.sha256 === before2.configSha256 && producerHooks.sha256 === before2.hooksSha256 && producerHooks.sha256 === options.hooksBefore.sha256, "RECONCILE_ADDITIONS_PRODUCER_PREIMAGE");
59229
59497
  const original = structure(options.configBefore.text), producer = structure(producerConfig.text), expectedProducer = structuredClone(original), originalKeys = options.journalHooks.map((hook) => hook.key);
@@ -59316,13 +59584,13 @@ function createCodexHookDiscoveryRecovery(binding, before2, current, hooks, addi
59316
59584
  need6(isDeepStrictEqual10(expected, actual) && codexTrustReconcileWitness(before2.text, keys2) === codexTrustReconcileWitness(current.text, keys2) && codexTrustUnmanagedSemantic(before2.text, keys2) === codexTrustUnmanagedSemantic(current.text, keys2), "RECONCILE_DISCOVERY_TRUST_WITNESS");
59317
59585
  unchanged2(before2);
59318
59586
  unchanged2(current);
59319
- const witness = Object.freeze({ configPath: current.file, beforeSha256: before2.sha256, currentSha256: current.sha256, discoverySha256: sha4(JSON.stringify(binding)), typedProjectionSha256: projection });
59587
+ const witness = Object.freeze({ configPath: current.file, beforeSha256: before2.sha256, currentSha256: current.sha256, discoverySha256: discoveryDigest(binding), typedProjectionSha256: projection });
59320
59588
  proofs2.set(witness, { before: before2, current, recheckAdditions });
59321
59589
  return witness;
59322
59590
  }
59323
59591
  function assertCodexHookDiscoveryRecovery(binding, witness) {
59324
59592
  const proof = proofs2.get(witness);
59325
- need6(!!proof && binding.agent === "codex" && witness.discoverySha256 === sha4(JSON.stringify(binding)), "RECONCILE_DISCOVERY_RECOVERY_CHANGED");
59593
+ need6(!!proof && binding.agent === "codex" && witness.discoverySha256 === discoveryDigest(binding), "RECONCILE_DISCOVERY_RECOVERY_CHANGED");
59326
59594
  unchanged2(proof.before);
59327
59595
  unchanged2(proof.current);
59328
59596
  proof.recheckAdditions();
@@ -59334,7 +59602,14 @@ function verifiesCodexHookDiscoverySource(binding, source, currentDigest, witnes
59334
59602
  need6(source.sha256 === witness.beforeSha256 && currentDigest === witness.currentSha256, "RECONCILE_DISCOVERY_RECOVERY_CHANGED");
59335
59603
  return true;
59336
59604
  }
59337
- var sha4 = (text3) => createHash24("sha256").update(text3).digest("hex"), fields, structure2 = (text3) => JSON.parse(JSON.stringify(Bun.TOML.parse(text3))), proofs2;
59605
+ var sha4 = (text3) => createHash24("sha256").update(text3).digest("hex"), fields, structure2 = (text3) => JSON.parse(JSON.stringify(Bun.TOML.parse(text3))), discoveryDigest = (binding) => {
59606
+ const controls = binding.codexDisabledPluginSkills;
59607
+ if (!Object.hasOwn(binding, "codexDisabledPluginSkills") || Array.isArray(controls) && controls.length === 0) {
59608
+ const { codexDisabledPluginSkills: _controls, ...withoutControls } = binding;
59609
+ return sha4(JSON.stringify({ ...withoutControls, codexDisabledPluginSkills: [] }));
59610
+ }
59611
+ return sha4(JSON.stringify(binding));
59612
+ }, proofs2;
59338
59613
  var init_codex_hook_discovery_recovery = __esm(() => {
59339
59614
  init_codex_hook_trust_files();
59340
59615
  init_codex_hook_trust_layout();
@@ -59347,7 +59622,7 @@ var init_codex_hook_discovery_recovery = __esm(() => {
59347
59622
  // src/lib/agent-discovery.ts
59348
59623
  import { createHash as createHash25 } from "crypto";
59349
59624
  import { lstatSync as lstatSync26, readFileSync as readFileSync21, readdirSync as readdirSync11, realpathSync as realpathSync11 } from "fs";
59350
- import { basename as basename12, dirname as dirname21, isAbsolute as isAbsolute23, join as join37, resolve as resolve22, sep as sep8 } from "path";
59625
+ import { basename as basename12, dirname as dirname21, isAbsolute as isAbsolute24, join as join37, resolve as resolve22, sep as sep8 } from "path";
59351
59626
  import { isDeepStrictEqual as isDeepStrictEqual11 } from "util";
59352
59627
  function discoveryRootUnresolved(agent, command, detail) {
59353
59628
  return new Error(`${DISCOVERY_ROOT_UNRESOLVED}: ${agent} discovery cannot resolve its "${command}" executable: ${detail}. The reviewed discovery is unchanged; this is an environment gap, not drift.`);
@@ -59381,7 +59656,7 @@ function parseConfig(text3, path, toml = false) {
59381
59656
  }
59382
59657
  }
59383
59658
  function safe4(path) {
59384
- if (!isAbsolute23(path) || path.includes("\x00"))
59659
+ if (!isAbsolute24(path) || path.includes("\x00"))
59385
59660
  throw new Error("Expected an absolute native discovery path");
59386
59661
  for (let cursor = path;; cursor = dirname21(cursor)) {
59387
59662
  if (lstatSync26(cursor, { throwIfNoEntry: false })?.isSymbolicLink())
@@ -59401,19 +59676,20 @@ function read2(path, changes) {
59401
59676
  throw new Error(`Unsupported or oversized native discovery input: ${path}`);
59402
59677
  return readFileSync21(path, "utf8");
59403
59678
  }
59404
- function assertReviewedClaudeCacheClosures(home, config, review) {
59679
+ function assertReviewedClaudeCacheClosures(home, config, review, canonical8) {
59405
59680
  const enabledIds = Object.entries(config.enabledPlugins ?? {}).filter(([, enabled]) => enabled === true).map(([id]) => id);
59406
59681
  if (enabledIds.length === 0)
59407
59682
  return;
59408
- const registryPath = join37(home, ".claude/plugins/installed_plugins.json");
59409
- const cacheRoot = join37(home, ".claude/plugins/cache");
59683
+ const registryPath = canonical8(join37(home, ".claude/plugins/installed_plugins.json"));
59684
+ const cacheAliasRoot = join37(home, ".claude/plugins/cache");
59685
+ const cacheRoot = canonical8(cacheAliasRoot);
59410
59686
  const registryText = read2(registryPath);
59411
59687
  if (registryText === null)
59412
59688
  return;
59413
59689
  const registry = parseConfig(registryText, registryPath);
59414
59690
  if (registry.version !== 2 || !registry.plugins || typeof registry.plugins !== "object" || Array.isArray(registry.plugins))
59415
59691
  throw new Error("Reviewed Claude installed plugin registrations are invalid");
59416
- const cachePath = (path) => typeof path === "string" && isAbsolute23(path) && resolve22(path) === path && (path === cacheRoot || path.startsWith(cacheRoot + sep8));
59692
+ const cachePath = (path) => typeof path === "string" && isAbsolute24(path) && resolve22(path) === path && [cacheAliasRoot, cacheRoot].some((root2) => path === root2 || path.startsWith(root2 + sep8));
59417
59693
  const activeRoots = new Set;
59418
59694
  for (const id of enabledIds) {
59419
59695
  const rows = registry.plugins[id];
@@ -59425,13 +59701,13 @@ function assertReviewedClaudeCacheClosures(home, config, review) {
59425
59701
  if (!row || typeof row !== "object" || Array.isArray(row) || typeof row.installPath !== "string") {
59426
59702
  throw new Error("Reviewed Claude enabled plugin registration requires an object with an installPath string");
59427
59703
  }
59428
- if (typeof row.installPath === "string" && (row.installPath === cacheRoot || row.installPath.startsWith(cacheRoot + sep8))) {
59704
+ if ([cacheAliasRoot, cacheRoot].some((root2) => row.installPath === root2 || row.installPath.startsWith(root2 + sep8))) {
59429
59705
  if (!cachePath(row.installPath) || row.installPath.length > AGENT_POLICY_LIMITS.pathCharacters || row.version !== undefined && (typeof row.version !== "string" || basename12(row.installPath) !== row.version)) {
59430
59706
  throw new Error("Reviewed Claude discovery has a malformed active cache registration");
59431
59707
  }
59432
- if (row.scope === "user" && (row.projectPath === undefined || row.projectPath === null)) {} else if (row.scope === "project" && typeof row.projectPath === "string" && isAbsolute23(row.projectPath) && resolve22(row.projectPath) === row.projectPath && row.projectPath.length <= AGENT_POLICY_LIMITS.pathCharacters) {} else
59708
+ if (row.scope === "user" && (row.projectPath === undefined || row.projectPath === null)) {} else if (row.scope === "project" && typeof row.projectPath === "string" && isAbsolute24(row.projectPath) && resolve22(row.projectPath) === row.projectPath && row.projectPath.length <= AGENT_POLICY_LIMITS.pathCharacters) {} else
59433
59709
  throw new Error("Reviewed Claude discovery has an unsupported active cache registration scope");
59434
- activeRoots.add(row.installPath);
59710
+ activeRoots.add(canonical8(row.installPath));
59435
59711
  }
59436
59712
  }
59437
59713
  }
@@ -59676,12 +59952,12 @@ function absentRetiredClaudeRoots(binding) {
59676
59952
  if (!row || typeof row !== "object" || Array.isArray(row))
59677
59953
  return null;
59678
59954
  const value = row;
59679
- if (typeof value.installPath !== "string" || /[\x00-\x1f\x7f]/.test(value.installPath) || !isAbsolute23(value.installPath) || resolve22(value.installPath) !== value.installPath || value.installPath.length > AGENT_POLICY_LIMITS.pathCharacters)
59955
+ if (typeof value.installPath !== "string" || /[\x00-\x1f\x7f]/.test(value.installPath) || !isAbsolute24(value.installPath) || resolve22(value.installPath) !== value.installPath || value.installPath.length > AGENT_POLICY_LIMITS.pathCharacters)
59680
59956
  return null;
59681
59957
  if (value.scope === "user")
59682
59958
  return value.projectPath === undefined || value.projectPath === null ? "user\x00" : null;
59683
59959
  if (value.scope === "project")
59684
- return typeof value.projectPath === "string" && !/[\x00-\x1f\x7f]/.test(value.projectPath) && value.projectPath.length <= AGENT_POLICY_LIMITS.pathCharacters && isAbsolute23(value.projectPath) && resolve22(value.projectPath) === value.projectPath ? `project\x00${value.projectPath}` : null;
59960
+ return typeof value.projectPath === "string" && !/[\x00-\x1f\x7f]/.test(value.projectPath) && value.projectPath.length <= AGENT_POLICY_LIMITS.pathCharacters && isAbsolute24(value.projectPath) && resolve22(value.projectPath) === value.projectPath ? `project\x00${value.projectPath}` : null;
59685
59961
  return null;
59686
59962
  };
59687
59963
  if (Object.values(installed.plugins).some((value) => !Array.isArray(value) || value.some((row) => !row || typeof row.installPath !== "string" || row.installPath === root2 || row.installPath.startsWith(root2 + sep8) || root2.startsWith(row.installPath + sep8))))
@@ -59945,7 +60221,7 @@ function resolveAgentDiscovery(options) {
59945
60221
  if (config.skills !== undefined && (!Array.isArray(config.skills) || config.skills.some((path) => typeof path !== "string")))
59946
60222
  unresolved("skills must be a string array");
59947
60223
  for (const value of config.skills ?? []) {
59948
- if (typeof value !== "string" || /[\0$]/.test(value) || !value || !(isAbsolute23(value) || value.startsWith("~/")))
60224
+ if (typeof value !== "string" || /[\0$]/.test(value) || !value || !(isAbsolute24(value) || value.startsWith("~/")))
59949
60225
  unresolved("remote or relative skill sources need a dedicated discovery adapter");
59950
60226
  roots.add(canonical8(value.startsWith("~/") ? join37(home, value.slice(2)) : value));
59951
60227
  }
@@ -60075,7 +60351,7 @@ function resolveAgentDiscovery(options) {
60075
60351
  return { path: source.path, sha256: manifestSha256, hashMode: "claude-plugin-manifest-v1" };
60076
60352
  });
60077
60353
  if (agent === "claude")
60078
- assertReviewedClaudeCacheClosures(home, config, review);
60354
+ assertReviewedClaudeCacheClosures(home, config, review, canonical8);
60079
60355
  const combined = [...reviewedSources, ...reviewedSourcesWithManifestProjection];
60080
60356
  const unique = combined.filter((source, index) => combined.findIndex((candidate2) => isDeepStrictEqual11(candidate2, source)) === index);
60081
60357
  return { ...supplied, roots: [...new Set([...roots, ...supplied.roots])].sort(), sources: unique, ...agent === "gemini" ? { builtinNames } : {} };
@@ -60135,7 +60411,7 @@ function resolveAgentDiscovery(options) {
60135
60411
  unresolved("unsupported plugin enablement");
60136
60412
  const split2 = id.lastIndexOf("@"), name = id.slice(0, split2), marketplace = id.slice(split2 + 1);
60137
60413
  const market = config.marketplaces?.[marketplace] ?? (marketplace === "personal" ? { source_type: "local", source: home } : undefined);
60138
- if (split2 < 1 || market?.source_type !== "local" || typeof market.source !== "string" || !isAbsolute23(market.source))
60414
+ if (split2 < 1 || market?.source_type !== "local" || typeof market.source !== "string" || !isAbsolute24(market.source))
60139
60415
  unresolved("enabled plugin marketplace is not an explicit local source");
60140
60416
  const catalogText = witness(join37(market.source, ".agents/plugins/marketplace.json"));
60141
60417
  if (catalogText === null)
@@ -60151,7 +60427,7 @@ function resolveAgentDiscovery(options) {
60151
60427
  if ((config.plugin?.length ?? 0) > 0 || config.skills?.urls?.length)
60152
60428
  unresolved("external plugin or remote skill source");
60153
60429
  for (const path of config.skills?.paths ?? []) {
60154
- if (typeof path !== "string" || !isAbsolute23(path))
60430
+ if (typeof path !== "string" || !isAbsolute24(path))
60155
60431
  unresolved("relative or malformed added skill root");
60156
60432
  roots.add(path);
60157
60433
  }
@@ -60336,10 +60612,10 @@ import {
60336
60612
  realpathSync as realpathSync13,
60337
60613
  renameSync as renameSync7,
60338
60614
  rmSync as rmSync5,
60339
- statSync as statSync12,
60615
+ statSync as statSync13,
60340
60616
  writeFileSync as writeFileSync10
60341
60617
  } from "fs";
60342
- import { basename as basename14, dirname as dirname23, isAbsolute as isAbsolute24, join as join39, normalize as normalize4, relative as relative7, resolve as resolve24, sep as sep10 } from "path";
60618
+ import { basename as basename14, dirname as dirname23, isAbsolute as isAbsolute25, join as join39, normalize as normalize4, relative as relative7, resolve as resolve24, sep as sep10 } from "path";
60343
60619
  function getPortableSkillsRoot(options = {}) {
60344
60620
  return resolvePortableSkillsRoot(options, true);
60345
60621
  }
@@ -60367,7 +60643,7 @@ function findPortableSkill(name, options = {}) {
60367
60643
  return null;
60368
60644
  }
60369
60645
  const path = getPortableSkillPath(normalized, options);
60370
- if (!existsSync19(path) || !statSync12(path).isDirectory())
60646
+ if (!existsSync19(path) || !statSync13(path).isDirectory())
60371
60647
  return null;
60372
60648
  try {
60373
60649
  return summarizePortableSkill(path, normalized);
@@ -60438,7 +60714,7 @@ function scaffoldPortableSkill(name, options = {}) {
60438
60714
  }
60439
60715
  function portPortableSkillDirectory(sourceDir, options = {}) {
60440
60716
  const absoluteSource = normalize4(sourceDir);
60441
- if (!existsSync19(absoluteSource) || !statSync12(absoluteSource).isDirectory()) {
60717
+ if (!existsSync19(absoluteSource) || !statSync13(absoluteSource).isDirectory()) {
60442
60718
  throw new Error(`Import directory not found: ${sourceDir}`);
60443
60719
  }
60444
60720
  const continueOnError = options.continueOnError ?? true;
@@ -60497,7 +60773,7 @@ function assertDisjointImportPaths(source, destination) {
60497
60773
  const destinationPath = physicalImportPath(destination);
60498
60774
  const contains2 = (parent, child2) => {
60499
60775
  const path = relative7(parent, child2);
60500
- return path === "" || !isAbsolute24(path) && path !== ".." && !path.startsWith(`..${sep10}`);
60776
+ return path === "" || !isAbsolute25(path) && path !== ".." && !path.startsWith(`..${sep10}`);
60501
60777
  };
60502
60778
  if (contains2(sourcePath, destinationPath) || contains2(destinationPath, sourcePath)) {
60503
60779
  throw new Error("Source and destination skill directories must not overlap");
@@ -60505,7 +60781,7 @@ function assertDisjointImportPaths(source, destination) {
60505
60781
  }
60506
60782
  function portPortableSkill(sourcePath, options = {}) {
60507
60783
  const absoluteSource = normalize4(sourcePath);
60508
- if (!existsSync19(absoluteSource) || !statSync12(absoluteSource).isDirectory()) {
60784
+ if (!existsSync19(absoluteSource) || !statSync13(absoluteSource).isDirectory()) {
60509
60785
  throw new Error(`Skill source directory not found: ${sourcePath}`);
60510
60786
  }
60511
60787
  const inferred = readPortableSkillManifestForImport(absoluteSource);
@@ -60668,7 +60944,7 @@ function validatePortableSkillDirectory(name, skillPath) {
60668
60944
  const entryPath = join39(skillPath, command.entry);
60669
60945
  if (!existsSync19(entryPath))
60670
60946
  add4(issues, "portable.command_entry_missing", `Command '${command.name}' entry '${command.entry}' is missing`);
60671
- else if (statSync12(entryPath).isDirectory())
60947
+ else if (statSync13(entryPath).isDirectory())
60672
60948
  add4(issues, "portable.command_entry_directory", `Command '${command.name}' entry '${command.entry}' must be a file`);
60673
60949
  }
60674
60950
  }
@@ -60708,13 +60984,13 @@ function summarizePortableSkill(skillPath, fallbackName) {
60708
60984
  }
60709
60985
  function safeIsDirectory(path) {
60710
60986
  try {
60711
- return statSync12(path).isDirectory();
60987
+ return statSync13(path).isDirectory();
60712
60988
  } catch {
60713
60989
  return false;
60714
60990
  }
60715
60991
  }
60716
60992
  function isSafeRelativePath2(value) {
60717
- if (!value.trim() || isAbsolute24(value))
60993
+ if (!value.trim() || isAbsolute25(value))
60718
60994
  return false;
60719
60995
  const normalized = normalize4(value).replace(/\\/g, "/");
60720
60996
  return normalized !== ".." && !normalized.startsWith("../") && !normalized.includes("/../");
@@ -62721,7 +62997,7 @@ var require_cli_spinners = __commonJS((exports, module) => {
62721
62997
  });
62722
62998
 
62723
62999
  // src/lib/auth-store.ts
62724
- import { chmodSync as chmodSync2, existsSync as existsSync21, mkdirSync as mkdirSync12, readFileSync as readFileSync25, renameSync as renameSync8, statSync as statSync13, unlinkSync as unlinkSync6, writeFileSync as writeFileSync11 } from "fs";
63000
+ import { chmodSync as chmodSync2, existsSync as existsSync21, mkdirSync as mkdirSync12, readFileSync as readFileSync25, renameSync as renameSync8, statSync as statSync14, unlinkSync as unlinkSync6, writeFileSync as writeFileSync11 } from "fs";
62725
63001
  import { basename as basename15, dirname as dirname24, join as join41 } from "path";
62726
63002
  function getAuthFilePath(env3 = process.env) {
62727
63003
  return skillsCredentialFilePath(env3);
@@ -62935,7 +63211,7 @@ function getApiUrl(action, env3 = process.env, options = {}) {
62935
63211
  }
62936
63212
  function credentialFileMode(env3 = process.env) {
62937
63213
  try {
62938
- return statSync13(skillsCredentialFilePath(env3)).mode & 511;
63214
+ return statSync14(skillsCredentialFilePath(env3)).mode & 511;
62939
63215
  } catch {
62940
63216
  return null;
62941
63217
  }
@@ -65168,8 +65444,8 @@ var cuid, cuid2, ulid, xid, ksuid, nanoid, duration, extendedDuration, guid, uui
65168
65444
  if (!version)
65169
65445
  return /^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$/;
65170
65446
  return new RegExp(`^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-${version}[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$`);
65171
- }, uuid42, uuid6, uuid7, email2, html5Email, rfc5322Email, unicodeEmail, idnEmail, browserEmail, _emoji = `^[\\p{Extended_Pictographic}\\p{Emoji_Component}]+$`, ipv4, ipv6, mac = (delimiter2) => {
65172
- const escapedDelim = escapeRegex(delimiter2 ?? ":");
65447
+ }, uuid42, uuid6, uuid7, email2, html5Email, rfc5322Email, unicodeEmail, idnEmail, browserEmail, _emoji = `^[\\p{Extended_Pictographic}\\p{Emoji_Component}]+$`, ipv4, ipv6, mac = (delimiter3) => {
65448
+ const escapedDelim = escapeRegex(delimiter3 ?? ":");
65173
65449
  return new RegExp(`^(?:[0-9A-F]{2}${escapedDelim}){5}[0-9A-F]{2}$|^(?:[0-9a-f]{2}${escapedDelim}){5}[0-9a-f]{2}$`);
65174
65450
  }, cidrv4, cidrv6, base64, base64url, hostname2, domain, httpProtocol, e164, creditCard, dateSource = `(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))`, date2, string = (params) => {
65175
65451
  const regex2 = params ? `[\\s\\S]{${params?.minimum ?? 0},${params?.maximum ?? ""}}` : `[\\s\\S]*`;
@@ -88469,7 +88745,7 @@ var init_init = __esm(() => {
88469
88745
  });
88470
88746
 
88471
88747
  // src/lib/home-adoption.ts
88472
- import { constants as constants17, closeSync as closeSync16, fstatSync as fstatSync16, lstatSync as lstatSync28, openSync as openSync16, readSync as readSync14, existsSync as existsSync25, mkdirSync as mkdirSync15, readdirSync as readdirSync15, readFileSync as readFileSync30, rmSync as rmSync7, statSync as statSync14, writeFileSync as writeFileSync15 } from "fs";
88748
+ import { constants as constants18, closeSync as closeSync16, fstatSync as fstatSync16, lstatSync as lstatSync28, openSync as openSync16, readSync as readSync14, existsSync as existsSync25, mkdirSync as mkdirSync15, readdirSync as readdirSync15, readFileSync as readFileSync30, rmSync as rmSync7, statSync as statSync15, writeFileSync as writeFileSync15 } from "fs";
88473
88749
  import { homedir as homedir8 } from "os";
88474
88750
  import { join as join47 } from "path";
88475
88751
  function indexCanonicalCorpus(corpusRoot) {
@@ -88505,7 +88781,7 @@ function selectedHomeNames(options, index, homeDir2, agents) {
88505
88781
  continue;
88506
88782
  const present = agents.some((agent) => {
88507
88783
  try {
88508
- return statSync14(join47(agentGlobalSkillsDir(agent, homeDir2), name)).isDirectory();
88784
+ return statSync15(join47(agentGlobalSkillsDir(agent, homeDir2), name)).isDirectory();
88509
88785
  } catch {
88510
88786
  return false;
88511
88787
  }
@@ -88539,7 +88815,7 @@ function scanUnmarkedHomes(options = {}) {
88539
88815
  continue;
88540
88816
  const dir = join47(home, skill);
88541
88817
  try {
88542
- if (!statSync14(dir).isDirectory())
88818
+ if (!statSync15(dir).isDirectory())
88543
88819
  continue;
88544
88820
  } catch {
88545
88821
  continue;
@@ -88552,7 +88828,7 @@ function scanUnmarkedHomes(options = {}) {
88552
88828
  if (!existsSync25(skillMdPath))
88553
88829
  continue;
88554
88830
  const hash5 = hashSkillMarkdownFile(skillMdPath);
88555
- const mtime = statSync14(skillMdPath).mtime.toISOString();
88831
+ const mtime = statSync15(skillMdPath).mtime.toISOString();
88556
88832
  const entry = { agent, skill, home, path: dir, hash: hash5, mtime };
88557
88833
  const canonicalHash = index.get(skill);
88558
88834
  if (canonicalHash === undefined) {
@@ -88647,7 +88923,7 @@ function pruneOwnership(dir) {
88647
88923
  const markerPath = join47(dir, SYNC_MARKER_FILE), markerPathBefore = lstatSync28(markerPath);
88648
88924
  if (!markerPathBefore.isFile())
88649
88925
  return;
88650
- descriptor = openSync16(markerPath, constants17.O_RDONLY | constants17.O_NOFOLLOW | constants17.O_NONBLOCK);
88926
+ descriptor = openSync16(markerPath, constants18.O_RDONLY | constants18.O_NOFOLLOW | constants18.O_NONBLOCK);
88651
88927
  const before2 = fstatSync16(descriptor);
88652
88928
  if (!before2.isFile() || before2.dev !== markerPathBefore.dev || before2.ino !== markerPathBefore.ino || before2.size !== markerPathBefore.size || before2.mtimeMs !== markerPathBefore.mtimeMs || before2.ctimeMs !== markerPathBefore.ctimeMs || before2.size < 1 || before2.size > 65536)
88653
88929
  return;
@@ -88698,7 +88974,7 @@ function pruneStrayHomes(options = {}) {
88698
88974
  continue;
88699
88975
  const dir = join47(home, skill);
88700
88976
  try {
88701
- if (!statSync14(dir).isDirectory())
88977
+ if (!statSync15(dir).isDirectory())
88702
88978
  continue;
88703
88979
  } catch {
88704
88980
  continue;
@@ -88756,7 +89032,7 @@ var init_home_adoption = __esm(() => {
88756
89032
  });
88757
89033
 
88758
89034
  // src/lib/home-census.ts
88759
- import { existsSync as existsSync26, readFileSync as readFileSync31, readdirSync as readdirSync16, statSync as statSync15 } from "fs";
89035
+ import { existsSync as existsSync26, readFileSync as readFileSync31, readdirSync as readdirSync16, statSync as statSync16 } from "fs";
88760
89036
  import { homedir as homedir9 } from "os";
88761
89037
  import { join as join48 } from "path";
88762
89038
  function sortEntries(entries) {
@@ -88801,7 +89077,7 @@ function censusHomeDrift(options = {}) {
88801
89077
  continue;
88802
89078
  const dir = join48(home, skill);
88803
89079
  try {
88804
- if (!statSync15(dir).isDirectory())
89080
+ if (!statSync16(dir).isDirectory())
88805
89081
  continue;
88806
89082
  } catch {
88807
89083
  continue;
@@ -88872,13 +89148,13 @@ var init_home_census = __esm(() => {
88872
89148
  });
88873
89149
 
88874
89150
  // src/cli/env-assignment.ts
88875
- import { closeSync as closeSync17, constants as constants18, fstatSync as fstatSync17, ftruncateSync as ftruncateSync2, lstatSync as lstatSync29, openSync as openSync17, readFileSync as readFileSync32, writeSync as writeSync4 } from "fs";
89151
+ import { closeSync as closeSync17, constants as constants19, fstatSync as fstatSync17, ftruncateSync as ftruncateSync2, lstatSync as lstatSync29, openSync as openSync17, readFileSync as readFileSync32, writeSync as writeSync4 } from "fs";
88876
89152
  function serializeValue(value) {
88877
89153
  if (controls.test(value))
88878
89154
  throw new EnvAssignmentError("Environment values cannot contain control characters or newlines.");
88879
89155
  if (/^[A-Za-z0-9_./:@+=,-]*$/.test(value))
88880
89156
  return value;
88881
- const quote3 = ["'", "`", '"'].find((delimiter2) => !value.includes(delimiter2) && (delimiter2 !== '"' || !value.includes("\\")));
89157
+ const quote3 = ["'", "`", '"'].find((delimiter3) => !value.includes(delimiter3) && (delimiter3 !== '"' || !value.includes("\\")));
88882
89158
  const trailingSlashes = value.match(/\\+$/)?.[0].length ?? 0;
88883
89159
  if (!quote3 || trailingSlashes % 2 !== 0 || value.endsWith("\\$")) {
88884
89160
  throw new EnvAssignmentError("Cannot safely encode this environment value; incompatible quote/backslash combinations require manual editing.");
@@ -88960,7 +89236,7 @@ function setEnvAssignment(path, assignment) {
88960
89236
  })();
88961
89237
  if (previous && !previous.isFile())
88962
89238
  throw new EnvAssignmentError("The project .env must be a regular file, not a symlink or special file.");
88963
- descriptor = openSync17(path, previous ? constants18.O_RDWR | constants18.O_NOFOLLOW | constants18.O_NONBLOCK : constants18.O_WRONLY | constants18.O_CREAT | constants18.O_EXCL | constants18.O_NOFOLLOW, 384);
89239
+ descriptor = openSync17(path, previous ? constants19.O_RDWR | constants19.O_NOFOLLOW | constants19.O_NONBLOCK : constants19.O_WRONLY | constants19.O_CREAT | constants19.O_EXCL | constants19.O_NOFOLLOW, 384);
88964
89240
  const opened = fstatSync17(descriptor);
88965
89241
  if (!opened.isFile() || previous && (opened.ino !== previous.ino || opened.dev !== previous.dev)) {
88966
89242
  throw new EnvAssignmentError("The project .env changed while opening it; retry with a regular file.");
@@ -89054,7 +89330,7 @@ var exports_diagnostic = {};
89054
89330
  __export(exports_diagnostic, {
89055
89331
  registerDiagnostic: () => registerDiagnostic
89056
89332
  });
89057
- import { existsSync as existsSync27, readFileSync as readFileSync33, readdirSync as readdirSync17, statSync as statSync16 } from "fs";
89333
+ import { existsSync as existsSync27, readFileSync as readFileSync33, readdirSync as readdirSync17, statSync as statSync17 } from "fs";
89058
89334
  import { join as join49 } from "path";
89059
89335
  import { execSync as execSync2 } from "child_process";
89060
89336
  function registerDiagnostic(parent) {
@@ -89247,7 +89523,7 @@ function handleWhoami(options) {
89247
89523
  let skillCount = 0;
89248
89524
  if (exists)
89249
89525
  try {
89250
- skillCount = readdirSync17(agentSkillsPath).filter((f) => !f.startsWith(".") && statSync16(join49(agentSkillsPath, f)).isDirectory()).length;
89526
+ skillCount = readdirSync17(agentSkillsPath).filter((f) => !f.startsWith(".") && statSync17(join49(agentSkillsPath, f)).isDirectory()).length;
89251
89527
  } catch {}
89252
89528
  agentConfigs.push({ agent, label: AGENT_LABELS[agent], path: agentSkillsPath, exists, skillCount });
89253
89529
  }
@@ -89505,12 +89781,12 @@ var init_cloud_executions = __esm(() => {
89505
89781
 
89506
89782
  // node_modules/@hasna/secrets/dist/sdk.js
89507
89783
  import { isIP as isIP3 } from "net";
89508
- import { spawnSync as spawnSync3 } from "child_process";
89784
+ import { spawnSync as spawnSync4 } from "child_process";
89509
89785
  import { closeSync as closeSync18, fstatSync as fstatSync18, openSync as openSync18, readFileSync as readFileSync34 } from "fs";
89510
89786
  import { O_NOFOLLOW as O_NOFOLLOW3, O_NONBLOCK as O_NONBLOCK3, O_RDONLY as O_RDONLY3 } from "constants";
89511
89787
  import { createRequire as createRequire2 } from "module";
89512
89788
  import { hostname as osHostname2 } from "os";
89513
- import { isAbsolute as isAbsolute25, join as join50 } from "path";
89789
+ import { isAbsolute as isAbsolute26, join as join50 } from "path";
89514
89790
  import { createRequire as createRequire22 } from "module";
89515
89791
  function envToken2(name) {
89516
89792
  return name.toUpperCase().replace(/-/g, "_");
@@ -89534,7 +89810,7 @@ function homeDir2(env3) {
89534
89810
  }
89535
89811
  function absoluteOverride2(env3, key) {
89536
89812
  const value = env3[key]?.trim();
89537
- return value && isAbsolute25(value) ? value : null;
89813
+ return value && isAbsolute26(value) ? value : null;
89538
89814
  }
89539
89815
  function hasnaHomeDir2(env3) {
89540
89816
  const override = absoluteOverride2(env3, HASNA_HOME_ENV_KEY2);
@@ -89780,7 +90056,7 @@ function isAmbientEnvironment2(env3) {
89780
90056
  return env3 === process.env || env3[AMBIENT_ENVIRONMENT2] === true;
89781
90057
  }
89782
90058
  function defaultKeychainRunner2(argv) {
89783
- const result2 = spawnSync3(KEYCHAIN_SECURITY_BIN2, [...argv], {
90059
+ const result2 = spawnSync4(KEYCHAIN_SECURITY_BIN2, [...argv], {
89784
90060
  encoding: "utf8",
89785
90061
  stdio: ["ignore", "pipe", "pipe"],
89786
90062
  timeout: KEYCHAIN_SPAWN_TIMEOUT_MS2
@@ -90806,7 +91082,7 @@ var init_sdk = __esm(() => {
90806
91082
  });
90807
91083
 
90808
91084
  // src/lib/execution-secrets.ts
90809
- import { constants as constants19, closeSync as closeSync19, fstatSync as fstatSync19, openSync as openSync19, readSync as readSync15, realpathSync as realpathSync14 } from "fs";
91085
+ import { constants as constants20, closeSync as closeSync19, fstatSync as fstatSync19, openSync as openSync19, readSync as readSync15, realpathSync as realpathSync14 } from "fs";
90810
91086
  import { hostname as stationHostname } from "os";
90811
91087
  function selectedSecretBindingsTemplate(scope, names, createClient2 = createSecretsClientFromEnv) {
90812
91088
  let secretsAuthority;
@@ -90850,7 +91126,7 @@ function declaredSecretNames(value) {
90850
91126
  function readSelectedSecretBindings(path) {
90851
91127
  let fd;
90852
91128
  try {
90853
- fd = openSync19(path, constants19.O_RDONLY | constants19.O_NOFOLLOW | constants19.O_NONBLOCK);
91129
+ fd = openSync19(path, constants20.O_RDONLY | constants20.O_NOFOLLOW | constants20.O_NONBLOCK);
90854
91130
  const stat2 = fstatSync19(fd);
90855
91131
  if (!stat2.isFile() || stat2.size > 65536)
90856
91132
  throw new Error;
@@ -95499,7 +95775,7 @@ var init_runs = __esm(() => {
95499
95775
 
95500
95776
  // src/lib/run-state.ts
95501
95777
  import { createHash as createHash33, randomBytes } from "crypto";
95502
- import { existsSync as existsSync28, mkdirSync as mkdirSync17, readFileSync as readFileSync35, readdirSync as readdirSync18, statSync as statSync17, writeFileSync as writeFileSync17 } from "fs";
95778
+ import { existsSync as existsSync28, mkdirSync as mkdirSync17, readFileSync as readFileSync35, readdirSync as readdirSync18, statSync as statSync18, writeFileSync as writeFileSync17 } from "fs";
95503
95779
  import { extname, join as join52, relative as relative8 } from "path";
95504
95780
  function createSkillRun(params, targetDir = process.cwd()) {
95505
95781
  const now3 = new Date;
@@ -95581,7 +95857,7 @@ function listSkillRuns(targetDir = process.cwd(), limit = 50) {
95581
95857
  const records = [];
95582
95858
  for (const day of readdirSync18(runsRoot).sort().reverse()) {
95583
95859
  const dayDir = join52(runsRoot, day);
95584
- if (!statSync17(dayDir).isDirectory())
95860
+ if (!statSync18(dayDir).isDirectory())
95585
95861
  continue;
95586
95862
  for (const runId2 of readdirSync18(dayDir).sort().reverse()) {
95587
95863
  const record11 = readRunRecord(join52(dayDir, runId2));
@@ -95630,7 +95906,7 @@ function collectRunArtifacts(context) {
95630
95906
  return [];
95631
95907
  const artifacts = [];
95632
95908
  for (const path of walkFiles(context.exportDir)) {
95633
- const stat2 = statSync17(path);
95909
+ const stat2 = statSync18(path);
95634
95910
  const bytes = readFileSync35(path);
95635
95911
  artifacts.push({
95636
95912
  path: toProjectRelative(context.targetDir, path),
@@ -95655,7 +95931,7 @@ function walkFiles(dir) {
95655
95931
  const files = [];
95656
95932
  for (const entry of readdirSync18(dir)) {
95657
95933
  const full = join52(dir, entry);
95658
- if (statSync17(full).isDirectory())
95934
+ if (statSync18(full).isDirectory())
95659
95935
  files.push(...walkFiles(full));
95660
95936
  else
95661
95937
  files.push(full);
@@ -99592,11 +99868,11 @@ var require_codegen = __commonJS((exports) => {
99592
99868
  const rhs = this.rhs === undefined ? "" : ` = ${this.rhs}`;
99593
99869
  return `${varKind} ${this.name}${rhs};` + _n;
99594
99870
  }
99595
- optimizeNames(names, constants20) {
99871
+ optimizeNames(names, constants21) {
99596
99872
  if (!names[this.name.str])
99597
99873
  return;
99598
99874
  if (this.rhs)
99599
- this.rhs = optimizeExpr(this.rhs, names, constants20);
99875
+ this.rhs = optimizeExpr(this.rhs, names, constants21);
99600
99876
  return this;
99601
99877
  }
99602
99878
  get names() {
@@ -99614,10 +99890,10 @@ var require_codegen = __commonJS((exports) => {
99614
99890
  render({ _n }) {
99615
99891
  return `${this.lhs} = ${this.rhs};` + _n;
99616
99892
  }
99617
- optimizeNames(names, constants20) {
99893
+ optimizeNames(names, constants21) {
99618
99894
  if (this.lhs instanceof code_1.Name && !names[this.lhs.str] && !this.sideEffects)
99619
99895
  return;
99620
- this.rhs = optimizeExpr(this.rhs, names, constants20);
99896
+ this.rhs = optimizeExpr(this.rhs, names, constants21);
99621
99897
  return this;
99622
99898
  }
99623
99899
  get names() {
@@ -99683,8 +99959,8 @@ var require_codegen = __commonJS((exports) => {
99683
99959
  optimizeNodes() {
99684
99960
  return `${this.code}` ? this : undefined;
99685
99961
  }
99686
- optimizeNames(names, constants20) {
99687
- this.code = optimizeExpr(this.code, names, constants20);
99962
+ optimizeNames(names, constants21) {
99963
+ this.code = optimizeExpr(this.code, names, constants21);
99688
99964
  return this;
99689
99965
  }
99690
99966
  get names() {
@@ -99714,12 +99990,12 @@ var require_codegen = __commonJS((exports) => {
99714
99990
  }
99715
99991
  return nodes.length > 0 ? this : undefined;
99716
99992
  }
99717
- optimizeNames(names, constants20) {
99993
+ optimizeNames(names, constants21) {
99718
99994
  const { nodes } = this;
99719
99995
  let i = nodes.length;
99720
99996
  while (i--) {
99721
99997
  const n2 = nodes[i];
99722
- if (n2.optimizeNames(names, constants20))
99998
+ if (n2.optimizeNames(names, constants21))
99723
99999
  continue;
99724
100000
  subtractNames(names, n2.names);
99725
100001
  nodes.splice(i, 1);
@@ -99776,12 +100052,12 @@ var require_codegen = __commonJS((exports) => {
99776
100052
  return;
99777
100053
  return this;
99778
100054
  }
99779
- optimizeNames(names, constants20) {
100055
+ optimizeNames(names, constants21) {
99780
100056
  var _a3;
99781
- this.else = (_a3 = this.else) === null || _a3 === undefined ? undefined : _a3.optimizeNames(names, constants20);
99782
- if (!(super.optimizeNames(names, constants20) || this.else))
100057
+ this.else = (_a3 = this.else) === null || _a3 === undefined ? undefined : _a3.optimizeNames(names, constants21);
100058
+ if (!(super.optimizeNames(names, constants21) || this.else))
99783
100059
  return;
99784
- this.condition = optimizeExpr(this.condition, names, constants20);
100060
+ this.condition = optimizeExpr(this.condition, names, constants21);
99785
100061
  return this;
99786
100062
  }
99787
100063
  get names() {
@@ -99806,10 +100082,10 @@ var require_codegen = __commonJS((exports) => {
99806
100082
  render(opts) {
99807
100083
  return `for(${this.iteration})` + super.render(opts);
99808
100084
  }
99809
- optimizeNames(names, constants20) {
99810
- if (!super.optimizeNames(names, constants20))
100085
+ optimizeNames(names, constants21) {
100086
+ if (!super.optimizeNames(names, constants21))
99811
100087
  return;
99812
- this.iteration = optimizeExpr(this.iteration, names, constants20);
100088
+ this.iteration = optimizeExpr(this.iteration, names, constants21);
99813
100089
  return this;
99814
100090
  }
99815
100091
  get names() {
@@ -99847,10 +100123,10 @@ var require_codegen = __commonJS((exports) => {
99847
100123
  render(opts) {
99848
100124
  return `for(${this.varKind} ${this.name} ${this.loop} ${this.iterable})` + super.render(opts);
99849
100125
  }
99850
- optimizeNames(names, constants20) {
99851
- if (!super.optimizeNames(names, constants20))
100126
+ optimizeNames(names, constants21) {
100127
+ if (!super.optimizeNames(names, constants21))
99852
100128
  return;
99853
- this.iterable = optimizeExpr(this.iterable, names, constants20);
100129
+ this.iterable = optimizeExpr(this.iterable, names, constants21);
99854
100130
  return this;
99855
100131
  }
99856
100132
  get names() {
@@ -99895,11 +100171,11 @@ var require_codegen = __commonJS((exports) => {
99895
100171
  (_b = this.finally) === null || _b === undefined || _b.optimizeNodes();
99896
100172
  return this;
99897
100173
  }
99898
- optimizeNames(names, constants20) {
100174
+ optimizeNames(names, constants21) {
99899
100175
  var _a3, _b;
99900
- super.optimizeNames(names, constants20);
99901
- (_a3 = this.catch) === null || _a3 === undefined || _a3.optimizeNames(names, constants20);
99902
- (_b = this.finally) === null || _b === undefined || _b.optimizeNames(names, constants20);
100176
+ super.optimizeNames(names, constants21);
100177
+ (_a3 = this.catch) === null || _a3 === undefined || _a3.optimizeNames(names, constants21);
100178
+ (_b = this.finally) === null || _b === undefined || _b.optimizeNames(names, constants21);
99903
100179
  return this;
99904
100180
  }
99905
100181
  get names() {
@@ -100173,7 +100449,7 @@ var require_codegen = __commonJS((exports) => {
100173
100449
  function addExprNames(names, from) {
100174
100450
  return from instanceof code_1._CodeOrName ? addNames(names, from.names) : names;
100175
100451
  }
100176
- function optimizeExpr(expr, names, constants20) {
100452
+ function optimizeExpr(expr, names, constants21) {
100177
100453
  if (expr instanceof code_1.Name)
100178
100454
  return replaceName(expr);
100179
100455
  if (!canOptimize(expr))
@@ -100188,14 +100464,14 @@ var require_codegen = __commonJS((exports) => {
100188
100464
  return items;
100189
100465
  }, []));
100190
100466
  function replaceName(n2) {
100191
- const c = constants20[n2.str];
100467
+ const c = constants21[n2.str];
100192
100468
  if (c === undefined || names[n2.str] !== 1)
100193
100469
  return n2;
100194
100470
  delete names[n2.str];
100195
100471
  return c;
100196
100472
  }
100197
100473
  function canOptimize(e2) {
100198
- return e2 instanceof code_1._Code && e2._items.some((c) => c instanceof code_1.Name && names[c.str] === 1 && constants20[c.str] !== undefined);
100474
+ return e2 instanceof code_1._Code && e2._items.some((c) => c instanceof code_1.Name && names[c.str] === 1 && constants21[c.str] !== undefined);
100199
100475
  }
100200
100476
  }
100201
100477
  function subtractNames(names, from) {
@@ -107671,7 +107947,7 @@ var init_remote_customer_operations = __esm(() => {
107671
107947
  });
107672
107948
 
107673
107949
  // src/lib/workspace-profile.ts
107674
- import { constants as constants20, closeSync as closeSync20, fstatSync as fstatSync20, lstatSync as lstatSync30, mkdirSync as mkdirSync18, mkdtempSync as mkdtempSync5, openSync as openSync20, readFileSync as readFileSync36, renameSync as renameSync11, rmSync as rmSync8, writeFileSync as writeFileSync18 } from "fs";
107950
+ import { constants as constants21, closeSync as closeSync20, fstatSync as fstatSync20, lstatSync as lstatSync30, mkdirSync as mkdirSync18, mkdtempSync as mkdtempSync5, openSync as openSync20, readFileSync as readFileSync36, renameSync as renameSync11, rmSync as rmSync8, writeFileSync as writeFileSync18 } from "fs";
107675
107951
  import { dirname as dirname28, join as join53 } from "path";
107676
107952
  function stat2(path) {
107677
107953
  try {
@@ -107685,7 +107961,7 @@ function stat2(path) {
107685
107961
  function safeText(file2) {
107686
107962
  if (stat2(file2) === null)
107687
107963
  return null;
107688
- const fd = openSync20(file2, constants20.O_RDONLY | constants20.O_NOFOLLOW | constants20.O_NONBLOCK);
107964
+ const fd = openSync20(file2, constants21.O_RDONLY | constants21.O_NOFOLLOW | constants21.O_NONBLOCK);
107689
107965
  try {
107690
107966
  const s = fstatSync20(fd);
107691
107967
  if (!s.isFile() || s.size > 65536 || ![256, 384].includes(s.mode & 4095) || process.getuid && s.uid !== process.getuid())
@@ -108039,8 +108315,8 @@ var init_recurring_customer = __esm(() => {
108039
108315
  });
108040
108316
 
108041
108317
  // src/lib/recurring-recovery.ts
108042
- import { constants as constants21, closeSync as closeSync21, fsyncSync as fsyncSync7, fstatSync as fstatSync21, lstatSync as lstatSync31, mkdirSync as mkdirSync19, openSync as openSync21, readSync as readSync16, realpathSync as realpathSync16, renameSync as renameSync12, unlinkSync as unlinkSync8, writeFileSync as writeFileSync19 } from "fs";
108043
- import { dirname as dirname29, isAbsolute as isAbsolute26, join as join54, resolve as resolve27 } from "path";
108318
+ import { constants as constants22, closeSync as closeSync21, fsyncSync as fsyncSync7, fstatSync as fstatSync21, lstatSync as lstatSync31, mkdirSync as mkdirSync19, openSync as openSync21, readSync as readSync16, realpathSync as realpathSync16, renameSync as renameSync12, unlinkSync as unlinkSync8, writeFileSync as writeFileSync19 } from "fs";
108319
+ import { dirname as dirname29, isAbsolute as isAbsolute27, join as join54, resolve as resolve27 } from "path";
108044
108320
  import { randomUUID as randomUUID8 } from "crypto";
108045
108321
 
108046
108322
  class RecoveryOwner {
@@ -108048,7 +108324,7 @@ class RecoveryOwner {
108048
108324
  parents = [];
108049
108325
  constructor(directory) {
108050
108326
  this.directory = directory;
108051
- if (!isAbsolute26(directory) || resolve27(directory) !== directory || realpathSync16(directory) !== directory)
108327
+ if (!isAbsolute27(directory) || resolve27(directory) !== directory || realpathSync16(directory) !== directory)
108052
108328
  invalid6();
108053
108329
  for (let path = directory;; path = dirname29(path)) {
108054
108330
  const stat3 = lstatSync31(path);
@@ -108074,7 +108350,7 @@ class RecoveryOwner {
108074
108350
  }
108075
108351
  read(name) {
108076
108352
  this.assert();
108077
- const fd = openSync21(join54(this.directory, name), constants21.O_RDONLY | constants21.O_NOFOLLOW | constants21.O_NONBLOCK);
108353
+ const fd = openSync21(join54(this.directory, name), constants22.O_RDONLY | constants22.O_NOFOLLOW | constants22.O_NONBLOCK);
108078
108354
  try {
108079
108355
  const before2 = fstatSync21(fd);
108080
108356
  if (!before2.isFile() || before2.nlink !== 1 || (before2.mode & 4095) !== 384 || before2.size < 1 || before2.size > 8192 || process.getuid && before2.uid !== process.getuid())
@@ -108100,7 +108376,7 @@ class RecoveryOwner {
108100
108376
  this.assert();
108101
108377
  const bytes = canonicalJson2(value, 8192) + `
108102
108378
  `;
108103
- const fd = openSync21(join54(this.directory, name), constants21.O_WRONLY | constants21.O_CREAT | constants21.O_EXCL | constants21.O_NOFOLLOW, 384);
108379
+ const fd = openSync21(join54(this.directory, name), constants22.O_WRONLY | constants22.O_CREAT | constants22.O_EXCL | constants22.O_NOFOLLOW, 384);
108104
108380
  try {
108105
108381
  writeFileSync19(fd, bytes);
108106
108382
  fsyncSync7(fd);
@@ -108112,7 +108388,7 @@ class RecoveryOwner {
108112
108388
  }
108113
108389
  sync() {
108114
108390
  this.assert();
108115
- const fd = openSync21(this.directory, constants21.O_RDONLY | constants21.O_NOFOLLOW);
108391
+ const fd = openSync21(this.directory, constants22.O_RDONLY | constants22.O_NOFOLLOW);
108116
108392
  try {
108117
108393
  fsyncSync7(fd);
108118
108394
  } finally {
@@ -108134,7 +108410,7 @@ class RecoveryOwner {
108134
108410
  this.assert();
108135
108411
  let fd;
108136
108412
  try {
108137
- fd = openSync21(join54(this.directory, "operation.lock"), constants21.O_WRONLY | constants21.O_CREAT | constants21.O_EXCL | constants21.O_NOFOLLOW, 384);
108413
+ fd = openSync21(join54(this.directory, "operation.lock"), constants22.O_WRONLY | constants22.O_CREAT | constants22.O_EXCL | constants22.O_NOFOLLOW, 384);
108138
108414
  } catch {
108139
108415
  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.");
108140
108416
  }
@@ -108183,7 +108459,7 @@ function base2(customer, organizationId) {
108183
108459
  };
108184
108460
  }
108185
108461
  function create3(directory, intent) {
108186
- if (!isAbsolute26(directory) || resolve27(directory) !== directory || realpathSync16(dirname29(directory)) !== dirname29(directory))
108462
+ if (!isAbsolute27(directory) || resolve27(directory) !== directory || realpathSync16(dirname29(directory)) !== dirname29(directory))
108187
108463
  invalid6();
108188
108464
  mkdirSync19(directory, { mode: 448 });
108189
108465
  const owner2 = new RecoveryOwner(directory), checked = intentSchema.parse(intent), intentSha256 = canonicalJsonSha256(checked);
@@ -108346,7 +108622,7 @@ var init_recurring_recovery = __esm(() => {
108346
108622
  });
108347
108623
 
108348
108624
  // src/lib/recurring-surface.ts
108349
- import { isAbsolute as isAbsolute27 } from "path";
108625
+ import { isAbsolute as isAbsolute28 } from "path";
108350
108626
  function recurringMcpSchema(action) {
108351
108627
  return action === "activate" ? recurringSurfaceSchemas.activate.extend({ code, confirm: exports_external.literal(true) }) : recurringSurfaceSchemas[action];
108352
108628
  }
@@ -108451,7 +108727,7 @@ var init_recurring_surface = __esm(() => {
108451
108727
  uuid12 = exports_external.string().regex(/^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/);
108452
108728
  context = { userId: uuid12.optional(), membershipId: uuid12.optional() };
108453
108729
  page2 = { limit: exports_external.number().int().min(1).max(100).optional(), cursor: exports_external.string().min(1).max(2048).optional() };
108454
- directory = exports_external.string().max(4096).refine(isAbsolute27, "Use an absolute recovery directory");
108730
+ directory = exports_external.string().max(4096).refine(isAbsolute28, "Use an absolute recovery directory");
108455
108731
  email4 = exports_external.string().trim().toLowerCase().email().max(254);
108456
108732
  code = exports_external.string().regex(/^\d{6}$/);
108457
108733
  recurringSurfaceSchemas = {
@@ -109823,7 +110099,7 @@ var init_run_routing = __esm(() => {
109823
110099
  });
109824
110100
 
109825
110101
  // src/mcp/operation-tools.ts
109826
- import { existsSync as existsSync29, readdirSync as readdirSync19, statSync as statSync18 } from "fs";
110102
+ import { existsSync as existsSync29, readdirSync as readdirSync19, statSync as statSync19 } from "fs";
109827
110103
  import { join as join55 } from "path";
109828
110104
  function registerOperationTools(server) {
109829
110105
  server.registerTool("cloud_skill_eligibility", {
@@ -110302,7 +110578,7 @@ function registerOperationTools(server) {
110302
110578
  try {
110303
110579
  skillCount = readdirSync19(agentSkillsPath).filter((f) => {
110304
110580
  const full = join55(agentSkillsPath, f);
110305
- return !f.startsWith(".") && statSync18(full).isDirectory();
110581
+ return !f.startsWith(".") && statSync19(full).isDirectory();
110306
110582
  }).length;
110307
110583
  } catch {}
110308
110584
  }
@@ -110889,7 +111165,7 @@ import {
110889
111165
  mkdirSync as mkdirSync22,
110890
111166
  readFileSync as readFileSync38,
110891
111167
  readdirSync as readdirSync20,
110892
- statSync as statSync19,
111168
+ statSync as statSync20,
110893
111169
  writeFileSync as writeFileSync21
110894
111170
  } from "fs";
110895
111171
  import { dirname as dirname31, join as join58, normalize as normalize5, relative as relative9, sep as sep11 } from "path";
@@ -111015,7 +111291,7 @@ function walkFiles2(dir) {
111015
111291
  const files = [];
111016
111292
  for (const entry of readdirSync20(dir)) {
111017
111293
  const full = join58(dir, entry);
111018
- const stats = statSync19(full);
111294
+ const stats = statSync20(full);
111019
111295
  if (stats.isDirectory())
111020
111296
  files.push(...walkFiles2(full));
111021
111297
  else
@@ -111252,11 +111528,11 @@ var init_private_publication_customer = __esm(() => {
111252
111528
  });
111253
111529
 
111254
111530
  // src/lib/private-publication-recovery.ts
111255
- import { constants as constants22, closeSync as closeSync23, fsyncSync as fsyncSync8, fstatSync as fstatSync23, lstatSync as lstatSync32, mkdirSync as mkdirSync23, openSync as openSync23, readSync as readSync17, realpathSync as realpathSync17, renameSync as renameSync13, unlinkSync as unlinkSync9, writeFileSync as writeFileSync22 } from "fs";
111256
- import { dirname as dirname32, isAbsolute as isAbsolute28, join as join59, resolve as resolve28 } from "path";
111531
+ import { constants as constants23, closeSync as closeSync23, fsyncSync as fsyncSync8, fstatSync as fstatSync23, lstatSync as lstatSync32, mkdirSync as mkdirSync23, openSync as openSync23, readSync as readSync17, realpathSync as realpathSync17, renameSync as renameSync13, unlinkSync as unlinkSync9, writeFileSync as writeFileSync22 } from "fs";
111532
+ import { dirname as dirname32, isAbsolute as isAbsolute29, join as join59, resolve as resolve28 } from "path";
111257
111533
  import { randomUUID as randomUUID9 } from "crypto";
111258
111534
  function safeDirectory(directory2) {
111259
- if (!isAbsolute28(directory2) || directory2 !== resolve28(directory2) || realpathSync17(directory2) !== directory2)
111535
+ if (!isAbsolute29(directory2) || directory2 !== resolve28(directory2) || realpathSync17(directory2) !== directory2)
111260
111536
  return fail5();
111261
111537
  for (let path = directory2;; path = dirname32(path)) {
111262
111538
  const stat3 = lstatSync32(path);
@@ -111277,7 +111553,7 @@ function unchangedDirectory(directory2, identity6) {
111277
111553
  }
111278
111554
  function readOwned(directory2, name, max2) {
111279
111555
  const identity6 = safeDirectory(directory2), file2 = join59(directory2, name);
111280
- const fd = openSync23(file2, constants22.O_RDONLY | constants22.O_NOFOLLOW);
111556
+ const fd = openSync23(file2, constants23.O_RDONLY | constants23.O_NOFOLLOW);
111281
111557
  try {
111282
111558
  const stat3 = fstatSync23(fd);
111283
111559
  if (!stat3.isFile() || stat3.nlink !== 1 || stat3.size > max2 || stat3.size < 1 || (stat3.mode & 63) !== 0 || process.getuid && stat3.uid !== process.getuid())
@@ -111300,7 +111576,7 @@ function readOwned(directory2, name, max2) {
111300
111576
  }
111301
111577
  }
111302
111578
  function writeOwned(directory2, name, bytes) {
111303
- const fd = openSync23(join59(directory2, name), constants22.O_WRONLY | constants22.O_CREAT | constants22.O_EXCL | constants22.O_NOFOLLOW, 384);
111579
+ const fd = openSync23(join59(directory2, name), constants23.O_WRONLY | constants23.O_CREAT | constants23.O_EXCL | constants23.O_NOFOLLOW, 384);
111304
111580
  try {
111305
111581
  writeFileSync22(fd, bytes);
111306
111582
  fsyncSync8(fd);
@@ -111314,7 +111590,7 @@ function save2(directory2, value) {
111314
111590
  `);
111315
111591
  unchangedDirectory(directory2, identity6);
111316
111592
  renameSync13(join59(directory2, temporary), join59(directory2, "receipt.json"));
111317
- const fd = openSync23(directory2, constants22.O_RDONLY | constants22.O_NOFOLLOW);
111593
+ const fd = openSync23(directory2, constants23.O_RDONLY | constants23.O_NOFOLLOW);
111318
111594
  try {
111319
111595
  fsyncSync8(fd);
111320
111596
  } finally {
@@ -111329,7 +111605,7 @@ async function locked(directory2, action) {
111329
111605
  const identity6 = safeDirectory(directory2), file2 = join59(directory2, "operation.lock");
111330
111606
  let fd;
111331
111607
  try {
111332
- fd = openSync23(file2, constants22.O_WRONLY | constants22.O_CREAT | constants22.O_EXCL | constants22.O_NOFOLLOW, 384);
111608
+ fd = openSync23(file2, constants23.O_WRONLY | constants23.O_CREAT | constants23.O_EXCL | constants23.O_NOFOLLOW, 384);
111333
111609
  } catch {
111334
111610
  throw new PrivatePublicationError("PUBLICATION_RECOVERY_BUSY", "Another operation holds this recovery directory. If it crashed, confirm that process has stopped before explicitly removing operation.lock and resuming.");
111335
111611
  }
@@ -111394,11 +111670,11 @@ async function preparePrivatePublication(client2, sourceDirectory, recoveryDirec
111394
111670
  phase: "prepared",
111395
111671
  intent: null
111396
111672
  };
111397
- if (!isAbsolute28(recoveryDirectory) || resolve28(recoveryDirectory) !== recoveryDirectory || realpathSync17(dirname32(recoveryDirectory)) !== dirname32(recoveryDirectory))
111673
+ if (!isAbsolute29(recoveryDirectory) || resolve28(recoveryDirectory) !== recoveryDirectory || realpathSync17(dirname32(recoveryDirectory)) !== dirname32(recoveryDirectory))
111398
111674
  return fail5();
111399
111675
  mkdirSync23(recoveryDirectory, { mode: 448 });
111400
111676
  safeDirectory(recoveryDirectory);
111401
- const parent = openSync23(dirname32(recoveryDirectory), constants22.O_RDONLY | constants22.O_NOFOLLOW);
111677
+ const parent = openSync23(dirname32(recoveryDirectory), constants23.O_RDONLY | constants23.O_NOFOLLOW);
111402
111678
  try {
111403
111679
  fsyncSync8(parent);
111404
111680
  } finally {
@@ -111495,10 +111771,10 @@ var init_private_publication_recovery = __esm(() => {
111495
111771
  });
111496
111772
 
111497
111773
  // src/mcp/private-publication-tools.ts
111498
- import { isAbsolute as isAbsolute29 } from "path";
111774
+ import { isAbsolute as isAbsolute30 } from "path";
111499
111775
  function registerPrivatePublicationTools(server) {
111500
111776
  const uuid9 = exports_external.string().regex(/^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/);
111501
- const directory2 = exports_external.string().max(4096).refine(isAbsolute29, "Use an absolute local directory");
111777
+ const directory2 = exports_external.string().max(4096).refine(isAbsolute30, "Use an absolute local directory");
111502
111778
  const verification2 = { email: exports_external.string().email().max(254), code: exports_external.string().regex(/^\d{6}$/), userId: uuid9, membershipId: uuid9, recoveryDirectory: directory2 };
111503
111779
  const description = "Manage a private source publication using fresh workspace-bound verification and a host-local recovery directory. Publishing requires explicit UUID current-version comparison and upload consent. Resume reuses immutable saved bytes and intent; an uncertain PUT is finalized for server verification, never uploaded twice. Sessions and signed URLs are not returned or persisted. Private execution is unavailable. Host request history may contain the supplied verification code.";
111504
111780
  const handler = (action) => async (value) => {
@@ -112290,44 +112566,50 @@ import {
112290
112566
  renameSync as renameSync14,
112291
112567
  writeFileSync as writeFileSync24
112292
112568
  } from "fs";
112293
- import { basename as basename17, delimiter as delimiter2, dirname as dirname34, isAbsolute as isAbsolute30, join as join61, relative as relative10, resolve as resolve29, sep as sep12 } from "path";
112569
+ import { basename as basename17, delimiter as delimiter3, dirname as dirname34, isAbsolute as isAbsolute31, join as join61, relative as relative10, resolve as resolve29, sep as sep12 } from "path";
112294
112570
  function oldLauncherState(item) {
112295
112571
  if (item.oldShape === "pinned")
112296
- return { shape: "pinned", runtime: item.oldRuntime, cwd: item.oldCwd, target: item.oldTarget, sha256: item.oldSha256 };
112572
+ return { shape: "pinned", runtime: item.oldRuntime, cwd: item.oldCwd, target: item.oldTarget, sha256: item.oldSha256, format: item.oldFormat, profile: item.oldProfile };
112297
112573
  return { shape: "symlink", linkTarget: item.oldLinkTarget, target: item.oldTarget };
112298
112574
  }
112299
112575
  function newLauncherState(item) {
112300
112576
  if (item.newShape === "pinned")
112301
- return { shape: "pinned", runtime: item.newRuntime, cwd: item.newCwd, target: item.newTarget, sha256: item.newSha256 };
112577
+ return { shape: "pinned", runtime: item.newRuntime, cwd: item.newCwd, target: item.newTarget, sha256: item.newSha256, format: item.newFormat, profile: item.newProfile };
112302
112578
  return { shape: "symlink", linkTarget: item.newTarget, target: item.newTarget };
112303
112579
  }
112304
- function assertLauncherRecordShapes(item) {
112580
+ function assertLauncherRecordShapes(item, expectedProfile) {
112305
112581
  const hex3 = /^[a-f0-9]{64}$/;
112306
112582
  for (const side of ["old", "new"]) {
112307
112583
  const shape = item[`${side}Shape`], runtime = item[`${side}Runtime`], cwd2 = item[`${side}Cwd`], sha6 = item[`${side}Sha256`];
112584
+ const format = item[`${side}Format`], profile = item[`${side}Profile`];
112308
112585
  if (shape === undefined) {
112309
- if (runtime !== undefined || cwd2 !== undefined || sha6 !== undefined)
112586
+ if (runtime !== undefined || cwd2 !== undefined || sha6 !== undefined || format !== undefined || profile !== undefined)
112310
112587
  throw new Error("RECEIPT_LAUNCHER_SHAPE_INVALID");
112311
112588
  continue;
112312
112589
  }
112313
112590
  if (shape === "symlink") {
112314
- if (runtime !== undefined || cwd2 !== undefined || sha6 !== undefined)
112591
+ if (runtime !== undefined || cwd2 !== undefined || sha6 !== undefined || format !== undefined || profile !== undefined)
112315
112592
  throw new Error("RECEIPT_LAUNCHER_SHAPE_INVALID");
112316
112593
  continue;
112317
112594
  }
112318
- if (shape !== "pinned" || typeof runtime !== "string" || !isAbsolute30(runtime) || typeof cwd2 !== "string" || !isAbsolute30(cwd2) || typeof sha6 !== "string" || !hex3.test(sha6)) {
112595
+ if (shape !== "pinned" || typeof runtime !== "string" || !isAbsolute31(runtime) || typeof cwd2 !== "string" || !isAbsolute31(cwd2) || typeof sha6 !== "string" || !hex3.test(sha6)) {
112319
112596
  throw new Error("RECEIPT_LAUNCHER_SHAPE_INVALID");
112320
112597
  }
112321
112598
  const target = side === "old" ? item.oldTarget : item.newTarget;
112322
112599
  if (side === "old" && item.oldLinkTarget !== item.oldTarget)
112323
112600
  throw new Error("RECEIPT_LAUNCHER_SHAPE_INVALID");
112324
- if (pinnedLauncherState(runtime, cwd2, target).sha256 !== sha6)
112601
+ if (format === "v2" && profile !== expectedProfile)
112325
112602
  throw new Error("RECEIPT_LAUNCHER_SHAPE_INVALID");
112603
+ try {
112604
+ pinnedLauncherText({ runtime, cwd: cwd2, target, sha256: sha6, format, profile });
112605
+ } catch {
112606
+ throw new Error("RECEIPT_LAUNCHER_SHAPE_INVALID");
112607
+ }
112326
112608
  }
112327
112609
  }
112328
- function pinnedRecordFields(runtime, cwd2, target) {
112329
- const state = pinnedLauncherState(runtime, cwd2, target);
112330
- return { newShape: "pinned", newRuntime: state.runtime, newCwd: state.cwd, newSha256: state.sha256 };
112610
+ function pinnedRecordFields(runtime, cwd2, target, profile) {
112611
+ const state = pinnedLauncherState(runtime, cwd2, target, { format: "v2", profile });
112612
+ return { newShape: "pinned", newRuntime: state.runtime, newCwd: state.cwd, newSha256: state.sha256, newFormat: state.format, newProfile: state.profile };
112331
112613
  }
112332
112614
  function object10(value, code2) {
112333
112615
  if (!value || typeof value !== "object" || Array.isArray(value))
@@ -112339,7 +112621,7 @@ function hash5(bytes) {
112339
112621
  }
112340
112622
  function isWithin(parent, child2) {
112341
112623
  const rel = relative10(parent, child2);
112342
- return rel === "" || !rel.startsWith(`..${sep12}`) && rel !== ".." && !isAbsolute30(rel);
112624
+ return rel === "" || !rel.startsWith(`..${sep12}`) && rel !== ".." && !isAbsolute31(rel);
112343
112625
  }
112344
112626
  function entryExists(path) {
112345
112627
  try {
@@ -112388,7 +112670,7 @@ function packageBins(pkg) {
112388
112670
  const entries = typeof raw === "string" ? [[PACKAGE_NAME.slice(PACKAGE_NAME.lastIndexOf("/") + 1), raw]] : raw && typeof raw === "object" && !Array.isArray(raw) ? Object.entries(raw) : [];
112389
112671
  const output2 = {};
112390
112672
  for (const [name, value] of entries) {
112391
- if (!/^[a-zA-Z0-9._-]+$/.test(name) || typeof value !== "string" || !value || isAbsolute30(value)) {
112673
+ if (!/^[a-zA-Z0-9._-]+$/.test(name) || typeof value !== "string" || !value || isAbsolute31(value)) {
112392
112674
  throw new Error("PACKAGE_BIN_INVALID");
112393
112675
  }
112394
112676
  const normalized = value.replaceAll("\\", "/");
@@ -112451,7 +112733,7 @@ function resolveRuntimeLayout(homeInput, pathInput) {
112451
112733
  }
112452
112734
  const launchers = [];
112453
112735
  const seenDirectories = new Set;
112454
- for (const rawDir of pathInput.split(delimiter2).filter(Boolean)) {
112736
+ for (const rawDir of pathInput.split(delimiter3).filter(Boolean)) {
112455
112737
  const dir = resolve29(rawDir);
112456
112738
  if (seenDirectories.has(dir))
112457
112739
  continue;
@@ -112481,7 +112763,7 @@ function resolveRuntimeLayout(homeInput, pathInput) {
112481
112763
  throw new Error("LAUNCHER_SYMLINK_CHAIN_UNSUPPORTED");
112482
112764
  launchers.push({ path, oldTarget: actual, oldLinkTarget: launcher.linkTarget, newTarget, backupPath, oldShape: "symlink" });
112483
112765
  } else {
112484
- launchers.push({ path, oldTarget: actual, oldLinkTarget: actual, newTarget, backupPath, oldShape: "pinned", oldRuntime: launcher.runtime, oldCwd: launcher.cwd, oldSha256: launcher.sha256 });
112766
+ launchers.push({ path, oldTarget: actual, oldLinkTarget: actual, newTarget, backupPath, oldShape: "pinned", oldRuntime: launcher.runtime, oldCwd: launcher.cwd, oldSha256: launcher.sha256, oldFormat: launcher.format, oldProfile: launcher.profile });
112485
112767
  }
112486
112768
  }
112487
112769
  }
@@ -113110,14 +113392,14 @@ function adoptCopyfileAliases(options = {}) {
113110
113392
  const actual = launcher.target;
113111
113393
  const oldLinkTarget = launcher.kind === "symlink" ? launcher.linkTarget : actual;
113112
113394
  const newTarget = join61(layout.currentPackageRoot, target);
113113
- if (actual === newTarget && launcher.kind === "pinned")
113395
+ if (actual === newTarget && launcher.kind === "pinned" && launcher.format === "v2" && launcher.profile === launcherProfileForBin(name, target))
113114
113396
  continue;
113115
113397
  const chain = inspectAliasPackageChain(home, path, oldLinkTarget, actual, target);
113116
113398
  const source = validateAliasSource(home, name, actual);
113117
113399
  const backupPath = `${path}.skills-alias-prev-${id2}`;
113118
113400
  if (entryExists(backupPath))
113119
113401
  throw new Error("ALIAS_BACKUP_COLLISION");
113120
- const oldFields = launcher.kind === "symlink" ? { oldShape: "symlink" } : { oldShape: "pinned", oldRuntime: launcher.runtime, oldCwd: launcher.cwd, oldSha256: launcher.sha256 };
113402
+ const oldFields = launcher.kind === "symlink" ? { oldShape: "symlink" } : { oldShape: "pinned", oldRuntime: launcher.runtime, oldCwd: launcher.cwd, oldSha256: launcher.sha256, oldFormat: launcher.format, oldProfile: launcher.profile };
113121
113403
  aliases.push({
113122
113404
  path,
113123
113405
  oldTarget: actual,
@@ -113127,7 +113409,7 @@ function adoptCopyfileAliases(options = {}) {
113127
113409
  newTarget,
113128
113410
  backupPath,
113129
113411
  ...oldFields,
113130
- ...pinnedRecordFields(launcherRuntime, currentRuntime, newTarget),
113412
+ ...pinnedRecordFields(launcherRuntime, currentRuntime, newTarget, launcherProfileForBin(name, target)),
113131
113413
  ...chain ? { chain } : {}
113132
113414
  });
113133
113415
  }
@@ -113247,7 +113529,7 @@ function rollbackCopyfileAliases(receiptId, options = {}) {
113247
113529
  throw new Error("ALIAS_RECEIPT_LAUNCHER_INVALID");
113248
113530
  }
113249
113531
  inspectAliasPackageChain(home, item.path, item.oldLinkTarget, item.oldTarget, target, item.chain, true);
113250
- assertLauncherRecordShapes(item);
113532
+ assertLauncherRecordShapes(item, launcherProfileForBin(name, target));
113251
113533
  seen.add(item.path);
113252
113534
  assertOwnedSafePath(dirname34(item.path), home, true);
113253
113535
  const source = validateAliasSource(home, name, item.oldTarget);
@@ -113319,7 +113601,7 @@ async function updateCopyfileRuntime(version2, options = {}) {
113319
113601
  throw new Error("REVIEWED_LOCK_INPUT_PAIR_REQUIRED");
113320
113602
  if (!policy)
113321
113603
  throw new Error("REVIEWED_LOCK_RELEASE_AGE_REQUIRED");
113322
- if (!isAbsolute30(options.reviewedLock))
113604
+ if (!isAbsolute31(options.reviewedLock))
113323
113605
  throw new Error("REVIEWED_LOCK_ABSOLUTE_PATH_REQUIRED");
113324
113606
  assertNoSymlinkAncestors(dirname34(options.reviewedLock));
113325
113607
  const stat3 = lstatSync33(options.reviewedLock);
@@ -113352,7 +113634,7 @@ async function updateCopyfileRuntime(version2, options = {}) {
113352
113634
  const launcherRuntime = pinnedLauncherRuntime();
113353
113635
  const launchers = layout.launchers.map((item) => {
113354
113636
  const newTarget = join61(finalPath, "node_modules", "@hasna", "skills", layout.bin[basename17(item.path)]);
113355
- return { ...item, newTarget, ...pinnedRecordFields(launcherRuntime, finalPath, newTarget) };
113637
+ return { ...item, newTarget, ...pinnedRecordFields(launcherRuntime, finalPath, newTarget, launcherProfileForBin(basename17(item.path), layout.bin[basename17(item.path)])) };
113356
113638
  });
113357
113639
  const releaseLock = acquireRuntimeLock(layout.runtimeRoot);
113358
113640
  let switched = [];
@@ -113566,10 +113848,10 @@ function rollbackCopyfileRuntime(receiptId, options = {}) {
113566
113848
  const seen = new Set;
113567
113849
  for (const item of receipt.launchers) {
113568
113850
  const bin = oldBins[basename17(item.path)];
113569
- if (!bin || !isAbsolute30(item.path) || seen.has(item.path) || item.oldTarget !== join61(receipt.currentPackageRoot, bin) || item.newTarget !== join61(receipt.targetPackageRoot, bin) || !/^.+\.skills-prev-[0-9a-f-]{36}$/.test(item.backupPath) || !item.backupPath.startsWith(`${item.path}.skills-prev-`) || typeof item.oldLinkTarget !== "string" || resolve29(dirname34(item.path), item.oldLinkTarget) !== item.oldTarget)
113851
+ if (!bin || !isAbsolute31(item.path) || seen.has(item.path) || item.oldTarget !== join61(receipt.currentPackageRoot, bin) || item.newTarget !== join61(receipt.targetPackageRoot, bin) || !/^.+\.skills-prev-[0-9a-f-]{36}$/.test(item.backupPath) || !item.backupPath.startsWith(`${item.path}.skills-prev-`) || typeof item.oldLinkTarget !== "string" || resolve29(dirname34(item.path), item.oldLinkTarget) !== item.oldTarget)
113570
113852
  throw new Error("RECEIPT_LAUNCHER_BINDING_INVALID");
113571
113853
  assertNoSymlinkAncestors(dirname34(item.path));
113572
- assertLauncherRecordShapes(item);
113854
+ assertLauncherRecordShapes(item, launcherProfileForBin(basename17(item.path), bin));
113573
113855
  seen.add(item.path);
113574
113856
  const oldState = oldLauncherState(item), newState = newLauncherState(item);
113575
113857
  let activeTarget;
@@ -113635,7 +113917,7 @@ __export(exports_runtime, {
113635
113917
  });
113636
113918
  import { createHash as createHash37, randomUUID as randomUUID11 } from "crypto";
113637
113919
  import { lstatSync as lstatSync34, mkdirSync as mkdirSync26, readFileSync as readFileSync41, writeFileSync as writeFileSync25 } from "fs";
113638
- import { basename as basename18, isAbsolute as isAbsolute31, join as join62 } from "path";
113920
+ import { basename as basename18, isAbsolute as isAbsolute32, join as join62 } from "path";
113639
113921
  import { createInterface } from "readline";
113640
113922
  function registerRuntime(parent) {
113641
113923
  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) => {
@@ -113834,7 +114116,7 @@ Updating ${name}...
113834
114116
  async function readUpdatedVersion(bunExecutable) {
113835
114117
  const output2 = await readUpdateCommand([bunExecutable, "pm", "bin", "-g"]);
113836
114118
  const globalBin = output2.replace(/\r?\n$/, "");
113837
- if (!globalBin || !isAbsolute31(globalBin) || /[\r\n\0]/.test(globalBin))
114119
+ if (!globalBin || !isAbsolute32(globalBin) || /[\r\n\0]/.test(globalBin))
113838
114120
  throw new Error("Update bin discovery failed");
113839
114121
  const installed = Bun.which("skills", { PATH: globalBin, cwd: globalBin });
113840
114122
  const selected = Bun.which("skills");
@@ -114889,10 +115171,10 @@ var exports_recurring = {};
114889
115171
  __export(exports_recurring, {
114890
115172
  registerRecurringCommands: () => registerRecurringCommands
114891
115173
  });
114892
- import { constants as constants23, closeSync as closeSync25, fstatSync as fstatSync25, lstatSync as lstatSync35, openSync as openSync25, readSync as readSync18 } from "fs";
115174
+ import { constants as constants24, closeSync as closeSync25, fstatSync as fstatSync25, lstatSync as lstatSync35, openSync as openSync25, readSync as readSync18 } from "fs";
114893
115175
  import { createInterface as createInterface2 } from "readline";
114894
115176
  function readRequest(path) {
114895
- const fd = openSync25(path, constants23.O_RDONLY | constants23.O_NOFOLLOW | constants23.O_NONBLOCK);
115177
+ const fd = openSync25(path, constants24.O_RDONLY | constants24.O_NOFOLLOW | constants24.O_NONBLOCK);
114896
115178
  try {
114897
115179
  const before2 = fstatSync25(fd);
114898
115180
  if (!before2.isFile() || before2.size > 1048576 || before2.size < 1)
@@ -115189,7 +115471,7 @@ var init_completion = __esm(() => {
115189
115471
  });
115190
115472
 
115191
115473
  // src/lib/portable-snapshot-filter.ts
115192
- import { readdirSync as readdirSync22, statSync as statSync20 } from "fs";
115474
+ import { readdirSync as readdirSync22, statSync as statSync21 } from "fs";
115193
115475
  import { homedir as homedir11 } from "os";
115194
115476
  import { join as join63, sep as sep13 } from "path";
115195
115477
  function isExcludedSkillFileName(fileName) {
@@ -115257,7 +115539,7 @@ function walkEntries(absoluteRoot) {
115257
115539
  }
115258
115540
  function isRegularFile(filePath) {
115259
115541
  try {
115260
- return statSync20(filePath).isFile();
115542
+ return statSync21(filePath).isFile();
115261
115543
  } catch {
115262
115544
  return false;
115263
115545
  }
@@ -115343,10 +115625,10 @@ import {
115343
115625
  copyFileSync as copyFileSync2,
115344
115626
  mkdirSync as mkdirSync27,
115345
115627
  readFileSync as readFileSync42,
115346
- statSync as statSync21,
115628
+ statSync as statSync22,
115347
115629
  writeFileSync as writeFileSync26
115348
115630
  } from "fs";
115349
- import { dirname as dirname36, isAbsolute as isAbsolute32, relative as relative11, resolve as resolve30, sep as sep14 } from "path";
115631
+ import { dirname as dirname36, isAbsolute as isAbsolute33, relative as relative11, resolve as resolve30, sep as sep14 } from "path";
115350
115632
  function validateStationId(stationId) {
115351
115633
  if (!/^[a-z0-9-]+$/.test(stationId)) {
115352
115634
  throw new StationSnapshotError("INVALID_STATION", `station id must be a slug, got: ${stationId}`);
@@ -115383,7 +115665,7 @@ function scanHome(definition, homesRoot) {
115383
115665
  skipped.push({ relativePath: entry.relativePath, reason: "not-regular-file" });
115384
115666
  continue;
115385
115667
  }
115386
- const info = statSync21(entry.fullPath);
115668
+ const info = statSync22(entry.fullPath);
115387
115669
  portable.push({
115388
115670
  relativePath: entry.relativePath,
115389
115671
  fullPath: entry.fullPath,
@@ -115452,7 +115734,7 @@ function writeStationSnapshot(options) {
115452
115734
  for (const plan of plans) {
115453
115735
  const destination = resolve30(repoRoot, plan.destination);
115454
115736
  const destinationRelative = relative11(repoRoot, destination);
115455
- if (destinationRelative.startsWith("..") || destinationRelative.startsWith(sep14) || isAbsolute32(destinationRelative)) {
115737
+ if (destinationRelative.startsWith("..") || destinationRelative.startsWith(sep14) || isAbsolute33(destinationRelative)) {
115456
115738
  throw new StationSnapshotError("DESTINATION_ESCAPE", `destination escapes repo root: ${plan.destination}`);
115457
115739
  }
115458
115740
  let existingDigest = null;
@@ -115924,6 +116206,50 @@ var init_create_sync_config = __esm(() => {
115924
116206
  init_station_snapshot();
115925
116207
  });
115926
116208
 
116209
+ // src/lib/agent-install-selection.ts
116210
+ import { lstatSync as lstatSync36 } from "fs";
116211
+ import { dirname as dirname37, join as join65, resolve as resolve31 } from "path";
116212
+ import { homedir as homedir12 } from "os";
116213
+ function detectedIntegrationAgents(options = {}) {
116214
+ const home = options.home ?? homedir12(), env3 = options.env ?? process.env;
116215
+ const policy = readManagedSkillPolicySnapshot(options.dataDir ?? getDataDirReadOnly())?.value;
116216
+ const bridge = policy?.bridge;
116217
+ if (bridge !== undefined && (!bridge || typeof bridge !== "object" || Array.isArray(bridge)))
116218
+ throw new Error("Invalid existing Skills bridge policy");
116219
+ const configured = bridge === undefined ? [] : bridge.agents;
116220
+ if (!Array.isArray(configured) || configured.some((agent) => !INTEGRATION_AGENTS.includes(agent)))
116221
+ throw new Error("Invalid existing bridge agent inventory");
116222
+ const present = (path) => {
116223
+ try {
116224
+ return lstatSync36(path, { throwIfNoEntry: false }) !== undefined;
116225
+ } catch {
116226
+ throw new Error("Agent presence cannot be inspected; review native configuration before hook installation");
116227
+ }
116228
+ };
116229
+ const selected = INTEGRATION_AGENTS.filter((agent) => {
116230
+ if (configured.includes(agent) || Bun.which(agent, { PATH: env3.PATH ?? "" }))
116231
+ return true;
116232
+ if (agent === "sumi") {
116233
+ const xdg = env3.XDG_CONFIG_HOME;
116234
+ const xdgSumi = xdg?.trim() ? resolve31(options.cwd ?? process.cwd(), xdg === "~" ? home : xdg.startsWith("~/") || xdg.startsWith("~\\") ? resolve31(home, xdg.slice(2)) : xdg, "sumi") : null;
116235
+ return ["SUMI_HOME", "SUMI_CONFIG_DIR", "SUMI_CONFIG", "SUMI_CONFIG_CONTENT"].some((key) => env3[key] !== undefined) || Bun.which("sumi-paths", { PATH: env3.PATH ?? "" }) !== null || NATIVE_SKILL_ROOTS.some(([provider, root2]) => provider === "sumi" && present(join65(home, dirname37(root2)))) || present(join65(home, ".config", "sumi")) || xdgSumi !== null && present(xdgSumi);
116236
+ }
116237
+ if (agent === "hermes" && env3.HERMES_HOME !== undefined)
116238
+ return true;
116239
+ const adapter = AGENT_ADAPTERS[agent];
116240
+ return present(join65(home, dirname37(adapter.config))) || NATIVE_SKILL_ROOTS.some(([provider, root2]) => provider === agent && dirname37(root2) === `.${agent}` && present(join65(home, dirname37(root2))));
116241
+ });
116242
+ if (!selected.length)
116243
+ throw new Error(`No configured or detected agents; select --agent <agent> explicitly (${INTEGRATION_AGENTS.join(", ")}).`);
116244
+ return selected;
116245
+ }
116246
+ var init_agent_install_selection = __esm(() => {
116247
+ init_agent_adapters();
116248
+ init_native_discovery_roots();
116249
+ init_managed_policy();
116250
+ init_config();
116251
+ });
116252
+
115927
116253
  // src/lib/codex-native-config.ts
115928
116254
  import { isDeepStrictEqual as isDeepStrictEqual14 } from "util";
115929
116255
  function isRecord8(value) {
@@ -115971,11 +116297,11 @@ var NUMBER_TAG = "$serde_json::private::Number";
115971
116297
  var init_codex_native_config = () => {};
115972
116298
 
115973
116299
  // src/lib/codex-hook-trust-identity.ts
115974
- import { lstatSync as lstatSync36, realpathSync as realpathSync19 } from "fs";
115975
- import { dirname as dirname37, isAbsolute as isAbsolute33, join as join65, resolve as resolve31 } from "path";
116300
+ import { lstatSync as lstatSync37, realpathSync as realpathSync19 } from "fs";
116301
+ import { dirname as dirname38, isAbsolute as isAbsolute34, join as join66, resolve as resolve32 } from "path";
115976
116302
  import { isDeepStrictEqual as isDeepStrictEqual15 } from "util";
115977
116303
  function commandPhysical(command) {
115978
- need6(typeof command === "string" && isAbsolute33(command) && !command.includes("\x00") && resolve31(command) === command, COMMAND_NOT_CANONICAL);
116304
+ need6(typeof command === "string" && isAbsolute34(command) && !command.includes("\x00") && resolve32(command) === command, COMMAND_NOT_CANONICAL);
115979
116305
  const physical = realpathSync19(command);
115980
116306
  let spelled;
115981
116307
  try {
@@ -115986,7 +116312,7 @@ function commandPhysical(command) {
115986
116312
  safeParents(spelled);
115987
116313
  let direct = false;
115988
116314
  try {
115989
- const leaf = lstatSync36(spelled);
116315
+ const leaf = lstatSync37(spelled);
115990
116316
  direct = leaf.isSymbolicLink() ? trustedAncestorOwner(leaf.uid) && directAliasTarget(spelled) === physical : spelled === physical;
115991
116317
  } catch {}
115992
116318
  need6(direct, COMMAND_ALIAS_UNSAFE);
@@ -115998,7 +116324,7 @@ function assertPinnedRuntime(runtime) {
115998
116324
  } catch {
115999
116325
  need6(false, "SKILLS_LAUNCHER_UNVERIFIED");
116000
116326
  }
116001
- need6(resolve31(runtime) === runtime, "SKILLS_LAUNCHER_UNVERIFIED");
116327
+ need6(resolve32(runtime) === runtime, "SKILLS_LAUNCHER_UNVERIFIED");
116002
116328
  safeParents(runtime);
116003
116329
  }
116004
116330
  function skillsCommandTarget(command) {
@@ -116030,12 +116356,12 @@ function targetUnchanged(command, target) {
116030
116356
  assertPinnedRuntime(target.runtime);
116031
116357
  }
116032
116358
  function inspectRecordedSkillsCli(command, expected) {
116033
- need6(isAbsolute33(command) && !command.includes("\x00"), "RECONCILE_RECORDED_COMMAND_REQUIRED");
116359
+ need6(isAbsolute34(command) && !command.includes("\x00"), "RECONCILE_RECORDED_COMMAND_REQUIRED");
116034
116360
  const target = skillsCommandTarget(command), resolved = target.entry;
116035
116361
  const cli = snapshot(resolved, false, { readOnlyPackage: true });
116036
- const manifest = snapshot(join65(dirname37(dirname37(resolved)), "package.json"), false, { readOnlyPackage: true });
116362
+ const manifest = snapshot(join66(dirname38(dirname38(resolved)), "package.json"), false, { readOnlyPackage: true });
116037
116363
  const pkg = JSON.parse(manifest.text);
116038
- need6(pkg.name === "@hasna/skills" && /^\d+\.\d+\.\d+$/.test(pkg.version) && pkg.bin?.skills === "bin/index.js" && resolved === join65(dirname37(manifest.file), "bin/index.js"), "SKILLS_PACKAGE_MISMATCH");
116364
+ need6(pkg.name === "@hasna/skills" && /^\d+\.\d+\.\d+$/.test(pkg.version) && pkg.bin?.skills === "bin/index.js" && resolved === join66(dirname38(manifest.file), "bin/index.js"), "SKILLS_PACKAGE_MISMATCH");
116039
116365
  need6((cli.stat.mode & 0o100n) !== 0n, "SKILLS_COMMAND_NOT_EXECUTABLE");
116040
116366
  const receipt = { path: resolved, version: pkg.version, sha256: cli.sha256, manifestSha256: manifest.sha256 };
116041
116367
  need6(isDeepStrictEqual15(receipt, expected), "RECONCILE_SKILLS_BINDING_CHANGED");
@@ -116049,16 +116375,16 @@ function bindSkillsCli(command, reviewed) {
116049
116375
  const normal = Bun.which("skills", { PATH: process.env.PATH });
116050
116376
  need6(normal, "SKILLS_COMMAND_UNAVAILABLE");
116051
116377
  const normalTarget = skillsCommandTarget(normal), resolved = normalTarget.entry;
116052
- const bound = isAbsolute33(command) ? command : command === "skills" ? normal : undefined;
116378
+ const bound = isAbsolute34(command) ? command : command === "skills" ? normal : undefined;
116053
116379
  need6(bound, "SKILLS_COMMAND_MISMATCH");
116054
116380
  const boundTarget = skillsCommandTarget(bound);
116055
116381
  need6(boundTarget.entry === resolved, "SKILLS_COMMAND_MISMATCH");
116056
116382
  const entrypoint = reviewed?.path ?? process.argv[1];
116057
116383
  need6(entrypoint && realpathSync19(entrypoint) === resolved, "SKILLS_ENTRYPOINT_MISMATCH");
116058
116384
  const cli = snapshot(resolved, false, { readOnlyPackage: true });
116059
- const manifest = snapshot(join65(dirname37(dirname37(resolved)), "package.json"), false, { readOnlyPackage: true });
116385
+ const manifest = snapshot(join66(dirname38(dirname38(resolved)), "package.json"), false, { readOnlyPackage: true });
116060
116386
  const pkg = JSON.parse(manifest.text);
116061
- need6(pkg.name === "@hasna/skills" && /^\d+\.\d+\.\d+$/.test(pkg.version) && pkg.bin?.skills === "bin/index.js" && resolved === join65(dirname37(manifest.file), "bin/index.js"), "SKILLS_PACKAGE_MISMATCH");
116387
+ need6(pkg.name === "@hasna/skills" && /^\d+\.\d+\.\d+$/.test(pkg.version) && pkg.bin?.skills === "bin/index.js" && resolved === join66(dirname38(manifest.file), "bin/index.js"), "SKILLS_PACKAGE_MISMATCH");
116062
116388
  if (reviewed)
116063
116389
  need6(/^[a-f0-9]{64}$/.test(reviewed.sha256) && reviewed.sha256 === cli.sha256 && reviewed.version === pkg.version, "SKILLS_RELEASE_MISMATCH");
116064
116390
  need6((cli.stat.mode & 0o100n) !== 0n, "SKILLS_COMMAND_NOT_EXECUTABLE");
@@ -116077,7 +116403,7 @@ function captureSkillsCliProducerIdentity(command) {
116077
116403
  const bound = bindSkillsCli(command);
116078
116404
  const target = skillsCommandTarget(command);
116079
116405
  const cli = snapshot(target.entry, false, { readOnlyPackage: true });
116080
- const manifest = snapshot(join65(dirname37(dirname37(target.entry)), "package.json"), false, { readOnlyPackage: true });
116406
+ const manifest = snapshot(join66(dirname38(dirname38(target.entry)), "package.json"), false, { readOnlyPackage: true });
116081
116407
  const pkg = JSON.parse(manifest.text);
116082
116408
  need6(pkg.name === "@hasna/skills" && pkg.version === bound.receipt.version && target.entry === bound.receipt.path, "SKILLS_PACKAGE_MISMATCH");
116083
116409
  const launcher = target.launcher ?? cli;
@@ -116131,20 +116457,20 @@ var init_codex_hook_policy_recovery = __esm(() => {
116131
116457
  });
116132
116458
 
116133
116459
  // src/lib/agent-codex-trust.ts
116134
- import { lstatSync as lstatSync37, mkdirSync as mkdirSync28, readdirSync as readdirSync23, readFileSync as readFileSync43, realpathSync as realpathSync20, statSync as statSync22 } from "fs";
116460
+ import { lstatSync as lstatSync38, mkdirSync as mkdirSync28, readdirSync as readdirSync23, readFileSync as readFileSync43, realpathSync as realpathSync20, statSync as statSync23 } from "fs";
116135
116461
  import { createHash as createHash39, randomUUID as randomUUID12 } from "crypto";
116136
116462
  import { execFileSync as execFileSync2 } from "child_process";
116137
- import { dirname as dirname38, isAbsolute as isAbsolute34, join as join66, resolve as resolve32 } from "path";
116138
- import { homedir as homedir12 } from "os";
116463
+ import { dirname as dirname39, isAbsolute as isAbsolute35, join as join67, resolve as resolve33 } from "path";
116464
+ import { homedir as homedir13 } from "os";
116139
116465
  import { isDeepStrictEqual as isDeepStrictEqual17 } from "util";
116140
116466
  function verifyReleaseArtifact(proof, skillsCli) {
116141
- need6(isAbsolute34(proof.packageTarPath) && !proof.packageTarPath.includes("\x00"), "RECONCILE_RELEASE_PROVENANCE_PATH");
116467
+ need6(isAbsolute35(proof.packageTarPath) && !proof.packageTarPath.includes("\x00"), "RECONCILE_RELEASE_PROVENANCE_PATH");
116142
116468
  const tarPath = realpathSync20(proof.packageTarPath);
116143
- need6(statSync22(tarPath).isFile(), "RECONCILE_RELEASE_PROVENANCE_PATH");
116469
+ need6(statSync23(tarPath).isFile(), "RECONCILE_RELEASE_PROVENANCE_PATH");
116144
116470
  const tarBytes = readFileSync43(tarPath);
116145
116471
  need6(tarBytes.byteLength === proof.packageTarBytes && createHash39("sha256").update(tarBytes).digest("hex") === proof.packageTarSha256, "RECONCILE_RELEASE_ARTIFACT_CHANGED");
116146
- const packageRoot = dirname38(dirname38(realpathSync20(skillsCli.receipt.path)));
116147
- const manifest = readFileSync43(join66(packageRoot, "package.json"));
116472
+ const packageRoot = dirname39(dirname39(realpathSync20(skillsCli.receipt.path)));
116473
+ const manifest = readFileSync43(join67(packageRoot, "package.json"));
116148
116474
  need6(createHash39("sha256").update(manifest).digest("hex") === skillsCli.receipt.manifestSha256 && skillsCli.receipt.manifestSha256 === proof.manifestSha256, "RECONCILE_RELEASE_MANIFEST_CHANGED");
116149
116475
  need6(createHash39("sha256").update(readFileSync43(skillsCli.receipt.path)).digest("hex") === proof.executableSha256 && skillsCli.receipt.sha256 === proof.executableSha256, "RECONCILE_RELEASE_EXECUTABLE_CHANGED");
116150
116476
  const members2 = [["package/package.json", manifest], ["package/bin/index.js", readFileSync43(skillsCli.receipt.path)]];
@@ -116161,26 +116487,26 @@ function verifyReleaseArtifact(proof, skillsCli) {
116161
116487
  async function reconcileCodexNativeHooks(options, connect = connectCodexHookRpc) {
116162
116488
  let rpc;
116163
116489
  try {
116164
- const home = resolve32(options.home ?? homedir12()), dataDir3 = resolve32(options.dataDir ?? getDataDirReadOnly());
116165
- const parent = resolve32(join66(dataDir3, "native-hook-trust")), journal = resolve32(options.journal);
116490
+ const home = resolve33(options.home ?? homedir13()), dataDir3 = resolve33(options.dataDir ?? getDataDirReadOnly());
116491
+ const parent = resolve33(join67(dataDir3, "native-hook-trust")), journal = resolve33(options.journal);
116166
116492
  need6(journal.startsWith(parent + "/") && /^[a-f0-9-]{36}$/.test(journal.slice(parent.length + 1)), "RECONCILE_JOURNAL_PATH");
116167
- const dir = lstatSync37(journal, { throwIfNoEntry: false });
116493
+ const dir = lstatSync38(journal, { throwIfNoEntry: false });
116168
116494
  need6(!!dir && dir.isDirectory() && !dir.isSymbolicLink() && dir.uid === process.getuid() && (dir.mode & 511) === 448, "UNSAFE_JOURNAL");
116169
- need6(!lstatSync37(join66(journal, "receipt.json"), { throwIfNoEntry: false }), "RECONCILE_ALREADY_COMPLETE");
116170
- need6(lstatSync37(join66(journal, "stopped.json"), { throwIfNoEntry: false })?.isFile(), "RECONCILE_JOURNAL_INCOMPLETE");
116171
- const stoppedFile = snapshot(join66(journal, "stopped.json"), true);
116172
- const intentFile = snapshot(join66(journal, "intent.json"), true), intent = JSON.parse(intentFile.text);
116173
- const configBefore = snapshot(join66(journal, "config.before.toml"), true), hooksBefore = snapshot(join66(journal, "hooks.before.json"), true), policyBefore = snapshot(join66(journal, "policy.before.json"), true);
116495
+ need6(!lstatSync38(join67(journal, "receipt.json"), { throwIfNoEntry: false }), "RECONCILE_ALREADY_COMPLETE");
116496
+ need6(lstatSync38(join67(journal, "stopped.json"), { throwIfNoEntry: false })?.isFile(), "RECONCILE_JOURNAL_INCOMPLETE");
116497
+ const stoppedFile = snapshot(join67(journal, "stopped.json"), true);
116498
+ const intentFile = snapshot(join67(journal, "intent.json"), true), intent = JSON.parse(intentFile.text);
116499
+ const configBefore = snapshot(join67(journal, "config.before.toml"), true), hooksBefore = snapshot(join67(journal, "hooks.before.json"), true), policyBefore = snapshot(join67(journal, "policy.before.json"), true);
116174
116500
  const legacyIntent = intent.home === undefined && intent.configSha256 === undefined && intent.configVersion === undefined && intent.declarations === undefined && intent.admitted === undefined && intent.nativeHooks === undefined;
116175
116501
  need6(intent.version === 1 && /^[a-f0-9]{64}$/.test(intent.planDigest) && typeof intent.configPath === "string" && /^[a-f0-9]{64}$/.test(intent.policySha256) && /^[a-f0-9]{64}$/.test(intent.hooksSha256) && Array.isArray(intent.hooks) && intent.hooks.length > 0 && intent.hooks.length <= 100 && (legacyIntent || typeof intent.home === "string" && intent.home === home && /^[a-f0-9]{64}$/.test(intent.configSha256) && typeof intent.configVersion === "string" && Array.isArray(intent.declarations) && Array.isArray(intent.admitted) && Array.isArray(intent.nativeHooks)), "RECONCILE_INTENT_INVALID");
116176
- const declarations = intent.declarations ?? intent.hooks.map((hook) => ({ event: hook.event, key: `${join66(home, ".codex/hooks.json")}${hook.key.slice(hook.key.indexOf(".codex/hooks.json") + ".codex/hooks.json".length)}`, command: hook.command }));
116502
+ const declarations = intent.declarations ?? intent.hooks.map((hook) => ({ event: hook.event, key: `${join67(home, ".codex/hooks.json")}${hook.key.slice(hook.key.indexOf(".codex/hooks.json") + ".codex/hooks.json".length)}`, command: hook.command }));
116177
116503
  const admitted = intent.admitted ?? intent.hooks;
116178
116504
  const configSha256 = intent.configSha256 ?? configBefore.sha256, configVersion = intent.configVersion ?? intent.expectedVersion;
116179
116505
  const digestInput = { version: 1, home: intent.home ?? home, configPath: intent.configPath, ...intent.nativeConfigPath !== undefined ? { nativeConfigPath: intent.nativeConfigPath } : {}, configSha256, configVersion, policySha256: intent.policySha256, hooksSha256: intent.hooksSha256, skillsCli: intent.skillsCli, nativeVersion: intent.nativeVersion, declarations, admitted };
116180
116506
  need6(makePlanDigest(digestInput) === intent.planDigest, "RECONCILE_PLAN_CHANGED");
116181
116507
  need6(isDeepStrictEqual17(intent.hooks, admitted.filter((hook) => !hook.enabled || hook.trustStatus !== "trusted")), "RECONCILE_INTENT_HOOKS_CHANGED");
116182
116508
  need6(configBefore.sha256 === (intent.beforeSha256 ?? intent.configSha256) && hooksBefore.sha256 === intent.hooksSha256 && policyBefore.sha256 === intent.policySha256, "RECONCILE_JOURNAL_CHANGED");
116183
- const policyCurrent = snapshot(join66(dataDir3, "agent-policy.json"), true);
116509
+ const policyCurrent = snapshot(join67(dataDir3, "agent-policy.json"), true);
116184
116510
  const { claudeDiscoveryRecovery: claudeRecovery, nativeHookAdditionsRecovery: additionsRecovery } = options;
116185
116511
  const recovery = claudeRecovery ?? additionsRecovery;
116186
116512
  need6(!recovery || !options.supersedeBinding, "RECONCILE_RECOVERY_MODE_CONFLICT");
@@ -116197,17 +116523,17 @@ async function reconcileCodexNativeHooks(options, connect = connectCodexHookRpc)
116197
116523
  if (supersededBinding || recovery) {
116198
116524
  need6(Array.isArray(intent.nativeHooks) && intent.nativeHooks.length > 0, "RECONCILE_NATIVE_INVENTORY_REQUIRED");
116199
116525
  const proof = options.releaseProof;
116200
- need6(!!proof && isAbsolute34(proof.packageTarPath) && /^[a-f0-9]{64}$/.test(proof.packageTarSha256) && Number.isInteger(proof.packageTarBytes) && proof.packageTarBytes > 0 && /^[a-f0-9]{64}$/.test(proof.manifestSha256) && /^[a-f0-9]{64}$/.test(proof.executableSha256), "RECONCILE_RELEASE_PROVENANCE_REQUIRED");
116526
+ need6(!!proof && isAbsolute35(proof.packageTarPath) && /^[a-f0-9]{64}$/.test(proof.packageTarSha256) && Number.isInteger(proof.packageTarBytes) && proof.packageTarBytes > 0 && /^[a-f0-9]{64}$/.test(proof.manifestSha256) && /^[a-f0-9]{64}$/.test(proof.executableSha256), "RECONCILE_RELEASE_PROVENANCE_REQUIRED");
116201
116527
  }
116202
116528
  const currentConfig = snapshot(intent.configPath, true);
116203
116529
  const policy = parseManagedSkillPolicy(policyCurrent.text), binding = policy.bridge;
116204
- const alias = binding.rootAliases?.find((item) => item.agent === "codex"), physicalRoot = alias?.target ?? join66(home, ".codex"), hooksPath = join66(physicalRoot, "hooks.json");
116205
- need6(resolve32(intent.configPath) === resolve32(join66(physicalRoot, "config.toml")), "RECONCILE_CONFIG_PATH_CHANGED");
116530
+ const alias = binding.rootAliases?.find((item) => item.agent === "codex"), physicalRoot = alias?.target ?? join67(home, ".codex"), hooksPath = join67(physicalRoot, "hooks.json");
116531
+ need6(resolve33(intent.configPath) === resolve33(join67(physicalRoot, "config.toml")), "RECONCILE_CONFIG_PATH_CHANGED");
116206
116532
  const nativeConfigPath = intent.nativeConfigPath ?? intent.configPath;
116207
- need6([join66(home, ".codex/config.toml"), join66(physicalRoot, "config.toml")].includes(nativeConfigPath), "RECONCILE_NATIVE_CONFIG_PATH_CHANGED");
116208
- const codexHome = nativeConfigPath !== intent.configPath ? undefined : dirname38(nativeConfigPath);
116533
+ need6([join67(home, ".codex/config.toml"), join67(physicalRoot, "config.toml")].includes(nativeConfigPath), "RECONCILE_NATIVE_CONFIG_PATH_CHANGED");
116534
+ const codexHome = nativeConfigPath !== intent.configPath ? undefined : dirname39(nativeConfigPath);
116209
116535
  const hooksCurrent = snapshot(hooksPath);
116210
- const additions = additionsRecovery ? reviewNativeHookAdditions({ path: additionsRecovery.path, intent: intentFile, policy: policyCurrent, configBefore, configCurrent: currentConfig, hooksBefore, hooksCurrent, nativeHooksPath: join66(dirname38(nativeConfigPath), "hooks.json"), journalHooks: intent.hooks, recordedNativeHooks: intent.nativeHooks }) : undefined;
116536
+ const additions = additionsRecovery ? reviewNativeHookAdditions({ path: additionsRecovery.path, intent: intentFile, policy: policyCurrent, configBefore, configCurrent: currentConfig, hooksBefore, hooksCurrent, nativeHooksPath: join67(dirname39(nativeConfigPath), "hooks.json"), journalHooks: intent.hooks, recordedNativeHooks: intent.nativeHooks }) : undefined;
116211
116537
  const managedHooks = [...intent.hooks, ...additions?.hooks ?? []];
116212
116538
  const managedKeys = managedHooks.map((h) => h.key);
116213
116539
  const witnessSame = codexTrustReconcileWitness(configBefore.text, managedKeys) === codexTrustReconcileWitness(currentConfig.text, managedKeys);
@@ -116271,7 +116597,7 @@ async function reconcileCodexNativeHooks(options, connect = connectCodexHookRpc)
116271
116597
  need6(isDeepStrictEqual17(actual, expected), "RECONCILE_UNRELATED_HOOK_CHANGED");
116272
116598
  }
116273
116599
  for (const wanted of intent.hooks) {
116274
- const matches2 = nativeHooks.filter((h2) => h2.key === wanted.key || h2.key === wanted.key.replace(join66(home, ".codex/hooks.json"), hooksPath));
116600
+ const matches2 = nativeHooks.filter((h2) => h2.key === wanted.key || h2.key === wanted.key.replace(join67(home, ".codex/hooks.json"), hooksPath));
116275
116601
  need6(matches2.length === 1, "RECONCILE_NATIVE_IDENTITY_CHANGED");
116276
116602
  const h = matches2[0];
116277
116603
  const trusted = h.trustStatus === "trusted";
@@ -116320,7 +116646,7 @@ async function reconcileCodexNativeHooks(options, connect = connectCodexHookRpc)
116320
116646
  const receipt = { version: 1, status: preview2 ? "recovery-review-required" : supersededBinding ? "superseded" : "reconciled", reconciled: !preview2, supersededBinding, automaticRollback: false, journal, planDigest: intent.planDigest, nativeVersion: rpc.version, nativeStateVerified: !nativeTrustPending, nativeTrustPending, bindingRefreshRequired: !!configDiscoveryRecovery, nativeExecutionVerified: false, configSha256: currentConfig.sha256, hooksSha256: hooksCurrent.sha256, policySha256: policyBefore.sha256, policyBeforeSha256: policyBefore.sha256, policyCurrentSha256: policyCurrent.sha256, previousSkillsCli: intent.skillsCli, skillsCli: skillsCli.receipt, releaseProof: options.releaseProof, nativeInventoryScope: recordedNativeHooks ? "complete" : "declared-managed-hooks-only", unrelatedNativeHooksPreserved: !!recordedNativeHooks, unrelatedSettingsAndCommentsPreserved: true, ...recoveryPlan ? { recoveryPlan, recoveryPlanDigest } : {} };
116321
116647
  if (preview2)
116322
116648
  return receipt;
116323
- save(join66(journal, "receipt.json"), json2(receipt));
116649
+ save(join67(journal, "receipt.json"), json2(receipt));
116324
116650
  return receipt;
116325
116651
  } catch (error61) {
116326
116652
  const message = error61 instanceof Error && error61.message.startsWith("CODEX_HOOK_TRUST_") ? error61.message : "CODEX_HOOK_TRUST_RECONCILE_REFUSED";
@@ -116330,21 +116656,21 @@ async function reconcileCodexNativeHooks(options, connect = connectCodexHookRpc)
116330
116656
  }
116331
116657
  }
116332
116658
  async function enrollCodexNativeHooks(options = {}, connect = connectCodexHookRpc) {
116333
- const home = resolve32(options.home ?? homedir12());
116334
- return withCodexCorpusWriteAsync([join66(home, ".codex")], () => enrollCodexNativeHooksUnlocked(options, connect), options);
116659
+ const home = resolve33(options.home ?? homedir13());
116660
+ return withCodexCorpusWriteAsync([join67(home, ".codex")], () => enrollCodexNativeHooksUnlocked(options, connect), options);
116335
116661
  }
116336
116662
  async function enrollCodexNativeHooksUnlocked(options, connect) {
116337
116663
  let rpc, journal;
116338
116664
  try {
116339
- const home = resolve32(options.home ?? homedir12()), dataDir3 = resolve32(options.dataDir ?? getDataDirReadOnly());
116665
+ const home = resolve33(options.home ?? homedir13()), dataDir3 = resolve33(options.dataDir ?? getDataDirReadOnly());
116340
116666
  assertManagedAgentBridge("codex", { home, dataDir: dataDir3, projectDir: home });
116341
- const policyFile = snapshot(join66(dataDir3, "agent-policy.json"), true), policy = parseManagedSkillPolicy(policyFile.text);
116667
+ const policyFile = snapshot(join67(dataDir3, "agent-policy.json"), true), policy = parseManagedSkillPolicy(policyFile.text);
116342
116668
  const binding = policy.bridge, alias = binding.rootAliases?.find((item) => item.agent === "codex");
116343
116669
  const skillsCli = bindSkillsCli(binding.commands.codex, options.reviewedSkillsCli);
116344
- const physicalRoot = alias?.target ?? join66(home, ".codex"), hooksPath = join66(physicalRoot, "hooks.json"), configPath = join66(physicalRoot, "config.toml");
116345
- need6(options.codexHome === undefined || isAbsolute34(options.codexHome) && [join66(home, ".codex"), physicalRoot].includes(options.codexHome), "NATIVE_HOME_NOT_ADMITTED");
116670
+ const physicalRoot = alias?.target ?? join67(home, ".codex"), hooksPath = join67(physicalRoot, "hooks.json"), configPath = join67(physicalRoot, "config.toml");
116671
+ need6(options.codexHome === undefined || isAbsolute35(options.codexHome) && [join67(home, ".codex"), physicalRoot].includes(options.codexHome), "NATIVE_HOME_NOT_ADMITTED");
116346
116672
  const codexHome = options.codexHome === undefined ? undefined : physicalRoot;
116347
- const nativeConfigPath = join66(codexHome ?? join66(home, ".codex"), "config.toml");
116673
+ const nativeConfigPath = join67(codexHome ?? join67(home, ".codex"), "config.toml");
116348
116674
  const hooksFile = snapshot(hooksPath), configFile = snapshot(configPath, true), original = structure3(configFile.text);
116349
116675
  const declarations = JSON.parse(hooksFile.text).hooks, expected = [];
116350
116676
  for (const [event, [nativeEvent, label]] of Object.entries(eventNames)) {
@@ -116353,25 +116679,25 @@ async function enrollCodexNativeHooksUnlocked(options, connect) {
116353
116679
  need6(Array.isArray(groups), "DECLARATION_CHANGED");
116354
116680
  const matches2 = groups.flatMap((group, gi) => (group.hooks ?? []).flatMap((entry, hi) => entry.command === command ? [{ group, entry, gi, hi }] : []));
116355
116681
  need6(matches2.length === 1 && isDeepStrictEqual17(matches2[0].group, { hooks: [{ type: "command", command, timeout: 15 }] }), "DECLARATION_CHANGED");
116356
- expected.push({ event: nativeEvent, key: `${join66(home, ".codex/hooks.json")}:${label}:${matches2[0].gi}:${matches2[0].hi}`, command });
116682
+ expected.push({ event: nativeEvent, key: `${join67(home, ".codex/hooks.json")}:${label}:${matches2[0].gi}:${matches2[0].hi}`, command });
116357
116683
  }
116358
116684
  codexTrustTextWitness(configFile.text, expected.map((h) => h.key));
116359
116685
  rpc = await connect({ command: options.codexCommand ?? "codex", home, codexHome });
116360
116686
  need6(SUPPORTED_CODEX_HOOK_VERSIONS.includes(rpc.version), "NATIVE_UNSUPPORTED_VERSION");
116361
116687
  const list2 = async () => {
116362
116688
  const response = await rpc.request("hooks/list", { cwds: [home] });
116363
- const nativeRoots = [...new Set([physicalRoot, join66(home, ".codex")])];
116364
- const coexistenceWarnings = nativeRoots.flatMap((hooksRoot) => nativeRoots.map((configRoot) => `loading hooks from both ${join66(hooksRoot, "hooks.json")} and ${join66(configRoot, "config.toml")}; prefer a single representation for this layer`));
116689
+ const nativeRoots = [...new Set([physicalRoot, join67(home, ".codex")])];
116690
+ const coexistenceWarnings = nativeRoots.flatMap((hooksRoot) => nativeRoots.map((configRoot) => `loading hooks from both ${join67(hooksRoot, "hooks.json")} and ${join67(configRoot, "config.toml")}; prefer a single representation for this layer`));
116365
116691
  const entry = response?.data?.[0];
116366
116692
  need6(Array.isArray(response?.data) && response.data.length === 1 && entry.cwd === home && Array.isArray(entry.hooks) && entry.hooks.length <= 1e4 && Array.isArray(entry.errors) && entry.errors.length === 0 && Array.isArray(entry.warnings) && entry.warnings.length <= 1 && entry.warnings.every((warning) => typeof warning === "string" && coexistenceWarnings.includes(warning)), "NATIVE_DISCOVERY_REFUSED");
116367
116693
  return response.data[0].hooks;
116368
116694
  };
116369
116695
  const admit = (hooks) => expected.map((wanted) => {
116370
- const canonicalKey = wanted.key.replace(join66(home, ".codex/hooks.json"), hooksPath);
116696
+ const canonicalKey = wanted.key.replace(join67(home, ".codex/hooks.json"), hooksPath);
116371
116697
  const matches2 = hooks.filter((h2) => h2.key === wanted.key || h2.key === canonicalKey);
116372
116698
  need6(matches2.length === 1, "AMBIGUOUS_IDENTITY");
116373
116699
  const h = matches2[0];
116374
- need6(h.eventName === wanted.event && h.handlerType === "command" && h.command === wanted.command && h.matcher === null && h.timeoutSec === 15 && h.async === false && h.statusMessage === null && h.additionalContextLimit === null && [hooksPath, join66(home, ".codex/hooks.json")].includes(h.sourcePath) && h.source === "user" && h.pluginId === null && h.isManaged === false && /^sha256:[a-f0-9]{64}$/.test(h.currentHash) && typeof h.enabled === "boolean", "NATIVE_IDENTITY_CHANGED");
116700
+ need6(h.eventName === wanted.event && h.handlerType === "command" && h.command === wanted.command && h.matcher === null && h.timeoutSec === 15 && h.async === false && h.statusMessage === null && h.additionalContextLimit === null && [hooksPath, join67(home, ".codex/hooks.json")].includes(h.sourcePath) && h.source === "user" && h.pluginId === null && h.isManaged === false && /^sha256:[a-f0-9]{64}$/.test(h.currentHash) && typeof h.enabled === "boolean", "NATIVE_IDENTITY_CHANGED");
116375
116701
  need6(hooks.filter((other) => other.command === wanted.command).length === 1, "AMBIGUOUS_IDENTITY");
116376
116702
  need6(["trusted", "untrusted", "modified"].includes(h.trustStatus), "UNKNOWN_TRUST_STATUS");
116377
116703
  return { key: h.key, event: wanted.event, command: wanted.command, handlerType: h.handlerType, timeoutSec: h.timeoutSec, sourcePath: h.sourcePath, currentHash: h.currentHash, enabled: h.enabled, trustStatus: h.trustStatus };
@@ -116397,27 +116723,27 @@ async function enrollCodexNativeHooksUnlocked(options, connect) {
116397
116723
  const baseReceipt = { planDigest, skillsCli: skillsCli.receipt, nativeVersion: rpc.version, nativeConfigPath, ownedNativeProcessId: rpc.processId, agent: "codex", applied: false, planned, nativeEligible: planned.length === 0, bindingRefreshRequired: false, transport: "owned-stdio-process", existingSessionsReloaded: false, nativeExecutionVerified: false };
116398
116724
  if (options.apply)
116399
116725
  need6(options.reviewedPlanDigest === planDigest, "PLAN_CHANGED: run the dry-run again and pass its reviewed --plan-digest with --apply");
116400
- const parent = join66(dataDir3, "native-hook-trust");
116401
- const st = lstatSync37(parent, { throwIfNoEntry: false });
116726
+ const parent = join67(dataDir3, "native-hook-trust");
116727
+ const st = lstatSync38(parent, { throwIfNoEntry: false });
116402
116728
  if (st) {
116403
116729
  need6(st.isDirectory() && !st.isSymbolicLink() && st.uid === process.getuid() && (st.mode & 511) === 448, "UNSAFE_JOURNAL");
116404
116730
  const priorJournals = readdirSync23(parent);
116405
116731
  need6(priorJournals.length < 1000, "JOURNAL_BOUND");
116406
116732
  for (const name of priorJournals) {
116407
116733
  need6(/^[a-f0-9-]{36}$/.test(name), "UNSAFE_JOURNAL");
116408
- need6(lstatSync37(join66(parent, name, "receipt.json"), { throwIfNoEntry: false })?.isFile(), "RECONCILE_REQUIRED: inspect the incomplete private journal before applying again");
116734
+ need6(lstatSync38(join67(parent, name, "receipt.json"), { throwIfNoEntry: false })?.isFile(), "RECONCILE_REQUIRED: inspect the incomplete private journal before applying again");
116409
116735
  }
116410
116736
  }
116411
116737
  if (!options.apply || !planned.length)
116412
116738
  return baseReceipt;
116413
116739
  if (!st)
116414
116740
  mkdirSync28(parent, { mode: 448 });
116415
- journal = join66(parent, randomUUID12());
116741
+ journal = join67(parent, randomUUID12());
116416
116742
  mkdirSync28(journal, { mode: 448 });
116417
- save(join66(journal, "config.before.toml"), configFile.bytes);
116418
- save(join66(journal, "hooks.before.json"), hooksFile.bytes);
116419
- save(join66(journal, "policy.before.json"), policyFile.bytes);
116420
- save(join66(journal, "intent.json"), json2({ ...digestInput, planDigest, hooks: planned, nativeHooks: discovered.map(safeNativeHook) }));
116743
+ save(join67(journal, "config.before.toml"), configFile.bytes);
116744
+ save(join67(journal, "hooks.before.json"), hooksFile.bytes);
116745
+ save(join67(journal, "policy.before.json"), policyFile.bytes);
116746
+ save(join67(journal, "intent.json"), json2({ ...digestInput, planDigest, hooks: planned, nativeHooks: discovered.map(safeNativeHook) }));
116421
116747
  need6(isDeepStrictEqual17(admit(await list2()), admitted), "NATIVE_DISCOVERY_CHANGED");
116422
116748
  checkInputs();
116423
116749
  let result2;
@@ -116433,7 +116759,7 @@ async function enrollCodexNativeHooksUnlocked(options, connect) {
116433
116759
  for (const h of planned)
116434
116760
  expectedConfig.hooks.state[h.key] = { ...expectedConfig.hooks.state[h.key], enabled: true, trusted_hash: h.currentHash };
116435
116761
  need6(isDeepStrictEqual17(structure3(after2.text), expectedConfig) && codexTrustTextWitness(after2.text, keys3) === preservationText, "PRESERVATION_FAILED");
116436
- const savedConfig = snapshot(join66(journal, "config.before.toml"), true);
116762
+ const savedConfig = snapshot(join67(journal, "config.before.toml"), true);
116437
116763
  need6(savedConfig.sha256 === configFile.sha256, "JOURNAL_CHANGED");
116438
116764
  const discoveryTransition = binding.discovery?.codex ? createCodexHookDiscoveryRecovery(binding.discovery.codex, savedConfig, after2, planned) : undefined;
116439
116765
  unchanged2(policyFile);
@@ -116449,13 +116775,13 @@ async function enrollCodexNativeHooksUnlocked(options, connect) {
116449
116775
  skillsCli.recheck();
116450
116776
  assertManagedAgentBridge("codex", { home, dataDir: dataDir3, projectDir: home, codexDiscoveryRecovery: discoveryTransition });
116451
116777
  const receipt = { ...baseReceipt, applied: true, nativeEligible: true, bindingRefreshRequired: !!discoveryTransition, ...discoveryTransition ? { discoveryTransition } : {}, nativeConfigVersion: result2.version, journal, beforeSha256: configFile.sha256, afterSha256: after2.sha256, unrelatedSettingsAndCommentsPreserved: true };
116452
- save(join66(journal, "receipt.json"), json2(receipt));
116778
+ save(join67(journal, "receipt.json"), json2(receipt));
116453
116779
  return receipt;
116454
116780
  } catch (error61) {
116455
116781
  const message = error61 instanceof Error && error61.message.startsWith("CODEX_HOOK_TRUST_") ? error61.message : "CODEX_HOOK_TRUST_REFUSED: verify managed bridge installation and native Codex support";
116456
116782
  if (journal) {
116457
116783
  try {
116458
- save(join66(journal, "stopped.json"), json2({ error: message.split(":")[0], automaticRollback: false, reconcileBeforeRetry: true }));
116784
+ save(join67(journal, "stopped.json"), json2({ error: message.split(":")[0], automaticRollback: false, reconcileBeforeRetry: true }));
116459
116785
  } catch {}
116460
116786
  }
116461
116787
  throw new Error(message);
@@ -116490,7 +116816,7 @@ var init_agent_codex_trust = __esm(() => {
116490
116816
  // src/lib/codex-native-trust.ts
116491
116817
  import { createHash as createHash40 } from "crypto";
116492
116818
  import { readFileSync as readFileSync44 } from "fs";
116493
- import { join as join67, resolve as resolve33 } from "path";
116819
+ import { join as join68, resolve as resolve34 } from "path";
116494
116820
  function refuse5(detail) {
116495
116821
  throw new Error(`NATIVE_SKILL_POLICY_TRUST_REFUSED: ${detail}`);
116496
116822
  }
@@ -116509,7 +116835,7 @@ function planCodexNativeTrust(options) {
116509
116835
  refuse5("digests must be unique");
116510
116836
  if (typeof expectedPolicySha256 !== "string" || !HEX_DIGEST2.test(expectedPolicySha256))
116511
116837
  refuse5("--expected-policy-sha256 must be lowercase SHA-256 hex");
116512
- const dataDir3 = resolve33(options.dataDir ?? getDataDirReadOnly()), policyPath = join67(dataDir3, "agent-policy.json");
116838
+ const dataDir3 = resolve34(options.dataDir ?? getDataDirReadOnly()), policyPath = join68(dataDir3, "agent-policy.json");
116513
116839
  assertOperatorTrustRoot(dataDir3);
116514
116840
  const snapshot2 = readManagedSkillPolicySnapshot(dataDir3);
116515
116841
  if (!snapshot2)
@@ -116692,8 +117018,8 @@ var init_hook_diagnostics = __esm(() => {
116692
117018
 
116693
117019
  // src/lib/claude-prospective-review.ts
116694
117020
  import { createHash as createHash41 } from "crypto";
116695
- import { lstatSync as lstatSync38, readFileSync as readFileSync45, readdirSync as readdirSync24, realpathSync as realpathSync21 } from "fs";
116696
- import { basename as basename19, dirname as dirname39, isAbsolute as isAbsolute35, join as join68, relative as relative12, resolve as resolve34, sep as sep15 } from "path";
117021
+ import { lstatSync as lstatSync39, readFileSync as readFileSync45, readdirSync as readdirSync24, realpathSync as realpathSync21 } from "fs";
117022
+ import { basename as basename19, dirname as dirname40, isAbsolute as isAbsolute36, join as join69, relative as relative12, resolve as resolve35, sep as sep15 } from "path";
116697
117023
  import { isDeepStrictEqual as isDeepStrictEqual18 } from "util";
116698
117024
  function hashClaudeDiscoveryBinding(binding) {
116699
117025
  return sha7(JSON.stringify(binding));
@@ -116744,7 +117070,7 @@ function keys3(value, expected, name) {
116744
117070
  refuse6(`${name} has an unsupported shape`);
116745
117071
  }
116746
117072
  function abs(path, name) {
116747
- if (typeof path !== "string" || !path || path.length > 4096 || /[\x00-\x1f\x7f]/.test(path) || !isAbsolute35(path) || resolve34(path) !== path)
117073
+ if (typeof path !== "string" || !path || path.length > 4096 || /[\x00-\x1f\x7f]/.test(path) || !isAbsolute36(path) || resolve35(path) !== path)
116748
117074
  refuse6(`${name} must be a normalized absolute path`);
116749
117075
  }
116750
117076
  function validUtcTimestamp(value) {
@@ -116752,27 +117078,27 @@ function validUtcTimestamp(value) {
116752
117078
  }
116753
117079
  function safeFile(path, name) {
116754
117080
  abs(path, name);
116755
- for (let at2 = dirname39(path);; at2 = dirname39(at2)) {
116756
- const stat4 = lstatSync38(at2, { throwIfNoEntry: false });
117081
+ for (let at2 = dirname40(path);; at2 = dirname40(at2)) {
117082
+ const stat4 = lstatSync39(at2, { throwIfNoEntry: false });
116757
117083
  if (!stat4?.isDirectory() || stat4.isSymbolicLink())
116758
117084
  refuse6(`${name} traverses a symlink or non-directory`);
116759
- if (at2 === dirname39(at2))
117085
+ if (at2 === dirname40(at2))
116760
117086
  break;
116761
117087
  }
116762
- const stat3 = lstatSync38(path, { throwIfNoEntry: false });
117088
+ const stat3 = lstatSync39(path, { throwIfNoEntry: false });
116763
117089
  if (!stat3?.isFile() || stat3.isSymbolicLink() || stat3.size > MAX_CANDIDATE_BYTES)
116764
117090
  refuse6(`${name} is not a bounded regular file`);
116765
117091
  return readFileSync45(path);
116766
117092
  }
116767
117093
  function canonicalDir(path, name) {
116768
117094
  abs(path, name);
116769
- if (realpathSync21(path) !== path || !lstatSync38(path).isDirectory())
117095
+ if (realpathSync21(path) !== path || !lstatSync39(path).isDirectory())
116770
117096
  refuse6(`${name} is not a canonical directory`);
116771
- for (let at2 = path;; at2 = dirname39(at2)) {
116772
- const stat3 = lstatSync38(at2);
117097
+ for (let at2 = path;; at2 = dirname40(at2)) {
117098
+ const stat3 = lstatSync39(at2);
116773
117099
  if (!stat3.isDirectory() || stat3.isSymbolicLink())
116774
117100
  refuse6(`${name} traverses a symlink`);
116775
- if (at2 === dirname39(at2))
117101
+ if (at2 === dirname40(at2))
116776
117102
  break;
116777
117103
  }
116778
117104
  }
@@ -116781,17 +117107,17 @@ function captureClaudeProspectiveCandidateClosure(root2) {
116781
117107
  const entries = [];
116782
117108
  let bytes = 0;
116783
117109
  const walk2 = (directory2) => {
116784
- const beforeDirectory = lstatSync38(directory2);
117110
+ const beforeDirectory = lstatSync39(directory2);
116785
117111
  const names = readdirSync24(directory2).sort();
116786
117112
  if (new Set(names).size !== names.length)
116787
117113
  refuse6("candidate contains ambiguous directory entries");
116788
117114
  for (const name of names) {
116789
117115
  if (!name || name === "." || name === ".." || name.includes("/") || name.includes("\\") || /[\x00-\x1f\x7f]/.test(name))
116790
117116
  refuse6("candidate contains an unsupported path member");
116791
- const path = join68(directory2, name), rel = relative12(root2, path).split(sep15).join("/");
117117
+ const path = join69(directory2, name), rel = relative12(root2, path).split(sep15).join("/");
116792
117118
  if (entries.length >= MAX_CANDIDATE_FILES)
116793
117119
  refuse6("candidate closure exceeds its member limit");
116794
- const stat3 = lstatSync38(path);
117120
+ const stat3 = lstatSync39(path);
116795
117121
  if (stat3.isSymbolicLink())
116796
117122
  refuse6("candidate closure contains a symlink");
116797
117123
  if (stat3.isDirectory()) {
@@ -116801,14 +117127,14 @@ function captureClaudeProspectiveCandidateClosure(root2) {
116801
117127
  bytes += stat3.size;
116802
117128
  if (bytes > MAX_CANDIDATE_BYTES)
116803
117129
  refuse6("candidate closure exceeds its byte limit");
116804
- const content = safeFile(path, "candidate member"), after2 = lstatSync38(path);
117130
+ const content = safeFile(path, "candidate member"), after2 = lstatSync39(path);
116805
117131
  if (!after2.isFile() || after2.dev !== stat3.dev || after2.ino !== stat3.ino || after2.size !== stat3.size || after2.mtimeMs !== stat3.mtimeMs || after2.ctimeMs !== stat3.ctimeMs)
116806
117132
  refuse6("candidate member changed while being read");
116807
117133
  entries.push([rel, "file", sha7(content)]);
116808
117134
  } else
116809
117135
  refuse6("candidate closure contains a special file");
116810
117136
  }
116811
- const afterDirectory = lstatSync38(directory2);
117137
+ const afterDirectory = lstatSync39(directory2);
116812
117138
  if (!afterDirectory.isDirectory() || afterDirectory.dev !== beforeDirectory.dev || afterDirectory.ino !== beforeDirectory.ino || afterDirectory.mtimeMs !== beforeDirectory.mtimeMs || afterDirectory.ctimeMs !== beforeDirectory.ctimeMs)
116813
117139
  refuse6("candidate directory changed while being read");
116814
117140
  };
@@ -116819,9 +117145,9 @@ function captureClaudeProspectiveCandidateClosure(root2) {
116819
117145
  function captureClaudeInstallerCandidate(root2, policyPath) {
116820
117146
  const closureSha256 = captureClaudeProspectiveCandidateClosure(root2);
116821
117147
  const dataDir3 = getDataDirReadOnly();
116822
- if (policyPath !== join68(dataDir3, "agent-policy.json"))
117148
+ if (policyPath !== join69(dataDir3, "agent-policy.json"))
116823
117149
  refuse6("Skills policy path differs from the package-owned resolver");
116824
- const catalogPath = join68(root2, ".claude-plugin/marketplace.json");
117150
+ const catalogPath = join69(root2, ".claude-plugin/marketplace.json");
116825
117151
  const catalog = jsonFile(catalogPath, "candidate catalog");
116826
117152
  if (!catalog || !Array.isArray(catalog.plugins))
116827
117153
  refuse6("candidate catalog is invalid");
@@ -116832,13 +117158,13 @@ function captureClaudeInstallerCandidate(root2, policyPath) {
116832
117158
  if (names.has(row2.name))
116833
117159
  refuse6("candidate catalog repeats a plugin name");
116834
117160
  names.add(row2.name);
116835
- if (typeof row2.source !== "string" || isAbsolute35(row2.source) || /[\\\x00-\x1f\x7f]/.test(row2.source))
117161
+ if (typeof row2.source !== "string" || isAbsolute36(row2.source) || /[\\\x00-\x1f\x7f]/.test(row2.source))
116836
117162
  refuse6("candidate catalog plugin source is invalid");
116837
- const pluginRoot = resolve34(root2, row2.source);
117163
+ const pluginRoot = resolve35(root2, row2.source);
116838
117164
  const relativeRoot = relative12(root2, pluginRoot);
116839
- if (!relativeRoot || relativeRoot === "." || relativeRoot === ".." || relativeRoot.startsWith(`..${sep15}`) || isAbsolute35(relativeRoot))
117165
+ if (!relativeRoot || relativeRoot === "." || relativeRoot === ".." || relativeRoot.startsWith(`..${sep15}`) || isAbsolute36(relativeRoot))
116840
117166
  refuse6("candidate plugin source escapes the candidate root");
116841
- const path = join68(pluginRoot, ".claude-plugin/plugin.json");
117167
+ const path = join69(pluginRoot, ".claude-plugin/plugin.json");
116842
117168
  return { plugin: row2.name, ...captureClaudePluginManifestFile(path) };
116843
117169
  });
116844
117170
  const policy = readManagedSkillPolicySnapshot(dataDir3);
@@ -116855,7 +117181,7 @@ function captureClaudeInstallerCandidate(root2, policyPath) {
116855
117181
  }
116856
117182
  function readWitness(path, expected, name) {
116857
117183
  abs(path, `${name} path`);
116858
- const stat3 = lstatSync38(path, { throwIfNoEntry: false });
117184
+ const stat3 = lstatSync39(path, { throwIfNoEntry: false });
116859
117185
  if (expected === null) {
116860
117186
  if (stat3)
116861
117187
  refuse6(`${name} was absent at review but is now present`);
@@ -116867,7 +117193,7 @@ function readWitness(path, expected, name) {
116867
117193
  refuse6(`${name} preimage changed`);
116868
117194
  }
116869
117195
  function jsonFile(path, name) {
116870
- const stat3 = lstatSync38(path, { throwIfNoEntry: false });
117196
+ const stat3 = lstatSync39(path, { throwIfNoEntry: false });
116871
117197
  if (!stat3)
116872
117198
  return null;
116873
117199
  let value;
@@ -116898,8 +117224,8 @@ function assertNoUnprojectedSkillPayload(root2, catalogPath, marketplace, plugin
116898
117224
  refuse6("candidate marketplace entry declares native skill or command payloads");
116899
117225
  const walk2 = (directory2) => {
116900
117226
  for (const name of readdirSync24(directory2).sort()) {
116901
- const path = join68(directory2, name), rel = relative12(root2, path).split(sep15).join("/");
116902
- const stat3 = lstatSync38(path);
117227
+ const path = join69(directory2, name), rel = relative12(root2, path).split(sep15).join("/");
117228
+ const stat3 = lstatSync39(path);
116903
117229
  if (stat3.isDirectory())
116904
117230
  walk2(path);
116905
117231
  else if (stat3.isFile()) {
@@ -116956,16 +117282,16 @@ function reviewClaudeProspectiveCandidate(request2, requestFileSha256) {
116956
117282
  refuse6("Skills policy root alias changed or is invalid");
116957
117283
  }
116958
117284
  const canonical8 = (path) => canonicalAgentPath(path, aliases);
116959
- const configRoot = canonical8(join68(request2.native.home, ".claude"));
117285
+ const configRoot = canonical8(join69(request2.native.home, ".claude"));
116960
117286
  canonicalDir(configRoot, "Claude config root");
116961
117287
  if (request2.native.configRoot !== configRoot)
116962
117288
  refuse6("Claude config root differs from the current resolver and reviewed root alias");
116963
- const pluginRoot = join68(configRoot, "plugins");
117289
+ const pluginRoot = join69(configRoot, "plugins");
116964
117290
  if (process.env.CLAUDE_CODE_PLUGIN_CACHE_DIR)
116965
117291
  refuse6("CLAUDE_CODE_PLUGIN_CACHE_DIR overrides are unsupported by this prospective schema; bind and review the actual cache root first");
116966
117292
  if (request2.native.pluginRoot !== pluginRoot)
116967
117293
  refuse6("Claude plugin root differs from the supported standard plugins directory; Cowork and custom cache roots require a separately bound schema");
116968
- const pluginRootStat = lstatSync38(pluginRoot, { throwIfNoEntry: false });
117294
+ const pluginRootStat = lstatSync39(pluginRoot, { throwIfNoEntry: false });
116969
117295
  if (pluginRootStat && (!pluginRootStat.isDirectory() || pluginRootStat.isSymbolicLink()))
116970
117296
  refuse6("Claude plugin root is not a regular directory");
116971
117297
  keys3(request2.candidate, ["marketplace", "root", "catalogPath", "catalogSha256", "closureSha256", "plugins", ...hasOwn2(request2.candidate, "releaseManifest") ? ["releaseManifest"] : [], ...hasOwn2(request2.candidate, "functionHooksEnv") ? ["functionHooksEnv"] : [], ...hasOwn2(request2.candidate, "settingsMarketplaceSource") ? ["settingsMarketplaceSource"] : []], "candidate");
@@ -116982,7 +117308,7 @@ function reviewClaudeProspectiveCandidate(request2, requestFileSha256) {
116982
117308
  abs(candidate2.catalogPath, "catalog path");
116983
117309
  if (!candidate2.catalogPath.startsWith(candidate2.root + sep15))
116984
117310
  refuse6("catalog must be inside the frozen candidate root");
116985
- if (candidate2.catalogPath !== join68(candidate2.root, ".claude-plugin", "marketplace.json"))
117311
+ if (candidate2.catalogPath !== join69(candidate2.root, ".claude-plugin", "marketplace.json"))
116986
117312
  refuse6("marketplace catalog must be at the frozen root's .claude-plugin/marketplace.json path");
116987
117313
  if (!SHA256.test(candidate2.catalogSha256) || !SHA256.test(candidate2.closureSha256))
116988
117314
  refuse6("candidate digests must be lowercase SHA-256");
@@ -117024,11 +117350,11 @@ function reviewClaudeProspectiveCandidate(request2, requestFileSha256) {
117024
117350
  if (Buffer.byteLength(canonicalJson3(selected.optionsPatch), "utf8") > 16 * 1024)
117025
117351
  refuse6("selected plugin optionsPatch exceeds its byte bound");
117026
117352
  abs(selected.manifestPath, "manifest path");
117027
- if (!selected.manifestPath.startsWith(candidate2.root + sep15) || basename19(dirname39(selected.manifestPath)) !== ".claude-plugin" || selected.manifestPath !== join68(dirname39(dirname39(selected.manifestPath)), ".claude-plugin", "plugin.json"))
117353
+ if (!selected.manifestPath.startsWith(candidate2.root + sep15) || basename19(dirname40(selected.manifestPath)) !== ".claude-plugin" || selected.manifestPath !== join69(dirname40(dirname40(selected.manifestPath)), ".claude-plugin", "plugin.json"))
117028
117354
  refuse6("plugin manifest must be under a plugin root inside the frozen marketplace closure");
117029
- const pluginRoot2 = dirname39(dirname39(selected.manifestPath));
117355
+ const pluginRoot2 = dirname40(dirname40(selected.manifestPath));
117030
117356
  const relativePluginRoot = relative12(candidate2.root, pluginRoot2);
117031
- if (!relativePluginRoot || relativePluginRoot === "." || relativePluginRoot === ".." || relativePluginRoot.startsWith(`..${sep15}`) || isAbsolute35(relativePluginRoot))
117357
+ if (!relativePluginRoot || relativePluginRoot === "." || relativePluginRoot === ".." || relativePluginRoot.startsWith(`..${sep15}`) || isAbsolute36(relativePluginRoot))
117032
117358
  refuse6("plugin root must be a child of the frozen marketplace root");
117033
117359
  canonicalDir(pluginRoot2, "candidate plugin root");
117034
117360
  if (!SHA256.test(selected.manifestSha256))
@@ -117062,7 +117388,7 @@ function reviewClaudeProspectiveCandidate(request2, requestFileSha256) {
117062
117388
  const sourcePath = selectedEntry.source;
117063
117389
  const sourceRelativePath = relative12(candidate2.root, pluginRoot2).split(sep15).join("/");
117064
117390
  const expectedSourcePath = sourceRelativePath === "." ? "./" : `./${sourceRelativePath}`;
117065
- if (typeof sourcePath !== "string" || isAbsolute35(sourcePath) || sourcePath !== expectedSourcePath || resolve34(dirname39(dirname39(candidate2.catalogPath)), sourcePath) !== pluginRoot2)
117391
+ if (typeof sourcePath !== "string" || isAbsolute36(sourcePath) || sourcePath !== expectedSourcePath || resolve35(dirname40(dirname40(candidate2.catalogPath)), sourcePath) !== pluginRoot2)
117066
117392
  refuse6("marketplace source does not resolve to the frozen plugin closure; external source mapping is not supported by this schema");
117067
117393
  const entry = captureClaudeMarketplaceEntry(candidate2.catalogPath, candidate2.marketplace, selected.plugin);
117068
117394
  if (entry.sha256.length !== 64)
@@ -117082,12 +117408,12 @@ function reviewClaudeProspectiveCandidate(request2, requestFileSha256) {
117082
117408
  for (const name of ["settings", "projectSettings", "projectSettingsLocal", "marketplaces", "installedPlugins"])
117083
117409
  keys3(request2.preimages[name], ["path", "sha256"], `${name} preimage`);
117084
117410
  const expectedPaths = {
117085
- settings: request2.scope.kind === "project" ? canonical8(join68(request2.scope.projectPath, ".claude/settings.json")) : canonical8(join68(request2.native.home, ".claude/settings.json")),
117086
- userSettings: canonical8(join68(request2.native.home, ".claude/settings.json")),
117087
- projectSettings: canonical8(join68(request2.scope.projectPath, ".claude/settings.json")),
117088
- projectSettingsLocal: canonical8(join68(request2.scope.projectPath, ".claude/settings.local.json")),
117089
- marketplaces: canonical8(join68(request2.native.home, ".claude/plugins/known_marketplaces.json")),
117090
- installedPlugins: canonical8(join68(request2.native.home, ".claude/plugins/installed_plugins.json"))
117411
+ settings: request2.scope.kind === "project" ? canonical8(join69(request2.scope.projectPath, ".claude/settings.json")) : canonical8(join69(request2.native.home, ".claude/settings.json")),
117412
+ userSettings: canonical8(join69(request2.native.home, ".claude/settings.json")),
117413
+ projectSettings: canonical8(join69(request2.scope.projectPath, ".claude/settings.json")),
117414
+ projectSettingsLocal: canonical8(join69(request2.scope.projectPath, ".claude/settings.local.json")),
117415
+ marketplaces: canonical8(join69(request2.native.home, ".claude/plugins/known_marketplaces.json")),
117416
+ installedPlugins: canonical8(join69(request2.native.home, ".claude/plugins/installed_plugins.json"))
117091
117417
  };
117092
117418
  for (const name of Object.keys(expectedPaths)) {
117093
117419
  const witness = request2.preimages[name];
@@ -117205,7 +117531,7 @@ function reviewClaudeProspectiveCandidate(request2, requestFileSha256) {
117205
117531
  const manifestVersion = manifest.version;
117206
117532
  const sanitizeComponent = (value) => value.replace(/[^A-Za-z0-9_-]/g, "-");
117207
117533
  const sanitizedVersion = manifestVersion === "." || manifestVersion === ".." ? "-" : manifestVersion.replace(/[^A-Za-z0-9._-]/g, "-");
117208
- const expectedInstallPath = join68(pluginRoot, "cache", sanitizeComponent(candidate2.marketplace), sanitizeComponent(plugin), sanitizedVersion);
117534
+ const expectedInstallPath = join69(pluginRoot, "cache", sanitizeComponent(candidate2.marketplace), sanitizeComponent(plugin), sanitizedVersion);
117209
117535
  if (expectedInstallPath.length > 4096)
117210
117536
  refuse6("candidate native cache path exceeds its bound");
117211
117537
  const targetRegistration = {
@@ -117343,7 +117669,7 @@ function reviewClaudeProspectiveCandidate(request2, requestFileSha256) {
117343
117669
  { name: "project-settings-local", path: expectedPaths.projectSettingsLocal, sha256: request2.preimages.projectSettingsLocal.sha256 },
117344
117670
  { name: "known-marketplaces", path: expectedPaths.marketplaces, sha256: request2.preimages.marketplaces.sha256 },
117345
117671
  { name: "installed-plugins", path: expectedPaths.installedPlugins, sha256: request2.preimages.installedPlugins.sha256 },
117346
- { name: "skills-policy", path: join68(request2.skills.dataDir, "agent-policy.json"), sha256: request2.skills.policySha256 }
117672
+ { name: "skills-policy", path: join69(request2.skills.dataDir, "agent-policy.json"), sha256: request2.skills.policySha256 }
117347
117673
  ],
117348
117674
  ownedDelta: { settingsEnabledPlugins: selectedPluginIds, selectedPluginOptions: selectedOptionPaths, functionHooksEnv: candidate2.functionHooksEnv ?? null, knownMarketplace: candidate2.marketplace, installedPlugins: selectedPluginIds, unrelatedGraph: "preserved-by-complete-semantic-documents" },
117349
117675
  identityPrecondition: "Harnesses must resolve the installed Claude home/config/plugin roots and executable path/version/hash plus the installed Skills data directory through their package-owned consumers, then compare every value before trusting this receipt; this validator checks supplied paths and current bytes only and does not establish actual consumer identity",
@@ -117369,10 +117695,10 @@ var init_claude_prospective_review = __esm(() => {
117369
117695
 
117370
117696
  // src/lib/self-spawn.ts
117371
117697
  import { realpathSync as realpathSync22 } from "fs";
117372
- import { dirname as dirname40, isAbsolute as isAbsolute36, sep as sep16 } from "path";
117698
+ import { dirname as dirname41, isAbsolute as isAbsolute37, sep as sep16 } from "path";
117373
117699
  function selfSpawnRoot(entry) {
117374
117700
  const index = entry.indexOf(INSTALLED_PACKAGE);
117375
- const root2 = index > 0 ? entry.slice(0, index) : dirname40(entry);
117701
+ const root2 = index > 0 ? entry.slice(0, index) : dirname41(entry);
117376
117702
  try {
117377
117703
  return realpathSync22(root2);
117378
117704
  } catch {
@@ -117382,12 +117708,12 @@ function selfSpawnRoot(entry) {
117382
117708
  function selfSpawnCommand(args2, options = {}) {
117383
117709
  const runtime = options.runtime ?? process.execPath;
117384
117710
  const entry = options.entry ?? process.argv[1];
117385
- if (!runtime || !isAbsolute36(runtime) || !entry || !isAbsolute36(entry))
117711
+ if (!runtime || !isAbsolute37(runtime) || !entry || !isAbsolute37(entry))
117386
117712
  throw new Error("SKILLS_SELF_SPAWN_ENTRY_UNRESOLVED");
117387
117713
  const root2 = selfSpawnRoot(entry);
117388
117714
  const env3 = pinnedLauncherEnvironment(options.env ?? process.env);
117389
117715
  env3[LAUNCH_CWD_VARIABLE] = options.callerCwd ?? process.cwd();
117390
- return { command: [runtime, ...PINNED_LAUNCHER_BUN_FLAGS, `--cwd=${root2}`, entry, ...args2], cwd: root2, env: env3 };
117716
+ return { command: [runtime, ...PINNED_LAUNCHER_BUN_FLAGS2, `--cwd=${root2}`, entry, ...args2], cwd: root2, env: env3 };
117391
117717
  }
117392
117718
  var INSTALLED_PACKAGE;
117393
117719
  var init_self_spawn = __esm(() => {
@@ -117396,8 +117722,8 @@ var init_self_spawn = __esm(() => {
117396
117722
  });
117397
117723
 
117398
117724
  // src/cli/commands/claude-installer-capture.ts
117399
- import { closeSync as closeSync26, constants as constants24, fstatSync as fstatSync26, lstatSync as lstatSync39, openSync as openSync26, readSync as readSync19 } from "fs";
117400
- import { isAbsolute as isAbsolute37, resolve as resolve35 } from "path";
117725
+ import { closeSync as closeSync26, constants as constants25, fstatSync as fstatSync26, lstatSync as lstatSync40, openSync as openSync26, readSync as readSync19 } from "fs";
117726
+ import { isAbsolute as isAbsolute38, resolve as resolve36 } from "path";
117401
117727
  function need8(condition, code2) {
117402
117728
  if (!condition)
117403
117729
  throw new CaptureRefusal(code2);
@@ -117411,14 +117737,14 @@ function exactKeys4(value, expected, operation) {
117411
117737
  }
117412
117738
  }
117413
117739
  function canonicalPath2(value) {
117414
- need8(typeof value === "string" && isAbsolute37(value) && resolve35(value) === value && !/[\x00-\x1f\x7f]/.test(value), "INVALID_PATH: path fields must be normalized absolute paths without control characters");
117740
+ need8(typeof value === "string" && isAbsolute38(value) && resolve36(value) === value && !/[\x00-\x1f\x7f]/.test(value), "INVALID_PATH: path fields must be normalized absolute paths without control characters");
117415
117741
  }
117416
117742
  function readRequest2(path) {
117417
117743
  canonicalPath2(path);
117418
- const before2 = lstatSync39(path, { throwIfNoEntry: false });
117744
+ const before2 = lstatSync40(path, { throwIfNoEntry: false });
117419
117745
  if (!before2?.isFile() || before2.isSymbolicLink() || before2.size > MAX_REQUEST_BYTES)
117420
117746
  throw new CaptureRefusal("INVALID_REQUEST_FILE: --request must name a regular non-symlink JSON file no larger than 64 KiB");
117421
- const fd = openSync26(path, constants24.O_RDONLY | (constants24.O_NOFOLLOW ?? 0) | constants24.O_NONBLOCK);
117747
+ const fd = openSync26(path, constants25.O_RDONLY | (constants25.O_NOFOLLOW ?? 0) | constants25.O_NONBLOCK);
117422
117748
  try {
117423
117749
  const opened = fstatSync26(fd);
117424
117750
  need8(opened.isFile() && opened.dev === before2.dev && opened.ino === before2.ino && opened.size === before2.size, "INVALID_REQUEST_FILE: --request must remain the same regular file while read");
@@ -117430,7 +117756,7 @@ function readRequest2(path) {
117430
117756
  break;
117431
117757
  length += count;
117432
117758
  }
117433
- const after2 = fstatSync26(fd), current = lstatSync39(path);
117759
+ const after2 = fstatSync26(fd), current = lstatSync40(path);
117434
117760
  need8(length <= MAX_REQUEST_BYTES && length === opened.size && after2.size === opened.size && after2.mtimeMs === opened.mtimeMs && after2.ctimeMs === opened.ctimeMs && current.dev === opened.dev && current.ino === opened.ino && current.mtimeMs === opened.mtimeMs && current.ctimeMs === opened.ctimeMs, "INVALID_REQUEST_FILE: --request must remain unchanged while read");
117435
117761
  try {
117436
117762
  return JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(bytes.subarray(0, length)));
@@ -117562,10 +117888,10 @@ var exports_agent_integration = {};
117562
117888
  __export(exports_agent_integration, {
117563
117889
  registerAgentIntegration: () => registerAgentIntegration
117564
117890
  });
117565
- import { existsSync as existsSync36, lstatSync as lstatSync40, readFileSync as readFileSync46, readSync as readSync20, writeFileSync as writeFileSync27 } from "fs";
117891
+ import { existsSync as existsSync36, lstatSync as lstatSync41, readFileSync as readFileSync46, readSync as readSync20, writeFileSync as writeFileSync27 } from "fs";
117566
117892
  import { createHash as createHash42 } from "crypto";
117567
- import { homedir as homedir13 } from "os";
117568
- import { isAbsolute as isAbsolute38 } from "path";
117893
+ import { homedir as homedir14 } from "os";
117894
+ import { isAbsolute as isAbsolute39 } from "path";
117569
117895
  function pinnedHookProfile(input3, configuredProfile) {
117570
117896
  try {
117571
117897
  const parsed = parseSkillContextInput(JSON.stringify(input3));
@@ -117661,13 +117987,13 @@ function registerAgentIntegration(parent) {
117661
117987
  });
117662
117988
  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) => {
117663
117989
  try {
117664
- if (!isAbsolute38(options.cwd) || !isAbsolute38(options.output))
117990
+ if (!isAbsolute39(options.cwd) || !isAbsolute39(options.output))
117665
117991
  throw new Error("CODEX_NATIVE_SKILL_CATALOG_ABSOLUTE_PATH_REQUIRED");
117666
117992
  if (existsSync36(options.output))
117667
117993
  throw new Error("CODEX_NATIVE_SKILL_CATALOG_OUTPUT_EXISTS");
117668
117994
  const catalog = await captureCodexNativeSkillCatalog({
117669
117995
  command: options.codexCommand,
117670
- home: homedir13(),
117996
+ home: homedir14(),
117671
117997
  ...process.env.CODEX_HOME === undefined ? {} : { codexHome: process.env.CODEX_HOME },
117672
117998
  cwd: options.cwd
117673
117999
  });
@@ -117680,7 +118006,7 @@ function registerAgentIntegration(parent) {
117680
118006
  throw new Error("CODEX_NATIVE_SKILL_CATALOG_OUTPUT_EXISTS");
117681
118007
  throw error61;
117682
118008
  }
117683
- const written = lstatSync40(options.output);
118009
+ const written = lstatSync41(options.output);
117684
118010
  if (!written.isFile() || written.isSymbolicLink() || (written.mode & 63) !== 0 || readFileSync46(options.output, "utf8") !== bytes)
117685
118011
  throw new Error("CODEX_NATIVE_SKILL_CATALOG_READBACK_FAILED");
117686
118012
  const receipt = {
@@ -117728,9 +118054,9 @@ function registerAgentIntegration(parent) {
117728
118054
  });
117729
118055
  hook.command("review-claude-candidate").requiredOption("--request <file>", "Frozen skills.claude-plugin-prospective-review/v1 JSON request").option("--json", "Return the validation-only receipt as JSON", false).description("Validate a prospective Claude plugin candidate and current preimages without changing native state; Harnesses must compare native and Skills paths against installed package-owned resolvers before trusting the receipt").action(async (options) => {
117730
118056
  try {
117731
- if (!isAbsolute38(options.request))
118057
+ if (!isAbsolute39(options.request))
117732
118058
  throw new Error("CLAUDE_CANDIDATE_REVIEW_REFUSED: --request must be an absolute path");
117733
- const stat3 = lstatSync40(options.request);
118059
+ const stat3 = lstatSync41(options.request);
117734
118060
  if (!stat3.isFile() || stat3.isSymbolicLink() || stat3.size > 1024 * 1024)
117735
118061
  throw new Error("CLAUDE_CANDIDATE_REVIEW_REFUSED: request must be a regular file no larger than 1 MiB");
117736
118062
  const requestBytes = readFileSync46(options.request);
@@ -117775,10 +118101,10 @@ function registerAgentIntegration(parent) {
117775
118101
  hook.command("agents").option("--json", "Output the adapter capability inventory", false).description("Show maintained native adapters and explicit coverage limits").action(async () => {
117776
118102
  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));
117777
118103
  });
117778
- 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-skill-denials <file>", "Explicit reviewed remote skill denials: array of exact name, path and document sha256; requires fresh catalog and discovery inputs").option("--codex-native-catalog <file>", "Reviewed supported Codex 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) => {
118104
+ hook.command("install").option("--agent <agent>", `Agent to configure: ${INTEGRATION_AGENTS.join(", ")}, all (default: configured or detected agents; explicit all requires every adapter)`).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-skill-denials <file>", "Explicit reviewed remote skill denials: array of exact name, path and document sha256; requires fresh catalog and discovery inputs").option("--codex-native-catalog <file>", "Reviewed supported Codex 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) => {
117779
118105
  try {
117780
118106
  const discoveryInputs = options.discoveryInputs ? JSON.parse(readFileSync46(options.discoveryInputs, "utf8")) : undefined;
117781
- 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, codexSkillDenials: options.codexSkillDenials ? JSON.parse(readFileSync46(options.codexSkillDenials, "utf8")) : undefined, codexNativeCatalog: options.codexNativeCatalog ? JSON.parse(readFileSync46(options.codexNativeCatalog, "utf8")) : undefined });
118107
+ const plan = planAgentIntegration({ projectDir: process.cwd(), agents: options.agent === undefined ? detectedIntegrationAgents() : agents(options.agent), command: options.command, profileId: options.selectionProfile, includeVendor: options.includeVendor, discoveryInputs, allowRootAliases: options.allowRootAliases, reviewedCacheAlias: options.reviewedCacheAlias, codexSkillDenials: options.codexSkillDenials ? JSON.parse(readFileSync46(options.codexSkillDenials, "utf8")) : undefined, codexNativeCatalog: options.codexNativeCatalog ? JSON.parse(readFileSync46(options.codexNativeCatalog, "utf8")) : undefined });
117782
118108
  const result2 = options.apply ? applyAgentIntegration(plan) : { changed: [], backups: [] };
117783
118109
  const receipt = { codexPluginSkillReview: plan.codexPluginSkillReview, codexPluginSkills: plan.changes.filter((change) => change.path.endsWith("agent-policy.json")).map((change) => JSON.parse(change.after).bridge?.codexPluginSkills ?? []).flat(), applied: options.apply, planned: plan.changes.map((change) => change.path), ...result2, rootAliases: plan.rootAliases ?? [], discovery: plan.discoveryAfter, nativeSkills: plan.nativeSkills.map((entry) => ({ agent: entry.agent, path: entry.path, managed: entry.managed, vendor: entry.vendor, system: entry.system === true, bridge: entry.bridge === true })), requiresNativeRetirement: plan.nativeSkills.some((entry) => !entry.bridge && !entry.system) };
117784
118110
  if (options.json)
@@ -117850,12 +118176,12 @@ function registerAgentIntegration(parent) {
117850
118176
  input3.hook_event_name = event;
117851
118177
  const projects = [process.cwd()];
117852
118178
  if (input3.cwd !== undefined) {
117853
- if (typeof input3.cwd !== "string" || !isAbsolute38(input3.cwd) || input3.cwd.includes("\x00"))
118179
+ if (typeof input3.cwd !== "string" || !isAbsolute39(input3.cwd) || input3.cwd.includes("\x00"))
117854
118180
  throw new Error("Invalid native hook working directory");
117855
118181
  projects.push(input3.cwd);
117856
118182
  }
117857
118183
  if (options.agent === "cursor") {
117858
- if (!Array.isArray(input3.workspace_roots) || input3.workspace_roots.length > 32 || input3.workspace_roots.some((path) => typeof path !== "string" || !isAbsolute38(path) || path.includes("\x00")))
118184
+ if (!Array.isArray(input3.workspace_roots) || input3.workspace_roots.length > 32 || input3.workspace_roots.some((path) => typeof path !== "string" || !isAbsolute39(path) || path.includes("\x00")))
117859
118185
  throw new Error("Invalid Cursor workspace roots");
117860
118186
  projects.push(...input3.workspace_roots);
117861
118187
  input3.cwd ??= input3.workspace_roots[0] ?? process.cwd();
@@ -117981,6 +118307,7 @@ var init_agent_integration2 = __esm(() => {
117981
118307
  init_agent_hermes();
117982
118308
  init_context();
117983
118309
  init_agent_adapters();
118310
+ init_agent_install_selection();
117984
118311
  init_agent_integration();
117985
118312
  init_agent_codex_trust();
117986
118313
  init_codex_native_skill_policy();
@@ -118133,9 +118460,9 @@ var exports_profiles = {};
118133
118460
  __export(exports_profiles, {
118134
118461
  registerProfiles: () => registerProfiles
118135
118462
  });
118136
- import { closeSync as closeSync27, constants as constants25, fstatSync as fstatSync27, openSync as openSync27, readSync as readSync21, writeFileSync as writeFileSync28 } from "fs";
118463
+ import { closeSync as closeSync27, constants as constants26, fstatSync as fstatSync27, openSync as openSync27, readSync as readSync21, writeFileSync as writeFileSync28 } from "fs";
118137
118464
  function readProfileInput(path) {
118138
- const fd = openSync27(path, constants25.O_RDONLY | constants25.O_NONBLOCK);
118465
+ const fd = openSync27(path, constants26.O_RDONLY | constants26.O_NONBLOCK);
118139
118466
  try {
118140
118467
  const stat3 = fstatSync27(fd);
118141
118468
  if (!stat3.isFile() || stat3.size > MAX_PROFILE_DOCUMENT_BYTES)
@@ -118203,7 +118530,7 @@ __export(exports_grants, {
118203
118530
  registerGrants: () => registerGrants
118204
118531
  });
118205
118532
  import {
118206
- constants as constants26,
118533
+ constants as constants27,
118207
118534
  closeSync as closeSync28,
118208
118535
  fstatSync as fstatSync28,
118209
118536
  openSync as openSync28,
@@ -118211,7 +118538,7 @@ import {
118211
118538
  writeFileSync as writeFileSync29
118212
118539
  } from "fs";
118213
118540
  function readInput(path) {
118214
- const fd = openSync28(path, constants26.O_RDONLY | constants26.O_NONBLOCK);
118541
+ const fd = openSync28(path, constants27.O_RDONLY | constants27.O_NONBLOCK);
118215
118542
  try {
118216
118543
  const stat3 = fstatSync28(fd);
118217
118544
  if (!stat3.isFile() || stat3.size > MAX_EXECUTION_GRANT_BYTES)
@@ -118274,19 +118601,19 @@ import {
118274
118601
  mkdirSync as mkdirSync29,
118275
118602
  readdirSync as readdirSync25,
118276
118603
  readFileSync as readFileSync47,
118277
- statSync as statSync23,
118604
+ statSync as statSync24,
118278
118605
  writeFileSync as writeFileSync30
118279
118606
  } from "fs";
118280
- import { dirname as dirname41, join as join69, resolve as resolve36, sep as sep17 } from "path";
118607
+ import { dirname as dirname42, join as join70, resolve as resolve37, sep as sep17 } from "path";
118281
118608
  function fail6(code2, message, detail = []) {
118282
118609
  throw new StationSnapshotError(code2, message, detail);
118283
118610
  }
118284
118611
  function snapshotRootFor(repoRoot, stationId) {
118285
- return join69(repoRoot, "resources", stationId, "skills");
118612
+ return join70(repoRoot, "resources", stationId, "skills");
118286
118613
  }
118287
118614
  function readSnapshotManifest(repoRoot, stationId) {
118288
118615
  const snapshotRoot = snapshotRootFor(repoRoot, stationId);
118289
- const manifestPath = join69(snapshotRoot, "sync-manifest.json");
118616
+ const manifestPath = join70(snapshotRoot, "sync-manifest.json");
118290
118617
  let manifest;
118291
118618
  try {
118292
118619
  manifest = JSON.parse(readFileSync47(manifestPath, "utf8"));
@@ -118313,7 +118640,7 @@ function planStationHydration(stationId, repoRoot) {
118313
118640
  const hashMismatches = [];
118314
118641
  const skippedByRule = [];
118315
118642
  for (const agent of SYNC_AGENTS) {
118316
- const agentRoot = join69(snapshotRoot, "agent-homes", agent);
118643
+ const agentRoot = join70(snapshotRoot, "agent-homes", agent);
118317
118644
  let identEntries;
118318
118645
  try {
118319
118646
  identEntries = readdirSync25(agentRoot, { withFileTypes: true });
@@ -118324,7 +118651,7 @@ function planStationHydration(stationId, repoRoot) {
118324
118651
  if (!identEntry.isDirectory() || identEntry.name.startsWith(".")) {
118325
118652
  continue;
118326
118653
  }
118327
- const identRoot = join69(agentRoot, identEntry.name);
118654
+ const identRoot = join70(agentRoot, identEntry.name);
118328
118655
  const entries = walkEntries(identRoot);
118329
118656
  for (const entry of entries) {
118330
118657
  const relativeParts = [identEntry.name, ...entry.relativePath.split(sep17)];
@@ -118371,7 +118698,7 @@ function planStationHydration(stationId, repoRoot) {
118371
118698
  });
118372
118699
  continue;
118373
118700
  }
118374
- const info = statSync23(entry.fullPath);
118701
+ const info = statSync24(entry.fullPath);
118375
118702
  const manifestHash = manifestHashes.get(`${agent}${MANIFEST_HASH_KEY_SEP}${homeRelative}`) ?? null;
118376
118703
  let verified = false;
118377
118704
  if (manifestHash !== null) {
@@ -118475,8 +118802,8 @@ function skillSha256(skill) {
118475
118802
  `)).digest("hex");
118476
118803
  }
118477
118804
  function writeStationHydration(options) {
118478
- const repoRoot = resolve36(options.repoRoot ?? process.cwd());
118479
- const cacheRoot = resolve36(options.cacheRoot ?? resolveCorpusRoot());
118805
+ const repoRoot = resolve37(options.repoRoot ?? process.cwd());
118806
+ const cacheRoot = resolve37(options.cacheRoot ?? resolveCorpusRoot());
118480
118807
  const plan = planStationHydration(options.stationId, repoRoot);
118481
118808
  const resultSkills = plan.winners.map((skill) => ({
118482
118809
  ident: skill.ident,
@@ -118509,7 +118836,7 @@ function writeStationHydration(options) {
118509
118836
  const toWrite = [];
118510
118837
  for (const skill of plan.winners) {
118511
118838
  for (const file2 of skill.files) {
118512
- const destination = join69(cacheRoot, skill.ident, file2.withinIdent);
118839
+ const destination = join70(cacheRoot, skill.ident, file2.withinIdent);
118513
118840
  const digest4 = sha256File(file2.winner.fullPath);
118514
118841
  let existingDigest = null;
118515
118842
  try {
@@ -118530,7 +118857,7 @@ function writeStationHydration(options) {
118530
118857
  }
118531
118858
  let written = 0;
118532
118859
  for (const entry of toWrite) {
118533
- mkdirSync29(dirname41(entry.destination), { recursive: true });
118860
+ mkdirSync29(dirname42(entry.destination), { recursive: true });
118534
118861
  copyFileSync3(entry.fullPath, entry.destination);
118535
118862
  written += 1;
118536
118863
  }
@@ -118551,8 +118878,8 @@ function writeStationHydration(options) {
118551
118878
  },
118552
118879
  skills: resultSkills
118553
118880
  };
118554
- const hydrationManifestPath = join69(dirname41(cacheRoot), `hydration-${options.stationId}.json`);
118555
- mkdirSync29(dirname41(hydrationManifestPath), { recursive: true });
118881
+ const hydrationManifestPath = join70(dirname42(cacheRoot), `hydration-${options.stationId}.json`);
118882
+ mkdirSync29(dirname42(hydrationManifestPath), { recursive: true });
118556
118883
  writeFileSync30(hydrationManifestPath, `${JSON.stringify(hydration, null, 2)}
118557
118884
  `);
118558
118885
  return {
@@ -118629,14 +118956,14 @@ var init_hydrate = __esm(() => {
118629
118956
 
118630
118957
  // src/lib/prepare-skill.ts
118631
118958
  import { createHash as createHash44, randomUUID as randomUUID13 } from "crypto";
118632
- import { chmodSync as chmodSync5, existsSync as existsSync37, lstatSync as lstatSync41, mkdirSync as mkdirSync30, mkdtempSync as mkdtempSync6, readFileSync as readFileSync48, readdirSync as readdirSync26, renameSync as renameSync15, rmSync as rmSync9, writeFileSync as writeFileSync31 } from "fs";
118959
+ import { chmodSync as chmodSync5, existsSync as existsSync37, lstatSync as lstatSync42, mkdirSync as mkdirSync30, mkdtempSync as mkdtempSync6, readFileSync as readFileSync48, readdirSync as readdirSync26, renameSync as renameSync15, rmSync as rmSync9, writeFileSync as writeFileSync31 } from "fs";
118633
118960
  import { tmpdir as tmpdir2 } from "os";
118634
- import { dirname as dirname42, isAbsolute as isAbsolute39, join as join70, relative as relative13, resolve as resolve37, sep as sep18 } from "path";
118961
+ import { dirname as dirname43, isAbsolute as isAbsolute40, join as join71, relative as relative13, resolve as resolve38, sep as sep18 } from "path";
118635
118962
  function prepareSkill(name, options) {
118636
118963
  const normalized = normalizePortableSkillName(name);
118637
118964
  if (!new RegExp(SEMVER_PATTERN).test(options.version))
118638
118965
  throw new Error("--version must be a semantic version, for example 0.2.0.");
118639
- const path = join70(getPortableSkillsRootReadOnly(options), normalized);
118966
+ const path = join71(getPortableSkillsRootReadOnly(options), normalized);
118640
118967
  assertPortableAuthoringPath(path, options);
118641
118968
  const before2 = snapshot2(path);
118642
118969
  const manifestFile = before2.files.find((file2) => file2.path === "skill.json");
@@ -118671,16 +118998,16 @@ function prepareSkill(name, options) {
118671
118998
  throw new Error("skill.json provenance must be an object.");
118672
118999
  const provenance = manifest.provenance;
118673
119000
  const candidate2 = { ...manifest, version: options.version, kind, provenance: { ...provenance } };
118674
- const staging = mkdtempSync6(join70(tmpdir2(), "skills-prepare-"));
119001
+ const staging = mkdtempSync6(join71(tmpdir2(), "skills-prepare-"));
118675
119002
  try {
118676
119003
  for (const directory2 of before2.directories)
118677
- mkdirSync30(join70(staging, directory2), { recursive: true });
119004
+ mkdirSync30(join71(staging, directory2), { recursive: true });
118678
119005
  for (const file2 of before2.files) {
118679
- const destination = join70(staging, file2.path);
118680
- mkdirSync30(dirname42(destination), { recursive: true });
119006
+ const destination = join71(staging, file2.path);
119007
+ mkdirSync30(dirname43(destination), { recursive: true });
118681
119008
  writeFileSync31(destination, file2.bytes, { mode: file2.mode });
118682
119009
  }
118683
- const stagedManifest = join70(staging, "skill.json");
119010
+ const stagedManifest = join71(staging, "skill.json");
118684
119011
  writeFileSync31(stagedManifest, `${JSON.stringify(candidate2, null, 2)}
118685
119012
  `);
118686
119013
  const contentHash = computeContentHash(staging);
@@ -118703,11 +119030,11 @@ ${validation.issues.map((issue2) => `${issue2.code}: ${issue2.message}`).join(`
118703
119030
  if (snapshot2(path).identity !== before2.identity)
118704
119031
  throw new Error("Skill changed during preparation; review the draft and run prepare again.");
118705
119032
  if (changed3 && !options.dryRun) {
118706
- const temporary = join70(path, `.skill-prepare-${randomUUID13()}.tmp`);
119033
+ const temporary = join71(path, `.skill-prepare-${randomUUID13()}.tmp`);
118707
119034
  try {
118708
119035
  writeFileSync31(temporary, candidateBytes, { flag: "wx", mode: manifestFile.mode });
118709
119036
  chmodSync5(temporary, manifestFile.mode);
118710
- renameSync15(temporary, join70(path, "skill.json"));
119037
+ renameSync15(temporary, join71(path, "skill.json"));
118711
119038
  } finally {
118712
119039
  rmSync9(temporary, { force: true });
118713
119040
  }
@@ -118737,8 +119064,8 @@ function validateRuntimeEntrypoint(candidate2, root2) {
118737
119064
  const entry = candidate2.runtime.entrypoint;
118738
119065
  if (typeof entry !== "string")
118739
119066
  return;
118740
- const target = resolve37(root2, entry), rel = relative13(root2, target);
118741
- if (isAbsolute39(entry) || /^[a-zA-Z]:/.test(entry) || entry.includes("\\") || !rel || rel === ".." || rel.startsWith(`..${sep18}`) || isAbsolute39(rel) || !existsSync37(target) || !lstatSync41(target).isFile()) {
119067
+ const target = resolve38(root2, entry), rel = relative13(root2, target);
119068
+ if (isAbsolute40(entry) || /^[a-zA-Z]:/.test(entry) || entry.includes("\\") || !rel || rel === ".." || rel.startsWith(`..${sep18}`) || isAbsolute40(rel) || !existsSync37(target) || !lstatSync42(target).isFile()) {
118742
119069
  throw new Error("Executable runtime.entrypoint must name an existing regular file inside the skill directory.");
118743
119070
  }
118744
119071
  }
@@ -118823,20 +119150,20 @@ function compareVersions(left, right) {
118823
119150
  return 0;
118824
119151
  }
118825
119152
  function snapshot2(root2) {
118826
- const rootStat = lstatSync41(root2);
119153
+ const rootStat = lstatSync42(root2);
118827
119154
  if (rootStat.isSymbolicLink() || !rootStat.isDirectory())
118828
119155
  throw new Error("Skill root must be a real directory, not a symlink.");
118829
119156
  const files = [], directories = [];
118830
119157
  const hash6 = createHash44("sha256").update(`${rootStat.dev}:${rootStat.ino}\x00`);
118831
119158
  let count = 0, bytes = 0;
118832
119159
  const walk2 = (relative14) => {
118833
- for (const name of readdirSync26(join70(root2, relative14)).sort()) {
119160
+ for (const name of readdirSync26(join71(root2, relative14)).sort()) {
118834
119161
  if (IGNORED.has(name.toLowerCase()) || !relative14 && ROOT_IGNORED.has(name.toLowerCase()))
118835
119162
  continue;
118836
119163
  const path = relative14 ? `${relative14}/${name}` : name;
118837
119164
  if (++count > 20000)
118838
119165
  throw new Error("Skill exceeds the preparation entry limit (20000).");
118839
- const absolute = join70(root2, path), stat3 = lstatSync41(absolute);
119166
+ const absolute = join71(root2, path), stat3 = lstatSync42(absolute);
118840
119167
  if (stat3.isSymbolicLink())
118841
119168
  throw new Error(`Skill contains a symlink: ${path}. No files were changed.`);
118842
119169
  if (stat3.isDirectory() && name === "node_modules")
@@ -119252,7 +119579,7 @@ var init_schedule = __esm(() => {
119252
119579
 
119253
119580
  // src/lib/registry-sync.ts
119254
119581
  import { mkdirSync as mkdirSync31, writeFileSync as writeFileSync32 } from "fs";
119255
- import { dirname as dirname43, relative as relative14 } from "path";
119582
+ import { dirname as dirname44, relative as relative14 } from "path";
119256
119583
  function createRegistrySyncArtifact(options = {}) {
119257
119584
  const profile = options.profile ?? "all";
119258
119585
  const includeDocs = options.includeDocs ?? true;
@@ -119309,7 +119636,7 @@ function createRegistrySyncArtifact(options = {}) {
119309
119636
  };
119310
119637
  }
119311
119638
  function writeRegistrySyncArtifact(path, artifact) {
119312
- mkdirSync31(dirname43(path), { recursive: true });
119639
+ mkdirSync31(dirname44(path), { recursive: true });
119313
119640
  writeFileSync32(path, `${JSON.stringify(artifact, null, 2)}
119314
119641
  `);
119315
119642
  }
@@ -119329,8 +119656,8 @@ var init_registry_sync = __esm(() => {
119329
119656
  });
119330
119657
 
119331
119658
  // src/lib/review-export.ts
119332
- import { constants as constants27, closeSync as closeSync29, existsSync as existsSync38, fstatSync as fstatSync29, fsyncSync as fsyncSync9, lstatSync as lstatSync42, openSync as openSync29, realpathSync as realpathSync23, statSync as statSync24, writeFileSync as writeFileSync33 } from "fs";
119333
- import { basename as basename20, dirname as dirname44, isAbsolute as isAbsolute40, join as join71, parse as parse13, resolve as resolve38, sep as sep19 } from "path";
119659
+ import { constants as constants28, closeSync as closeSync29, existsSync as existsSync38, fstatSync as fstatSync29, fsyncSync as fsyncSync9, lstatSync as lstatSync43, openSync as openSync29, realpathSync as realpathSync23, statSync as statSync25, writeFileSync as writeFileSync33 } from "fs";
119660
+ import { basename as basename20, dirname as dirname45, isAbsolute as isAbsolute41, join as join72, parse as parse13, resolve as resolve39, sep as sep19 } from "path";
119334
119661
  function exactVersion(spec) {
119335
119662
  const at2 = spec.indexOf("@");
119336
119663
  const slug2 = spec.slice(0, at2);
@@ -119341,14 +119668,14 @@ function exactVersion(spec) {
119341
119668
  return { slug: slug2, version: version2 };
119342
119669
  }
119343
119670
  function assertPrivateDestination(output2) {
119344
- if (!isAbsolute40(output2) || resolve38(output2) !== output2 || !basename20(output2).endsWith(".tar.gz")) {
119671
+ if (!isAbsolute41(output2) || resolve39(output2) !== output2 || !basename20(output2).endsWith(".tar.gz")) {
119345
119672
  throw new Error("Review output must be an absolute, normalized .tar.gz path.");
119346
119673
  }
119347
- const parent = dirname44(output2);
119348
- if (realpathSync23(parent) !== parent || lstatSync42(parent).isSymbolicLink()) {
119674
+ const parent = dirname45(output2);
119675
+ if (realpathSync23(parent) !== parent || lstatSync43(parent).isSymbolicLink()) {
119349
119676
  throw new Error("Review output parent must be a real directory, not a symlink.");
119350
119677
  }
119351
- const parentStat = statSync24(parent);
119678
+ const parentStat = statSync25(parent);
119352
119679
  if (!parentStat.isDirectory() || (parentStat.mode & 63) !== 0 || process.getuid && parentStat.uid !== process.getuid()) {
119353
119680
  throw new Error("Review output parent must be an owner-only directory (mode 0700).");
119354
119681
  }
@@ -119356,8 +119683,8 @@ function assertPrivateDestination(output2) {
119356
119683
  if (segments.some((segment) => NATIVE_CONTAINERS.has(segment)) || segments.some((segment, index) => segment === ".config" && segments[index + 1] === "opencode") || segments.some((segment, index) => segment === ".hasna" && segments[index + 1] === "skills")) {
119357
119684
  throw new Error("Review output cannot be placed in agent-native discovery or Skills installation paths.");
119358
119685
  }
119359
- for (let current = parent;; current = dirname44(current)) {
119360
- if (existsSync38(join71(current, ".git"))) {
119686
+ for (let current = parent;; current = dirname45(current)) {
119687
+ if (existsSync38(join72(current, ".git"))) {
119361
119688
  throw new Error("Review output cannot be placed inside a Git worktree.");
119362
119689
  }
119363
119690
  if (current === parse13(current).root)
@@ -119393,7 +119720,7 @@ async function exportSkillVersionForReview(spec, output2, client2) {
119393
119720
  if (bytes.byteLength !== metadata2.bundleByteSize || sha256Hex(bytes) !== metadata2.bundleSha256.toLowerCase()) {
119394
119721
  throw new Error("Published bundle bytes do not match the exact version metadata.");
119395
119722
  }
119396
- const fd = openSync29(target, constants27.O_WRONLY | constants27.O_CREAT | constants27.O_EXCL | constants27.O_NOFOLLOW, 384);
119723
+ const fd = openSync29(target, constants28.O_WRONLY | constants28.O_CREAT | constants28.O_EXCL | constants28.O_NOFOLLOW, 384);
119397
119724
  try {
119398
119725
  writeFileSync33(fd, bytes);
119399
119726
  fsyncSync9(fd);
@@ -119433,12 +119760,12 @@ function registerRegistry(parent) {
119433
119760
  async function writeJson2(value, space) {
119434
119761
  const text4 = `${JSON.stringify(value, null, space)}
119435
119762
  `;
119436
- await new Promise((resolve39, reject2) => {
119763
+ await new Promise((resolve40, reject2) => {
119437
119764
  process.stdout.write(text4, (error61) => {
119438
119765
  if (error61)
119439
119766
  reject2(error61);
119440
119767
  else
119441
- resolve39();
119768
+ resolve40();
119442
119769
  });
119443
119770
  });
119444
119771
  }
@@ -119644,7 +119971,7 @@ __export(exports_publish, {
119644
119971
  import { execFileSync as execFileSync3 } from "child_process";
119645
119972
  import { existsSync as existsSync39, readFileSync as readFileSync49 } from "fs";
119646
119973
  import { hostname as hostname5 } from "os";
119647
- import { join as join72 } from "path";
119974
+ import { join as join73 } from "path";
119648
119975
  function registerPublish(parent) {
119649
119976
  parent.command("push").argument("<name>", "Name of a skill in the local corpus (~/.hasna/skills/installed or the migrated ~/.hasna/skills/skills)").option("--version <version>", "Override the version recorded on the instance").option("--force-new-version", "If name@version already exists with different content, publish as the next patch version", false).option("--dry-run", "Pack and validate without uploading", false).option("--json", "Output result as JSON", false).description("Publish a local skill to the configured skills instance").action(async (name, options) => {
119650
119977
  try {
@@ -119696,7 +120023,7 @@ async function pushSkill(name, options = {}) {
119696
120023
  const packed = packSkillBundle(skill.path, { maxUnpackedBytes: MAX_UNPACKED_BYTES });
119697
120024
  await verifyPackedCanonicalHash(skill.name, packed);
119698
120025
  const versionManifest = buildVersionManifest(skill.path, packed);
119699
- const skillMdPath = join72(skill.path, "SKILL.md");
120026
+ const skillMdPath = join73(skill.path, "SKILL.md");
119700
120027
  const skillMd = existsSync39(skillMdPath) ? readFileSync49(skillMdPath, "utf-8") : undefined;
119701
120028
  const base3 = {
119702
120029
  slug: skill.name,
@@ -119935,7 +120262,7 @@ var exports_private_publications = {};
119935
120262
  __export(exports_private_publications, {
119936
120263
  registerPrivatePublications: () => registerPrivatePublications
119937
120264
  });
119938
- import { resolve as resolve39 } from "path";
120265
+ import { resolve as resolve40 } from "path";
119939
120266
  function verifyOptions(options, action) {
119940
120267
  if (options.userId === undefined !== (options.membershipId === undefined) || options.userId !== undefined && (!publicationUuid(options.userId) || !publicationUuid(options.membershipId)))
119941
120268
  throw new PrivatePublicationError("PUBLICATION_CONTEXT_REQUIRED", "Provide both observed --user-id and --membership-id UUIDs.");
@@ -119980,9 +120307,9 @@ function registerPrivatePublications(parent) {
119980
120307
  if (code2 === null)
119981
120308
  return;
119982
120309
  const context2 = options.userId ? { userId: options.userId, membershipId: options.membershipId } : undefined;
119983
- const client2 = await privatePublicationSession(options.email, code2, context2), directory2 = resolve39(options.recoveryDir);
120310
+ const client2 = await privatePublicationSession(options.email, code2, context2), directory2 = resolve40(options.recoveryDir);
119984
120311
  if (action === "publish")
119985
- await preparePrivatePublication(client2, resolve39(args2[0]), directory2, { skillId: options.skillId, expectedCurrentVersionId: options.expectedCurrentVersion ?? null, idempotencyKey: options.idempotencyKey });
120312
+ await preparePrivatePublication(client2, resolve40(args2[0]), directory2, { skillId: options.skillId, expectedCurrentVersionId: options.expectedCurrentVersion ?? null, idempotencyKey: options.idempotencyKey });
119986
120313
  const result2 = action === "publish" || action === "resume" ? await continuePrivatePublication(client2, directory2, { confirm: true, waitMs: Number(options.waitSeconds) * 1000 }) : await inspectPrivatePublication(client2, directory2, action === "cancel");
119987
120314
  print2(result2, options.json);
119988
120315
  } catch (error61) {
@@ -120084,7 +120411,7 @@ __export(exports_auth, {
120084
120411
  import { createInterface as createInterface3 } from "readline";
120085
120412
  function prompt(question) {
120086
120413
  const rl = createInterface3({ input: process.stdin, output: process.stdout });
120087
- return new Promise((resolve40) => {
120414
+ return new Promise((resolve41) => {
120088
120415
  let settled = false;
120089
120416
  const finish = (answer) => {
120090
120417
  if (settled)
@@ -120093,7 +120420,7 @@ function prompt(question) {
120093
120420
  rl.close();
120094
120421
  if (answer === null)
120095
120422
  process.exitCode = 130;
120096
- resolve40(answer);
120423
+ resolve41(answer);
120097
120424
  };
120098
120425
  rl.once("SIGINT", () => finish(null));
120099
120426
  rl.once("close", () => finish(null));
@@ -120271,7 +120598,7 @@ Skipped. Run it any time: skills setup agents`));
120271
120598
  function promptHidden(question) {
120272
120599
  const stdin = process.stdin;
120273
120600
  process.stdout.write(question);
120274
- return new Promise((resolve40) => {
120601
+ return new Promise((resolve41) => {
120275
120602
  let value = "";
120276
120603
  const done = (answer) => {
120277
120604
  stdin.off("data", onData);
@@ -120281,7 +120608,7 @@ function promptHidden(question) {
120281
120608
  `);
120282
120609
  if (answer === null)
120283
120610
  process.exitCode = 130;
120284
- resolve40(answer);
120611
+ resolve41(answer);
120285
120612
  };
120286
120613
  const onData = (chunk2) => {
120287
120614
  for (const character of chunk2.toString()) {
@@ -120837,7 +121164,7 @@ function promptInvitationProof(kind) {
120837
121164
  const label = kind === "token" ? "invitation token" : "recovery code";
120838
121165
  const character = kind === "token" ? /^[A-Za-z0-9_-]$/ : /^\d$/;
120839
121166
  const { stdin, stderr: output2 } = process, wasRaw = stdin.isRaw, wasFlowing = stdin.readableFlowing;
120840
- return new Promise((resolve40) => {
121167
+ return new Promise((resolve41) => {
120841
121168
  let value = "", settled = false, overflow = false;
120842
121169
  const finish = (answer) => {
120843
121170
  if (settled)
@@ -120854,7 +121181,7 @@ function promptInvitationProof(kind) {
120854
121181
  `);
120855
121182
  if (answer === null)
120856
121183
  process.exitCode = 130;
120857
- resolve40(answer);
121184
+ resolve41(answer);
120858
121185
  };
120859
121186
  const cancel = () => finish(null);
120860
121187
  const keypress = (text4, key) => {
@@ -121426,11 +121753,11 @@ var init_storage2 = __esm(() => {
121426
121753
  });
121427
121754
 
121428
121755
  // src/lib/registry-reconcile.ts
121429
- import { existsSync as existsSync40, readFileSync as readFileSync50, statSync as statSync25, writeFileSync as writeFileSync34 } from "fs";
121430
- import { join as join73 } from "path";
121756
+ import { existsSync as existsSync40, readFileSync as readFileSync50, statSync as statSync26, writeFileSync as writeFileSync34 } from "fs";
121757
+ import { join as join74 } from "path";
121431
121758
  function isDirectory2(path) {
121432
121759
  try {
121433
- return statSync25(path).isDirectory();
121760
+ return statSync26(path).isDirectory();
121434
121761
  } catch {
121435
121762
  return false;
121436
121763
  }
@@ -121438,11 +121765,11 @@ function isDirectory2(path) {
121438
121765
  function migrationNeeded(options) {
121439
121766
  if (options.rootDir)
121440
121767
  return false;
121441
- const appDir = options.homeDir ? join73(options.homeDir, ".hasna", "skills") : getDataDir();
121442
- return !(isOwnerLayoutMigrated(appDir) && isDirectory2(join73(appDir, SKILLS_CACHE_DIRNAME)));
121768
+ const appDir = options.homeDir ? join74(options.homeDir, ".hasna", "skills") : getDataDir();
121769
+ return !(isOwnerLayoutMigrated(appDir) && isDirectory2(join74(appDir, SKILLS_CACHE_DIRNAME)));
121443
121770
  }
121444
121771
  function readBaseline(skillDir) {
121445
- const markerPath = join73(skillDir, PULL_MARKER_FILE);
121772
+ const markerPath = join74(skillDir, PULL_MARKER_FILE);
121446
121773
  if (!existsSync40(markerPath))
121447
121774
  return;
121448
121775
  try {
@@ -121458,7 +121785,7 @@ function readBaseline(skillDir) {
121458
121785
  }
121459
121786
  }
121460
121787
  function readCursor(root2) {
121461
- const path = join73(root2, SYNC_CURSOR_FILE);
121788
+ const path = join74(root2, SYNC_CURSOR_FILE);
121462
121789
  if (!existsSync40(path))
121463
121790
  return { runCount: 0 };
121464
121791
  try {
@@ -121471,12 +121798,12 @@ function readCursor(root2) {
121471
121798
  function resolveCorpusRootReadOnly(options) {
121472
121799
  if (options.rootDir)
121473
121800
  return { root: options.rootDir, migrationPending: false };
121474
- const appDir = options.homeDir ? join73(options.homeDir, ".hasna", "skills") : getDataDirReadOnly();
121475
- const cache3 = join73(appDir, SKILLS_CACHE_DIRNAME);
121801
+ const appDir = options.homeDir ? join74(options.homeDir, ".hasna", "skills") : getDataDirReadOnly();
121802
+ const cache3 = join74(appDir, SKILLS_CACHE_DIRNAME);
121476
121803
  if (isOwnerLayoutMigrated(appDir) && isDirectory2(cache3)) {
121477
121804
  return { root: cache3, migrationPending: false };
121478
121805
  }
121479
- return { root: join73(appDir, INSTALLED_SKILLS_DIRNAME), migrationPending: true };
121806
+ return { root: join74(appDir, INSTALLED_SKILLS_DIRNAME), migrationPending: true };
121480
121807
  }
121481
121808
  function remoteRowToSkill(record12) {
121482
121809
  const slug2 = typeof record12.slug === "string" ? record12.slug : typeof record12.name === "string" ? record12.name : undefined;
@@ -121610,7 +121937,7 @@ async function reconcileRegistry(options = {}) {
121610
121937
  for (const slug2 of allSlugs) {
121611
121938
  const local = locals.get(slug2);
121612
121939
  const remote = remotes.get(slug2);
121613
- const baseline = local ? readBaseline(join73(root2, slug2)) : undefined;
121940
+ const baseline = local ? readBaseline(join74(root2, slug2)) : undefined;
121614
121941
  const { state, reason: reason2 } = classifySkill(local, remote, baseline);
121615
121942
  let { action, reason: actionReason } = resolveAction(state, direction, conflict);
121616
121943
  if (state === "remote-only" && isDigestless(remote)) {
@@ -121669,7 +121996,7 @@ async function reconcileRegistry(options = {}) {
121669
121996
  try {
121670
121997
  await pushSkill(slug2, { rootDir: root2, client: client2 });
121671
121998
  const pushed = locals.get(slug2);
121672
- writePullMarker(join73(root2, slug2), {
121999
+ writePullMarker(join74(root2, slug2), {
121673
122000
  skill: slug2,
121674
122001
  ...pushed?.version ? { version: pushed.version } : {},
121675
122002
  ...pushed?.sha256 ? { contentHash: pushed.sha256 } : {},
@@ -121741,7 +122068,7 @@ async function reconcileRegistry(options = {}) {
121741
122068
  runCount: readCursor(root2).runCount + 1,
121742
122069
  summary
121743
122070
  };
121744
- writeFileSync34(join73(root2, SYNC_CURSOR_FILE), `${JSON.stringify(cursor2, null, 2)}
122071
+ writeFileSync34(join74(root2, SYNC_CURSOR_FILE), `${JSON.stringify(cursor2, null, 2)}
121745
122072
  `);
121746
122073
  return {
121747
122074
  corpusRoot: root2,