@hasna/skills 0.10.60 → 0.10.62

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.62",
36892
36892
  description: "Skills library for AI coding agents",
36893
36893
  type: "module",
36894
36894
  bin: {
@@ -36925,9 +36925,11 @@ 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",
36932
+ "docs/runtime-activation.md",
36931
36933
  "schemas/",
36932
36934
  "LICENSE",
36933
36935
  "README.md",
@@ -36938,8 +36940,8 @@ var init_package = __esm(() => {
36938
36940
  types: "./dist/index.d.ts",
36939
36941
  scripts: {
36940
36942
  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",
36943
+ 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 ./src/runtime-prerequisites.ts --outdir ./dist --target bun && tsc --emitDeclarationOnly --declaration --outDir dist && bun scripts/stage-kernel-lock-assets.ts",
36944
+ "build:js": "rm -rf dist && bun build ./src/index.ts ./src/storage.ts ./src/sdk/index.ts ./src/admin-contract.ts ./src/runtime-prerequisites.ts --outdir ./dist --target bun && tsc --emitDeclarationOnly --declaration --outDir dist && bun scripts/stage-kernel-lock-assets.ts",
36943
36945
  test: "bun test --timeout 30000",
36944
36946
  dev: "bun run ./src/cli/index.tsx",
36945
36947
  "dev:watch": "bun --watch run ./src/cli/index.tsx",
@@ -37016,6 +37018,10 @@ var init_package = __esm(() => {
37016
37018
  homepage: "https://github.com/hasna/skills/tree/main/apps/skills",
37017
37019
  bugs: {
37018
37020
  url: "https://github.com/hasna/skills/issues"
37021
+ },
37022
+ skillsRuntimePrerequisites: {
37023
+ version: 1,
37024
+ entry: "dist/runtime-prerequisites.js"
37019
37025
  }
37020
37026
  };
37021
37027
  });
@@ -39899,7 +39905,7 @@ var init_agent_adapters = __esm(() => {
39899
39905
  codex: { root: ".codex/skills", config: ".codex/hooks.json", events: ["UserPromptSubmit", "SessionStart", "SubagentStart"], promptContext: true },
39900
39906
  gemini: { root: ".gemini/skills", config: ".gemini/settings.json", events: ["BeforeAgent", "SessionStart"], promptContext: true },
39901
39907
  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 },
39908
+ sumi: { root: null, config: null, events: ["prompt", "context"], promptContext: true },
39903
39909
  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
39910
  cursor: { root: ".cursor/skills", config: ".cursor/hooks.json", events: ["beforeSubmitPrompt", "sessionStart"], promptContext: false }
39905
39911
  };
@@ -54091,37 +54097,136 @@ var init_agent_codex = __esm(() => {
54091
54097
  });
54092
54098
 
54093
54099
  // 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) {
54100
+ import { spawnSync as spawnSync3 } from "child_process";
54101
+ import { accessSync as accessSync2, constants as constants11, existsSync as existsSync12, lstatSync as lstatSync18, realpathSync as realpathSync8, statSync as statSync9 } from "fs";
54102
+ import { delimiter as delimiter2, isAbsolute as isAbsolute15, join as join27, resolve as resolve15 } from "path";
54103
+ function recordWithKeys(value, keys2) {
54104
+ return value !== null && typeof value === "object" && !Array.isArray(value) && Object.keys(value).length === keys2.length && keys2.every((key) => Object.hasOwn(value, key));
54105
+ }
54106
+ function absolutePath3(value) {
54107
+ return typeof value === "string" && value.length > 0 && value.length <= 32768 && !/[\x00-\x1f\x7f]/.test(value) && isAbsolute15(value) && resolve15(value) === value;
54108
+ }
54109
+ function absoluteInput(value) {
54110
+ return value.length > 0 && value.length <= 32768 && !/[\x00-\x1f\x7f]/.test(value) && isAbsolute15(value);
54111
+ }
54112
+ function resolveSumiPathsCommand(pathValue) {
54113
+ if (!pathValue)
54114
+ return null;
54115
+ for (const directory of pathValue.split(delimiter2)) {
54116
+ if (!directory || /[\x00-\x1f\x7f]/.test(directory))
54117
+ continue;
54118
+ const candidate = resolve15(directory, "sumi-paths");
54119
+ try {
54120
+ accessSync2(candidate, constants11.X_OK);
54121
+ if (statSync9(candidate).isFile())
54122
+ return candidate;
54123
+ } catch {}
54124
+ }
54125
+ return null;
54126
+ }
54127
+ function validPathPlan(value, home, cwd2) {
54128
+ if (!recordWithKeys(value, ["schemaVersion", "kind", "home", "cwd", "roots", "legacyRoots", "configFiles", "skillRoots"]))
54129
+ return false;
54130
+ if (value.schemaVersion !== 1 || value.kind !== "sumi-paths" || value.home !== resolve15(home) || value.cwd !== resolve15(cwd2))
54131
+ return false;
54132
+ if (!recordWithKeys(value.roots, SUMI_PATH_KEYS) || !recordWithKeys(value.legacyRoots, SUMI_PATH_KEYS))
54133
+ return false;
54134
+ for (const key of SUMI_PATH_KEYS) {
54135
+ if (!absolutePath3(value.roots[key]))
54136
+ return false;
54137
+ if (value.legacyRoots[key] !== null && !absolutePath3(value.legacyRoots[key]))
54138
+ return false;
54139
+ }
54140
+ if (!recordWithKeys(value.configFiles, ["canonical", "legacy"]) || !recordWithKeys(value.skillRoots, ["canonical", "legacy"]))
54141
+ return false;
54142
+ if (!absolutePath3(value.configFiles.canonical) || !absolutePath3(value.skillRoots.canonical))
54143
+ return false;
54144
+ if (value.configFiles.legacy !== null && !absolutePath3(value.configFiles.legacy))
54145
+ return false;
54146
+ if (value.skillRoots.legacy !== null && !absolutePath3(value.skillRoots.legacy))
54147
+ return false;
54148
+ const configRoot = value.roots.config;
54149
+ const legacyConfigRoot = value.legacyRoots.config;
54150
+ if (typeof configRoot !== "string" || legacyConfigRoot !== null && typeof legacyConfigRoot !== "string")
54151
+ return false;
54152
+ if (value.configFiles.canonical !== join27(configRoot, "sumi.json") || value.skillRoots.canonical !== join27(configRoot, "skills"))
54153
+ return false;
54154
+ if (legacyConfigRoot === null)
54155
+ return value.configFiles.legacy === null && value.skillRoots.legacy === null;
54156
+ return value.configFiles.legacy === join27(legacyConfigRoot, "sumi.json") && value.skillRoots.legacy === join27(legacyConfigRoot, "skills");
54157
+ }
54158
+ function sumiPathPlan(home, cwd2 = process.cwd(), env3 = process.env) {
54097
54159
  for (const key of ["SUMI_CONFIG", "SUMI_CONFIG_CONTENT"])
54098
54160
  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))
54161
+ throw new SumiPathResolverError("SUMI_PATH_CONFIG_UNSUPPORTED");
54162
+ if (!absoluteInput(home) || !absoluteInput(cwd2))
54163
+ throw new SumiPathResolverError("SUMI_PATH_INPUT_REFUSED");
54164
+ const runtimePath = process.env.PATH ?? "";
54165
+ const executable2 = resolveSumiPathsCommand(runtimePath);
54166
+ if (!executable2 || !isAbsolute15(executable2))
54167
+ throw new SumiPathResolverError("SUMI_PATH_RESOLVER_UNAVAILABLE");
54168
+ const childEnv = { PATH: runtimePath };
54169
+ for (const key of SUMI_PATH_SELECTORS)
54170
+ if (env3[key] !== undefined)
54171
+ childEnv[key] = env3[key];
54172
+ let child2;
54173
+ try {
54174
+ child2 = spawnSync3(executable2, ["--json", "--home", resolve15(home), "--cwd", resolve15(cwd2)], {
54175
+ cwd: resolve15(cwd2),
54176
+ env: childEnv,
54177
+ encoding: "buffer",
54178
+ timeout: 3000,
54179
+ maxBuffer: SUMI_PATH_OUTPUT_LIMIT,
54180
+ shell: false
54181
+ });
54182
+ } catch {
54183
+ throw new SumiPathResolverError("SUMI_PATH_RESOLVER_UNAVAILABLE");
54184
+ }
54185
+ const stdoutBytes = child2.stdout === null ? 0 : Buffer.byteLength(child2.stdout);
54186
+ const stderrBytes = child2.stderr === null ? 0 : Buffer.byteLength(child2.stderr);
54187
+ if (child2.error || child2.signal || !child2.stdout || stdoutBytes > SUMI_PATH_OUTPUT_LIMIT || stderrBytes > 0) {
54188
+ throw new SumiPathResolverError("SUMI_PATH_RESOLVER_UNAVAILABLE");
54189
+ }
54190
+ let result2;
54191
+ try {
54192
+ result2 = JSON.parse(child2.stdout.toString("utf8"));
54193
+ } catch {
54194
+ throw new SumiPathResolverError("SUMI_PATH_RESOLVER_INVALID_RESPONSE");
54195
+ }
54196
+ 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) {
54197
+ throw new SumiPathResolverError(result2.code);
54198
+ }
54199
+ if (child2.status !== 0 || !validPathPlan(result2, home, cwd2))
54200
+ throw new SumiPathResolverError("SUMI_PATH_RESOLVER_INVALID_RESPONSE");
54201
+ return result2;
54202
+ }
54203
+ function selectedConfigDirectory(plan) {
54204
+ const canonical7 = plan.roots.config, legacy = plan.legacyRoots.config;
54205
+ if (legacy === null)
54206
+ return existsSync12(canonical7) ? realpathSync8(canonical7) : canonical7;
54207
+ const canonicalStat = lstatSync18(canonical7, { throwIfNoEntry: false }), legacyStat = lstatSync18(legacy, { throwIfNoEntry: false });
54208
+ if (canonicalStat && legacyStat && realpathSync8(canonical7) !== realpathSync8(legacy))
54111
54209
  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))
54210
+ const selected = canonicalStat ? canonical7 : legacyStat ? legacy : canonical7;
54211
+ if (!existsSync12(selected))
54212
+ return selected;
54213
+ const physical = realpathSync8(selected);
54214
+ if ((canonicalStat?.isSymbolicLink() || legacyStat?.isSymbolicLink()) && ![canonical7, legacy].includes(physical))
54117
54215
  throw new Error("Sumi config alias must resolve to its canonical or legacy root");
54118
54216
  return physical;
54119
54217
  }
54120
- function sumiBridgeRoot(home) {
54121
- return join27(sumiConfigDirectory(home), "skills");
54218
+ function sumiConfigDirectory(home, env3 = process.env, cwd2 = process.cwd()) {
54219
+ return selectedConfigDirectory(sumiPathPlan(home, cwd2, env3));
54220
+ }
54221
+ function sumiSkillRoots(home, cwd2 = process.cwd(), env3 = process.env) {
54222
+ const plan = sumiPathPlan(home, cwd2, env3);
54223
+ return [join27(selectedConfigDirectory(plan), "skills")];
54224
+ }
54225
+ function sumiBridgeRoot(home, cwd2 = process.cwd(), env3 = process.env) {
54226
+ return sumiSkillRoots(home, cwd2, env3)[0];
54122
54227
  }
54123
- function sumiConfigPath(home) {
54124
- return join27(sumiConfigDirectory(home), "sumi.json");
54228
+ function sumiConfigPath(home, cwd2 = process.cwd(), env3 = process.env) {
54229
+ return join27(sumiConfigDirectory(home, env3, cwd2), "sumi.json");
54125
54230
  }
54126
54231
  function renderSumiPlugin(command, profile) {
54127
54232
  return renderSumiPluginVersion(command, profile, false);
@@ -54207,8 +54312,19 @@ export default {
54207
54312
  };
54208
54313
  `;
54209
54314
  }
54210
- var SUMI_SKILL_PERMISSIONS;
54315
+ var SUMI_PATH_SELECTORS, SUMI_PATH_KEYS, SUMI_PATH_OUTPUT_LIMIT, SumiPathResolverError, SUMI_SKILL_PERMISSIONS;
54211
54316
  var init_agent_sumi = __esm(() => {
54317
+ SUMI_PATH_SELECTORS = ["SUMI_HOME", "SUMI_CONFIG_DIR", "XDG_DATA_HOME", "XDG_CACHE_HOME", "XDG_CONFIG_HOME", "XDG_STATE_HOME"];
54318
+ SUMI_PATH_KEYS = ["data", "cache", "config", "state"];
54319
+ SUMI_PATH_OUTPUT_LIMIT = 128 * 1024;
54320
+ SumiPathResolverError = class SumiPathResolverError extends Error {
54321
+ code;
54322
+ constructor(code) {
54323
+ super(`Sumi path discovery refused (${code})`);
54324
+ this.code = code;
54325
+ this.name = "SumiPathResolverError";
54326
+ }
54327
+ };
54212
54328
  SUMI_SKILL_PERMISSIONS = [
54213
54329
  { action: "skill", resource: "*", effect: "deny" },
54214
54330
  { action: "skill", resource: "skills-cli", effect: "allow" }
@@ -54216,9 +54332,9 @@ var init_agent_sumi = __esm(() => {
54216
54332
  });
54217
54333
 
54218
54334
  // 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";
54335
+ 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
54336
  import { createHash as createHash18 } from "crypto";
54221
- import { dirname as dirname15, isAbsolute as isAbsolute15, resolve as resolve16 } from "path";
54337
+ import { dirname as dirname15, isAbsolute as isAbsolute16, resolve as resolve16 } from "path";
54222
54338
  function need6(value, code) {
54223
54339
  if (!value)
54224
54340
  throw new Error(`CODEX_HOOK_TRUST_${code}`);
@@ -54238,7 +54354,7 @@ function safeParents(file) {
54238
54354
  function directAliasTarget(link2) {
54239
54355
  const text2 = readlinkSync5(link2), parts = text2.split("/");
54240
54356
  let first = 0;
54241
- if (isAbsolute15(text2))
54357
+ if (isAbsolute16(text2))
54242
54358
  first = 1;
54243
54359
  else
54244
54360
  while (parts[first] === "..")
@@ -54254,7 +54370,7 @@ function snapshot(file, privateFile = false, options = {}) {
54254
54370
  const initial2 = lstatSync19(file, { bigint: true });
54255
54371
  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
54372
  need6(initial2.size <= 8n * 1024n * 1024n, "FILE_BOUND");
54257
- const fd = openSync10(file, constants11.O_RDONLY | constants11.O_NOFOLLOW | constants11.O_NONBLOCK);
54373
+ const fd = openSync10(file, constants12.O_RDONLY | constants12.O_NOFOLLOW | constants12.O_NONBLOCK);
54258
54374
  try {
54259
54375
  const before2 = fstatSync10(fd, { bigint: true });
54260
54376
  need6(sameStat(initial2, before2), "INPUT_CHANGED");
@@ -54279,7 +54395,7 @@ function unchanged2(before2) {
54279
54395
  }
54280
54396
  function save(file, content) {
54281
54397
  safeParents(file);
54282
- const fd = openSync10(file, constants11.O_WRONLY | constants11.O_CREAT | constants11.O_EXCL | constants11.O_NOFOLLOW, 384);
54398
+ const fd = openSync10(file, constants12.O_WRONLY | constants12.O_CREAT | constants12.O_EXCL | constants12.O_NOFOLLOW, 384);
54283
54399
  try {
54284
54400
  writeFileSync5(fd, content);
54285
54401
  fsyncSync3(fd);
@@ -54290,35 +54406,152 @@ function save(file, content) {
54290
54406
  var sameStat = (a, b) => ["dev", "ino", "uid", "nlink", "mode", "size", "mtimeNs", "ctimeNs"].every((key) => a[key] === b[key]);
54291
54407
  var init_codex_hook_trust_files = () => {};
54292
54408
 
54409
+ // src/server/launcher-environment-policy.ts
54410
+ function renderLegacyPinnedLauncher(binding) {
54411
+ const names = LEGACY_ENV_NAMES.join(" ");
54412
+ const prefixes = LEGACY_ENV_PREFIXES.join("|");
54413
+ return [
54414
+ "#!/bin/sh -p",
54415
+ `# ${LEGACY_PINNED_LAUNCHER_SCHEMA}`,
54416
+ "# Written by `skills self-update`; rewrite it with `skills self-update`, do not edit by hand.",
54417
+ "# Runs the exact Skills entry below under one exact Bun from one trusted directory with",
54418
+ "# no working-directory configuration (no bunfig.toml, no .env, no macros, no auto-install)",
54419
+ "# and only the environment names allowed here. Everything else, BUN_* and NODE_OPTIONS",
54420
+ "# included, never reaches the runtime. The CLI returns to the caller's directory itself.",
54421
+ "# `-p` keeps the caller's exported functions and shell options out of this shell.",
54422
+ "set -eu",
54423
+ `${LAUNCH_CWD_VARIABLE2}=$(pwd -P 2>/dev/null || :)`,
54424
+ `export ${LAUNCH_CWD_VARIABLE2}`,
54425
+ `set -- '${binding.runtime}' ${PINNED_LAUNCHER_BUN_FLAGS.join(" ")} '--cwd=${binding.cwd}' '${binding.entry}' "$@"`,
54426
+ "hasna_skills_env=$(LC_ALL=C /usr/bin/awk 'BEGIN {",
54427
+ ` n = split("${names}", exact, " ")`,
54428
+ " for (i = 1; i <= n; i++) allow[exact[i]] = 1",
54429
+ " for (name in ENVIRON) {",
54430
+ " if (name !~ /^[A-Za-z_][A-Za-z0-9_]*$/) continue",
54431
+ ` if (name == "LC_ALL" || (!(name in allow) && name !~ /^(${prefixes})_/)) continue`,
54432
+ ' value = ENVIRON[name]; quoted = ""',
54433
+ ' while ((k = index(value, "\\047")) > 0) { quoted = quoted substr(value, 1, k - 1) "\\047\\\\\\047\\047"; value = substr(value, k + 1) }',
54434
+ ' printf "\\047%s=%s\\047 ", name, quoted value',
54435
+ " }",
54436
+ "}')",
54437
+ 'eval "set -- $hasna_skills_env \\"\\$@\\""',
54438
+ 'if [ "${LC_ALL+x}" = x ]; then set -- "LC_ALL=$LC_ALL" "$@"; fi',
54439
+ 'exec /usr/bin/env -i "$@"',
54440
+ ""
54441
+ ].join(`
54442
+ `);
54443
+ }
54444
+ function isStorageLocatorEnvironmentName(name) {
54445
+ return storageLocators.has(name);
54446
+ }
54447
+ 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`;
54448
+ var init_launcher_environment_policy = __esm(() => {
54449
+ PINNED_LAUNCHER_BUN_FLAGS = ["--config=/dev/null", "--no-env-file", "--no-macros", "--no-install"];
54450
+ LEGACY_ENV_NAMES = [
54451
+ "HOME",
54452
+ "PATH",
54453
+ "TMPDIR",
54454
+ "TERM",
54455
+ "TERM_PROGRAM",
54456
+ "TERM_PROGRAM_VERSION",
54457
+ "COLORTERM",
54458
+ "LANG",
54459
+ "USER",
54460
+ "LOGNAME",
54461
+ "SHELL",
54462
+ "TZ",
54463
+ "NO_COLOR",
54464
+ "FORCE_COLOR",
54465
+ "CI",
54466
+ "COLUMNS",
54467
+ "LINES",
54468
+ "EDITOR",
54469
+ "VISUAL",
54470
+ "PAGER",
54471
+ "SSH_AUTH_SOCK",
54472
+ "DATABASE_URL",
54473
+ "TERMINAL_CWD",
54474
+ "CODEX_HOME",
54475
+ "HERMES_HOME",
54476
+ "HERMES_ENABLE_PROJECT_PLUGINS",
54477
+ "HOST",
54478
+ "PORT",
54479
+ "NODE_ENV",
54480
+ "AGENT_ID",
54481
+ "ECS_CONTAINER_METADATA_URI_V4"
54482
+ ];
54483
+ LEGACY_ENV_PREFIXES = ["HASNA", "SKILLS", "SKILL", "MCP", "XDG", "LC", "AWS"];
54484
+ SERVER_LAUNCHER_ENV_NAMES = ["DATABASE_URL"];
54485
+ STORAGE_LOCATOR_ENV_NAMES = ["DATABASE_URL", "HASNA_SKILLS_DATABASE_URL", "SKILLS_DATABASE_URL"];
54486
+ storageLocators = new Set(STORAGE_LOCATOR_ENV_NAMES);
54487
+ });
54488
+
54293
54489
  // src/cli/commands/runtime-launcher.ts
54294
54490
  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) {
54491
+ 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";
54492
+ import { isAbsolute as isAbsolute17 } from "path";
54493
+ function pinnedLauncherEnvironment(env3, profile = "client") {
54494
+ assertLauncherProfile(profile);
54298
54495
  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))
54496
+ for (const name of Object.keys(env3)) {
54497
+ if (!ENV_NAME.test(name))
54498
+ continue;
54499
+ const storageLocator = isStorageLocatorEnvironmentName(name);
54500
+ if (storageLocator && profile === "client")
54301
54501
  continue;
54302
- result2[name] = value;
54502
+ if (!storageLocator && !ENV_EXACT.has(name) && !ENV_PREFIX.test(name))
54503
+ continue;
54504
+ const value = env3[name];
54505
+ if (value !== undefined)
54506
+ result2[name] = value;
54303
54507
  }
54304
54508
  return result2;
54305
54509
  }
54510
+ function assertLauncherProfile(profile) {
54511
+ if (profile !== "client" && profile !== "server")
54512
+ throw new Error("LAUNCHER_PROFILE_INVALID");
54513
+ }
54514
+ function launcherProfileForBin(name, entry) {
54515
+ const bins = {
54516
+ skills: ["bin/index.js", "client"],
54517
+ "skills-mcp": ["bin/mcp.js", "client"],
54518
+ "skills-serve": ["bin/server.js", "server"],
54519
+ "skills-server": ["bin/server.js", "server"],
54520
+ "skills-worker": ["bin/worker.js", "server"],
54521
+ "skills-maintenance": ["bin/maintenance.js", "server"],
54522
+ "skills-migrate": ["bin/migrate.js", "server"]
54523
+ };
54524
+ const contract = bins[name];
54525
+ if (!contract || entry !== contract[0])
54526
+ throw new Error("LAUNCHER_BIN_CONTRACT_INVALID");
54527
+ return contract[1];
54528
+ }
54306
54529
  function sha2562(bytes) {
54307
54530
  return createHash19("sha256").update(bytes).digest("hex");
54308
54531
  }
54309
54532
  function assertLauncherPath(value, code) {
54310
- if (typeof value !== "string" || !isAbsolute16(value) || /['\x00-\x1f\x7f]/.test(value))
54533
+ if (typeof value !== "string" || !isAbsolute17(value) || /['\x00-\x1f\x7f]/.test(value))
54311
54534
  throw new Error(code);
54312
54535
  }
54313
54536
  function renderPinnedLauncher(binding) {
54314
54537
  assertLauncherPath(binding.runtime, "LAUNCHER_RUNTIME_PATH_INVALID");
54315
54538
  assertLauncherPath(binding.cwd, "LAUNCHER_CWD_PATH_INVALID");
54316
54539
  assertLauncherPath(binding.entry, "LAUNCHER_ENTRY_PATH_INVALID");
54317
- const names = PINNED_LAUNCHER_ENV_NAMES.join(" ");
54540
+ if (binding.format === "v1") {
54541
+ if (binding.profile !== undefined)
54542
+ throw new Error("LAUNCHER_PROFILE_INVALID");
54543
+ return renderLegacyPinnedLauncher(binding);
54544
+ }
54545
+ if (binding.format !== undefined && binding.format !== "v2")
54546
+ throw new Error("LAUNCHER_FORMAT_INVALID");
54547
+ const profile = binding.profile === undefined ? "client" : binding.profile;
54548
+ assertLauncherProfile(profile);
54549
+ const names = [...PINNED_LAUNCHER_ENV_NAMES, ...profile === "server" ? SERVER_LAUNCHER_ENV_NAMES : []].join(" ");
54318
54550
  const prefixes = PINNED_LAUNCHER_ENV_PREFIXES.join("|");
54319
54551
  return [
54320
54552
  "#!/bin/sh -p",
54321
54553
  `# ${PINNED_LAUNCHER_SCHEMA}`,
54554
+ `# environment-profile: ${profile}`,
54322
54555
  "# Written by `skills self-update`; rewrite it with `skills self-update`, do not edit by hand.",
54323
54556
  "# Runs the exact Skills entry below under one exact Bun from one trusted directory with",
54324
54557
  "# no working-directory configuration (no bunfig.toml, no .env, no macros, no auto-install)",
@@ -54326,15 +54559,16 @@ function renderPinnedLauncher(binding) {
54326
54559
  "# included, never reaches the runtime. The CLI returns to the caller's directory itself.",
54327
54560
  "# `-p` keeps the caller's exported functions and shell options out of this shell.",
54328
54561
  "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}' "$@"`,
54562
+ `${LAUNCH_CWD_VARIABLE3}=$(pwd -P 2>/dev/null || :)`,
54563
+ `export ${LAUNCH_CWD_VARIABLE3}`,
54564
+ `set -- '${binding.runtime}' ${PINNED_LAUNCHER_BUN_FLAGS2.join(" ")} '--cwd=${binding.cwd}' '${binding.entry}' "$@"`,
54332
54565
  "hasna_skills_env=$(LC_ALL=C /usr/bin/awk 'BEGIN {",
54333
54566
  ` n = split("${names}", exact, " ")`,
54334
54567
  " for (i = 1; i <= n; i++) allow[exact[i]] = 1",
54335
54568
  " for (name in ENVIRON) {",
54336
54569
  " if (name !~ /^[A-Za-z_][A-Za-z0-9_]*$/) continue",
54337
54570
  ` if (name == "LC_ALL" || (!(name in allow) && name !~ /^(${prefixes})_/)) continue`,
54571
+ ...profile === "client" ? [CLIENT_LAUNCHER_STORAGE_DENY_AWK] : [],
54338
54572
  ' value = ENVIRON[name]; quoted = ""',
54339
54573
  ' while ((k = index(value, "\\047")) > 0) { quoted = quoted substr(value, 1, k - 1) "\\047\\\\\\047\\047"; value = substr(value, k + 1) }',
54340
54574
  ' printf "\\047%s=%s\\047 ", name, quoted value',
@@ -54351,7 +54585,19 @@ function parsePinnedLauncher(text2) {
54351
54585
  const match = COMMAND_LINE.exec(text2);
54352
54586
  if (!match)
54353
54587
  return null;
54354
- const binding = { runtime: match[1], cwd: match[2], entry: match[3] };
54588
+ let metadata;
54589
+ if (text2.split(`
54590
+ `)[1] === `# ${LEGACY_PINNED_LAUNCHER_SCHEMA}`)
54591
+ metadata = { format: "v1" };
54592
+ else if (text2.split(`
54593
+ `)[1] === `# ${PINNED_LAUNCHER_SCHEMA}`) {
54594
+ const profile = /^# environment-profile: (client|server)$/m.exec(text2)?.[1];
54595
+ if (!profile)
54596
+ return null;
54597
+ metadata = { format: "v2", profile };
54598
+ } else
54599
+ return null;
54600
+ const binding = { runtime: match[1], cwd: match[2], entry: match[3], ...metadata };
54355
54601
  try {
54356
54602
  if (renderPinnedLauncher(binding) !== text2)
54357
54603
  return null;
@@ -54398,7 +54644,7 @@ function inspectLauncher(path) {
54398
54644
  const binding = parsePinnedLauncher(text2);
54399
54645
  if (!binding)
54400
54646
  return { kind: "foreign" };
54401
- return { kind: "pinned", runtime: binding.runtime, cwd: binding.cwd, target: binding.entry, sha256: sha2562(text2), text: text2 };
54647
+ return { kind: "pinned", format: binding.format, profile: binding.profile, runtime: binding.runtime, cwd: binding.cwd, target: binding.entry, sha256: sha2562(text2), text: text2 };
54402
54648
  }
54403
54649
  function launcherTarget(path) {
54404
54650
  const inspected = inspectLauncher(path);
@@ -54415,17 +54661,22 @@ function launcherIs(path, state) {
54415
54661
  }
54416
54662
  if (state.shape === "symlink")
54417
54663
  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;
54664
+ 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
54665
  }
54420
54666
  function pinnedLauncherText(state) {
54421
- const text2 = renderPinnedLauncher({ runtime: state.runtime, cwd: state.cwd, entry: state.target });
54667
+ if (state.format === "v2")
54668
+ assertLauncherProfile(state.profile);
54669
+ const text2 = renderPinnedLauncher({ runtime: state.runtime, cwd: state.cwd, entry: state.target, format: state.format === undefined ? "v1" : state.format, profile: state.profile });
54422
54670
  if (sha2562(text2) !== state.sha256)
54423
54671
  throw new Error("LAUNCHER_TEXT_DIGEST_MISMATCH");
54424
54672
  return text2;
54425
54673
  }
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) };
54674
+ function pinnedLauncherState(runtime, cwd2, target, metadata = { format: "v2", profile: "client" }) {
54675
+ const format = metadata.format === undefined ? "v1" : metadata.format, profile = metadata.profile;
54676
+ if (format === "v2")
54677
+ assertLauncherProfile(profile);
54678
+ const text2 = renderPinnedLauncher({ runtime, cwd: cwd2, entry: target, format, profile });
54679
+ return { shape: "pinned", runtime, cwd: cwd2, target, sha256: sha2562(text2), format, ...profile ? { profile } : {} };
54429
54680
  }
54430
54681
  function materializeLauncher(path, state) {
54431
54682
  if (state.shape === "symlink") {
@@ -54435,7 +54686,7 @@ function materializeLauncher(path, state) {
54435
54686
  return;
54436
54687
  }
54437
54688
  const text2 = pinnedLauncherText(state);
54438
- const fd = openSync11(path, constants12.O_WRONLY | constants12.O_CREAT | constants12.O_EXCL | constants12.O_NOFOLLOW, 493);
54689
+ const fd = openSync11(path, constants13.O_WRONLY | constants13.O_CREAT | constants13.O_EXCL | constants13.O_NOFOLLOW, 493);
54439
54690
  try {
54440
54691
  const bytes = Buffer.from(text2, "utf8");
54441
54692
  let written = 0;
@@ -54491,9 +54742,10 @@ function assertPinnedLauncherShell() {
54491
54742
  if (probe.exitCode !== 0)
54492
54743
  throw new Error("LAUNCHER_SHELL_UNSUPPORTED");
54493
54744
  }
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;
54745
+ 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
54746
  var init_runtime_launcher = __esm(() => {
54496
- PINNED_LAUNCHER_BUN_FLAGS = ["--config=/dev/null", "--no-env-file", "--no-macros", "--no-install"];
54747
+ init_launcher_environment_policy();
54748
+ PINNED_LAUNCHER_BUN_FLAGS2 = ["--config=/dev/null", "--no-env-file", "--no-macros", "--no-install"];
54497
54749
  PINNED_LAUNCHER_ENV_NAMES = [
54498
54750
  "HOME",
54499
54751
  "PATH",
@@ -54516,7 +54768,6 @@ var init_runtime_launcher = __esm(() => {
54516
54768
  "VISUAL",
54517
54769
  "PAGER",
54518
54770
  "SSH_AUTH_SOCK",
54519
- "DATABASE_URL",
54520
54771
  "TERMINAL_CWD",
54521
54772
  "CODEX_HOME",
54522
54773
  "HERMES_HOME",
@@ -54531,16 +54782,32 @@ var init_runtime_launcher = __esm(() => {
54531
54782
  ENV_NAME = /^[A-Za-z_][A-Za-z0-9_]*$/;
54532
54783
  ENV_PREFIX = new RegExp(`^(${PINNED_LAUNCHER_ENV_PREFIXES.join("|")})_`);
54533
54784
  ENV_EXACT = new Set(PINNED_LAUNCHER_ENV_NAMES);
54534
- COMMAND_LINE = new RegExp(`^set -- '([^']+)' ${PINNED_LAUNCHER_BUN_FLAGS.join(" ")} '--cwd=([^']+)' '([^']+)' "\\$@"$`, "m");
54785
+ COMMAND_LINE = new RegExp(`^set -- '([^']+)' ${PINNED_LAUNCHER_BUN_FLAGS2.join(" ")} '--cwd=([^']+)' '([^']+)' "\\$@"$`, "m");
54535
54786
  PINNED_LAUNCHER_MAX_BYTES = 16 * 1024;
54536
54787
  });
54537
54788
 
54538
54789
  // src/lib/agent-integration.ts
54539
54790
  import { createHash as createHash20, randomUUID as randomUUID6 } from "crypto";
54540
54791
  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";
54792
+ 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";
54793
+ import { dirname as dirname16, join as join28, resolve as resolve17, relative as relative6, isAbsolute as isAbsolute18, sep as sep7 } from "path";
54543
54794
  import { homedir as homedir3 } from "os";
54795
+ function nativeAgentRoot(home, agent, cwd2 = process.cwd()) {
54796
+ if (agent === "sumi")
54797
+ return sumiBridgeRoot(home, cwd2);
54798
+ const root = AGENT_ADAPTERS[agent].root;
54799
+ if (typeof root !== "string")
54800
+ throw new Error(`Native skill root is unavailable for ${agent}`);
54801
+ return join28(home, root);
54802
+ }
54803
+ function nativeAgentConfig(home, agent, cwd2 = process.cwd()) {
54804
+ if (agent === "sumi")
54805
+ return sumiConfigPath(home, cwd2);
54806
+ const config = AGENT_ADAPTERS[agent].config;
54807
+ if (typeof config !== "string")
54808
+ throw new Error(`Native configuration path is unavailable for ${agent}`);
54809
+ return join28(home, config);
54810
+ }
54544
54811
  function hasTrustedDarwinAcl(fd, allowDenyOnly = false) {
54545
54812
  try {
54546
54813
  const { dlopen, read: read2, ptr } = __require("bun:ffi");
@@ -54603,7 +54870,7 @@ function isSystemRootAlias(path) {
54603
54870
  throw new Error("Writable system alias directory");
54604
54871
  } else if ((stat.mode & 0o1000n) === 0n)
54605
54872
  throw new Error("Unprotected system temporary directory");
54606
- const fd = openSync12(directory, constants13.O_RDONLY | constants13.O_DIRECTORY | constants13.O_NOFOLLOW);
54873
+ const fd = openSync12(directory, constants14.O_RDONLY | constants14.O_DIRECTORY | constants14.O_NOFOLLOW);
54607
54874
  try {
54608
54875
  if (directoryIdentity(fstatSync12(fd, { bigint: true })) !== directoryIdentity(stat) || !hasTrustedDarwinAcl(fd) || directoryIdentity(fstatSync12(fd, { bigint: true })) !== directoryIdentity(stat))
54609
54876
  throw new Error("Unverified system alias directory ACL");
@@ -54648,7 +54915,7 @@ function readRootAlias(home, agent) {
54648
54915
  if (!targetStat?.isDirectory())
54649
54916
  throw new Error(`Agent root alias must target an existing directory: ${alias}`);
54650
54917
  const target = realpathSync10(targetPath), inside = relative6(realHome, target);
54651
- if (!inside || inside === ".." || inside.startsWith(`..${sep7}`) || isAbsolute17(inside))
54918
+ if (!inside || inside === ".." || inside.startsWith(`..${sep7}`) || isAbsolute18(inside))
54652
54919
  throw new Error(`Agent root alias target must be inside the real home: ${alias}`);
54653
54920
  return { agent, home: realHome, alias, target, link: link2, aliasIdentity: `${stat.dev}:${stat.ino}:${stat.ctimeNs}`, targetIdentity: `${targetStat.dev}:${targetStat.ino}` };
54654
54921
  }
@@ -54674,13 +54941,13 @@ function disabledCodexSkillPaths(config, aliases) {
54674
54941
  const rows = skills.config;
54675
54942
  if (!Array.isArray(rows))
54676
54943
  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())))
54944
+ 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
54945
  return [];
54679
54946
  if (rows.some((entry) => entry.name !== undefined && entry.enabled !== false))
54680
54947
  return [];
54681
54948
  const settings = new Map;
54682
54949
  for (const entry of rows) {
54683
- if (typeof entry.path !== "string" || !isAbsolute17(entry.path))
54950
+ if (typeof entry.path !== "string" || !isAbsolute18(entry.path))
54684
54951
  continue;
54685
54952
  let document3;
54686
54953
  try {
@@ -54712,7 +54979,7 @@ function readNativeBytes(path, maximum = 64 * 1024 * 1024) {
54712
54979
  const before2 = lstatSync21(path);
54713
54980
  if (!before2.isFile() || before2.size > maximum)
54714
54981
  throw new Error("Unsupported or oversized native skill file");
54715
- const descriptor = openSync12(path, constants13.O_RDONLY | constants13.O_NOFOLLOW | constants13.O_NONBLOCK);
54982
+ const descriptor = openSync12(path, constants14.O_RDONLY | constants14.O_NOFOLLOW | constants14.O_NONBLOCK);
54716
54983
  try {
54717
54984
  const opened = fstatSync12(descriptor);
54718
54985
  if (!opened.isFile() || opened.dev !== before2.dev || opened.ino !== before2.ino || opened.size !== before2.size)
@@ -54785,16 +55052,16 @@ function parseNativeMigrationTargetManifest(input) {
54785
55052
  throw new Error("Invalid native migration target fields");
54786
55053
  if (!ROOTS.some(([agent]) => agent === item.agent))
54787
55054
  throw new Error(`Unsupported native migration target agent: ${item.agent}`);
54788
- if (!isAbsolute17(item.projectRoot) || resolve17(item.projectRoot) !== item.projectRoot)
55055
+ if (!isAbsolute18(item.projectRoot) || resolve17(item.projectRoot) !== item.projectRoot)
54789
55056
  throw new Error(`Native migration target project root must be an existing absolute directory: ${item.projectRoot}`);
54790
55057
  const projectRoot = canonicalSystemPath(item.projectRoot);
54791
55058
  if (!existsSync13(projectRoot) || !lstatSync21(projectRoot).isDirectory())
54792
55059
  throw new Error(`Native migration target project root must be an existing absolute directory: ${item.projectRoot}`);
54793
55060
  assertSafePath(projectRoot);
54794
- if (isAbsolute17(item.path) || item.path.includes("\\") || item.path.length === 0 || item.path.includes("\x00"))
55061
+ if (isAbsolute18(item.path) || item.path.includes("\\") || item.path.length === 0 || item.path.includes("\x00"))
54795
55062
  throw new Error(`Native migration target path must be normalized and project-relative: ${item.path}`);
54796
55063
  const resolved = resolve17(projectRoot, item.path), normalized = relative6(projectRoot, resolved);
54797
- if (!normalized || normalized === ".." || normalized.startsWith(`..${sep7}`) || isAbsolute17(normalized) || normalized !== item.path)
55064
+ if (!normalized || normalized === ".." || normalized.startsWith(`..${sep7}`) || isAbsolute18(normalized) || normalized !== item.path)
54798
55065
  throw new Error(`Native migration target path escapes or is not normalized: ${item.path}`);
54799
55066
  if (!/^[0-9a-f]{64}$/.test(item.treeSha256))
54800
55067
  throw new Error(`Invalid native migration tree digest for ${item.path}`);
@@ -54815,13 +55082,13 @@ function selectNativeMigrationTargets(inventory, manifest) {
54815
55082
  const identities = new Set;
54816
55083
  const selected = [];
54817
55084
  for (const target of manifest.targets) {
54818
- if (!isAbsolute17(target.projectRoot) || resolve17(target.projectRoot) !== target.projectRoot)
55085
+ if (!isAbsolute18(target.projectRoot) || resolve17(target.projectRoot) !== target.projectRoot)
54819
55086
  throw new Error(`Native migration target project root must be an existing absolute directory: ${target.projectRoot}`);
54820
55087
  const projectRoot = canonicalSystemPath(target.projectRoot), normalized = relative6(projectRoot, resolve17(projectRoot, target.path));
54821
55088
  if (!existsSync13(projectRoot) || !lstatSync21(projectRoot).isDirectory())
54822
55089
  throw new Error(`Native migration target project root must be an existing absolute directory: ${target.projectRoot}`);
54823
55090
  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))
55091
+ 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
55092
  throw new Error(`Invalid native migration target: ${target.path}`);
54826
55093
  const identity6 = `${target.agent}\x00${canonicalSystemPath(projectRoot)}\x00${normalized}`;
54827
55094
  if (identities.has(identity6))
@@ -54864,25 +55131,32 @@ function isCodexSkillDiscoveryInput(path) {
54864
55131
  }
54865
55132
  function inventoryNativeSkills(home = homedir3(), options = {}) {
54866
55133
  home = canonicalSystemPath(home);
54867
- if (options.reviewedCacheAlias !== undefined && (!options.includeVendor || !isAbsolute17(options.reviewedCacheAlias) || resolve17(options.reviewedCacheAlias) !== options.reviewedCacheAlias))
55134
+ if (options.reviewedCacheAlias !== undefined && (!options.includeVendor || !isAbsolute18(options.reviewedCacheAlias) || resolve17(options.reviewedCacheAlias) !== options.reviewedCacheAlias))
54868
55135
  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))
55136
+ if (options.disabledVendorPaths?.some((path) => !isAbsolute18(path) || resolve17(path) !== path))
54870
55137
  throw new Error("Disabled vendor paths must be exact absolute paths");
54871
55138
  const reviewedCacheAlias = options.reviewedCacheAlias === undefined ? undefined : canonicalSystemPath(options.reviewedCacheAlias);
54872
55139
  const disabledVendorPaths = new Set((options.disabledVendorPaths ?? []).map(canonicalSystemPath));
54873
55140
  const aliases = rootAliases(home, options.allowRootAliases);
54874
55141
  const selectedAgents = options.agents ? new Set(options.agents) : undefined;
54875
55142
  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;
55143
+ 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
55144
  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));
55145
+ const includesSumi = !selectedAgents || selectedAgents.has("sumi");
55146
+ if (includesSumi)
55147
+ for (const path of sumiSkillRoots(home))
55148
+ roots.push(["sumi", canonicalAgentPath(path, aliases)]);
55149
+ const bridgePaths = Object.entries(AGENT_ADAPTERS).filter(([agent]) => agent !== "sumi" || includesSumi).map(([agent]) => canonicalAgentPath(join28(nativeAgentRoot(home, agent), CLI_BRIDGE_NAME), aliases));
54879
55150
  for (const project of projectAncestorDirectories([...options.projectDirs ?? [], ...options.projectDir ? [options.projectDir] : []])) {
54880
55151
  for (const [agent, path] of rootDefinitions)
54881
55152
  roots.push([agent, canonicalAgentPath(join28(project, path), aliases)]);
54882
- if (selectedAgents?.has("sumi"))
55153
+ if (selectedAgents?.has("sumi")) {
55154
+ for (const path of sumiSkillRoots(home, project))
55155
+ roots.push(["sumi", canonicalAgentPath(path, aliases)]);
54883
55156
  for (const directory of [".claude", ".agents"])
54884
55157
  for (const name of ["skill", "skills"])
54885
55158
  roots.push(["sumi", canonicalAgentPath(join28(project, directory, name), aliases)]);
55159
+ }
54886
55160
  }
54887
55161
  const installationInputs = options.codexInstallationInputRoots ?? [];
54888
55162
  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 +55174,7 @@ function inventoryNativeSkills(home = homedir3(), options = {}) {
54900
55174
  let reviewedCacheAliasFound = false;
54901
55175
  function verifiedSiblingCacheAlias(agent, path, parent) {
54902
55176
  const link2 = readlinkSync7(path), lexicalTarget = resolve17(parent, link2);
54903
- if (isAbsolute17(link2) ? link2 !== lexicalTarget : dirname16(link2) !== ".")
55177
+ if (isAbsolute18(link2) ? link2 !== lexicalTarget : dirname16(link2) !== ".")
54904
55178
  return false;
54905
55179
  const target = canonicalSystemPath(lexicalTarget);
54906
55180
  if (dirname16(target) !== parent)
@@ -54980,7 +55254,7 @@ function inventoryNativeSkills(home = homedir3(), options = {}) {
54980
55254
  continue;
54981
55255
  const child2 = join28(path, name);
54982
55256
  if (isVendor && lstatSync21(child2, { throwIfNoEntry: false })?.isSymbolicLink()) {
54983
- const target = statSync9(child2, { throwIfNoEntry: false });
55257
+ const target = statSync10(child2, { throwIfNoEntry: false });
54984
55258
  if (target?.isFile() || pluginCache && target?.isDirectory() && verifiedSiblingCacheAlias(agent, child2, path)) {
54985
55259
  scan.entries++;
54986
55260
  continue;
@@ -55244,8 +55518,7 @@ function planAgentIntegration(options) {
55244
55518
  if (!INTEGRATION_AGENTS.includes(agent))
55245
55519
  throw new Error(`Unsupported agent: ${agent}`);
55246
55520
  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);
55521
+ const bridgePath = canonicalAgentPath(join28(nativeAgentRoot(home, agent, options.projectDir ?? process.cwd()), CLI_BRIDGE_NAME), aliases);
55249
55522
  assertSafePath(bridgePath);
55250
55523
  if (existsSync13(bridgePath) && !isOwnedCliBridge(bridgePath, [bridgePath]))
55251
55524
  throw new Error(`Refusing to overwrite an unrecognized or modified Skills bridge: ${bridgePath}`);
@@ -55254,7 +55527,7 @@ function planAgentIntegration(options) {
55254
55527
  if (before3 !== after3)
55255
55528
  changes.push({ path: path2, before: before3, after: after3 });
55256
55529
  }
55257
- const path = canonicalAgentPath(agent === "sumi" ? sumiConfigPath(home) : join28(home, adapter.config), aliases);
55530
+ const path = canonicalAgentPath(nativeAgentConfig(home, agent, options.projectDir ?? process.cwd()), aliases);
55258
55531
  const before2 = readOptional(path);
55259
55532
  if (agent === "hermes") {
55260
55533
  const supervisorPath = join28(dataDir3, "agent-hooks", "hermes.js"), supervisorBefore = readOptional(supervisorPath), supervisorAfter = renderHermesSupervisor(command, profileId2);
@@ -55279,7 +55552,7 @@ function planAgentIntegration(options) {
55279
55552
  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
55553
  throw new Error("Expected Sumi native permission rules");
55281
55554
  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);
55555
+ const pluginPath = join28(sumiConfigDirectory(home, process.env, options.projectDir ?? process.cwd()), "plugins", "skills-cli.js"), pluginBefore = readOptional(pluginPath);
55283
55556
  const pluginAfter = renderSumiPlugin(command, profileId2);
55284
55557
  const priorCommand = policy.bridge?.commands?.sumi, priorProfile = policy.bridge?.profiles?.sumi ?? policy.profileId;
55285
55558
  if (pluginBefore !== null && pluginBefore !== pluginAfter && !(typeof priorCommand === "string" && typeof priorProfile === "string" && isManagedSumiPlugin(pluginBefore, priorCommand, priorProfile)))
@@ -55370,7 +55643,7 @@ function projectedHookAcl(path, observed) {
55370
55643
  if (process.platform !== "darwin")
55371
55644
  return;
55372
55645
  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));
55646
+ const fd = openSync12(path, constants14.O_RDONLY | constants14.O_NOFOLLOW | constants14.O_NONBLOCK | (observed.isDirectory() ? constants14.O_DIRECTORY : 0));
55374
55647
  try {
55375
55648
  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
55649
  hookProjectionRefusal("EXECUTABLE_UNVERIFIED");
@@ -55380,7 +55653,7 @@ function projectedHookAcl(path, observed) {
55380
55653
  }
55381
55654
  function projectedHookExecutable(command, expectedResolved) {
55382
55655
  try {
55383
- if (!isAbsolute17(command) || /[\0\r\n]/.test(command) || resolve17(command) !== command)
55656
+ if (!isAbsolute18(command) || /[\0\r\n]/.test(command) || resolve17(command) !== command)
55384
55657
  hookProjectionRefusal("EXECUTABLE_UNVERIFIED");
55385
55658
  command = canonicalSystemPath(command);
55386
55659
  const parents2 = (file = command) => {
@@ -55600,7 +55873,7 @@ function planAgentSettingsWitnessUpgrade(options) {
55600
55873
  const binding = policy.bridge?.discovery?.[options.agent];
55601
55874
  if (!binding || binding.agent !== options.agent || binding.method !== "reviewed")
55602
55875
  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);
55876
+ 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
55877
  const settings = readOptional(configPath);
55605
55878
  if (settings === null || sha3(settings) !== options.expectedSettingsSha256)
55606
55879
  throw new Error("Native settings preimage changed");
@@ -55778,7 +56051,7 @@ function applyAgentIntegrationUnlocked(plan, options = {}, assertCurrent) {
55778
56051
  }
55779
56052
  function syncArchiveDirectory(path) {
55780
56053
  assertSafePath(path);
55781
- const descriptor = openSync12(path, constants13.O_RDONLY | constants13.O_DIRECTORY | constants13.O_NOFOLLOW | constants13.O_NONBLOCK);
56054
+ const descriptor = openSync12(path, constants14.O_RDONLY | constants14.O_DIRECTORY | constants14.O_NOFOLLOW | constants14.O_NONBLOCK);
55782
56055
  try {
55783
56056
  fsyncSync5(descriptor);
55784
56057
  } finally {
@@ -55790,7 +56063,7 @@ function writeArchiveJournal(path, value) {
55790
56063
  const temporary = `${path}.skills-${randomUUID6()}`;
55791
56064
  let descriptor;
55792
56065
  try {
55793
- descriptor = openSync12(temporary, constants13.O_WRONLY | constants13.O_CREAT | constants13.O_EXCL | constants13.O_NOFOLLOW, 384);
56066
+ descriptor = openSync12(temporary, constants14.O_WRONLY | constants14.O_CREAT | constants14.O_EXCL | constants14.O_NOFOLLOW, 384);
55794
56067
  writeFileSync6(descriptor, `${JSON.stringify(value)}
55795
56068
  `);
55796
56069
  fsyncSync5(descriptor);
@@ -55824,7 +56097,7 @@ function archiveNativeSkillsUnlocked(inventory, options, assertCurrent) {
55824
56097
  recheckRootAliases(aliases);
55825
56098
  for (const entry of inventory.filter((entry2) => entry2.bridge)) {
55826
56099
  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;
56100
+ const expected = adapter && entry.bridgeHome ? canonicalAgentPath(join28(nativeAgentRoot(entry.bridgeHome, entry.agent), CLI_BRIDGE_NAME), aliases) : undefined;
55828
56101
  if (!expected || treeHash(entry.path) !== entry.hash || !isOwnedCliBridge(entry.path, [expected]))
55829
56102
  throw new Error(`Skills bridge changed after planning: ${entry.path}`);
55830
56103
  }
@@ -55948,7 +56221,7 @@ function isInertCodexPluginCacheCopy(entry, cache3, allowedHostPaths, read2) {
55948
56221
  return false;
55949
56222
  const document3 = join28(entry.path, "SKILL.md");
55950
56223
  const inside = relative6(cache3, entry.path);
55951
- if (!inside || isAbsolute17(inside) || inside.split(sep7).some((segment) => segment === ".."))
56224
+ if (!inside || isAbsolute18(inside) || inside.split(sep7).some((segment) => segment === ".."))
55952
56225
  return false;
55953
56226
  assertSafePath(entry.path);
55954
56227
  if (!lstatSync21(cache3).isDirectory() || !lstatSync21(entry.path).isDirectory() || !lstatSync21(document3).isFile())
@@ -55980,14 +56253,14 @@ function assertManagedAgentBridgeWithDiscovery(agent, options = {}, provenDiscov
55980
56253
  if (!Array.isArray(aliases))
55981
56254
  throw new Error("NATIVE_SKILL_DRIFT: invalid root alias binding");
55982
56255
  recheckRootAliases(aliases);
55983
- const expected = canonicalAgentPath(join28(agent === "sumi" ? sumiBridgeRoot(home) : join28(home, AGENT_ADAPTERS[agent].root), CLI_BRIDGE_NAME), aliases);
56256
+ const expected = canonicalAgentPath(join28(nativeAgentRoot(home, agent, options.projectDir ?? process.cwd()), CLI_BRIDGE_NAME), aliases);
55984
56257
  if (!isOwnedCliBridge(expected, [expected]))
55985
56258
  throw new Error("NATIVE_SKILL_DRIFT: the native Skills bridge is missing or modified; repair it before continuing");
55986
56259
  const roots = projectAncestorDirectories([options.projectDir ?? process.cwd(), ...options.projectDirs ?? [], ...agent === "hermes" && process.env.TERMINAL_CWD ? [process.cwd()] : []]);
55987
56260
  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
56261
  const discovery = provenDiscovery ?? binding.discovery?.[agent];
55989
56262
  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);
56263
+ const configPath = canonicalAgentPath(nativeAgentConfig(home, agent, options.projectDir ?? process.cwd()), aliases), config = agent === "hermes" ? parseHermesConfig(readOptional(configPath)) : jsonObject(readOptional(configPath), configPath);
55991
56264
  const command = binding.commands?.[agent], profile = binding.profiles?.[agent];
55992
56265
  if (typeof command !== "string" || typeof profile !== "string")
55993
56266
  throw new Error("NATIVE_SKILL_DRIFT: the native hook command/profile binding is missing");
@@ -55999,7 +56272,7 @@ function assertManagedAgentBridgeWithDiscovery(agent, options = {}, provenDiscov
55999
56272
  throw new Error("NATIVE_SKILL_DRIFT: Hermes supervisor binding changed; run skills hook install");
56000
56273
  assertHermesProtection(home, config, command, profile, supervisor);
56001
56274
  } 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))
56275
+ 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
56276
  throw new Error("NATIVE_SKILL_DRIFT: Sumi bridge protection changed; run skills hook install");
56004
56277
  } else if (agent === "opencode") {
56005
56278
  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 +56378,7 @@ function assertManagedAgentBridgeWithDiscovery(agent, options = {}, provenDiscov
56105
56378
  return escaped.length > 768 ? `${escaped.slice(0, 384)}...${escaped.slice(-381)}` : escaped;
56106
56379
  });
56107
56380
  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}` : ""}`);
56381
+ 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
56382
  }
56110
56383
  recheckRootAliases(aliases);
56111
56384
  }
@@ -56170,7 +56443,7 @@ var init_agent_integration = __esm(() => {
56170
56443
  });
56171
56444
 
56172
56445
  // 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";
56446
+ import { existsSync as existsSync14, mkdirSync as mkdirSync7, readdirSync as readdirSync9, renameSync as renameSync4, rmSync, statSync as statSync11, writeFileSync as writeFileSync7 } from "fs";
56174
56447
  import { join as join29 } from "path";
56175
56448
  function layoutMigrationRecordPath(appDir) {
56176
56449
  return join29(appDir, SKILLS_CACHE_DIRNAME, LAYOUT_MIGRATION_RECORD);
@@ -56183,7 +56456,7 @@ function migrationAppDir(homeDir2) {
56183
56456
  }
56184
56457
  function looksLikeSkillDirectory(path) {
56185
56458
  try {
56186
- if (!statSync10(path).isDirectory())
56459
+ if (!statSync11(path).isDirectory())
56187
56460
  return false;
56188
56461
  } catch {
56189
56462
  return false;
@@ -56315,7 +56588,7 @@ import {
56315
56588
  readdirSync as readdirSync10,
56316
56589
  renameSync as renameSync5,
56317
56590
  rmSync as rmSync2,
56318
- statSync as statSync11,
56591
+ statSync as statSync12,
56319
56592
  writeFileSync as writeFileSync8
56320
56593
  } from "fs";
56321
56594
  import { homedir as homedir4 } from "os";
@@ -56432,7 +56705,7 @@ function containsSkillDirectories(path) {
56432
56705
  }
56433
56706
  function isDirectory(path) {
56434
56707
  try {
56435
- return statSync11(path).isDirectory();
56708
+ return statSync12(path).isDirectory();
56436
56709
  } catch {
56437
56710
  return false;
56438
56711
  }
@@ -57962,8 +58235,8 @@ var init_plugin_projection = __esm(() => {
57962
58235
 
57963
58236
  // src/lib/plugin-projection-store.ts
57964
58237
  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";
58238
+ 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";
58239
+ import { dirname as dirname18, isAbsolute as isAbsolute19, join as join34, parse as parse6, resolve as resolve18 } from "path";
57967
58240
  function stat(path) {
57968
58241
  try {
57969
58242
  return lstatSync23(path, { bigint: true });
@@ -57974,7 +58247,7 @@ function stat(path) {
57974
58247
  }
57975
58248
  }
57976
58249
  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");
58250
+ 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
58251
  }
57979
58252
  function owner(stats, system = false) {
57980
58253
  const current = uid();
@@ -58324,8 +58597,8 @@ function pluginExecutableDigest(path) {
58324
58597
  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
58598
  var init_plugin_projection_store = __esm(() => {
58326
58599
  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;
58600
+ READ_FLAGS = constants15.O_RDONLY | constants15.O_NOFOLLOW | constants15.O_NONBLOCK;
58601
+ WRITE_FLAGS = constants15.O_WRONLY | constants15.O_CREAT | constants15.O_EXCL | constants15.O_NOFOLLOW | constants15.O_NONBLOCK;
58329
58602
  });
58330
58603
 
58331
58604
  // src/lib/selected-manifest.ts
@@ -58356,7 +58629,7 @@ var init_selected_manifest = __esm(() => {
58356
58629
 
58357
58630
  // src/lib/plugin-admission.ts
58358
58631
  import { homedir as homedir6 } from "os";
58359
- import { isAbsolute as isAbsolute19, join as join35, resolve as resolve19 } from "path";
58632
+ import { isAbsolute as isAbsolute20, join as join35, resolve as resolve19 } from "path";
58360
58633
  function pluginAdmissionRoot() {
58361
58634
  return join35(homedir6(), ".hasna", "skills", "plugin-admission");
58362
58635
  }
@@ -58369,7 +58642,7 @@ function validatePluginTarget(value) {
58369
58642
  for (const registration of value.registrations) {
58370
58643
  pluginKeys(registration, ["scope", "projectPath"]);
58371
58644
  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");
58645
+ 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
58646
  const key = JSON.stringify([registration.scope, registration.projectPath]);
58374
58647
  pluginNeed(!scopes.has(key), "Duplicate plugin registration scope");
58375
58648
  scopes.add(key);
@@ -58377,7 +58650,7 @@ function validatePluginTarget(value) {
58377
58650
  for (const key of ["native", "resolver"]) {
58378
58651
  pluginKeys(value[key], key === "native" ? ["version", "executable", "digest"] : ["executable", "digest"]);
58379
58652
  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");
58653
+ pluginNeed(isAbsolute20(value[key].executable) && resolve19(value[key].executable) === value[key].executable, "Plugin executable must have a canonical absolute path");
58381
58654
  pluginDigest(value[key].digest);
58382
58655
  }
58383
58656
  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 +58800,7 @@ function pluginResolverCommand(binding) {
58527
58800
  }
58528
58801
  function root(options) {
58529
58802
  const path = options.storeRoot ?? pluginAdmissionRoot();
58530
- pluginNeed(isAbsolute19(path) && resolve19(path) === path, "Invalid plugin admission store root");
58803
+ pluginNeed(isAbsolute20(path) && resolve19(path) === path, "Invalid plugin admission store root");
58531
58804
  return path;
58532
58805
  }
58533
58806
  function pluginBindingPath(storeRoot, id) {
@@ -58734,8 +59007,8 @@ var init_plugin_admission = __esm(() => {
58734
59007
  });
58735
59008
 
58736
59009
  // 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";
59010
+ import { closeSync as closeSync14, constants as constants16, fstatSync as fstatSync14, lstatSync as lstatSync24, openSync as openSync14, opendirSync as opendirSync5, readSync as readSync11 } from "fs";
59011
+ import { basename as basename10, dirname as dirname19, isAbsolute as isAbsolute21, join as join36, resolve as resolve20 } from "path";
58739
59012
  function validateManagedPluginWitnesses(value) {
58740
59013
  pluginNeed(Array.isArray(value) && value.length > 0 && value.length <= PLUGIN_PROJECTION_LIMITS.registrations, "Invalid managed plugin witness collection");
58741
59014
  const seen = new Set;
@@ -58744,12 +59017,12 @@ function validateManagedPluginWitnesses(value) {
58744
59017
  pluginNeed(typeof item.bindingId === "string" && /^[a-f0-9]{64}$/.test(item.bindingId) && !seen.has(item.bindingId), "Invalid or duplicate managed plugin witness");
58745
59018
  seen.add(item.bindingId);
58746
59019
  pluginText(item.storeRoot);
58747
- pluginNeed(isAbsolute20(item.storeRoot) && resolve20(item.storeRoot) === item.storeRoot, "Invalid plugin receipt store path");
59020
+ pluginNeed(isAbsolute21(item.storeRoot) && resolve20(item.storeRoot) === item.storeRoot, "Invalid plugin receipt store path");
58748
59021
  }
58749
59022
  }
58750
59023
  function safe3(path) {
58751
59024
  pluginText(path);
58752
- pluginNeed(isAbsolute20(path) && resolve20(path) === path, "Invalid plugin registry path");
59025
+ pluginNeed(isAbsolute21(path) && resolve20(path) === path, "Invalid plugin registry path");
58753
59026
  for (let at2 = path;; at2 = dirname19(at2)) {
58754
59027
  pluginNeed(!lstatSync24(at2, { throwIfNoEntry: false })?.isSymbolicLink(), "Plugin registry path traverses a symlink");
58755
59028
  if (at2 === dirname19(at2))
@@ -58760,7 +59033,7 @@ function readRegistry(path) {
58760
59033
  safe3(path);
58761
59034
  const initial2 = lstatSync24(path);
58762
59035
  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);
59036
+ const fd = openSync14(path, constants16.O_RDONLY | constants16.O_NOFOLLOW | constants16.O_NONBLOCK);
58764
59037
  try {
58765
59038
  const opened = fstatSync14(fd);
58766
59039
  pluginNeed(opened.isFile() && opened.ino === initial2.ino && opened.dev === initial2.dev, "Plugin registry changed during open");
@@ -58886,14 +59159,14 @@ var init_plugin_discovery = __esm(() => {
58886
59159
 
58887
59160
  // src/lib/claude-marketplace-registry.ts
58888
59161
  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";
59162
+ import { closeSync as closeSync15, constants as constants17, fstatSync as fstatSync15, lstatSync as lstatSync25, openSync as openSync15, readSync as readSync12 } from "fs";
59163
+ import { basename as basename11, dirname as dirname20, isAbsolute as isAbsolute22, resolve as resolve21 } from "path";
58891
59164
  function need7(value, reason2) {
58892
59165
  if (!value)
58893
59166
  throw new Error(`Claude marketplace registry ${reason2}`);
58894
59167
  }
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");
59168
+ function absolutePath4(value) {
59169
+ 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
59170
  }
58898
59171
  function parents2(path) {
58899
59172
  const result2 = [];
@@ -58906,13 +59179,13 @@ function parents2(path) {
58906
59179
  }
58907
59180
  }
58908
59181
  function readRegistry2(path, budget2) {
58909
- absolutePath3(path);
59182
+ absolutePath4(path);
58910
59183
  need7(basename11(path) === "known_marketplaces.json", "requires known_marketplaces.json");
58911
59184
  need7(Number.isSafeInteger(budget2.remaining) && budget2.remaining >= 0, "has an invalid byte budget");
58912
59185
  const ancestors2 = parents2(path), initial2 = lstatSync25(path, { bigint: true });
58913
59186
  need7(initial2.isFile() && !initial2.isSymbolicLink() && initial2.size <= BigInt(CLAUDE_MARKETPLACE_REGISTRY_LIMITS.bytes), "is not a bounded regular file");
58914
59187
  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);
59188
+ const fd = openSync15(path, constants17.O_RDONLY | constants17.O_NOFOLLOW | constants17.O_NONBLOCK);
58916
59189
  try {
58917
59190
  const opened = fstatSync15(fd, { bigint: true });
58918
59191
  need7(opened.isFile() && sameFile2(initial2, opened), "changed during open");
@@ -59039,8 +59312,8 @@ function normalizeRow(row, version = 1) {
59039
59312
  return;
59040
59313
  const sourceLocation = textField(field2(source, location));
59041
59314
  if (type.value === "directory")
59042
- absolutePath3(sourceLocation);
59043
- absolutePath3(textField(field2(row, "installLocation")));
59315
+ absolutePath4(sourceLocation);
59316
+ absolutePath4(textField(field2(row, "installLocation")));
59044
59317
  const updated = textField(field2(row, "lastUpdated"));
59045
59318
  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
59319
  const millis = Date.parse(updated);
@@ -59201,7 +59474,7 @@ var fail3 = () => new Error('CODEX_HOOK_TRUST_UNSUPPORTED_LAYOUT: preserve and c
59201
59474
  var init_codex_hook_trust_layout = () => {};
59202
59475
 
59203
59476
  // src/lib/codex-hook-additions-review.ts
59204
- import { isAbsolute as isAbsolute22 } from "path";
59477
+ import { isAbsolute as isAbsolute23 } from "path";
59205
59478
  import { isDeepStrictEqual as isDeepStrictEqual9 } from "util";
59206
59479
  function exactKeys2(value, keys2) {
59207
59480
  need6(value && typeof value === "object" && !Array.isArray(value) && isDeepStrictEqual9(Object.keys(value).sort(), [...keys2].sort()), "RECONCILE_ADDITIONS_REVIEW_SCHEMA");
@@ -59215,7 +59488,7 @@ function readReviewedAdditionTrustStates(proof, before2, current, journalHooks)
59215
59488
  return captured.states;
59216
59489
  }
59217
59490
  function reviewNativeHookAdditions(options) {
59218
- need6(isAbsolute22(options.path), "RECONCILE_ADDITIONS_REVIEW_PATH");
59491
+ need6(isAbsolute23(options.path), "RECONCILE_ADDITIONS_REVIEW_PATH");
59219
59492
  const reviewFile = snapshot(options.path, true), review = JSON.parse(reviewFile.text);
59220
59493
  exactKeys2(review, ["version", "kind", "reason", "producerEvidence", "journalIntentSha256", "policySha256", "configCurrentSha256", "hooksCurrentSha256", "producerBefore", "additions"]);
59221
59494
  need6((review.version === 1 || review.version === 2) && review.kind === "native-hook-additions" && text2(review.reason) && text2(review.producerEvidence), "RECONCILE_ADDITIONS_REVIEW_SCHEMA");
@@ -59223,7 +59496,7 @@ function reviewNativeHookAdditions(options) {
59223
59496
  need6(hash2(review[name]) && review[name] === expected, "RECONCILE_ADDITIONS_REVIEW_CHANGED");
59224
59497
  exactKeys2(review.producerBefore, ["configPath", "configSha256", "hooksPath", "hooksSha256"]);
59225
59498
  const before2 = review.producerBefore;
59226
- need6(isAbsolute22(before2.configPath) && isAbsolute22(before2.hooksPath) && hash2(before2.configSha256) && hash2(before2.hooksSha256), "RECONCILE_ADDITIONS_PRODUCER_PREIMAGE");
59499
+ need6(isAbsolute23(before2.configPath) && isAbsolute23(before2.hooksPath) && hash2(before2.configSha256) && hash2(before2.hooksSha256), "RECONCILE_ADDITIONS_PRODUCER_PREIMAGE");
59227
59500
  const producerConfig = snapshot(before2.configPath, true), producerHooks = snapshot(before2.hooksPath, true);
59228
59501
  need6(producerConfig.sha256 === before2.configSha256 && producerHooks.sha256 === before2.hooksSha256 && producerHooks.sha256 === options.hooksBefore.sha256, "RECONCILE_ADDITIONS_PRODUCER_PREIMAGE");
59229
59502
  const original = structure(options.configBefore.text), producer = structure(producerConfig.text), expectedProducer = structuredClone(original), originalKeys = options.journalHooks.map((hook) => hook.key);
@@ -59316,13 +59589,13 @@ function createCodexHookDiscoveryRecovery(binding, before2, current, hooks, addi
59316
59589
  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
59590
  unchanged2(before2);
59318
59591
  unchanged2(current);
59319
- const witness = Object.freeze({ configPath: current.file, beforeSha256: before2.sha256, currentSha256: current.sha256, discoverySha256: sha4(JSON.stringify(binding)), typedProjectionSha256: projection });
59592
+ const witness = Object.freeze({ configPath: current.file, beforeSha256: before2.sha256, currentSha256: current.sha256, discoverySha256: discoveryDigest(binding), typedProjectionSha256: projection });
59320
59593
  proofs2.set(witness, { before: before2, current, recheckAdditions });
59321
59594
  return witness;
59322
59595
  }
59323
59596
  function assertCodexHookDiscoveryRecovery(binding, witness) {
59324
59597
  const proof = proofs2.get(witness);
59325
- need6(!!proof && binding.agent === "codex" && witness.discoverySha256 === sha4(JSON.stringify(binding)), "RECONCILE_DISCOVERY_RECOVERY_CHANGED");
59598
+ need6(!!proof && binding.agent === "codex" && witness.discoverySha256 === discoveryDigest(binding), "RECONCILE_DISCOVERY_RECOVERY_CHANGED");
59326
59599
  unchanged2(proof.before);
59327
59600
  unchanged2(proof.current);
59328
59601
  proof.recheckAdditions();
@@ -59334,7 +59607,14 @@ function verifiesCodexHookDiscoverySource(binding, source, currentDigest, witnes
59334
59607
  need6(source.sha256 === witness.beforeSha256 && currentDigest === witness.currentSha256, "RECONCILE_DISCOVERY_RECOVERY_CHANGED");
59335
59608
  return true;
59336
59609
  }
59337
- var sha4 = (text3) => createHash24("sha256").update(text3).digest("hex"), fields, structure2 = (text3) => JSON.parse(JSON.stringify(Bun.TOML.parse(text3))), proofs2;
59610
+ var sha4 = (text3) => createHash24("sha256").update(text3).digest("hex"), fields, structure2 = (text3) => JSON.parse(JSON.stringify(Bun.TOML.parse(text3))), discoveryDigest = (binding) => {
59611
+ const controls = binding.codexDisabledPluginSkills;
59612
+ if (!Object.hasOwn(binding, "codexDisabledPluginSkills") || Array.isArray(controls) && controls.length === 0) {
59613
+ const { codexDisabledPluginSkills: _controls, ...withoutControls } = binding;
59614
+ return sha4(JSON.stringify({ ...withoutControls, codexDisabledPluginSkills: [] }));
59615
+ }
59616
+ return sha4(JSON.stringify(binding));
59617
+ }, proofs2;
59338
59618
  var init_codex_hook_discovery_recovery = __esm(() => {
59339
59619
  init_codex_hook_trust_files();
59340
59620
  init_codex_hook_trust_layout();
@@ -59347,7 +59627,7 @@ var init_codex_hook_discovery_recovery = __esm(() => {
59347
59627
  // src/lib/agent-discovery.ts
59348
59628
  import { createHash as createHash25 } from "crypto";
59349
59629
  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";
59630
+ import { basename as basename12, dirname as dirname21, isAbsolute as isAbsolute24, join as join37, resolve as resolve22, sep as sep8 } from "path";
59351
59631
  import { isDeepStrictEqual as isDeepStrictEqual11 } from "util";
59352
59632
  function discoveryRootUnresolved(agent, command, detail) {
59353
59633
  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 +59661,7 @@ function parseConfig(text3, path, toml = false) {
59381
59661
  }
59382
59662
  }
59383
59663
  function safe4(path) {
59384
- if (!isAbsolute23(path) || path.includes("\x00"))
59664
+ if (!isAbsolute24(path) || path.includes("\x00"))
59385
59665
  throw new Error("Expected an absolute native discovery path");
59386
59666
  for (let cursor = path;; cursor = dirname21(cursor)) {
59387
59667
  if (lstatSync26(cursor, { throwIfNoEntry: false })?.isSymbolicLink())
@@ -59401,19 +59681,20 @@ function read2(path, changes) {
59401
59681
  throw new Error(`Unsupported or oversized native discovery input: ${path}`);
59402
59682
  return readFileSync21(path, "utf8");
59403
59683
  }
59404
- function assertReviewedClaudeCacheClosures(home, config, review) {
59684
+ function assertReviewedClaudeCacheClosures(home, config, review, canonical8) {
59405
59685
  const enabledIds = Object.entries(config.enabledPlugins ?? {}).filter(([, enabled]) => enabled === true).map(([id]) => id);
59406
59686
  if (enabledIds.length === 0)
59407
59687
  return;
59408
- const registryPath = join37(home, ".claude/plugins/installed_plugins.json");
59409
- const cacheRoot = join37(home, ".claude/plugins/cache");
59688
+ const registryPath = canonical8(join37(home, ".claude/plugins/installed_plugins.json"));
59689
+ const cacheAliasRoot = join37(home, ".claude/plugins/cache");
59690
+ const cacheRoot = canonical8(cacheAliasRoot);
59410
59691
  const registryText = read2(registryPath);
59411
59692
  if (registryText === null)
59412
59693
  return;
59413
59694
  const registry = parseConfig(registryText, registryPath);
59414
59695
  if (registry.version !== 2 || !registry.plugins || typeof registry.plugins !== "object" || Array.isArray(registry.plugins))
59415
59696
  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));
59697
+ const cachePath = (path) => typeof path === "string" && isAbsolute24(path) && resolve22(path) === path && [cacheAliasRoot, cacheRoot].some((root2) => path === root2 || path.startsWith(root2 + sep8));
59417
59698
  const activeRoots = new Set;
59418
59699
  for (const id of enabledIds) {
59419
59700
  const rows = registry.plugins[id];
@@ -59425,13 +59706,13 @@ function assertReviewedClaudeCacheClosures(home, config, review) {
59425
59706
  if (!row || typeof row !== "object" || Array.isArray(row) || typeof row.installPath !== "string") {
59426
59707
  throw new Error("Reviewed Claude enabled plugin registration requires an object with an installPath string");
59427
59708
  }
59428
- if (typeof row.installPath === "string" && (row.installPath === cacheRoot || row.installPath.startsWith(cacheRoot + sep8))) {
59709
+ if ([cacheAliasRoot, cacheRoot].some((root2) => row.installPath === root2 || row.installPath.startsWith(root2 + sep8))) {
59429
59710
  if (!cachePath(row.installPath) || row.installPath.length > AGENT_POLICY_LIMITS.pathCharacters || row.version !== undefined && (typeof row.version !== "string" || basename12(row.installPath) !== row.version)) {
59430
59711
  throw new Error("Reviewed Claude discovery has a malformed active cache registration");
59431
59712
  }
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
59713
+ 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
59714
  throw new Error("Reviewed Claude discovery has an unsupported active cache registration scope");
59434
- activeRoots.add(row.installPath);
59715
+ activeRoots.add(canonical8(row.installPath));
59435
59716
  }
59436
59717
  }
59437
59718
  }
@@ -59676,12 +59957,12 @@ function absentRetiredClaudeRoots(binding) {
59676
59957
  if (!row || typeof row !== "object" || Array.isArray(row))
59677
59958
  return null;
59678
59959
  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)
59960
+ 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
59961
  return null;
59681
59962
  if (value.scope === "user")
59682
59963
  return value.projectPath === undefined || value.projectPath === null ? "user\x00" : null;
59683
59964
  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;
59965
+ 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
59966
  return null;
59686
59967
  };
59687
59968
  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 +60226,7 @@ function resolveAgentDiscovery(options) {
59945
60226
  if (config.skills !== undefined && (!Array.isArray(config.skills) || config.skills.some((path) => typeof path !== "string")))
59946
60227
  unresolved("skills must be a string array");
59947
60228
  for (const value of config.skills ?? []) {
59948
- if (typeof value !== "string" || /[\0$]/.test(value) || !value || !(isAbsolute23(value) || value.startsWith("~/")))
60229
+ if (typeof value !== "string" || /[\0$]/.test(value) || !value || !(isAbsolute24(value) || value.startsWith("~/")))
59949
60230
  unresolved("remote or relative skill sources need a dedicated discovery adapter");
59950
60231
  roots.add(canonical8(value.startsWith("~/") ? join37(home, value.slice(2)) : value));
59951
60232
  }
@@ -60075,7 +60356,7 @@ function resolveAgentDiscovery(options) {
60075
60356
  return { path: source.path, sha256: manifestSha256, hashMode: "claude-plugin-manifest-v1" };
60076
60357
  });
60077
60358
  if (agent === "claude")
60078
- assertReviewedClaudeCacheClosures(home, config, review);
60359
+ assertReviewedClaudeCacheClosures(home, config, review, canonical8);
60079
60360
  const combined = [...reviewedSources, ...reviewedSourcesWithManifestProjection];
60080
60361
  const unique = combined.filter((source, index) => combined.findIndex((candidate2) => isDeepStrictEqual11(candidate2, source)) === index);
60081
60362
  return { ...supplied, roots: [...new Set([...roots, ...supplied.roots])].sort(), sources: unique, ...agent === "gemini" ? { builtinNames } : {} };
@@ -60135,7 +60416,7 @@ function resolveAgentDiscovery(options) {
60135
60416
  unresolved("unsupported plugin enablement");
60136
60417
  const split2 = id.lastIndexOf("@"), name = id.slice(0, split2), marketplace = id.slice(split2 + 1);
60137
60418
  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))
60419
+ if (split2 < 1 || market?.source_type !== "local" || typeof market.source !== "string" || !isAbsolute24(market.source))
60139
60420
  unresolved("enabled plugin marketplace is not an explicit local source");
60140
60421
  const catalogText = witness(join37(market.source, ".agents/plugins/marketplace.json"));
60141
60422
  if (catalogText === null)
@@ -60151,7 +60432,7 @@ function resolveAgentDiscovery(options) {
60151
60432
  if ((config.plugin?.length ?? 0) > 0 || config.skills?.urls?.length)
60152
60433
  unresolved("external plugin or remote skill source");
60153
60434
  for (const path of config.skills?.paths ?? []) {
60154
- if (typeof path !== "string" || !isAbsolute23(path))
60435
+ if (typeof path !== "string" || !isAbsolute24(path))
60155
60436
  unresolved("relative or malformed added skill root");
60156
60437
  roots.add(path);
60157
60438
  }
@@ -60336,10 +60617,10 @@ import {
60336
60617
  realpathSync as realpathSync13,
60337
60618
  renameSync as renameSync7,
60338
60619
  rmSync as rmSync5,
60339
- statSync as statSync12,
60620
+ statSync as statSync13,
60340
60621
  writeFileSync as writeFileSync10
60341
60622
  } 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";
60623
+ 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
60624
  function getPortableSkillsRoot(options = {}) {
60344
60625
  return resolvePortableSkillsRoot(options, true);
60345
60626
  }
@@ -60367,7 +60648,7 @@ function findPortableSkill(name, options = {}) {
60367
60648
  return null;
60368
60649
  }
60369
60650
  const path = getPortableSkillPath(normalized, options);
60370
- if (!existsSync19(path) || !statSync12(path).isDirectory())
60651
+ if (!existsSync19(path) || !statSync13(path).isDirectory())
60371
60652
  return null;
60372
60653
  try {
60373
60654
  return summarizePortableSkill(path, normalized);
@@ -60438,7 +60719,7 @@ function scaffoldPortableSkill(name, options = {}) {
60438
60719
  }
60439
60720
  function portPortableSkillDirectory(sourceDir, options = {}) {
60440
60721
  const absoluteSource = normalize4(sourceDir);
60441
- if (!existsSync19(absoluteSource) || !statSync12(absoluteSource).isDirectory()) {
60722
+ if (!existsSync19(absoluteSource) || !statSync13(absoluteSource).isDirectory()) {
60442
60723
  throw new Error(`Import directory not found: ${sourceDir}`);
60443
60724
  }
60444
60725
  const continueOnError = options.continueOnError ?? true;
@@ -60497,7 +60778,7 @@ function assertDisjointImportPaths(source, destination) {
60497
60778
  const destinationPath = physicalImportPath(destination);
60498
60779
  const contains2 = (parent, child2) => {
60499
60780
  const path = relative7(parent, child2);
60500
- return path === "" || !isAbsolute24(path) && path !== ".." && !path.startsWith(`..${sep10}`);
60781
+ return path === "" || !isAbsolute25(path) && path !== ".." && !path.startsWith(`..${sep10}`);
60501
60782
  };
60502
60783
  if (contains2(sourcePath, destinationPath) || contains2(destinationPath, sourcePath)) {
60503
60784
  throw new Error("Source and destination skill directories must not overlap");
@@ -60505,7 +60786,7 @@ function assertDisjointImportPaths(source, destination) {
60505
60786
  }
60506
60787
  function portPortableSkill(sourcePath, options = {}) {
60507
60788
  const absoluteSource = normalize4(sourcePath);
60508
- if (!existsSync19(absoluteSource) || !statSync12(absoluteSource).isDirectory()) {
60789
+ if (!existsSync19(absoluteSource) || !statSync13(absoluteSource).isDirectory()) {
60509
60790
  throw new Error(`Skill source directory not found: ${sourcePath}`);
60510
60791
  }
60511
60792
  const inferred = readPortableSkillManifestForImport(absoluteSource);
@@ -60668,7 +60949,7 @@ function validatePortableSkillDirectory(name, skillPath) {
60668
60949
  const entryPath = join39(skillPath, command.entry);
60669
60950
  if (!existsSync19(entryPath))
60670
60951
  add4(issues, "portable.command_entry_missing", `Command '${command.name}' entry '${command.entry}' is missing`);
60671
- else if (statSync12(entryPath).isDirectory())
60952
+ else if (statSync13(entryPath).isDirectory())
60672
60953
  add4(issues, "portable.command_entry_directory", `Command '${command.name}' entry '${command.entry}' must be a file`);
60673
60954
  }
60674
60955
  }
@@ -60708,13 +60989,13 @@ function summarizePortableSkill(skillPath, fallbackName) {
60708
60989
  }
60709
60990
  function safeIsDirectory(path) {
60710
60991
  try {
60711
- return statSync12(path).isDirectory();
60992
+ return statSync13(path).isDirectory();
60712
60993
  } catch {
60713
60994
  return false;
60714
60995
  }
60715
60996
  }
60716
60997
  function isSafeRelativePath2(value) {
60717
- if (!value.trim() || isAbsolute24(value))
60998
+ if (!value.trim() || isAbsolute25(value))
60718
60999
  return false;
60719
61000
  const normalized = normalize4(value).replace(/\\/g, "/");
60720
61001
  return normalized !== ".." && !normalized.startsWith("../") && !normalized.includes("/../");
@@ -62721,7 +63002,7 @@ var require_cli_spinners = __commonJS((exports, module) => {
62721
63002
  });
62722
63003
 
62723
63004
  // 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";
63005
+ 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
63006
  import { basename as basename15, dirname as dirname24, join as join41 } from "path";
62726
63007
  function getAuthFilePath(env3 = process.env) {
62727
63008
  return skillsCredentialFilePath(env3);
@@ -62935,7 +63216,7 @@ function getApiUrl(action, env3 = process.env, options = {}) {
62935
63216
  }
62936
63217
  function credentialFileMode(env3 = process.env) {
62937
63218
  try {
62938
- return statSync13(skillsCredentialFilePath(env3)).mode & 511;
63219
+ return statSync14(skillsCredentialFilePath(env3)).mode & 511;
62939
63220
  } catch {
62940
63221
  return null;
62941
63222
  }
@@ -65168,8 +65449,8 @@ var cuid, cuid2, ulid, xid, ksuid, nanoid, duration, extendedDuration, guid, uui
65168
65449
  if (!version)
65169
65450
  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
65451
  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 ?? ":");
65452
+ }, uuid42, uuid6, uuid7, email2, html5Email, rfc5322Email, unicodeEmail, idnEmail, browserEmail, _emoji = `^[\\p{Extended_Pictographic}\\p{Emoji_Component}]+$`, ipv4, ipv6, mac = (delimiter3) => {
65453
+ const escapedDelim = escapeRegex(delimiter3 ?? ":");
65173
65454
  return new RegExp(`^(?:[0-9A-F]{2}${escapedDelim}){5}[0-9A-F]{2}$|^(?:[0-9a-f]{2}${escapedDelim}){5}[0-9a-f]{2}$`);
65174
65455
  }, 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
65456
  const regex2 = params ? `[\\s\\S]{${params?.minimum ?? 0},${params?.maximum ?? ""}}` : `[\\s\\S]*`;
@@ -88469,7 +88750,7 @@ var init_init = __esm(() => {
88469
88750
  });
88470
88751
 
88471
88752
  // 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";
88753
+ 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
88754
  import { homedir as homedir8 } from "os";
88474
88755
  import { join as join47 } from "path";
88475
88756
  function indexCanonicalCorpus(corpusRoot) {
@@ -88505,7 +88786,7 @@ function selectedHomeNames(options, index, homeDir2, agents) {
88505
88786
  continue;
88506
88787
  const present = agents.some((agent) => {
88507
88788
  try {
88508
- return statSync14(join47(agentGlobalSkillsDir(agent, homeDir2), name)).isDirectory();
88789
+ return statSync15(join47(agentGlobalSkillsDir(agent, homeDir2), name)).isDirectory();
88509
88790
  } catch {
88510
88791
  return false;
88511
88792
  }
@@ -88539,7 +88820,7 @@ function scanUnmarkedHomes(options = {}) {
88539
88820
  continue;
88540
88821
  const dir = join47(home, skill);
88541
88822
  try {
88542
- if (!statSync14(dir).isDirectory())
88823
+ if (!statSync15(dir).isDirectory())
88543
88824
  continue;
88544
88825
  } catch {
88545
88826
  continue;
@@ -88552,7 +88833,7 @@ function scanUnmarkedHomes(options = {}) {
88552
88833
  if (!existsSync25(skillMdPath))
88553
88834
  continue;
88554
88835
  const hash5 = hashSkillMarkdownFile(skillMdPath);
88555
- const mtime = statSync14(skillMdPath).mtime.toISOString();
88836
+ const mtime = statSync15(skillMdPath).mtime.toISOString();
88556
88837
  const entry = { agent, skill, home, path: dir, hash: hash5, mtime };
88557
88838
  const canonicalHash = index.get(skill);
88558
88839
  if (canonicalHash === undefined) {
@@ -88647,7 +88928,7 @@ function pruneOwnership(dir) {
88647
88928
  const markerPath = join47(dir, SYNC_MARKER_FILE), markerPathBefore = lstatSync28(markerPath);
88648
88929
  if (!markerPathBefore.isFile())
88649
88930
  return;
88650
- descriptor = openSync16(markerPath, constants17.O_RDONLY | constants17.O_NOFOLLOW | constants17.O_NONBLOCK);
88931
+ descriptor = openSync16(markerPath, constants18.O_RDONLY | constants18.O_NOFOLLOW | constants18.O_NONBLOCK);
88651
88932
  const before2 = fstatSync16(descriptor);
88652
88933
  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
88934
  return;
@@ -88698,7 +88979,7 @@ function pruneStrayHomes(options = {}) {
88698
88979
  continue;
88699
88980
  const dir = join47(home, skill);
88700
88981
  try {
88701
- if (!statSync14(dir).isDirectory())
88982
+ if (!statSync15(dir).isDirectory())
88702
88983
  continue;
88703
88984
  } catch {
88704
88985
  continue;
@@ -88756,7 +89037,7 @@ var init_home_adoption = __esm(() => {
88756
89037
  });
88757
89038
 
88758
89039
  // src/lib/home-census.ts
88759
- import { existsSync as existsSync26, readFileSync as readFileSync31, readdirSync as readdirSync16, statSync as statSync15 } from "fs";
89040
+ import { existsSync as existsSync26, readFileSync as readFileSync31, readdirSync as readdirSync16, statSync as statSync16 } from "fs";
88760
89041
  import { homedir as homedir9 } from "os";
88761
89042
  import { join as join48 } from "path";
88762
89043
  function sortEntries(entries) {
@@ -88801,7 +89082,7 @@ function censusHomeDrift(options = {}) {
88801
89082
  continue;
88802
89083
  const dir = join48(home, skill);
88803
89084
  try {
88804
- if (!statSync15(dir).isDirectory())
89085
+ if (!statSync16(dir).isDirectory())
88805
89086
  continue;
88806
89087
  } catch {
88807
89088
  continue;
@@ -88872,13 +89153,13 @@ var init_home_census = __esm(() => {
88872
89153
  });
88873
89154
 
88874
89155
  // 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";
89156
+ 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
89157
  function serializeValue(value) {
88877
89158
  if (controls.test(value))
88878
89159
  throw new EnvAssignmentError("Environment values cannot contain control characters or newlines.");
88879
89160
  if (/^[A-Za-z0-9_./:@+=,-]*$/.test(value))
88880
89161
  return value;
88881
- const quote3 = ["'", "`", '"'].find((delimiter2) => !value.includes(delimiter2) && (delimiter2 !== '"' || !value.includes("\\")));
89162
+ const quote3 = ["'", "`", '"'].find((delimiter3) => !value.includes(delimiter3) && (delimiter3 !== '"' || !value.includes("\\")));
88882
89163
  const trailingSlashes = value.match(/\\+$/)?.[0].length ?? 0;
88883
89164
  if (!quote3 || trailingSlashes % 2 !== 0 || value.endsWith("\\$")) {
88884
89165
  throw new EnvAssignmentError("Cannot safely encode this environment value; incompatible quote/backslash combinations require manual editing.");
@@ -88960,7 +89241,7 @@ function setEnvAssignment(path, assignment) {
88960
89241
  })();
88961
89242
  if (previous && !previous.isFile())
88962
89243
  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);
89244
+ 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
89245
  const opened = fstatSync17(descriptor);
88965
89246
  if (!opened.isFile() || previous && (opened.ino !== previous.ino || opened.dev !== previous.dev)) {
88966
89247
  throw new EnvAssignmentError("The project .env changed while opening it; retry with a regular file.");
@@ -89054,7 +89335,7 @@ var exports_diagnostic = {};
89054
89335
  __export(exports_diagnostic, {
89055
89336
  registerDiagnostic: () => registerDiagnostic
89056
89337
  });
89057
- import { existsSync as existsSync27, readFileSync as readFileSync33, readdirSync as readdirSync17, statSync as statSync16 } from "fs";
89338
+ import { existsSync as existsSync27, readFileSync as readFileSync33, readdirSync as readdirSync17, statSync as statSync17 } from "fs";
89058
89339
  import { join as join49 } from "path";
89059
89340
  import { execSync as execSync2 } from "child_process";
89060
89341
  function registerDiagnostic(parent) {
@@ -89247,7 +89528,7 @@ function handleWhoami(options) {
89247
89528
  let skillCount = 0;
89248
89529
  if (exists)
89249
89530
  try {
89250
- skillCount = readdirSync17(agentSkillsPath).filter((f) => !f.startsWith(".") && statSync16(join49(agentSkillsPath, f)).isDirectory()).length;
89531
+ skillCount = readdirSync17(agentSkillsPath).filter((f) => !f.startsWith(".") && statSync17(join49(agentSkillsPath, f)).isDirectory()).length;
89251
89532
  } catch {}
89252
89533
  agentConfigs.push({ agent, label: AGENT_LABELS[agent], path: agentSkillsPath, exists, skillCount });
89253
89534
  }
@@ -89505,12 +89786,12 @@ var init_cloud_executions = __esm(() => {
89505
89786
 
89506
89787
  // node_modules/@hasna/secrets/dist/sdk.js
89507
89788
  import { isIP as isIP3 } from "net";
89508
- import { spawnSync as spawnSync3 } from "child_process";
89789
+ import { spawnSync as spawnSync4 } from "child_process";
89509
89790
  import { closeSync as closeSync18, fstatSync as fstatSync18, openSync as openSync18, readFileSync as readFileSync34 } from "fs";
89510
89791
  import { O_NOFOLLOW as O_NOFOLLOW3, O_NONBLOCK as O_NONBLOCK3, O_RDONLY as O_RDONLY3 } from "constants";
89511
89792
  import { createRequire as createRequire2 } from "module";
89512
89793
  import { hostname as osHostname2 } from "os";
89513
- import { isAbsolute as isAbsolute25, join as join50 } from "path";
89794
+ import { isAbsolute as isAbsolute26, join as join50 } from "path";
89514
89795
  import { createRequire as createRequire22 } from "module";
89515
89796
  function envToken2(name) {
89516
89797
  return name.toUpperCase().replace(/-/g, "_");
@@ -89534,7 +89815,7 @@ function homeDir2(env3) {
89534
89815
  }
89535
89816
  function absoluteOverride2(env3, key) {
89536
89817
  const value = env3[key]?.trim();
89537
- return value && isAbsolute25(value) ? value : null;
89818
+ return value && isAbsolute26(value) ? value : null;
89538
89819
  }
89539
89820
  function hasnaHomeDir2(env3) {
89540
89821
  const override = absoluteOverride2(env3, HASNA_HOME_ENV_KEY2);
@@ -89780,7 +90061,7 @@ function isAmbientEnvironment2(env3) {
89780
90061
  return env3 === process.env || env3[AMBIENT_ENVIRONMENT2] === true;
89781
90062
  }
89782
90063
  function defaultKeychainRunner2(argv) {
89783
- const result2 = spawnSync3(KEYCHAIN_SECURITY_BIN2, [...argv], {
90064
+ const result2 = spawnSync4(KEYCHAIN_SECURITY_BIN2, [...argv], {
89784
90065
  encoding: "utf8",
89785
90066
  stdio: ["ignore", "pipe", "pipe"],
89786
90067
  timeout: KEYCHAIN_SPAWN_TIMEOUT_MS2
@@ -90806,7 +91087,7 @@ var init_sdk = __esm(() => {
90806
91087
  });
90807
91088
 
90808
91089
  // 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";
91090
+ import { constants as constants20, closeSync as closeSync19, fstatSync as fstatSync19, openSync as openSync19, readSync as readSync15, realpathSync as realpathSync14 } from "fs";
90810
91091
  import { hostname as stationHostname } from "os";
90811
91092
  function selectedSecretBindingsTemplate(scope, names, createClient2 = createSecretsClientFromEnv) {
90812
91093
  let secretsAuthority;
@@ -90850,7 +91131,7 @@ function declaredSecretNames(value) {
90850
91131
  function readSelectedSecretBindings(path) {
90851
91132
  let fd;
90852
91133
  try {
90853
- fd = openSync19(path, constants19.O_RDONLY | constants19.O_NOFOLLOW | constants19.O_NONBLOCK);
91134
+ fd = openSync19(path, constants20.O_RDONLY | constants20.O_NOFOLLOW | constants20.O_NONBLOCK);
90854
91135
  const stat2 = fstatSync19(fd);
90855
91136
  if (!stat2.isFile() || stat2.size > 65536)
90856
91137
  throw new Error;
@@ -95499,7 +95780,7 @@ var init_runs = __esm(() => {
95499
95780
 
95500
95781
  // src/lib/run-state.ts
95501
95782
  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";
95783
+ import { existsSync as existsSync28, mkdirSync as mkdirSync17, readFileSync as readFileSync35, readdirSync as readdirSync18, statSync as statSync18, writeFileSync as writeFileSync17 } from "fs";
95503
95784
  import { extname, join as join52, relative as relative8 } from "path";
95504
95785
  function createSkillRun(params, targetDir = process.cwd()) {
95505
95786
  const now3 = new Date;
@@ -95581,7 +95862,7 @@ function listSkillRuns(targetDir = process.cwd(), limit = 50) {
95581
95862
  const records = [];
95582
95863
  for (const day of readdirSync18(runsRoot).sort().reverse()) {
95583
95864
  const dayDir = join52(runsRoot, day);
95584
- if (!statSync17(dayDir).isDirectory())
95865
+ if (!statSync18(dayDir).isDirectory())
95585
95866
  continue;
95586
95867
  for (const runId2 of readdirSync18(dayDir).sort().reverse()) {
95587
95868
  const record11 = readRunRecord(join52(dayDir, runId2));
@@ -95630,7 +95911,7 @@ function collectRunArtifacts(context) {
95630
95911
  return [];
95631
95912
  const artifacts = [];
95632
95913
  for (const path of walkFiles(context.exportDir)) {
95633
- const stat2 = statSync17(path);
95914
+ const stat2 = statSync18(path);
95634
95915
  const bytes = readFileSync35(path);
95635
95916
  artifacts.push({
95636
95917
  path: toProjectRelative(context.targetDir, path),
@@ -95655,7 +95936,7 @@ function walkFiles(dir) {
95655
95936
  const files = [];
95656
95937
  for (const entry of readdirSync18(dir)) {
95657
95938
  const full = join52(dir, entry);
95658
- if (statSync17(full).isDirectory())
95939
+ if (statSync18(full).isDirectory())
95659
95940
  files.push(...walkFiles(full));
95660
95941
  else
95661
95942
  files.push(full);
@@ -99592,11 +99873,11 @@ var require_codegen = __commonJS((exports) => {
99592
99873
  const rhs = this.rhs === undefined ? "" : ` = ${this.rhs}`;
99593
99874
  return `${varKind} ${this.name}${rhs};` + _n;
99594
99875
  }
99595
- optimizeNames(names, constants20) {
99876
+ optimizeNames(names, constants21) {
99596
99877
  if (!names[this.name.str])
99597
99878
  return;
99598
99879
  if (this.rhs)
99599
- this.rhs = optimizeExpr(this.rhs, names, constants20);
99880
+ this.rhs = optimizeExpr(this.rhs, names, constants21);
99600
99881
  return this;
99601
99882
  }
99602
99883
  get names() {
@@ -99614,10 +99895,10 @@ var require_codegen = __commonJS((exports) => {
99614
99895
  render({ _n }) {
99615
99896
  return `${this.lhs} = ${this.rhs};` + _n;
99616
99897
  }
99617
- optimizeNames(names, constants20) {
99898
+ optimizeNames(names, constants21) {
99618
99899
  if (this.lhs instanceof code_1.Name && !names[this.lhs.str] && !this.sideEffects)
99619
99900
  return;
99620
- this.rhs = optimizeExpr(this.rhs, names, constants20);
99901
+ this.rhs = optimizeExpr(this.rhs, names, constants21);
99621
99902
  return this;
99622
99903
  }
99623
99904
  get names() {
@@ -99683,8 +99964,8 @@ var require_codegen = __commonJS((exports) => {
99683
99964
  optimizeNodes() {
99684
99965
  return `${this.code}` ? this : undefined;
99685
99966
  }
99686
- optimizeNames(names, constants20) {
99687
- this.code = optimizeExpr(this.code, names, constants20);
99967
+ optimizeNames(names, constants21) {
99968
+ this.code = optimizeExpr(this.code, names, constants21);
99688
99969
  return this;
99689
99970
  }
99690
99971
  get names() {
@@ -99714,12 +99995,12 @@ var require_codegen = __commonJS((exports) => {
99714
99995
  }
99715
99996
  return nodes.length > 0 ? this : undefined;
99716
99997
  }
99717
- optimizeNames(names, constants20) {
99998
+ optimizeNames(names, constants21) {
99718
99999
  const { nodes } = this;
99719
100000
  let i = nodes.length;
99720
100001
  while (i--) {
99721
100002
  const n2 = nodes[i];
99722
- if (n2.optimizeNames(names, constants20))
100003
+ if (n2.optimizeNames(names, constants21))
99723
100004
  continue;
99724
100005
  subtractNames(names, n2.names);
99725
100006
  nodes.splice(i, 1);
@@ -99776,12 +100057,12 @@ var require_codegen = __commonJS((exports) => {
99776
100057
  return;
99777
100058
  return this;
99778
100059
  }
99779
- optimizeNames(names, constants20) {
100060
+ optimizeNames(names, constants21) {
99780
100061
  var _a3;
99781
- this.else = (_a3 = this.else) === null || _a3 === undefined ? undefined : _a3.optimizeNames(names, constants20);
99782
- if (!(super.optimizeNames(names, constants20) || this.else))
100062
+ this.else = (_a3 = this.else) === null || _a3 === undefined ? undefined : _a3.optimizeNames(names, constants21);
100063
+ if (!(super.optimizeNames(names, constants21) || this.else))
99783
100064
  return;
99784
- this.condition = optimizeExpr(this.condition, names, constants20);
100065
+ this.condition = optimizeExpr(this.condition, names, constants21);
99785
100066
  return this;
99786
100067
  }
99787
100068
  get names() {
@@ -99806,10 +100087,10 @@ var require_codegen = __commonJS((exports) => {
99806
100087
  render(opts) {
99807
100088
  return `for(${this.iteration})` + super.render(opts);
99808
100089
  }
99809
- optimizeNames(names, constants20) {
99810
- if (!super.optimizeNames(names, constants20))
100090
+ optimizeNames(names, constants21) {
100091
+ if (!super.optimizeNames(names, constants21))
99811
100092
  return;
99812
- this.iteration = optimizeExpr(this.iteration, names, constants20);
100093
+ this.iteration = optimizeExpr(this.iteration, names, constants21);
99813
100094
  return this;
99814
100095
  }
99815
100096
  get names() {
@@ -99847,10 +100128,10 @@ var require_codegen = __commonJS((exports) => {
99847
100128
  render(opts) {
99848
100129
  return `for(${this.varKind} ${this.name} ${this.loop} ${this.iterable})` + super.render(opts);
99849
100130
  }
99850
- optimizeNames(names, constants20) {
99851
- if (!super.optimizeNames(names, constants20))
100131
+ optimizeNames(names, constants21) {
100132
+ if (!super.optimizeNames(names, constants21))
99852
100133
  return;
99853
- this.iterable = optimizeExpr(this.iterable, names, constants20);
100134
+ this.iterable = optimizeExpr(this.iterable, names, constants21);
99854
100135
  return this;
99855
100136
  }
99856
100137
  get names() {
@@ -99895,11 +100176,11 @@ var require_codegen = __commonJS((exports) => {
99895
100176
  (_b = this.finally) === null || _b === undefined || _b.optimizeNodes();
99896
100177
  return this;
99897
100178
  }
99898
- optimizeNames(names, constants20) {
100179
+ optimizeNames(names, constants21) {
99899
100180
  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);
100181
+ super.optimizeNames(names, constants21);
100182
+ (_a3 = this.catch) === null || _a3 === undefined || _a3.optimizeNames(names, constants21);
100183
+ (_b = this.finally) === null || _b === undefined || _b.optimizeNames(names, constants21);
99903
100184
  return this;
99904
100185
  }
99905
100186
  get names() {
@@ -100173,7 +100454,7 @@ var require_codegen = __commonJS((exports) => {
100173
100454
  function addExprNames(names, from) {
100174
100455
  return from instanceof code_1._CodeOrName ? addNames(names, from.names) : names;
100175
100456
  }
100176
- function optimizeExpr(expr, names, constants20) {
100457
+ function optimizeExpr(expr, names, constants21) {
100177
100458
  if (expr instanceof code_1.Name)
100178
100459
  return replaceName(expr);
100179
100460
  if (!canOptimize(expr))
@@ -100188,14 +100469,14 @@ var require_codegen = __commonJS((exports) => {
100188
100469
  return items;
100189
100470
  }, []));
100190
100471
  function replaceName(n2) {
100191
- const c = constants20[n2.str];
100472
+ const c = constants21[n2.str];
100192
100473
  if (c === undefined || names[n2.str] !== 1)
100193
100474
  return n2;
100194
100475
  delete names[n2.str];
100195
100476
  return c;
100196
100477
  }
100197
100478
  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);
100479
+ return e2 instanceof code_1._Code && e2._items.some((c) => c instanceof code_1.Name && names[c.str] === 1 && constants21[c.str] !== undefined);
100199
100480
  }
100200
100481
  }
100201
100482
  function subtractNames(names, from) {
@@ -107671,7 +107952,7 @@ var init_remote_customer_operations = __esm(() => {
107671
107952
  });
107672
107953
 
107673
107954
  // 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";
107955
+ 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
107956
  import { dirname as dirname28, join as join53 } from "path";
107676
107957
  function stat2(path) {
107677
107958
  try {
@@ -107685,7 +107966,7 @@ function stat2(path) {
107685
107966
  function safeText(file2) {
107686
107967
  if (stat2(file2) === null)
107687
107968
  return null;
107688
- const fd = openSync20(file2, constants20.O_RDONLY | constants20.O_NOFOLLOW | constants20.O_NONBLOCK);
107969
+ const fd = openSync20(file2, constants21.O_RDONLY | constants21.O_NOFOLLOW | constants21.O_NONBLOCK);
107689
107970
  try {
107690
107971
  const s = fstatSync20(fd);
107691
107972
  if (!s.isFile() || s.size > 65536 || ![256, 384].includes(s.mode & 4095) || process.getuid && s.uid !== process.getuid())
@@ -108039,8 +108320,8 @@ var init_recurring_customer = __esm(() => {
108039
108320
  });
108040
108321
 
108041
108322
  // 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";
108323
+ 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";
108324
+ import { dirname as dirname29, isAbsolute as isAbsolute27, join as join54, resolve as resolve27 } from "path";
108044
108325
  import { randomUUID as randomUUID8 } from "crypto";
108045
108326
 
108046
108327
  class RecoveryOwner {
@@ -108048,7 +108329,7 @@ class RecoveryOwner {
108048
108329
  parents = [];
108049
108330
  constructor(directory) {
108050
108331
  this.directory = directory;
108051
- if (!isAbsolute26(directory) || resolve27(directory) !== directory || realpathSync16(directory) !== directory)
108332
+ if (!isAbsolute27(directory) || resolve27(directory) !== directory || realpathSync16(directory) !== directory)
108052
108333
  invalid6();
108053
108334
  for (let path = directory;; path = dirname29(path)) {
108054
108335
  const stat3 = lstatSync31(path);
@@ -108074,7 +108355,7 @@ class RecoveryOwner {
108074
108355
  }
108075
108356
  read(name) {
108076
108357
  this.assert();
108077
- const fd = openSync21(join54(this.directory, name), constants21.O_RDONLY | constants21.O_NOFOLLOW | constants21.O_NONBLOCK);
108358
+ const fd = openSync21(join54(this.directory, name), constants22.O_RDONLY | constants22.O_NOFOLLOW | constants22.O_NONBLOCK);
108078
108359
  try {
108079
108360
  const before2 = fstatSync21(fd);
108080
108361
  if (!before2.isFile() || before2.nlink !== 1 || (before2.mode & 4095) !== 384 || before2.size < 1 || before2.size > 8192 || process.getuid && before2.uid !== process.getuid())
@@ -108100,7 +108381,7 @@ class RecoveryOwner {
108100
108381
  this.assert();
108101
108382
  const bytes = canonicalJson2(value, 8192) + `
108102
108383
  `;
108103
- const fd = openSync21(join54(this.directory, name), constants21.O_WRONLY | constants21.O_CREAT | constants21.O_EXCL | constants21.O_NOFOLLOW, 384);
108384
+ const fd = openSync21(join54(this.directory, name), constants22.O_WRONLY | constants22.O_CREAT | constants22.O_EXCL | constants22.O_NOFOLLOW, 384);
108104
108385
  try {
108105
108386
  writeFileSync19(fd, bytes);
108106
108387
  fsyncSync7(fd);
@@ -108112,7 +108393,7 @@ class RecoveryOwner {
108112
108393
  }
108113
108394
  sync() {
108114
108395
  this.assert();
108115
- const fd = openSync21(this.directory, constants21.O_RDONLY | constants21.O_NOFOLLOW);
108396
+ const fd = openSync21(this.directory, constants22.O_RDONLY | constants22.O_NOFOLLOW);
108116
108397
  try {
108117
108398
  fsyncSync7(fd);
108118
108399
  } finally {
@@ -108134,7 +108415,7 @@ class RecoveryOwner {
108134
108415
  this.assert();
108135
108416
  let fd;
108136
108417
  try {
108137
- fd = openSync21(join54(this.directory, "operation.lock"), constants21.O_WRONLY | constants21.O_CREAT | constants21.O_EXCL | constants21.O_NOFOLLOW, 384);
108418
+ fd = openSync21(join54(this.directory, "operation.lock"), constants22.O_WRONLY | constants22.O_CREAT | constants22.O_EXCL | constants22.O_NOFOLLOW, 384);
108138
108419
  } catch {
108139
108420
  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
108421
  }
@@ -108183,7 +108464,7 @@ function base2(customer, organizationId) {
108183
108464
  };
108184
108465
  }
108185
108466
  function create3(directory, intent) {
108186
- if (!isAbsolute26(directory) || resolve27(directory) !== directory || realpathSync16(dirname29(directory)) !== dirname29(directory))
108467
+ if (!isAbsolute27(directory) || resolve27(directory) !== directory || realpathSync16(dirname29(directory)) !== dirname29(directory))
108187
108468
  invalid6();
108188
108469
  mkdirSync19(directory, { mode: 448 });
108189
108470
  const owner2 = new RecoveryOwner(directory), checked = intentSchema.parse(intent), intentSha256 = canonicalJsonSha256(checked);
@@ -108346,7 +108627,7 @@ var init_recurring_recovery = __esm(() => {
108346
108627
  });
108347
108628
 
108348
108629
  // src/lib/recurring-surface.ts
108349
- import { isAbsolute as isAbsolute27 } from "path";
108630
+ import { isAbsolute as isAbsolute28 } from "path";
108350
108631
  function recurringMcpSchema(action) {
108351
108632
  return action === "activate" ? recurringSurfaceSchemas.activate.extend({ code, confirm: exports_external.literal(true) }) : recurringSurfaceSchemas[action];
108352
108633
  }
@@ -108451,7 +108732,7 @@ var init_recurring_surface = __esm(() => {
108451
108732
  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
108733
  context = { userId: uuid12.optional(), membershipId: uuid12.optional() };
108453
108734
  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");
108735
+ directory = exports_external.string().max(4096).refine(isAbsolute28, "Use an absolute recovery directory");
108455
108736
  email4 = exports_external.string().trim().toLowerCase().email().max(254);
108456
108737
  code = exports_external.string().regex(/^\d{6}$/);
108457
108738
  recurringSurfaceSchemas = {
@@ -109823,7 +110104,7 @@ var init_run_routing = __esm(() => {
109823
110104
  });
109824
110105
 
109825
110106
  // src/mcp/operation-tools.ts
109826
- import { existsSync as existsSync29, readdirSync as readdirSync19, statSync as statSync18 } from "fs";
110107
+ import { existsSync as existsSync29, readdirSync as readdirSync19, statSync as statSync19 } from "fs";
109827
110108
  import { join as join55 } from "path";
109828
110109
  function registerOperationTools(server) {
109829
110110
  server.registerTool("cloud_skill_eligibility", {
@@ -110302,7 +110583,7 @@ function registerOperationTools(server) {
110302
110583
  try {
110303
110584
  skillCount = readdirSync19(agentSkillsPath).filter((f) => {
110304
110585
  const full = join55(agentSkillsPath, f);
110305
- return !f.startsWith(".") && statSync18(full).isDirectory();
110586
+ return !f.startsWith(".") && statSync19(full).isDirectory();
110306
110587
  }).length;
110307
110588
  } catch {}
110308
110589
  }
@@ -110889,7 +111170,7 @@ import {
110889
111170
  mkdirSync as mkdirSync22,
110890
111171
  readFileSync as readFileSync38,
110891
111172
  readdirSync as readdirSync20,
110892
- statSync as statSync19,
111173
+ statSync as statSync20,
110893
111174
  writeFileSync as writeFileSync21
110894
111175
  } from "fs";
110895
111176
  import { dirname as dirname31, join as join58, normalize as normalize5, relative as relative9, sep as sep11 } from "path";
@@ -111015,7 +111296,7 @@ function walkFiles2(dir) {
111015
111296
  const files = [];
111016
111297
  for (const entry of readdirSync20(dir)) {
111017
111298
  const full = join58(dir, entry);
111018
- const stats = statSync19(full);
111299
+ const stats = statSync20(full);
111019
111300
  if (stats.isDirectory())
111020
111301
  files.push(...walkFiles2(full));
111021
111302
  else
@@ -111252,11 +111533,11 @@ var init_private_publication_customer = __esm(() => {
111252
111533
  });
111253
111534
 
111254
111535
  // 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";
111536
+ 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";
111537
+ import { dirname as dirname32, isAbsolute as isAbsolute29, join as join59, resolve as resolve28 } from "path";
111257
111538
  import { randomUUID as randomUUID9 } from "crypto";
111258
111539
  function safeDirectory(directory2) {
111259
- if (!isAbsolute28(directory2) || directory2 !== resolve28(directory2) || realpathSync17(directory2) !== directory2)
111540
+ if (!isAbsolute29(directory2) || directory2 !== resolve28(directory2) || realpathSync17(directory2) !== directory2)
111260
111541
  return fail5();
111261
111542
  for (let path = directory2;; path = dirname32(path)) {
111262
111543
  const stat3 = lstatSync32(path);
@@ -111277,7 +111558,7 @@ function unchangedDirectory(directory2, identity6) {
111277
111558
  }
111278
111559
  function readOwned(directory2, name, max2) {
111279
111560
  const identity6 = safeDirectory(directory2), file2 = join59(directory2, name);
111280
- const fd = openSync23(file2, constants22.O_RDONLY | constants22.O_NOFOLLOW);
111561
+ const fd = openSync23(file2, constants23.O_RDONLY | constants23.O_NOFOLLOW);
111281
111562
  try {
111282
111563
  const stat3 = fstatSync23(fd);
111283
111564
  if (!stat3.isFile() || stat3.nlink !== 1 || stat3.size > max2 || stat3.size < 1 || (stat3.mode & 63) !== 0 || process.getuid && stat3.uid !== process.getuid())
@@ -111300,7 +111581,7 @@ function readOwned(directory2, name, max2) {
111300
111581
  }
111301
111582
  }
111302
111583
  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);
111584
+ const fd = openSync23(join59(directory2, name), constants23.O_WRONLY | constants23.O_CREAT | constants23.O_EXCL | constants23.O_NOFOLLOW, 384);
111304
111585
  try {
111305
111586
  writeFileSync22(fd, bytes);
111306
111587
  fsyncSync8(fd);
@@ -111314,7 +111595,7 @@ function save2(directory2, value) {
111314
111595
  `);
111315
111596
  unchangedDirectory(directory2, identity6);
111316
111597
  renameSync13(join59(directory2, temporary), join59(directory2, "receipt.json"));
111317
- const fd = openSync23(directory2, constants22.O_RDONLY | constants22.O_NOFOLLOW);
111598
+ const fd = openSync23(directory2, constants23.O_RDONLY | constants23.O_NOFOLLOW);
111318
111599
  try {
111319
111600
  fsyncSync8(fd);
111320
111601
  } finally {
@@ -111329,7 +111610,7 @@ async function locked(directory2, action) {
111329
111610
  const identity6 = safeDirectory(directory2), file2 = join59(directory2, "operation.lock");
111330
111611
  let fd;
111331
111612
  try {
111332
- fd = openSync23(file2, constants22.O_WRONLY | constants22.O_CREAT | constants22.O_EXCL | constants22.O_NOFOLLOW, 384);
111613
+ fd = openSync23(file2, constants23.O_WRONLY | constants23.O_CREAT | constants23.O_EXCL | constants23.O_NOFOLLOW, 384);
111333
111614
  } catch {
111334
111615
  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
111616
  }
@@ -111394,11 +111675,11 @@ async function preparePrivatePublication(client2, sourceDirectory, recoveryDirec
111394
111675
  phase: "prepared",
111395
111676
  intent: null
111396
111677
  };
111397
- if (!isAbsolute28(recoveryDirectory) || resolve28(recoveryDirectory) !== recoveryDirectory || realpathSync17(dirname32(recoveryDirectory)) !== dirname32(recoveryDirectory))
111678
+ if (!isAbsolute29(recoveryDirectory) || resolve28(recoveryDirectory) !== recoveryDirectory || realpathSync17(dirname32(recoveryDirectory)) !== dirname32(recoveryDirectory))
111398
111679
  return fail5();
111399
111680
  mkdirSync23(recoveryDirectory, { mode: 448 });
111400
111681
  safeDirectory(recoveryDirectory);
111401
- const parent = openSync23(dirname32(recoveryDirectory), constants22.O_RDONLY | constants22.O_NOFOLLOW);
111682
+ const parent = openSync23(dirname32(recoveryDirectory), constants23.O_RDONLY | constants23.O_NOFOLLOW);
111402
111683
  try {
111403
111684
  fsyncSync8(parent);
111404
111685
  } finally {
@@ -111495,10 +111776,10 @@ var init_private_publication_recovery = __esm(() => {
111495
111776
  });
111496
111777
 
111497
111778
  // src/mcp/private-publication-tools.ts
111498
- import { isAbsolute as isAbsolute29 } from "path";
111779
+ import { isAbsolute as isAbsolute30 } from "path";
111499
111780
  function registerPrivatePublicationTools(server) {
111500
111781
  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");
111782
+ const directory2 = exports_external.string().max(4096).refine(isAbsolute30, "Use an absolute local directory");
111502
111783
  const verification2 = { email: exports_external.string().email().max(254), code: exports_external.string().regex(/^\d{6}$/), userId: uuid9, membershipId: uuid9, recoveryDirectory: directory2 };
111503
111784
  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
111785
  const handler = (action) => async (value) => {
@@ -112277,6 +112558,7 @@ var init_reviewed_runtime_lock = __esm(() => {
112277
112558
  import { createHash as createHash36, randomUUID as randomUUID10 } from "crypto";
112278
112559
  import { Readable } from "stream";
112279
112560
  import { createGunzip as createGunzip2 } from "zlib";
112561
+ import { spawnSync as spawnSync5 } from "child_process";
112280
112562
  import {
112281
112563
  chmodSync as chmodSync4,
112282
112564
  copyFileSync,
@@ -112290,44 +112572,108 @@ import {
112290
112572
  renameSync as renameSync14,
112291
112573
  writeFileSync as writeFileSync24
112292
112574
  } 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";
112575
+ 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
112576
  function oldLauncherState(item) {
112295
112577
  if (item.oldShape === "pinned")
112296
- return { shape: "pinned", runtime: item.oldRuntime, cwd: item.oldCwd, target: item.oldTarget, sha256: item.oldSha256 };
112578
+ return { shape: "pinned", runtime: item.oldRuntime, cwd: item.oldCwd, target: item.oldTarget, sha256: item.oldSha256, format: item.oldFormat, profile: item.oldProfile };
112297
112579
  return { shape: "symlink", linkTarget: item.oldLinkTarget, target: item.oldTarget };
112298
112580
  }
112299
112581
  function newLauncherState(item) {
112300
112582
  if (item.newShape === "pinned")
112301
- return { shape: "pinned", runtime: item.newRuntime, cwd: item.newCwd, target: item.newTarget, sha256: item.newSha256 };
112583
+ return { shape: "pinned", runtime: item.newRuntime, cwd: item.newCwd, target: item.newTarget, sha256: item.newSha256, format: item.newFormat, profile: item.newProfile };
112302
112584
  return { shape: "symlink", linkTarget: item.newTarget, target: item.newTarget };
112303
112585
  }
112304
- function assertLauncherRecordShapes(item) {
112586
+ function assertLauncherRecordShapes(item, expectedProfile) {
112305
112587
  const hex3 = /^[a-f0-9]{64}$/;
112306
112588
  for (const side of ["old", "new"]) {
112307
112589
  const shape = item[`${side}Shape`], runtime = item[`${side}Runtime`], cwd2 = item[`${side}Cwd`], sha6 = item[`${side}Sha256`];
112590
+ const format = item[`${side}Format`], profile = item[`${side}Profile`];
112308
112591
  if (shape === undefined) {
112309
- if (runtime !== undefined || cwd2 !== undefined || sha6 !== undefined)
112592
+ if (runtime !== undefined || cwd2 !== undefined || sha6 !== undefined || format !== undefined || profile !== undefined)
112310
112593
  throw new Error("RECEIPT_LAUNCHER_SHAPE_INVALID");
112311
112594
  continue;
112312
112595
  }
112313
112596
  if (shape === "symlink") {
112314
- if (runtime !== undefined || cwd2 !== undefined || sha6 !== undefined)
112597
+ if (runtime !== undefined || cwd2 !== undefined || sha6 !== undefined || format !== undefined || profile !== undefined)
112315
112598
  throw new Error("RECEIPT_LAUNCHER_SHAPE_INVALID");
112316
112599
  continue;
112317
112600
  }
112318
- if (shape !== "pinned" || typeof runtime !== "string" || !isAbsolute30(runtime) || typeof cwd2 !== "string" || !isAbsolute30(cwd2) || typeof sha6 !== "string" || !hex3.test(sha6)) {
112601
+ if (shape !== "pinned" || typeof runtime !== "string" || !isAbsolute31(runtime) || typeof cwd2 !== "string" || !isAbsolute31(cwd2) || typeof sha6 !== "string" || !hex3.test(sha6)) {
112319
112602
  throw new Error("RECEIPT_LAUNCHER_SHAPE_INVALID");
112320
112603
  }
112321
112604
  const target = side === "old" ? item.oldTarget : item.newTarget;
112322
112605
  if (side === "old" && item.oldLinkTarget !== item.oldTarget)
112323
112606
  throw new Error("RECEIPT_LAUNCHER_SHAPE_INVALID");
112324
- if (pinnedLauncherState(runtime, cwd2, target).sha256 !== sha6)
112607
+ if (format === "v2" && profile !== expectedProfile)
112325
112608
  throw new Error("RECEIPT_LAUNCHER_SHAPE_INVALID");
112609
+ try {
112610
+ pinnedLauncherText({ runtime, cwd: cwd2, target, sha256: sha6, format, profile });
112611
+ } catch {
112612
+ throw new Error("RECEIPT_LAUNCHER_SHAPE_INVALID");
112613
+ }
112326
112614
  }
112327
112615
  }
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 };
112616
+ function pinnedRecordFields(runtime, cwd2, target, profile) {
112617
+ const state = pinnedLauncherState(runtime, cwd2, target, { format: "v2", profile });
112618
+ return { newShape: "pinned", newRuntime: state.runtime, newCwd: state.cwd, newSha256: state.sha256, newFormat: state.format, newProfile: state.profile };
112619
+ }
112620
+ function verifyTargetPrerequisites(manifest, packageRoot, home, cwd2, pathValue) {
112621
+ const declaration = manifest.skillsRuntimePrerequisites;
112622
+ if (declaration === undefined)
112623
+ return { status: "not-declared" };
112624
+ const contract = object10(declaration, "RUNTIME_PREREQUISITE_CONTRACT_INVALID");
112625
+ if (Object.keys(contract).length !== 2 || contract.version !== 1 || contract.entry !== "dist/runtime-prerequisites.js") {
112626
+ throw new Error("RUNTIME_PREREQUISITE_CONTRACT_INVALID");
112627
+ }
112628
+ const entry = join61(packageRoot, contract.entry);
112629
+ if (!entryExists(entry) || !lstatSync33(entry).isFile() || lstatSync33(entry).isSymbolicLink())
112630
+ throw new Error("RUNTIME_PREREQUISITE_ENTRY_MISSING");
112631
+ const entrySha256 = hash5(readFileSync40(entry));
112632
+ const env3 = { HOME: home, PATH: pathValue, BUN_RUNTIME_TRANSPILER_CACHE_PATH: "0" };
112633
+ for (const key of ["HASNA_SKILLS_DIR", "HASNA_SKILLS_HOME", "SKILLS_HOME", "HASNA_DATA_HOME", "XDG_DATA_HOME", "XDG_CONFIG_HOME", "XDG_CACHE_HOME", "XDG_STATE_HOME", "SUMI_HOME", "SUMI_CONFIG_DIR", "HERMES_HOME"]) {
112634
+ if (process.env[key] !== undefined)
112635
+ env3[key] = process.env[key];
112636
+ }
112637
+ for (const key of ["SUMI_CONFIG", "SUMI_CONFIG_CONTENT"])
112638
+ if (process.env[key] !== undefined)
112639
+ env3[key] = "";
112640
+ const child2 = spawnSync5(pinnedLauncherRuntime(), [...PINNED_LAUNCHER_BUN_FLAGS2, entry, home, cwd2], {
112641
+ cwd: dirname34(packageRoot),
112642
+ env: env3,
112643
+ encoding: "buffer",
112644
+ timeout: 5000,
112645
+ maxBuffer: 128 * 1024,
112646
+ shell: false
112647
+ });
112648
+ if (child2.error || child2.signal || !child2.stdout || child2.stderr?.byteLength)
112649
+ throw new Error("RUNTIME_PREREQUISITE_CHECK_UNAVAILABLE");
112650
+ let result2;
112651
+ try {
112652
+ result2 = object10(JSON.parse(child2.stdout.toString("utf8")), "RUNTIME_PREREQUISITE_RESPONSE_INVALID");
112653
+ } catch {
112654
+ throw new Error("RUNTIME_PREREQUISITE_RESPONSE_INVALID");
112655
+ }
112656
+ if (Object.keys(result2).length !== 5 || result2.schema !== "skills.runtime-prerequisites.v1" || result2.targetVersion !== manifest.version || typeof result2.ok !== "boolean" || !Array.isArray(result2.checked) || result2.checked.length > 1 || result2.checked.some((value) => value !== "sumi-paths"))
112657
+ throw new Error("RUNTIME_PREREQUISITE_RESPONSE_INVALID");
112658
+ const codes = [
112659
+ "RUNTIME_CONSUMER_DISCOVERY_REFUSED",
112660
+ "RUNTIME_PREREQUISITE_INPUT_REFUSED",
112661
+ "SUMI_PATH_INPUT_REFUSED",
112662
+ "SUMI_PATH_CONFIG_UNSUPPORTED",
112663
+ "SUMI_PATH_RESOLVER_UNAVAILABLE",
112664
+ "SUMI_PATH_RESOLVER_INVALID_RESPONSE",
112665
+ "SUMI_PATH_DISCOVERY_REFUSED"
112666
+ ];
112667
+ if (!result2.ok) {
112668
+ if (child2.status !== 2 || typeof result2.code !== "string" || !codes.includes(result2.code))
112669
+ throw new Error("RUNTIME_PREREQUISITE_RESPONSE_INVALID");
112670
+ throw new Error(`RUNTIME_PREREQUISITE_REFUSED_${result2.code}`);
112671
+ }
112672
+ if (child2.status !== 0 || result2.code !== null)
112673
+ throw new Error("RUNTIME_PREREQUISITE_RESPONSE_INVALID");
112674
+ if (hash5(readFileSync40(entry)) !== entrySha256)
112675
+ throw new Error("RUNTIME_PREREQUISITE_ENTRY_CHANGED");
112676
+ return { status: "verified", schema: result2.schema, targetVersion: result2.targetVersion, entry: contract.entry, entrySha256, checked: result2.checked };
112331
112677
  }
112332
112678
  function object10(value, code2) {
112333
112679
  if (!value || typeof value !== "object" || Array.isArray(value))
@@ -112339,7 +112685,7 @@ function hash5(bytes) {
112339
112685
  }
112340
112686
  function isWithin(parent, child2) {
112341
112687
  const rel = relative10(parent, child2);
112342
- return rel === "" || !rel.startsWith(`..${sep12}`) && rel !== ".." && !isAbsolute30(rel);
112688
+ return rel === "" || !rel.startsWith(`..${sep12}`) && rel !== ".." && !isAbsolute31(rel);
112343
112689
  }
112344
112690
  function entryExists(path) {
112345
112691
  try {
@@ -112388,7 +112734,7 @@ function packageBins(pkg) {
112388
112734
  const entries = typeof raw === "string" ? [[PACKAGE_NAME.slice(PACKAGE_NAME.lastIndexOf("/") + 1), raw]] : raw && typeof raw === "object" && !Array.isArray(raw) ? Object.entries(raw) : [];
112389
112735
  const output2 = {};
112390
112736
  for (const [name, value] of entries) {
112391
- if (!/^[a-zA-Z0-9._-]+$/.test(name) || typeof value !== "string" || !value || isAbsolute30(value)) {
112737
+ if (!/^[a-zA-Z0-9._-]+$/.test(name) || typeof value !== "string" || !value || isAbsolute31(value)) {
112392
112738
  throw new Error("PACKAGE_BIN_INVALID");
112393
112739
  }
112394
112740
  const normalized = value.replaceAll("\\", "/");
@@ -112451,7 +112797,7 @@ function resolveRuntimeLayout(homeInput, pathInput) {
112451
112797
  }
112452
112798
  const launchers = [];
112453
112799
  const seenDirectories = new Set;
112454
- for (const rawDir of pathInput.split(delimiter2).filter(Boolean)) {
112800
+ for (const rawDir of pathInput.split(delimiter3).filter(Boolean)) {
112455
112801
  const dir = resolve29(rawDir);
112456
112802
  if (seenDirectories.has(dir))
112457
112803
  continue;
@@ -112481,7 +112827,7 @@ function resolveRuntimeLayout(homeInput, pathInput) {
112481
112827
  throw new Error("LAUNCHER_SYMLINK_CHAIN_UNSUPPORTED");
112482
112828
  launchers.push({ path, oldTarget: actual, oldLinkTarget: launcher.linkTarget, newTarget, backupPath, oldShape: "symlink" });
112483
112829
  } else {
112484
- launchers.push({ path, oldTarget: actual, oldLinkTarget: actual, newTarget, backupPath, oldShape: "pinned", oldRuntime: launcher.runtime, oldCwd: launcher.cwd, oldSha256: launcher.sha256 });
112830
+ 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
112831
  }
112486
112832
  }
112487
112833
  }
@@ -113110,14 +113456,14 @@ function adoptCopyfileAliases(options = {}) {
113110
113456
  const actual = launcher.target;
113111
113457
  const oldLinkTarget = launcher.kind === "symlink" ? launcher.linkTarget : actual;
113112
113458
  const newTarget = join61(layout.currentPackageRoot, target);
113113
- if (actual === newTarget && launcher.kind === "pinned")
113459
+ if (actual === newTarget && launcher.kind === "pinned" && launcher.format === "v2" && launcher.profile === launcherProfileForBin(name, target))
113114
113460
  continue;
113115
113461
  const chain = inspectAliasPackageChain(home, path, oldLinkTarget, actual, target);
113116
113462
  const source = validateAliasSource(home, name, actual);
113117
113463
  const backupPath = `${path}.skills-alias-prev-${id2}`;
113118
113464
  if (entryExists(backupPath))
113119
113465
  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 };
113466
+ 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
113467
  aliases.push({
113122
113468
  path,
113123
113469
  oldTarget: actual,
@@ -113127,7 +113473,7 @@ function adoptCopyfileAliases(options = {}) {
113127
113473
  newTarget,
113128
113474
  backupPath,
113129
113475
  ...oldFields,
113130
- ...pinnedRecordFields(launcherRuntime, currentRuntime, newTarget),
113476
+ ...pinnedRecordFields(launcherRuntime, currentRuntime, newTarget, launcherProfileForBin(name, target)),
113131
113477
  ...chain ? { chain } : {}
113132
113478
  });
113133
113479
  }
@@ -113247,7 +113593,7 @@ function rollbackCopyfileAliases(receiptId, options = {}) {
113247
113593
  throw new Error("ALIAS_RECEIPT_LAUNCHER_INVALID");
113248
113594
  }
113249
113595
  inspectAliasPackageChain(home, item.path, item.oldLinkTarget, item.oldTarget, target, item.chain, true);
113250
- assertLauncherRecordShapes(item);
113596
+ assertLauncherRecordShapes(item, launcherProfileForBin(name, target));
113251
113597
  seen.add(item.path);
113252
113598
  assertOwnedSafePath(dirname34(item.path), home, true);
113253
113599
  const source = validateAliasSource(home, name, item.oldTarget);
@@ -113319,7 +113665,7 @@ async function updateCopyfileRuntime(version2, options = {}) {
113319
113665
  throw new Error("REVIEWED_LOCK_INPUT_PAIR_REQUIRED");
113320
113666
  if (!policy)
113321
113667
  throw new Error("REVIEWED_LOCK_RELEASE_AGE_REQUIRED");
113322
- if (!isAbsolute30(options.reviewedLock))
113668
+ if (!isAbsolute31(options.reviewedLock))
113323
113669
  throw new Error("REVIEWED_LOCK_ABSOLUTE_PATH_REQUIRED");
113324
113670
  assertNoSymlinkAncestors(dirname34(options.reviewedLock));
113325
113671
  const stat3 = lstatSync33(options.reviewedLock);
@@ -113352,7 +113698,7 @@ async function updateCopyfileRuntime(version2, options = {}) {
113352
113698
  const launcherRuntime = pinnedLauncherRuntime();
113353
113699
  const launchers = layout.launchers.map((item) => {
113354
113700
  const newTarget = join61(finalPath, "node_modules", "@hasna", "skills", layout.bin[basename17(item.path)]);
113355
- return { ...item, newTarget, ...pinnedRecordFields(launcherRuntime, finalPath, newTarget) };
113701
+ return { ...item, newTarget, ...pinnedRecordFields(launcherRuntime, finalPath, newTarget, launcherProfileForBin(basename17(item.path), layout.bin[basename17(item.path)])) };
113356
113702
  });
113357
113703
  const releaseLock = acquireRuntimeLock(layout.runtimeRoot);
113358
113704
  let switched = [];
@@ -113448,6 +113794,15 @@ async function updateCopyfileRuntime(version2, options = {}) {
113448
113794
  rollbackCompletedLaunchers: []
113449
113795
  };
113450
113796
  writeJsonPrivate(join61(stagePath, "rollout-receipt.json"), receipt);
113797
+ try {
113798
+ receipt.prerequisites = verifyTargetPrerequisites(installed.data, installedPackage, home, resolve29(options.cwd ?? process.env[LAUNCH_CWD_VARIABLE3] ?? process.cwd()), options.pathValue ?? process.env.PATH ?? "");
113799
+ } catch (error61) {
113800
+ const code2 = error61 instanceof Error && /^RUNTIME_PREREQUISITE_[A-Z_]+$/.test(error61.message) ? error61.message : "RUNTIME_PREREQUISITE_CHECK_UNAVAILABLE";
113801
+ receipt.prerequisites = { status: "refused", code: code2 };
113802
+ persistReceipt(join61(stagePath, "rollout-receipt.json"), receipt);
113803
+ throw new Error(code2);
113804
+ }
113805
+ persistReceipt(join61(stagePath, "rollout-receipt.json"), receipt);
113451
113806
  const finalNodeModules = join61(stagePackage, "node_modules");
113452
113807
  const stagedNodeModules = join61(stagePath, "node_modules");
113453
113808
  renameSync14(finalNodeModules, stagedNodeModules);
@@ -113481,7 +113836,7 @@ async function updateCopyfileRuntime(version2, options = {}) {
113481
113836
  }
113482
113837
  receipt.state = "switched";
113483
113838
  persistReceipt(join61(finalPath, "rollout-receipt.json"), receipt);
113484
- return { updated: true, version: version2, currentVersion: layout.currentVersion, receiptId: id2, runtimeRoot: finalPath, tarballSha256: artifact.sha256, tarballIntegrity: artifact.integrity, runtimeTreeSha256: stagedTree.digest, launcherCount: launchers.length, configCount: configPreimages.length, ...policy ? { dependencyPolicy: { ...policy, npmVersion } } : {}, ...reviewedLockBytes ? { reviewedLockSha256: options.reviewedLockSha256 } : {} };
113839
+ return { updated: true, version: version2, currentVersion: layout.currentVersion, receiptId: id2, runtimeRoot: finalPath, tarballSha256: artifact.sha256, tarballIntegrity: artifact.integrity, runtimeTreeSha256: stagedTree.digest, launcherCount: launchers.length, configCount: configPreimages.length, prerequisites: receipt.prerequisites, ...policy ? { dependencyPolicy: { ...policy, npmVersion } } : {}, ...reviewedLockBytes ? { reviewedLockSha256: options.reviewedLockSha256 } : {} };
113485
113840
  } catch (error61) {
113486
113841
  if (switched.length > 0 || moved) {
113487
113842
  let rollbackFailed = false;
@@ -113566,10 +113921,10 @@ function rollbackCopyfileRuntime(receiptId, options = {}) {
113566
113921
  const seen = new Set;
113567
113922
  for (const item of receipt.launchers) {
113568
113923
  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)
113924
+ 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
113925
  throw new Error("RECEIPT_LAUNCHER_BINDING_INVALID");
113571
113926
  assertNoSymlinkAncestors(dirname34(item.path));
113572
- assertLauncherRecordShapes(item);
113927
+ assertLauncherRecordShapes(item, launcherProfileForBin(basename17(item.path), bin));
113573
113928
  seen.add(item.path);
113574
113929
  const oldState = oldLauncherState(item), newState = newLauncherState(item);
113575
113930
  let activeTarget;
@@ -113635,7 +113990,7 @@ __export(exports_runtime, {
113635
113990
  });
113636
113991
  import { createHash as createHash37, randomUUID as randomUUID11 } from "crypto";
113637
113992
  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";
113993
+ import { basename as basename18, isAbsolute as isAbsolute32, join as join62 } from "path";
113639
113994
  import { createInterface } from "readline";
113640
113995
  function registerRuntime(parent) {
113641
113996
  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 +114189,7 @@ Updating ${name}...
113834
114189
  async function readUpdatedVersion(bunExecutable) {
113835
114190
  const output2 = await readUpdateCommand([bunExecutable, "pm", "bin", "-g"]);
113836
114191
  const globalBin = output2.replace(/\r?\n$/, "");
113837
- if (!globalBin || !isAbsolute31(globalBin) || /[\r\n\0]/.test(globalBin))
114192
+ if (!globalBin || !isAbsolute32(globalBin) || /[\r\n\0]/.test(globalBin))
113838
114193
  throw new Error("Update bin discovery failed");
113839
114194
  const installed = Bun.which("skills", { PATH: globalBin, cwd: globalBin });
113840
114195
  const selected = Bun.which("skills");
@@ -114889,10 +115244,10 @@ var exports_recurring = {};
114889
115244
  __export(exports_recurring, {
114890
115245
  registerRecurringCommands: () => registerRecurringCommands
114891
115246
  });
114892
- import { constants as constants23, closeSync as closeSync25, fstatSync as fstatSync25, lstatSync as lstatSync35, openSync as openSync25, readSync as readSync18 } from "fs";
115247
+ import { constants as constants24, closeSync as closeSync25, fstatSync as fstatSync25, lstatSync as lstatSync35, openSync as openSync25, readSync as readSync18 } from "fs";
114893
115248
  import { createInterface as createInterface2 } from "readline";
114894
115249
  function readRequest(path) {
114895
- const fd = openSync25(path, constants23.O_RDONLY | constants23.O_NOFOLLOW | constants23.O_NONBLOCK);
115250
+ const fd = openSync25(path, constants24.O_RDONLY | constants24.O_NOFOLLOW | constants24.O_NONBLOCK);
114896
115251
  try {
114897
115252
  const before2 = fstatSync25(fd);
114898
115253
  if (!before2.isFile() || before2.size > 1048576 || before2.size < 1)
@@ -115189,7 +115544,7 @@ var init_completion = __esm(() => {
115189
115544
  });
115190
115545
 
115191
115546
  // src/lib/portable-snapshot-filter.ts
115192
- import { readdirSync as readdirSync22, statSync as statSync20 } from "fs";
115547
+ import { readdirSync as readdirSync22, statSync as statSync21 } from "fs";
115193
115548
  import { homedir as homedir11 } from "os";
115194
115549
  import { join as join63, sep as sep13 } from "path";
115195
115550
  function isExcludedSkillFileName(fileName) {
@@ -115257,7 +115612,7 @@ function walkEntries(absoluteRoot) {
115257
115612
  }
115258
115613
  function isRegularFile(filePath) {
115259
115614
  try {
115260
- return statSync20(filePath).isFile();
115615
+ return statSync21(filePath).isFile();
115261
115616
  } catch {
115262
115617
  return false;
115263
115618
  }
@@ -115343,10 +115698,10 @@ import {
115343
115698
  copyFileSync as copyFileSync2,
115344
115699
  mkdirSync as mkdirSync27,
115345
115700
  readFileSync as readFileSync42,
115346
- statSync as statSync21,
115701
+ statSync as statSync22,
115347
115702
  writeFileSync as writeFileSync26
115348
115703
  } from "fs";
115349
- import { dirname as dirname36, isAbsolute as isAbsolute32, relative as relative11, resolve as resolve30, sep as sep14 } from "path";
115704
+ import { dirname as dirname36, isAbsolute as isAbsolute33, relative as relative11, resolve as resolve30, sep as sep14 } from "path";
115350
115705
  function validateStationId(stationId) {
115351
115706
  if (!/^[a-z0-9-]+$/.test(stationId)) {
115352
115707
  throw new StationSnapshotError("INVALID_STATION", `station id must be a slug, got: ${stationId}`);
@@ -115383,7 +115738,7 @@ function scanHome(definition, homesRoot) {
115383
115738
  skipped.push({ relativePath: entry.relativePath, reason: "not-regular-file" });
115384
115739
  continue;
115385
115740
  }
115386
- const info = statSync21(entry.fullPath);
115741
+ const info = statSync22(entry.fullPath);
115387
115742
  portable.push({
115388
115743
  relativePath: entry.relativePath,
115389
115744
  fullPath: entry.fullPath,
@@ -115452,7 +115807,7 @@ function writeStationSnapshot(options) {
115452
115807
  for (const plan of plans) {
115453
115808
  const destination = resolve30(repoRoot, plan.destination);
115454
115809
  const destinationRelative = relative11(repoRoot, destination);
115455
- if (destinationRelative.startsWith("..") || destinationRelative.startsWith(sep14) || isAbsolute32(destinationRelative)) {
115810
+ if (destinationRelative.startsWith("..") || destinationRelative.startsWith(sep14) || isAbsolute33(destinationRelative)) {
115456
115811
  throw new StationSnapshotError("DESTINATION_ESCAPE", `destination escapes repo root: ${plan.destination}`);
115457
115812
  }
115458
115813
  let existingDigest = null;
@@ -115924,6 +116279,50 @@ var init_create_sync_config = __esm(() => {
115924
116279
  init_station_snapshot();
115925
116280
  });
115926
116281
 
116282
+ // src/lib/agent-install-selection.ts
116283
+ import { lstatSync as lstatSync36 } from "fs";
116284
+ import { dirname as dirname37, join as join65, resolve as resolve31 } from "path";
116285
+ import { homedir as homedir12 } from "os";
116286
+ function detectedIntegrationAgents(options = {}) {
116287
+ const home = options.home ?? homedir12(), env3 = options.env ?? process.env;
116288
+ const policy = readManagedSkillPolicySnapshot(options.dataDir ?? getDataDirReadOnly())?.value;
116289
+ const bridge = policy?.bridge;
116290
+ if (bridge !== undefined && (!bridge || typeof bridge !== "object" || Array.isArray(bridge)))
116291
+ throw new Error("Invalid existing Skills bridge policy");
116292
+ const configured = bridge === undefined ? [] : bridge.agents;
116293
+ if (!Array.isArray(configured) || configured.some((agent) => !INTEGRATION_AGENTS.includes(agent)))
116294
+ throw new Error("Invalid existing bridge agent inventory");
116295
+ const present = (path) => {
116296
+ try {
116297
+ return lstatSync36(path, { throwIfNoEntry: false }) !== undefined;
116298
+ } catch {
116299
+ throw new Error("Agent presence cannot be inspected; review native configuration before hook installation");
116300
+ }
116301
+ };
116302
+ const selected = INTEGRATION_AGENTS.filter((agent) => {
116303
+ if (configured.includes(agent) || Bun.which(agent, { PATH: env3.PATH ?? "" }))
116304
+ return true;
116305
+ if (agent === "sumi") {
116306
+ const xdg = env3.XDG_CONFIG_HOME;
116307
+ const xdgSumi = xdg?.trim() ? resolve31(options.cwd ?? process.cwd(), xdg === "~" ? home : xdg.startsWith("~/") || xdg.startsWith("~\\") ? resolve31(home, xdg.slice(2)) : xdg, "sumi") : null;
116308
+ 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);
116309
+ }
116310
+ if (agent === "hermes" && env3.HERMES_HOME !== undefined)
116311
+ return true;
116312
+ const adapter = AGENT_ADAPTERS[agent];
116313
+ return present(join65(home, dirname37(adapter.config))) || NATIVE_SKILL_ROOTS.some(([provider, root2]) => provider === agent && dirname37(root2) === `.${agent}` && present(join65(home, dirname37(root2))));
116314
+ });
116315
+ if (!selected.length && !options.allowEmpty)
116316
+ throw new Error(`No configured or detected agents; select --agent <agent> explicitly (${INTEGRATION_AGENTS.join(", ")}).`);
116317
+ return selected;
116318
+ }
116319
+ var init_agent_install_selection = __esm(() => {
116320
+ init_agent_adapters();
116321
+ init_native_discovery_roots();
116322
+ init_managed_policy();
116323
+ init_config();
116324
+ });
116325
+
115927
116326
  // src/lib/codex-native-config.ts
115928
116327
  import { isDeepStrictEqual as isDeepStrictEqual14 } from "util";
115929
116328
  function isRecord8(value) {
@@ -115971,11 +116370,11 @@ var NUMBER_TAG = "$serde_json::private::Number";
115971
116370
  var init_codex_native_config = () => {};
115972
116371
 
115973
116372
  // 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";
116373
+ import { lstatSync as lstatSync37, realpathSync as realpathSync19 } from "fs";
116374
+ import { dirname as dirname38, isAbsolute as isAbsolute34, join as join66, resolve as resolve32 } from "path";
115976
116375
  import { isDeepStrictEqual as isDeepStrictEqual15 } from "util";
115977
116376
  function commandPhysical(command) {
115978
- need6(typeof command === "string" && isAbsolute33(command) && !command.includes("\x00") && resolve31(command) === command, COMMAND_NOT_CANONICAL);
116377
+ need6(typeof command === "string" && isAbsolute34(command) && !command.includes("\x00") && resolve32(command) === command, COMMAND_NOT_CANONICAL);
115979
116378
  const physical = realpathSync19(command);
115980
116379
  let spelled;
115981
116380
  try {
@@ -115986,7 +116385,7 @@ function commandPhysical(command) {
115986
116385
  safeParents(spelled);
115987
116386
  let direct = false;
115988
116387
  try {
115989
- const leaf = lstatSync36(spelled);
116388
+ const leaf = lstatSync37(spelled);
115990
116389
  direct = leaf.isSymbolicLink() ? trustedAncestorOwner(leaf.uid) && directAliasTarget(spelled) === physical : spelled === physical;
115991
116390
  } catch {}
115992
116391
  need6(direct, COMMAND_ALIAS_UNSAFE);
@@ -115998,7 +116397,7 @@ function assertPinnedRuntime(runtime) {
115998
116397
  } catch {
115999
116398
  need6(false, "SKILLS_LAUNCHER_UNVERIFIED");
116000
116399
  }
116001
- need6(resolve31(runtime) === runtime, "SKILLS_LAUNCHER_UNVERIFIED");
116400
+ need6(resolve32(runtime) === runtime, "SKILLS_LAUNCHER_UNVERIFIED");
116002
116401
  safeParents(runtime);
116003
116402
  }
116004
116403
  function skillsCommandTarget(command) {
@@ -116030,12 +116429,12 @@ function targetUnchanged(command, target) {
116030
116429
  assertPinnedRuntime(target.runtime);
116031
116430
  }
116032
116431
  function inspectRecordedSkillsCli(command, expected) {
116033
- need6(isAbsolute33(command) && !command.includes("\x00"), "RECONCILE_RECORDED_COMMAND_REQUIRED");
116432
+ need6(isAbsolute34(command) && !command.includes("\x00"), "RECONCILE_RECORDED_COMMAND_REQUIRED");
116034
116433
  const target = skillsCommandTarget(command), resolved = target.entry;
116035
116434
  const cli = snapshot(resolved, false, { readOnlyPackage: true });
116036
- const manifest = snapshot(join65(dirname37(dirname37(resolved)), "package.json"), false, { readOnlyPackage: true });
116435
+ const manifest = snapshot(join66(dirname38(dirname38(resolved)), "package.json"), false, { readOnlyPackage: true });
116037
116436
  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");
116437
+ 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
116438
  need6((cli.stat.mode & 0o100n) !== 0n, "SKILLS_COMMAND_NOT_EXECUTABLE");
116040
116439
  const receipt = { path: resolved, version: pkg.version, sha256: cli.sha256, manifestSha256: manifest.sha256 };
116041
116440
  need6(isDeepStrictEqual15(receipt, expected), "RECONCILE_SKILLS_BINDING_CHANGED");
@@ -116049,16 +116448,16 @@ function bindSkillsCli(command, reviewed) {
116049
116448
  const normal = Bun.which("skills", { PATH: process.env.PATH });
116050
116449
  need6(normal, "SKILLS_COMMAND_UNAVAILABLE");
116051
116450
  const normalTarget = skillsCommandTarget(normal), resolved = normalTarget.entry;
116052
- const bound = isAbsolute33(command) ? command : command === "skills" ? normal : undefined;
116451
+ const bound = isAbsolute34(command) ? command : command === "skills" ? normal : undefined;
116053
116452
  need6(bound, "SKILLS_COMMAND_MISMATCH");
116054
116453
  const boundTarget = skillsCommandTarget(bound);
116055
116454
  need6(boundTarget.entry === resolved, "SKILLS_COMMAND_MISMATCH");
116056
116455
  const entrypoint = reviewed?.path ?? process.argv[1];
116057
116456
  need6(entrypoint && realpathSync19(entrypoint) === resolved, "SKILLS_ENTRYPOINT_MISMATCH");
116058
116457
  const cli = snapshot(resolved, false, { readOnlyPackage: true });
116059
- const manifest = snapshot(join65(dirname37(dirname37(resolved)), "package.json"), false, { readOnlyPackage: true });
116458
+ const manifest = snapshot(join66(dirname38(dirname38(resolved)), "package.json"), false, { readOnlyPackage: true });
116060
116459
  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");
116460
+ 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
116461
  if (reviewed)
116063
116462
  need6(/^[a-f0-9]{64}$/.test(reviewed.sha256) && reviewed.sha256 === cli.sha256 && reviewed.version === pkg.version, "SKILLS_RELEASE_MISMATCH");
116064
116463
  need6((cli.stat.mode & 0o100n) !== 0n, "SKILLS_COMMAND_NOT_EXECUTABLE");
@@ -116077,7 +116476,7 @@ function captureSkillsCliProducerIdentity(command) {
116077
116476
  const bound = bindSkillsCli(command);
116078
116477
  const target = skillsCommandTarget(command);
116079
116478
  const cli = snapshot(target.entry, false, { readOnlyPackage: true });
116080
- const manifest = snapshot(join65(dirname37(dirname37(target.entry)), "package.json"), false, { readOnlyPackage: true });
116479
+ const manifest = snapshot(join66(dirname38(dirname38(target.entry)), "package.json"), false, { readOnlyPackage: true });
116081
116480
  const pkg = JSON.parse(manifest.text);
116082
116481
  need6(pkg.name === "@hasna/skills" && pkg.version === bound.receipt.version && target.entry === bound.receipt.path, "SKILLS_PACKAGE_MISMATCH");
116083
116482
  const launcher = target.launcher ?? cli;
@@ -116131,20 +116530,20 @@ var init_codex_hook_policy_recovery = __esm(() => {
116131
116530
  });
116132
116531
 
116133
116532
  // 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";
116533
+ import { lstatSync as lstatSync38, mkdirSync as mkdirSync28, readdirSync as readdirSync23, readFileSync as readFileSync43, realpathSync as realpathSync20, statSync as statSync23 } from "fs";
116135
116534
  import { createHash as createHash39, randomUUID as randomUUID12 } from "crypto";
116136
116535
  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";
116536
+ import { dirname as dirname39, isAbsolute as isAbsolute35, join as join67, resolve as resolve33 } from "path";
116537
+ import { homedir as homedir13 } from "os";
116139
116538
  import { isDeepStrictEqual as isDeepStrictEqual17 } from "util";
116140
116539
  function verifyReleaseArtifact(proof, skillsCli) {
116141
- need6(isAbsolute34(proof.packageTarPath) && !proof.packageTarPath.includes("\x00"), "RECONCILE_RELEASE_PROVENANCE_PATH");
116540
+ need6(isAbsolute35(proof.packageTarPath) && !proof.packageTarPath.includes("\x00"), "RECONCILE_RELEASE_PROVENANCE_PATH");
116142
116541
  const tarPath = realpathSync20(proof.packageTarPath);
116143
- need6(statSync22(tarPath).isFile(), "RECONCILE_RELEASE_PROVENANCE_PATH");
116542
+ need6(statSync23(tarPath).isFile(), "RECONCILE_RELEASE_PROVENANCE_PATH");
116144
116543
  const tarBytes = readFileSync43(tarPath);
116145
116544
  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"));
116545
+ const packageRoot = dirname39(dirname39(realpathSync20(skillsCli.receipt.path)));
116546
+ const manifest = readFileSync43(join67(packageRoot, "package.json"));
116148
116547
  need6(createHash39("sha256").update(manifest).digest("hex") === skillsCli.receipt.manifestSha256 && skillsCli.receipt.manifestSha256 === proof.manifestSha256, "RECONCILE_RELEASE_MANIFEST_CHANGED");
116149
116548
  need6(createHash39("sha256").update(readFileSync43(skillsCli.receipt.path)).digest("hex") === proof.executableSha256 && skillsCli.receipt.sha256 === proof.executableSha256, "RECONCILE_RELEASE_EXECUTABLE_CHANGED");
116150
116549
  const members2 = [["package/package.json", manifest], ["package/bin/index.js", readFileSync43(skillsCli.receipt.path)]];
@@ -116161,26 +116560,26 @@ function verifyReleaseArtifact(proof, skillsCli) {
116161
116560
  async function reconcileCodexNativeHooks(options, connect = connectCodexHookRpc) {
116162
116561
  let rpc;
116163
116562
  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);
116563
+ const home = resolve33(options.home ?? homedir13()), dataDir3 = resolve33(options.dataDir ?? getDataDirReadOnly());
116564
+ const parent = resolve33(join67(dataDir3, "native-hook-trust")), journal = resolve33(options.journal);
116166
116565
  need6(journal.startsWith(parent + "/") && /^[a-f0-9-]{36}$/.test(journal.slice(parent.length + 1)), "RECONCILE_JOURNAL_PATH");
116167
- const dir = lstatSync37(journal, { throwIfNoEntry: false });
116566
+ const dir = lstatSync38(journal, { throwIfNoEntry: false });
116168
116567
  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);
116568
+ need6(!lstatSync38(join67(journal, "receipt.json"), { throwIfNoEntry: false }), "RECONCILE_ALREADY_COMPLETE");
116569
+ need6(lstatSync38(join67(journal, "stopped.json"), { throwIfNoEntry: false })?.isFile(), "RECONCILE_JOURNAL_INCOMPLETE");
116570
+ const stoppedFile = snapshot(join67(journal, "stopped.json"), true);
116571
+ const intentFile = snapshot(join67(journal, "intent.json"), true), intent = JSON.parse(intentFile.text);
116572
+ 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
116573
  const legacyIntent = intent.home === undefined && intent.configSha256 === undefined && intent.configVersion === undefined && intent.declarations === undefined && intent.admitted === undefined && intent.nativeHooks === undefined;
116175
116574
  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 }));
116575
+ 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
116576
  const admitted = intent.admitted ?? intent.hooks;
116178
116577
  const configSha256 = intent.configSha256 ?? configBefore.sha256, configVersion = intent.configVersion ?? intent.expectedVersion;
116179
116578
  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
116579
  need6(makePlanDigest(digestInput) === intent.planDigest, "RECONCILE_PLAN_CHANGED");
116181
116580
  need6(isDeepStrictEqual17(intent.hooks, admitted.filter((hook) => !hook.enabled || hook.trustStatus !== "trusted")), "RECONCILE_INTENT_HOOKS_CHANGED");
116182
116581
  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);
116582
+ const policyCurrent = snapshot(join67(dataDir3, "agent-policy.json"), true);
116184
116583
  const { claudeDiscoveryRecovery: claudeRecovery, nativeHookAdditionsRecovery: additionsRecovery } = options;
116185
116584
  const recovery = claudeRecovery ?? additionsRecovery;
116186
116585
  need6(!recovery || !options.supersedeBinding, "RECONCILE_RECOVERY_MODE_CONFLICT");
@@ -116197,17 +116596,17 @@ async function reconcileCodexNativeHooks(options, connect = connectCodexHookRpc)
116197
116596
  if (supersededBinding || recovery) {
116198
116597
  need6(Array.isArray(intent.nativeHooks) && intent.nativeHooks.length > 0, "RECONCILE_NATIVE_INVENTORY_REQUIRED");
116199
116598
  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");
116599
+ 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
116600
  }
116202
116601
  const currentConfig = snapshot(intent.configPath, true);
116203
116602
  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");
116603
+ const alias = binding.rootAliases?.find((item) => item.agent === "codex"), physicalRoot = alias?.target ?? join67(home, ".codex"), hooksPath = join67(physicalRoot, "hooks.json");
116604
+ need6(resolve33(intent.configPath) === resolve33(join67(physicalRoot, "config.toml")), "RECONCILE_CONFIG_PATH_CHANGED");
116206
116605
  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);
116606
+ need6([join67(home, ".codex/config.toml"), join67(physicalRoot, "config.toml")].includes(nativeConfigPath), "RECONCILE_NATIVE_CONFIG_PATH_CHANGED");
116607
+ const codexHome = nativeConfigPath !== intent.configPath ? undefined : dirname39(nativeConfigPath);
116209
116608
  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;
116609
+ 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
116610
  const managedHooks = [...intent.hooks, ...additions?.hooks ?? []];
116212
116611
  const managedKeys = managedHooks.map((h) => h.key);
116213
116612
  const witnessSame = codexTrustReconcileWitness(configBefore.text, managedKeys) === codexTrustReconcileWitness(currentConfig.text, managedKeys);
@@ -116271,7 +116670,7 @@ async function reconcileCodexNativeHooks(options, connect = connectCodexHookRpc)
116271
116670
  need6(isDeepStrictEqual17(actual, expected), "RECONCILE_UNRELATED_HOOK_CHANGED");
116272
116671
  }
116273
116672
  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));
116673
+ const matches2 = nativeHooks.filter((h2) => h2.key === wanted.key || h2.key === wanted.key.replace(join67(home, ".codex/hooks.json"), hooksPath));
116275
116674
  need6(matches2.length === 1, "RECONCILE_NATIVE_IDENTITY_CHANGED");
116276
116675
  const h = matches2[0];
116277
116676
  const trusted = h.trustStatus === "trusted";
@@ -116320,7 +116719,7 @@ async function reconcileCodexNativeHooks(options, connect = connectCodexHookRpc)
116320
116719
  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
116720
  if (preview2)
116322
116721
  return receipt;
116323
- save(join66(journal, "receipt.json"), json2(receipt));
116722
+ save(join67(journal, "receipt.json"), json2(receipt));
116324
116723
  return receipt;
116325
116724
  } catch (error61) {
116326
116725
  const message = error61 instanceof Error && error61.message.startsWith("CODEX_HOOK_TRUST_") ? error61.message : "CODEX_HOOK_TRUST_RECONCILE_REFUSED";
@@ -116330,21 +116729,21 @@ async function reconcileCodexNativeHooks(options, connect = connectCodexHookRpc)
116330
116729
  }
116331
116730
  }
116332
116731
  async function enrollCodexNativeHooks(options = {}, connect = connectCodexHookRpc) {
116333
- const home = resolve32(options.home ?? homedir12());
116334
- return withCodexCorpusWriteAsync([join66(home, ".codex")], () => enrollCodexNativeHooksUnlocked(options, connect), options);
116732
+ const home = resolve33(options.home ?? homedir13());
116733
+ return withCodexCorpusWriteAsync([join67(home, ".codex")], () => enrollCodexNativeHooksUnlocked(options, connect), options);
116335
116734
  }
116336
116735
  async function enrollCodexNativeHooksUnlocked(options, connect) {
116337
116736
  let rpc, journal;
116338
116737
  try {
116339
- const home = resolve32(options.home ?? homedir12()), dataDir3 = resolve32(options.dataDir ?? getDataDirReadOnly());
116738
+ const home = resolve33(options.home ?? homedir13()), dataDir3 = resolve33(options.dataDir ?? getDataDirReadOnly());
116340
116739
  assertManagedAgentBridge("codex", { home, dataDir: dataDir3, projectDir: home });
116341
- const policyFile = snapshot(join66(dataDir3, "agent-policy.json"), true), policy = parseManagedSkillPolicy(policyFile.text);
116740
+ const policyFile = snapshot(join67(dataDir3, "agent-policy.json"), true), policy = parseManagedSkillPolicy(policyFile.text);
116342
116741
  const binding = policy.bridge, alias = binding.rootAliases?.find((item) => item.agent === "codex");
116343
116742
  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");
116743
+ const physicalRoot = alias?.target ?? join67(home, ".codex"), hooksPath = join67(physicalRoot, "hooks.json"), configPath = join67(physicalRoot, "config.toml");
116744
+ need6(options.codexHome === undefined || isAbsolute35(options.codexHome) && [join67(home, ".codex"), physicalRoot].includes(options.codexHome), "NATIVE_HOME_NOT_ADMITTED");
116346
116745
  const codexHome = options.codexHome === undefined ? undefined : physicalRoot;
116347
- const nativeConfigPath = join66(codexHome ?? join66(home, ".codex"), "config.toml");
116746
+ const nativeConfigPath = join67(codexHome ?? join67(home, ".codex"), "config.toml");
116348
116747
  const hooksFile = snapshot(hooksPath), configFile = snapshot(configPath, true), original = structure3(configFile.text);
116349
116748
  const declarations = JSON.parse(hooksFile.text).hooks, expected = [];
116350
116749
  for (const [event, [nativeEvent, label]] of Object.entries(eventNames)) {
@@ -116353,25 +116752,25 @@ async function enrollCodexNativeHooksUnlocked(options, connect) {
116353
116752
  need6(Array.isArray(groups), "DECLARATION_CHANGED");
116354
116753
  const matches2 = groups.flatMap((group, gi) => (group.hooks ?? []).flatMap((entry, hi) => entry.command === command ? [{ group, entry, gi, hi }] : []));
116355
116754
  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 });
116755
+ expected.push({ event: nativeEvent, key: `${join67(home, ".codex/hooks.json")}:${label}:${matches2[0].gi}:${matches2[0].hi}`, command });
116357
116756
  }
116358
116757
  codexTrustTextWitness(configFile.text, expected.map((h) => h.key));
116359
116758
  rpc = await connect({ command: options.codexCommand ?? "codex", home, codexHome });
116360
116759
  need6(SUPPORTED_CODEX_HOOK_VERSIONS.includes(rpc.version), "NATIVE_UNSUPPORTED_VERSION");
116361
116760
  const list2 = async () => {
116362
116761
  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`));
116762
+ const nativeRoots = [...new Set([physicalRoot, join67(home, ".codex")])];
116763
+ 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
116764
  const entry = response?.data?.[0];
116366
116765
  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
116766
  return response.data[0].hooks;
116368
116767
  };
116369
116768
  const admit = (hooks) => expected.map((wanted) => {
116370
- const canonicalKey = wanted.key.replace(join66(home, ".codex/hooks.json"), hooksPath);
116769
+ const canonicalKey = wanted.key.replace(join67(home, ".codex/hooks.json"), hooksPath);
116371
116770
  const matches2 = hooks.filter((h2) => h2.key === wanted.key || h2.key === canonicalKey);
116372
116771
  need6(matches2.length === 1, "AMBIGUOUS_IDENTITY");
116373
116772
  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");
116773
+ 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
116774
  need6(hooks.filter((other) => other.command === wanted.command).length === 1, "AMBIGUOUS_IDENTITY");
116376
116775
  need6(["trusted", "untrusted", "modified"].includes(h.trustStatus), "UNKNOWN_TRUST_STATUS");
116377
116776
  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 +116796,27 @@ async function enrollCodexNativeHooksUnlocked(options, connect) {
116397
116796
  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
116797
  if (options.apply)
116399
116798
  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 });
116799
+ const parent = join67(dataDir3, "native-hook-trust");
116800
+ const st = lstatSync38(parent, { throwIfNoEntry: false });
116402
116801
  if (st) {
116403
116802
  need6(st.isDirectory() && !st.isSymbolicLink() && st.uid === process.getuid() && (st.mode & 511) === 448, "UNSAFE_JOURNAL");
116404
116803
  const priorJournals = readdirSync23(parent);
116405
116804
  need6(priorJournals.length < 1000, "JOURNAL_BOUND");
116406
116805
  for (const name of priorJournals) {
116407
116806
  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");
116807
+ need6(lstatSync38(join67(parent, name, "receipt.json"), { throwIfNoEntry: false })?.isFile(), "RECONCILE_REQUIRED: inspect the incomplete private journal before applying again");
116409
116808
  }
116410
116809
  }
116411
116810
  if (!options.apply || !planned.length)
116412
116811
  return baseReceipt;
116413
116812
  if (!st)
116414
116813
  mkdirSync28(parent, { mode: 448 });
116415
- journal = join66(parent, randomUUID12());
116814
+ journal = join67(parent, randomUUID12());
116416
116815
  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) }));
116816
+ save(join67(journal, "config.before.toml"), configFile.bytes);
116817
+ save(join67(journal, "hooks.before.json"), hooksFile.bytes);
116818
+ save(join67(journal, "policy.before.json"), policyFile.bytes);
116819
+ save(join67(journal, "intent.json"), json2({ ...digestInput, planDigest, hooks: planned, nativeHooks: discovered.map(safeNativeHook) }));
116421
116820
  need6(isDeepStrictEqual17(admit(await list2()), admitted), "NATIVE_DISCOVERY_CHANGED");
116422
116821
  checkInputs();
116423
116822
  let result2;
@@ -116433,7 +116832,7 @@ async function enrollCodexNativeHooksUnlocked(options, connect) {
116433
116832
  for (const h of planned)
116434
116833
  expectedConfig.hooks.state[h.key] = { ...expectedConfig.hooks.state[h.key], enabled: true, trusted_hash: h.currentHash };
116435
116834
  need6(isDeepStrictEqual17(structure3(after2.text), expectedConfig) && codexTrustTextWitness(after2.text, keys3) === preservationText, "PRESERVATION_FAILED");
116436
- const savedConfig = snapshot(join66(journal, "config.before.toml"), true);
116835
+ const savedConfig = snapshot(join67(journal, "config.before.toml"), true);
116437
116836
  need6(savedConfig.sha256 === configFile.sha256, "JOURNAL_CHANGED");
116438
116837
  const discoveryTransition = binding.discovery?.codex ? createCodexHookDiscoveryRecovery(binding.discovery.codex, savedConfig, after2, planned) : undefined;
116439
116838
  unchanged2(policyFile);
@@ -116449,13 +116848,13 @@ async function enrollCodexNativeHooksUnlocked(options, connect) {
116449
116848
  skillsCli.recheck();
116450
116849
  assertManagedAgentBridge("codex", { home, dataDir: dataDir3, projectDir: home, codexDiscoveryRecovery: discoveryTransition });
116451
116850
  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));
116851
+ save(join67(journal, "receipt.json"), json2(receipt));
116453
116852
  return receipt;
116454
116853
  } catch (error61) {
116455
116854
  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
116855
  if (journal) {
116457
116856
  try {
116458
- save(join66(journal, "stopped.json"), json2({ error: message.split(":")[0], automaticRollback: false, reconcileBeforeRetry: true }));
116857
+ save(join67(journal, "stopped.json"), json2({ error: message.split(":")[0], automaticRollback: false, reconcileBeforeRetry: true }));
116459
116858
  } catch {}
116460
116859
  }
116461
116860
  throw new Error(message);
@@ -116490,7 +116889,7 @@ var init_agent_codex_trust = __esm(() => {
116490
116889
  // src/lib/codex-native-trust.ts
116491
116890
  import { createHash as createHash40 } from "crypto";
116492
116891
  import { readFileSync as readFileSync44 } from "fs";
116493
- import { join as join67, resolve as resolve33 } from "path";
116892
+ import { join as join68, resolve as resolve34 } from "path";
116494
116893
  function refuse5(detail) {
116495
116894
  throw new Error(`NATIVE_SKILL_POLICY_TRUST_REFUSED: ${detail}`);
116496
116895
  }
@@ -116509,7 +116908,7 @@ function planCodexNativeTrust(options) {
116509
116908
  refuse5("digests must be unique");
116510
116909
  if (typeof expectedPolicySha256 !== "string" || !HEX_DIGEST2.test(expectedPolicySha256))
116511
116910
  refuse5("--expected-policy-sha256 must be lowercase SHA-256 hex");
116512
- const dataDir3 = resolve33(options.dataDir ?? getDataDirReadOnly()), policyPath = join67(dataDir3, "agent-policy.json");
116911
+ const dataDir3 = resolve34(options.dataDir ?? getDataDirReadOnly()), policyPath = join68(dataDir3, "agent-policy.json");
116513
116912
  assertOperatorTrustRoot(dataDir3);
116514
116913
  const snapshot2 = readManagedSkillPolicySnapshot(dataDir3);
116515
116914
  if (!snapshot2)
@@ -116692,8 +117091,8 @@ var init_hook_diagnostics = __esm(() => {
116692
117091
 
116693
117092
  // src/lib/claude-prospective-review.ts
116694
117093
  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";
117094
+ import { lstatSync as lstatSync39, readFileSync as readFileSync45, readdirSync as readdirSync24, realpathSync as realpathSync21 } from "fs";
117095
+ 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
117096
  import { isDeepStrictEqual as isDeepStrictEqual18 } from "util";
116698
117097
  function hashClaudeDiscoveryBinding(binding) {
116699
117098
  return sha7(JSON.stringify(binding));
@@ -116744,7 +117143,7 @@ function keys3(value, expected, name) {
116744
117143
  refuse6(`${name} has an unsupported shape`);
116745
117144
  }
116746
117145
  function abs(path, name) {
116747
- if (typeof path !== "string" || !path || path.length > 4096 || /[\x00-\x1f\x7f]/.test(path) || !isAbsolute35(path) || resolve34(path) !== path)
117146
+ if (typeof path !== "string" || !path || path.length > 4096 || /[\x00-\x1f\x7f]/.test(path) || !isAbsolute36(path) || resolve35(path) !== path)
116748
117147
  refuse6(`${name} must be a normalized absolute path`);
116749
117148
  }
116750
117149
  function validUtcTimestamp(value) {
@@ -116752,27 +117151,27 @@ function validUtcTimestamp(value) {
116752
117151
  }
116753
117152
  function safeFile(path, name) {
116754
117153
  abs(path, name);
116755
- for (let at2 = dirname39(path);; at2 = dirname39(at2)) {
116756
- const stat4 = lstatSync38(at2, { throwIfNoEntry: false });
117154
+ for (let at2 = dirname40(path);; at2 = dirname40(at2)) {
117155
+ const stat4 = lstatSync39(at2, { throwIfNoEntry: false });
116757
117156
  if (!stat4?.isDirectory() || stat4.isSymbolicLink())
116758
117157
  refuse6(`${name} traverses a symlink or non-directory`);
116759
- if (at2 === dirname39(at2))
117158
+ if (at2 === dirname40(at2))
116760
117159
  break;
116761
117160
  }
116762
- const stat3 = lstatSync38(path, { throwIfNoEntry: false });
117161
+ const stat3 = lstatSync39(path, { throwIfNoEntry: false });
116763
117162
  if (!stat3?.isFile() || stat3.isSymbolicLink() || stat3.size > MAX_CANDIDATE_BYTES)
116764
117163
  refuse6(`${name} is not a bounded regular file`);
116765
117164
  return readFileSync45(path);
116766
117165
  }
116767
117166
  function canonicalDir(path, name) {
116768
117167
  abs(path, name);
116769
- if (realpathSync21(path) !== path || !lstatSync38(path).isDirectory())
117168
+ if (realpathSync21(path) !== path || !lstatSync39(path).isDirectory())
116770
117169
  refuse6(`${name} is not a canonical directory`);
116771
- for (let at2 = path;; at2 = dirname39(at2)) {
116772
- const stat3 = lstatSync38(at2);
117170
+ for (let at2 = path;; at2 = dirname40(at2)) {
117171
+ const stat3 = lstatSync39(at2);
116773
117172
  if (!stat3.isDirectory() || stat3.isSymbolicLink())
116774
117173
  refuse6(`${name} traverses a symlink`);
116775
- if (at2 === dirname39(at2))
117174
+ if (at2 === dirname40(at2))
116776
117175
  break;
116777
117176
  }
116778
117177
  }
@@ -116781,17 +117180,17 @@ function captureClaudeProspectiveCandidateClosure(root2) {
116781
117180
  const entries = [];
116782
117181
  let bytes = 0;
116783
117182
  const walk2 = (directory2) => {
116784
- const beforeDirectory = lstatSync38(directory2);
117183
+ const beforeDirectory = lstatSync39(directory2);
116785
117184
  const names = readdirSync24(directory2).sort();
116786
117185
  if (new Set(names).size !== names.length)
116787
117186
  refuse6("candidate contains ambiguous directory entries");
116788
117187
  for (const name of names) {
116789
117188
  if (!name || name === "." || name === ".." || name.includes("/") || name.includes("\\") || /[\x00-\x1f\x7f]/.test(name))
116790
117189
  refuse6("candidate contains an unsupported path member");
116791
- const path = join68(directory2, name), rel = relative12(root2, path).split(sep15).join("/");
117190
+ const path = join69(directory2, name), rel = relative12(root2, path).split(sep15).join("/");
116792
117191
  if (entries.length >= MAX_CANDIDATE_FILES)
116793
117192
  refuse6("candidate closure exceeds its member limit");
116794
- const stat3 = lstatSync38(path);
117193
+ const stat3 = lstatSync39(path);
116795
117194
  if (stat3.isSymbolicLink())
116796
117195
  refuse6("candidate closure contains a symlink");
116797
117196
  if (stat3.isDirectory()) {
@@ -116801,14 +117200,14 @@ function captureClaudeProspectiveCandidateClosure(root2) {
116801
117200
  bytes += stat3.size;
116802
117201
  if (bytes > MAX_CANDIDATE_BYTES)
116803
117202
  refuse6("candidate closure exceeds its byte limit");
116804
- const content = safeFile(path, "candidate member"), after2 = lstatSync38(path);
117203
+ const content = safeFile(path, "candidate member"), after2 = lstatSync39(path);
116805
117204
  if (!after2.isFile() || after2.dev !== stat3.dev || after2.ino !== stat3.ino || after2.size !== stat3.size || after2.mtimeMs !== stat3.mtimeMs || after2.ctimeMs !== stat3.ctimeMs)
116806
117205
  refuse6("candidate member changed while being read");
116807
117206
  entries.push([rel, "file", sha7(content)]);
116808
117207
  } else
116809
117208
  refuse6("candidate closure contains a special file");
116810
117209
  }
116811
- const afterDirectory = lstatSync38(directory2);
117210
+ const afterDirectory = lstatSync39(directory2);
116812
117211
  if (!afterDirectory.isDirectory() || afterDirectory.dev !== beforeDirectory.dev || afterDirectory.ino !== beforeDirectory.ino || afterDirectory.mtimeMs !== beforeDirectory.mtimeMs || afterDirectory.ctimeMs !== beforeDirectory.ctimeMs)
116813
117212
  refuse6("candidate directory changed while being read");
116814
117213
  };
@@ -116819,9 +117218,9 @@ function captureClaudeProspectiveCandidateClosure(root2) {
116819
117218
  function captureClaudeInstallerCandidate(root2, policyPath) {
116820
117219
  const closureSha256 = captureClaudeProspectiveCandidateClosure(root2);
116821
117220
  const dataDir3 = getDataDirReadOnly();
116822
- if (policyPath !== join68(dataDir3, "agent-policy.json"))
117221
+ if (policyPath !== join69(dataDir3, "agent-policy.json"))
116823
117222
  refuse6("Skills policy path differs from the package-owned resolver");
116824
- const catalogPath = join68(root2, ".claude-plugin/marketplace.json");
117223
+ const catalogPath = join69(root2, ".claude-plugin/marketplace.json");
116825
117224
  const catalog = jsonFile(catalogPath, "candidate catalog");
116826
117225
  if (!catalog || !Array.isArray(catalog.plugins))
116827
117226
  refuse6("candidate catalog is invalid");
@@ -116832,13 +117231,13 @@ function captureClaudeInstallerCandidate(root2, policyPath) {
116832
117231
  if (names.has(row2.name))
116833
117232
  refuse6("candidate catalog repeats a plugin name");
116834
117233
  names.add(row2.name);
116835
- if (typeof row2.source !== "string" || isAbsolute35(row2.source) || /[\\\x00-\x1f\x7f]/.test(row2.source))
117234
+ if (typeof row2.source !== "string" || isAbsolute36(row2.source) || /[\\\x00-\x1f\x7f]/.test(row2.source))
116836
117235
  refuse6("candidate catalog plugin source is invalid");
116837
- const pluginRoot = resolve34(root2, row2.source);
117236
+ const pluginRoot = resolve35(root2, row2.source);
116838
117237
  const relativeRoot = relative12(root2, pluginRoot);
116839
- if (!relativeRoot || relativeRoot === "." || relativeRoot === ".." || relativeRoot.startsWith(`..${sep15}`) || isAbsolute35(relativeRoot))
117238
+ if (!relativeRoot || relativeRoot === "." || relativeRoot === ".." || relativeRoot.startsWith(`..${sep15}`) || isAbsolute36(relativeRoot))
116840
117239
  refuse6("candidate plugin source escapes the candidate root");
116841
- const path = join68(pluginRoot, ".claude-plugin/plugin.json");
117240
+ const path = join69(pluginRoot, ".claude-plugin/plugin.json");
116842
117241
  return { plugin: row2.name, ...captureClaudePluginManifestFile(path) };
116843
117242
  });
116844
117243
  const policy = readManagedSkillPolicySnapshot(dataDir3);
@@ -116855,7 +117254,7 @@ function captureClaudeInstallerCandidate(root2, policyPath) {
116855
117254
  }
116856
117255
  function readWitness(path, expected, name) {
116857
117256
  abs(path, `${name} path`);
116858
- const stat3 = lstatSync38(path, { throwIfNoEntry: false });
117257
+ const stat3 = lstatSync39(path, { throwIfNoEntry: false });
116859
117258
  if (expected === null) {
116860
117259
  if (stat3)
116861
117260
  refuse6(`${name} was absent at review but is now present`);
@@ -116867,7 +117266,7 @@ function readWitness(path, expected, name) {
116867
117266
  refuse6(`${name} preimage changed`);
116868
117267
  }
116869
117268
  function jsonFile(path, name) {
116870
- const stat3 = lstatSync38(path, { throwIfNoEntry: false });
117269
+ const stat3 = lstatSync39(path, { throwIfNoEntry: false });
116871
117270
  if (!stat3)
116872
117271
  return null;
116873
117272
  let value;
@@ -116898,8 +117297,8 @@ function assertNoUnprojectedSkillPayload(root2, catalogPath, marketplace, plugin
116898
117297
  refuse6("candidate marketplace entry declares native skill or command payloads");
116899
117298
  const walk2 = (directory2) => {
116900
117299
  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);
117300
+ const path = join69(directory2, name), rel = relative12(root2, path).split(sep15).join("/");
117301
+ const stat3 = lstatSync39(path);
116903
117302
  if (stat3.isDirectory())
116904
117303
  walk2(path);
116905
117304
  else if (stat3.isFile()) {
@@ -116956,16 +117355,16 @@ function reviewClaudeProspectiveCandidate(request2, requestFileSha256) {
116956
117355
  refuse6("Skills policy root alias changed or is invalid");
116957
117356
  }
116958
117357
  const canonical8 = (path) => canonicalAgentPath(path, aliases);
116959
- const configRoot = canonical8(join68(request2.native.home, ".claude"));
117358
+ const configRoot = canonical8(join69(request2.native.home, ".claude"));
116960
117359
  canonicalDir(configRoot, "Claude config root");
116961
117360
  if (request2.native.configRoot !== configRoot)
116962
117361
  refuse6("Claude config root differs from the current resolver and reviewed root alias");
116963
- const pluginRoot = join68(configRoot, "plugins");
117362
+ const pluginRoot = join69(configRoot, "plugins");
116964
117363
  if (process.env.CLAUDE_CODE_PLUGIN_CACHE_DIR)
116965
117364
  refuse6("CLAUDE_CODE_PLUGIN_CACHE_DIR overrides are unsupported by this prospective schema; bind and review the actual cache root first");
116966
117365
  if (request2.native.pluginRoot !== pluginRoot)
116967
117366
  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 });
117367
+ const pluginRootStat = lstatSync39(pluginRoot, { throwIfNoEntry: false });
116969
117368
  if (pluginRootStat && (!pluginRootStat.isDirectory() || pluginRootStat.isSymbolicLink()))
116970
117369
  refuse6("Claude plugin root is not a regular directory");
116971
117370
  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 +117381,7 @@ function reviewClaudeProspectiveCandidate(request2, requestFileSha256) {
116982
117381
  abs(candidate2.catalogPath, "catalog path");
116983
117382
  if (!candidate2.catalogPath.startsWith(candidate2.root + sep15))
116984
117383
  refuse6("catalog must be inside the frozen candidate root");
116985
- if (candidate2.catalogPath !== join68(candidate2.root, ".claude-plugin", "marketplace.json"))
117384
+ if (candidate2.catalogPath !== join69(candidate2.root, ".claude-plugin", "marketplace.json"))
116986
117385
  refuse6("marketplace catalog must be at the frozen root's .claude-plugin/marketplace.json path");
116987
117386
  if (!SHA256.test(candidate2.catalogSha256) || !SHA256.test(candidate2.closureSha256))
116988
117387
  refuse6("candidate digests must be lowercase SHA-256");
@@ -117024,11 +117423,11 @@ function reviewClaudeProspectiveCandidate(request2, requestFileSha256) {
117024
117423
  if (Buffer.byteLength(canonicalJson3(selected.optionsPatch), "utf8") > 16 * 1024)
117025
117424
  refuse6("selected plugin optionsPatch exceeds its byte bound");
117026
117425
  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"))
117426
+ 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
117427
  refuse6("plugin manifest must be under a plugin root inside the frozen marketplace closure");
117029
- const pluginRoot2 = dirname39(dirname39(selected.manifestPath));
117428
+ const pluginRoot2 = dirname40(dirname40(selected.manifestPath));
117030
117429
  const relativePluginRoot = relative12(candidate2.root, pluginRoot2);
117031
- if (!relativePluginRoot || relativePluginRoot === "." || relativePluginRoot === ".." || relativePluginRoot.startsWith(`..${sep15}`) || isAbsolute35(relativePluginRoot))
117430
+ if (!relativePluginRoot || relativePluginRoot === "." || relativePluginRoot === ".." || relativePluginRoot.startsWith(`..${sep15}`) || isAbsolute36(relativePluginRoot))
117032
117431
  refuse6("plugin root must be a child of the frozen marketplace root");
117033
117432
  canonicalDir(pluginRoot2, "candidate plugin root");
117034
117433
  if (!SHA256.test(selected.manifestSha256))
@@ -117062,7 +117461,7 @@ function reviewClaudeProspectiveCandidate(request2, requestFileSha256) {
117062
117461
  const sourcePath = selectedEntry.source;
117063
117462
  const sourceRelativePath = relative12(candidate2.root, pluginRoot2).split(sep15).join("/");
117064
117463
  const expectedSourcePath = sourceRelativePath === "." ? "./" : `./${sourceRelativePath}`;
117065
- if (typeof sourcePath !== "string" || isAbsolute35(sourcePath) || sourcePath !== expectedSourcePath || resolve34(dirname39(dirname39(candidate2.catalogPath)), sourcePath) !== pluginRoot2)
117464
+ if (typeof sourcePath !== "string" || isAbsolute36(sourcePath) || sourcePath !== expectedSourcePath || resolve35(dirname40(dirname40(candidate2.catalogPath)), sourcePath) !== pluginRoot2)
117066
117465
  refuse6("marketplace source does not resolve to the frozen plugin closure; external source mapping is not supported by this schema");
117067
117466
  const entry = captureClaudeMarketplaceEntry(candidate2.catalogPath, candidate2.marketplace, selected.plugin);
117068
117467
  if (entry.sha256.length !== 64)
@@ -117082,12 +117481,12 @@ function reviewClaudeProspectiveCandidate(request2, requestFileSha256) {
117082
117481
  for (const name of ["settings", "projectSettings", "projectSettingsLocal", "marketplaces", "installedPlugins"])
117083
117482
  keys3(request2.preimages[name], ["path", "sha256"], `${name} preimage`);
117084
117483
  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"))
117484
+ settings: request2.scope.kind === "project" ? canonical8(join69(request2.scope.projectPath, ".claude/settings.json")) : canonical8(join69(request2.native.home, ".claude/settings.json")),
117485
+ userSettings: canonical8(join69(request2.native.home, ".claude/settings.json")),
117486
+ projectSettings: canonical8(join69(request2.scope.projectPath, ".claude/settings.json")),
117487
+ projectSettingsLocal: canonical8(join69(request2.scope.projectPath, ".claude/settings.local.json")),
117488
+ marketplaces: canonical8(join69(request2.native.home, ".claude/plugins/known_marketplaces.json")),
117489
+ installedPlugins: canonical8(join69(request2.native.home, ".claude/plugins/installed_plugins.json"))
117091
117490
  };
117092
117491
  for (const name of Object.keys(expectedPaths)) {
117093
117492
  const witness = request2.preimages[name];
@@ -117205,7 +117604,7 @@ function reviewClaudeProspectiveCandidate(request2, requestFileSha256) {
117205
117604
  const manifestVersion = manifest.version;
117206
117605
  const sanitizeComponent = (value) => value.replace(/[^A-Za-z0-9_-]/g, "-");
117207
117606
  const sanitizedVersion = manifestVersion === "." || manifestVersion === ".." ? "-" : manifestVersion.replace(/[^A-Za-z0-9._-]/g, "-");
117208
- const expectedInstallPath = join68(pluginRoot, "cache", sanitizeComponent(candidate2.marketplace), sanitizeComponent(plugin), sanitizedVersion);
117607
+ const expectedInstallPath = join69(pluginRoot, "cache", sanitizeComponent(candidate2.marketplace), sanitizeComponent(plugin), sanitizedVersion);
117209
117608
  if (expectedInstallPath.length > 4096)
117210
117609
  refuse6("candidate native cache path exceeds its bound");
117211
117610
  const targetRegistration = {
@@ -117343,7 +117742,7 @@ function reviewClaudeProspectiveCandidate(request2, requestFileSha256) {
117343
117742
  { name: "project-settings-local", path: expectedPaths.projectSettingsLocal, sha256: request2.preimages.projectSettingsLocal.sha256 },
117344
117743
  { name: "known-marketplaces", path: expectedPaths.marketplaces, sha256: request2.preimages.marketplaces.sha256 },
117345
117744
  { 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 }
117745
+ { name: "skills-policy", path: join69(request2.skills.dataDir, "agent-policy.json"), sha256: request2.skills.policySha256 }
117347
117746
  ],
117348
117747
  ownedDelta: { settingsEnabledPlugins: selectedPluginIds, selectedPluginOptions: selectedOptionPaths, functionHooksEnv: candidate2.functionHooksEnv ?? null, knownMarketplace: candidate2.marketplace, installedPlugins: selectedPluginIds, unrelatedGraph: "preserved-by-complete-semantic-documents" },
117349
117748
  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 +117768,10 @@ var init_claude_prospective_review = __esm(() => {
117369
117768
 
117370
117769
  // src/lib/self-spawn.ts
117371
117770
  import { realpathSync as realpathSync22 } from "fs";
117372
- import { dirname as dirname40, isAbsolute as isAbsolute36, sep as sep16 } from "path";
117771
+ import { dirname as dirname41, isAbsolute as isAbsolute37, sep as sep16 } from "path";
117373
117772
  function selfSpawnRoot(entry) {
117374
117773
  const index = entry.indexOf(INSTALLED_PACKAGE);
117375
- const root2 = index > 0 ? entry.slice(0, index) : dirname40(entry);
117774
+ const root2 = index > 0 ? entry.slice(0, index) : dirname41(entry);
117376
117775
  try {
117377
117776
  return realpathSync22(root2);
117378
117777
  } catch {
@@ -117382,12 +117781,12 @@ function selfSpawnRoot(entry) {
117382
117781
  function selfSpawnCommand(args2, options = {}) {
117383
117782
  const runtime = options.runtime ?? process.execPath;
117384
117783
  const entry = options.entry ?? process.argv[1];
117385
- if (!runtime || !isAbsolute36(runtime) || !entry || !isAbsolute36(entry))
117784
+ if (!runtime || !isAbsolute37(runtime) || !entry || !isAbsolute37(entry))
117386
117785
  throw new Error("SKILLS_SELF_SPAWN_ENTRY_UNRESOLVED");
117387
117786
  const root2 = selfSpawnRoot(entry);
117388
117787
  const env3 = pinnedLauncherEnvironment(options.env ?? process.env);
117389
117788
  env3[LAUNCH_CWD_VARIABLE] = options.callerCwd ?? process.cwd();
117390
- return { command: [runtime, ...PINNED_LAUNCHER_BUN_FLAGS, `--cwd=${root2}`, entry, ...args2], cwd: root2, env: env3 };
117789
+ return { command: [runtime, ...PINNED_LAUNCHER_BUN_FLAGS2, `--cwd=${root2}`, entry, ...args2], cwd: root2, env: env3 };
117391
117790
  }
117392
117791
  var INSTALLED_PACKAGE;
117393
117792
  var init_self_spawn = __esm(() => {
@@ -117396,8 +117795,8 @@ var init_self_spawn = __esm(() => {
117396
117795
  });
117397
117796
 
117398
117797
  // 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";
117798
+ import { closeSync as closeSync26, constants as constants25, fstatSync as fstatSync26, lstatSync as lstatSync40, openSync as openSync26, readSync as readSync19 } from "fs";
117799
+ import { isAbsolute as isAbsolute38, resolve as resolve36 } from "path";
117401
117800
  function need8(condition, code2) {
117402
117801
  if (!condition)
117403
117802
  throw new CaptureRefusal(code2);
@@ -117411,14 +117810,14 @@ function exactKeys4(value, expected, operation) {
117411
117810
  }
117412
117811
  }
117413
117812
  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");
117813
+ 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
117814
  }
117416
117815
  function readRequest2(path) {
117417
117816
  canonicalPath2(path);
117418
- const before2 = lstatSync39(path, { throwIfNoEntry: false });
117817
+ const before2 = lstatSync40(path, { throwIfNoEntry: false });
117419
117818
  if (!before2?.isFile() || before2.isSymbolicLink() || before2.size > MAX_REQUEST_BYTES)
117420
117819
  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);
117820
+ const fd = openSync26(path, constants25.O_RDONLY | (constants25.O_NOFOLLOW ?? 0) | constants25.O_NONBLOCK);
117422
117821
  try {
117423
117822
  const opened = fstatSync26(fd);
117424
117823
  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 +117829,7 @@ function readRequest2(path) {
117430
117829
  break;
117431
117830
  length += count;
117432
117831
  }
117433
- const after2 = fstatSync26(fd), current = lstatSync39(path);
117832
+ const after2 = fstatSync26(fd), current = lstatSync40(path);
117434
117833
  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
117834
  try {
117436
117835
  return JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(bytes.subarray(0, length)));
@@ -117562,10 +117961,10 @@ var exports_agent_integration = {};
117562
117961
  __export(exports_agent_integration, {
117563
117962
  registerAgentIntegration: () => registerAgentIntegration
117564
117963
  });
117565
- import { existsSync as existsSync36, lstatSync as lstatSync40, readFileSync as readFileSync46, readSync as readSync20, writeFileSync as writeFileSync27 } from "fs";
117964
+ import { existsSync as existsSync36, lstatSync as lstatSync41, readFileSync as readFileSync46, readSync as readSync20, writeFileSync as writeFileSync27 } from "fs";
117566
117965
  import { createHash as createHash42 } from "crypto";
117567
- import { homedir as homedir13 } from "os";
117568
- import { isAbsolute as isAbsolute38 } from "path";
117966
+ import { homedir as homedir14 } from "os";
117967
+ import { isAbsolute as isAbsolute39 } from "path";
117569
117968
  function pinnedHookProfile(input3, configuredProfile) {
117570
117969
  try {
117571
117970
  const parsed = parseSkillContextInput(JSON.stringify(input3));
@@ -117661,13 +118060,13 @@ function registerAgentIntegration(parent) {
117661
118060
  });
117662
118061
  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
118062
  try {
117664
- if (!isAbsolute38(options.cwd) || !isAbsolute38(options.output))
118063
+ if (!isAbsolute39(options.cwd) || !isAbsolute39(options.output))
117665
118064
  throw new Error("CODEX_NATIVE_SKILL_CATALOG_ABSOLUTE_PATH_REQUIRED");
117666
118065
  if (existsSync36(options.output))
117667
118066
  throw new Error("CODEX_NATIVE_SKILL_CATALOG_OUTPUT_EXISTS");
117668
118067
  const catalog = await captureCodexNativeSkillCatalog({
117669
118068
  command: options.codexCommand,
117670
- home: homedir13(),
118069
+ home: homedir14(),
117671
118070
  ...process.env.CODEX_HOME === undefined ? {} : { codexHome: process.env.CODEX_HOME },
117672
118071
  cwd: options.cwd
117673
118072
  });
@@ -117680,7 +118079,7 @@ function registerAgentIntegration(parent) {
117680
118079
  throw new Error("CODEX_NATIVE_SKILL_CATALOG_OUTPUT_EXISTS");
117681
118080
  throw error61;
117682
118081
  }
117683
- const written = lstatSync40(options.output);
118082
+ const written = lstatSync41(options.output);
117684
118083
  if (!written.isFile() || written.isSymbolicLink() || (written.mode & 63) !== 0 || readFileSync46(options.output, "utf8") !== bytes)
117685
118084
  throw new Error("CODEX_NATIVE_SKILL_CATALOG_READBACK_FAILED");
117686
118085
  const receipt = {
@@ -117728,9 +118127,9 @@ function registerAgentIntegration(parent) {
117728
118127
  });
117729
118128
  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
118129
  try {
117731
- if (!isAbsolute38(options.request))
118130
+ if (!isAbsolute39(options.request))
117732
118131
  throw new Error("CLAUDE_CANDIDATE_REVIEW_REFUSED: --request must be an absolute path");
117733
- const stat3 = lstatSync40(options.request);
118132
+ const stat3 = lstatSync41(options.request);
117734
118133
  if (!stat3.isFile() || stat3.isSymbolicLink() || stat3.size > 1024 * 1024)
117735
118134
  throw new Error("CLAUDE_CANDIDATE_REVIEW_REFUSED: request must be a regular file no larger than 1 MiB");
117736
118135
  const requestBytes = readFileSync46(options.request);
@@ -117775,10 +118174,10 @@ function registerAgentIntegration(parent) {
117775
118174
  hook.command("agents").option("--json", "Output the adapter capability inventory", false).description("Show maintained native adapters and explicit coverage limits").action(async () => {
117776
118175
  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
118176
  });
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) => {
118177
+ 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
118178
  try {
117780
118179
  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 });
118180
+ 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
118181
  const result2 = options.apply ? applyAgentIntegration(plan) : { changed: [], backups: [] };
117783
118182
  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
118183
  if (options.json)
@@ -117850,12 +118249,12 @@ function registerAgentIntegration(parent) {
117850
118249
  input3.hook_event_name = event;
117851
118250
  const projects = [process.cwd()];
117852
118251
  if (input3.cwd !== undefined) {
117853
- if (typeof input3.cwd !== "string" || !isAbsolute38(input3.cwd) || input3.cwd.includes("\x00"))
118252
+ if (typeof input3.cwd !== "string" || !isAbsolute39(input3.cwd) || input3.cwd.includes("\x00"))
117854
118253
  throw new Error("Invalid native hook working directory");
117855
118254
  projects.push(input3.cwd);
117856
118255
  }
117857
118256
  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")))
118257
+ 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
118258
  throw new Error("Invalid Cursor workspace roots");
117860
118259
  projects.push(...input3.workspace_roots);
117861
118260
  input3.cwd ??= input3.workspace_roots[0] ?? process.cwd();
@@ -117981,6 +118380,7 @@ var init_agent_integration2 = __esm(() => {
117981
118380
  init_agent_hermes();
117982
118381
  init_context();
117983
118382
  init_agent_adapters();
118383
+ init_agent_install_selection();
117984
118384
  init_agent_integration();
117985
118385
  init_agent_codex_trust();
117986
118386
  init_codex_native_skill_policy();
@@ -118133,9 +118533,9 @@ var exports_profiles = {};
118133
118533
  __export(exports_profiles, {
118134
118534
  registerProfiles: () => registerProfiles
118135
118535
  });
118136
- import { closeSync as closeSync27, constants as constants25, fstatSync as fstatSync27, openSync as openSync27, readSync as readSync21, writeFileSync as writeFileSync28 } from "fs";
118536
+ import { closeSync as closeSync27, constants as constants26, fstatSync as fstatSync27, openSync as openSync27, readSync as readSync21, writeFileSync as writeFileSync28 } from "fs";
118137
118537
  function readProfileInput(path) {
118138
- const fd = openSync27(path, constants25.O_RDONLY | constants25.O_NONBLOCK);
118538
+ const fd = openSync27(path, constants26.O_RDONLY | constants26.O_NONBLOCK);
118139
118539
  try {
118140
118540
  const stat3 = fstatSync27(fd);
118141
118541
  if (!stat3.isFile() || stat3.size > MAX_PROFILE_DOCUMENT_BYTES)
@@ -118203,7 +118603,7 @@ __export(exports_grants, {
118203
118603
  registerGrants: () => registerGrants
118204
118604
  });
118205
118605
  import {
118206
- constants as constants26,
118606
+ constants as constants27,
118207
118607
  closeSync as closeSync28,
118208
118608
  fstatSync as fstatSync28,
118209
118609
  openSync as openSync28,
@@ -118211,7 +118611,7 @@ import {
118211
118611
  writeFileSync as writeFileSync29
118212
118612
  } from "fs";
118213
118613
  function readInput(path) {
118214
- const fd = openSync28(path, constants26.O_RDONLY | constants26.O_NONBLOCK);
118614
+ const fd = openSync28(path, constants27.O_RDONLY | constants27.O_NONBLOCK);
118215
118615
  try {
118216
118616
  const stat3 = fstatSync28(fd);
118217
118617
  if (!stat3.isFile() || stat3.size > MAX_EXECUTION_GRANT_BYTES)
@@ -118274,19 +118674,19 @@ import {
118274
118674
  mkdirSync as mkdirSync29,
118275
118675
  readdirSync as readdirSync25,
118276
118676
  readFileSync as readFileSync47,
118277
- statSync as statSync23,
118677
+ statSync as statSync24,
118278
118678
  writeFileSync as writeFileSync30
118279
118679
  } from "fs";
118280
- import { dirname as dirname41, join as join69, resolve as resolve36, sep as sep17 } from "path";
118680
+ import { dirname as dirname42, join as join70, resolve as resolve37, sep as sep17 } from "path";
118281
118681
  function fail6(code2, message, detail = []) {
118282
118682
  throw new StationSnapshotError(code2, message, detail);
118283
118683
  }
118284
118684
  function snapshotRootFor(repoRoot, stationId) {
118285
- return join69(repoRoot, "resources", stationId, "skills");
118685
+ return join70(repoRoot, "resources", stationId, "skills");
118286
118686
  }
118287
118687
  function readSnapshotManifest(repoRoot, stationId) {
118288
118688
  const snapshotRoot = snapshotRootFor(repoRoot, stationId);
118289
- const manifestPath = join69(snapshotRoot, "sync-manifest.json");
118689
+ const manifestPath = join70(snapshotRoot, "sync-manifest.json");
118290
118690
  let manifest;
118291
118691
  try {
118292
118692
  manifest = JSON.parse(readFileSync47(manifestPath, "utf8"));
@@ -118313,7 +118713,7 @@ function planStationHydration(stationId, repoRoot) {
118313
118713
  const hashMismatches = [];
118314
118714
  const skippedByRule = [];
118315
118715
  for (const agent of SYNC_AGENTS) {
118316
- const agentRoot = join69(snapshotRoot, "agent-homes", agent);
118716
+ const agentRoot = join70(snapshotRoot, "agent-homes", agent);
118317
118717
  let identEntries;
118318
118718
  try {
118319
118719
  identEntries = readdirSync25(agentRoot, { withFileTypes: true });
@@ -118324,7 +118724,7 @@ function planStationHydration(stationId, repoRoot) {
118324
118724
  if (!identEntry.isDirectory() || identEntry.name.startsWith(".")) {
118325
118725
  continue;
118326
118726
  }
118327
- const identRoot = join69(agentRoot, identEntry.name);
118727
+ const identRoot = join70(agentRoot, identEntry.name);
118328
118728
  const entries = walkEntries(identRoot);
118329
118729
  for (const entry of entries) {
118330
118730
  const relativeParts = [identEntry.name, ...entry.relativePath.split(sep17)];
@@ -118371,7 +118771,7 @@ function planStationHydration(stationId, repoRoot) {
118371
118771
  });
118372
118772
  continue;
118373
118773
  }
118374
- const info = statSync23(entry.fullPath);
118774
+ const info = statSync24(entry.fullPath);
118375
118775
  const manifestHash = manifestHashes.get(`${agent}${MANIFEST_HASH_KEY_SEP}${homeRelative}`) ?? null;
118376
118776
  let verified = false;
118377
118777
  if (manifestHash !== null) {
@@ -118475,8 +118875,8 @@ function skillSha256(skill) {
118475
118875
  `)).digest("hex");
118476
118876
  }
118477
118877
  function writeStationHydration(options) {
118478
- const repoRoot = resolve36(options.repoRoot ?? process.cwd());
118479
- const cacheRoot = resolve36(options.cacheRoot ?? resolveCorpusRoot());
118878
+ const repoRoot = resolve37(options.repoRoot ?? process.cwd());
118879
+ const cacheRoot = resolve37(options.cacheRoot ?? resolveCorpusRoot());
118480
118880
  const plan = planStationHydration(options.stationId, repoRoot);
118481
118881
  const resultSkills = plan.winners.map((skill) => ({
118482
118882
  ident: skill.ident,
@@ -118509,7 +118909,7 @@ function writeStationHydration(options) {
118509
118909
  const toWrite = [];
118510
118910
  for (const skill of plan.winners) {
118511
118911
  for (const file2 of skill.files) {
118512
- const destination = join69(cacheRoot, skill.ident, file2.withinIdent);
118912
+ const destination = join70(cacheRoot, skill.ident, file2.withinIdent);
118513
118913
  const digest4 = sha256File(file2.winner.fullPath);
118514
118914
  let existingDigest = null;
118515
118915
  try {
@@ -118530,7 +118930,7 @@ function writeStationHydration(options) {
118530
118930
  }
118531
118931
  let written = 0;
118532
118932
  for (const entry of toWrite) {
118533
- mkdirSync29(dirname41(entry.destination), { recursive: true });
118933
+ mkdirSync29(dirname42(entry.destination), { recursive: true });
118534
118934
  copyFileSync3(entry.fullPath, entry.destination);
118535
118935
  written += 1;
118536
118936
  }
@@ -118551,8 +118951,8 @@ function writeStationHydration(options) {
118551
118951
  },
118552
118952
  skills: resultSkills
118553
118953
  };
118554
- const hydrationManifestPath = join69(dirname41(cacheRoot), `hydration-${options.stationId}.json`);
118555
- mkdirSync29(dirname41(hydrationManifestPath), { recursive: true });
118954
+ const hydrationManifestPath = join70(dirname42(cacheRoot), `hydration-${options.stationId}.json`);
118955
+ mkdirSync29(dirname42(hydrationManifestPath), { recursive: true });
118556
118956
  writeFileSync30(hydrationManifestPath, `${JSON.stringify(hydration, null, 2)}
118557
118957
  `);
118558
118958
  return {
@@ -118629,14 +119029,14 @@ var init_hydrate = __esm(() => {
118629
119029
 
118630
119030
  // src/lib/prepare-skill.ts
118631
119031
  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";
119032
+ 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
119033
  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";
119034
+ import { dirname as dirname43, isAbsolute as isAbsolute40, join as join71, relative as relative13, resolve as resolve38, sep as sep18 } from "path";
118635
119035
  function prepareSkill(name, options) {
118636
119036
  const normalized = normalizePortableSkillName(name);
118637
119037
  if (!new RegExp(SEMVER_PATTERN).test(options.version))
118638
119038
  throw new Error("--version must be a semantic version, for example 0.2.0.");
118639
- const path = join70(getPortableSkillsRootReadOnly(options), normalized);
119039
+ const path = join71(getPortableSkillsRootReadOnly(options), normalized);
118640
119040
  assertPortableAuthoringPath(path, options);
118641
119041
  const before2 = snapshot2(path);
118642
119042
  const manifestFile = before2.files.find((file2) => file2.path === "skill.json");
@@ -118671,16 +119071,16 @@ function prepareSkill(name, options) {
118671
119071
  throw new Error("skill.json provenance must be an object.");
118672
119072
  const provenance = manifest.provenance;
118673
119073
  const candidate2 = { ...manifest, version: options.version, kind, provenance: { ...provenance } };
118674
- const staging = mkdtempSync6(join70(tmpdir2(), "skills-prepare-"));
119074
+ const staging = mkdtempSync6(join71(tmpdir2(), "skills-prepare-"));
118675
119075
  try {
118676
119076
  for (const directory2 of before2.directories)
118677
- mkdirSync30(join70(staging, directory2), { recursive: true });
119077
+ mkdirSync30(join71(staging, directory2), { recursive: true });
118678
119078
  for (const file2 of before2.files) {
118679
- const destination = join70(staging, file2.path);
118680
- mkdirSync30(dirname42(destination), { recursive: true });
119079
+ const destination = join71(staging, file2.path);
119080
+ mkdirSync30(dirname43(destination), { recursive: true });
118681
119081
  writeFileSync31(destination, file2.bytes, { mode: file2.mode });
118682
119082
  }
118683
- const stagedManifest = join70(staging, "skill.json");
119083
+ const stagedManifest = join71(staging, "skill.json");
118684
119084
  writeFileSync31(stagedManifest, `${JSON.stringify(candidate2, null, 2)}
118685
119085
  `);
118686
119086
  const contentHash = computeContentHash(staging);
@@ -118703,11 +119103,11 @@ ${validation.issues.map((issue2) => `${issue2.code}: ${issue2.message}`).join(`
118703
119103
  if (snapshot2(path).identity !== before2.identity)
118704
119104
  throw new Error("Skill changed during preparation; review the draft and run prepare again.");
118705
119105
  if (changed3 && !options.dryRun) {
118706
- const temporary = join70(path, `.skill-prepare-${randomUUID13()}.tmp`);
119106
+ const temporary = join71(path, `.skill-prepare-${randomUUID13()}.tmp`);
118707
119107
  try {
118708
119108
  writeFileSync31(temporary, candidateBytes, { flag: "wx", mode: manifestFile.mode });
118709
119109
  chmodSync5(temporary, manifestFile.mode);
118710
- renameSync15(temporary, join70(path, "skill.json"));
119110
+ renameSync15(temporary, join71(path, "skill.json"));
118711
119111
  } finally {
118712
119112
  rmSync9(temporary, { force: true });
118713
119113
  }
@@ -118737,8 +119137,8 @@ function validateRuntimeEntrypoint(candidate2, root2) {
118737
119137
  const entry = candidate2.runtime.entrypoint;
118738
119138
  if (typeof entry !== "string")
118739
119139
  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()) {
119140
+ const target = resolve38(root2, entry), rel = relative13(root2, target);
119141
+ if (isAbsolute40(entry) || /^[a-zA-Z]:/.test(entry) || entry.includes("\\") || !rel || rel === ".." || rel.startsWith(`..${sep18}`) || isAbsolute40(rel) || !existsSync37(target) || !lstatSync42(target).isFile()) {
118742
119142
  throw new Error("Executable runtime.entrypoint must name an existing regular file inside the skill directory.");
118743
119143
  }
118744
119144
  }
@@ -118823,20 +119223,20 @@ function compareVersions(left, right) {
118823
119223
  return 0;
118824
119224
  }
118825
119225
  function snapshot2(root2) {
118826
- const rootStat = lstatSync41(root2);
119226
+ const rootStat = lstatSync42(root2);
118827
119227
  if (rootStat.isSymbolicLink() || !rootStat.isDirectory())
118828
119228
  throw new Error("Skill root must be a real directory, not a symlink.");
118829
119229
  const files = [], directories = [];
118830
119230
  const hash6 = createHash44("sha256").update(`${rootStat.dev}:${rootStat.ino}\x00`);
118831
119231
  let count = 0, bytes = 0;
118832
119232
  const walk2 = (relative14) => {
118833
- for (const name of readdirSync26(join70(root2, relative14)).sort()) {
119233
+ for (const name of readdirSync26(join71(root2, relative14)).sort()) {
118834
119234
  if (IGNORED.has(name.toLowerCase()) || !relative14 && ROOT_IGNORED.has(name.toLowerCase()))
118835
119235
  continue;
118836
119236
  const path = relative14 ? `${relative14}/${name}` : name;
118837
119237
  if (++count > 20000)
118838
119238
  throw new Error("Skill exceeds the preparation entry limit (20000).");
118839
- const absolute = join70(root2, path), stat3 = lstatSync41(absolute);
119239
+ const absolute = join71(root2, path), stat3 = lstatSync42(absolute);
118840
119240
  if (stat3.isSymbolicLink())
118841
119241
  throw new Error(`Skill contains a symlink: ${path}. No files were changed.`);
118842
119242
  if (stat3.isDirectory() && name === "node_modules")
@@ -119252,7 +119652,7 @@ var init_schedule = __esm(() => {
119252
119652
 
119253
119653
  // src/lib/registry-sync.ts
119254
119654
  import { mkdirSync as mkdirSync31, writeFileSync as writeFileSync32 } from "fs";
119255
- import { dirname as dirname43, relative as relative14 } from "path";
119655
+ import { dirname as dirname44, relative as relative14 } from "path";
119256
119656
  function createRegistrySyncArtifact(options = {}) {
119257
119657
  const profile = options.profile ?? "all";
119258
119658
  const includeDocs = options.includeDocs ?? true;
@@ -119309,7 +119709,7 @@ function createRegistrySyncArtifact(options = {}) {
119309
119709
  };
119310
119710
  }
119311
119711
  function writeRegistrySyncArtifact(path, artifact) {
119312
- mkdirSync31(dirname43(path), { recursive: true });
119712
+ mkdirSync31(dirname44(path), { recursive: true });
119313
119713
  writeFileSync32(path, `${JSON.stringify(artifact, null, 2)}
119314
119714
  `);
119315
119715
  }
@@ -119329,8 +119729,8 @@ var init_registry_sync = __esm(() => {
119329
119729
  });
119330
119730
 
119331
119731
  // 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";
119732
+ 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";
119733
+ 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
119734
  function exactVersion(spec) {
119335
119735
  const at2 = spec.indexOf("@");
119336
119736
  const slug2 = spec.slice(0, at2);
@@ -119341,14 +119741,14 @@ function exactVersion(spec) {
119341
119741
  return { slug: slug2, version: version2 };
119342
119742
  }
119343
119743
  function assertPrivateDestination(output2) {
119344
- if (!isAbsolute40(output2) || resolve38(output2) !== output2 || !basename20(output2).endsWith(".tar.gz")) {
119744
+ if (!isAbsolute41(output2) || resolve39(output2) !== output2 || !basename20(output2).endsWith(".tar.gz")) {
119345
119745
  throw new Error("Review output must be an absolute, normalized .tar.gz path.");
119346
119746
  }
119347
- const parent = dirname44(output2);
119348
- if (realpathSync23(parent) !== parent || lstatSync42(parent).isSymbolicLink()) {
119747
+ const parent = dirname45(output2);
119748
+ if (realpathSync23(parent) !== parent || lstatSync43(parent).isSymbolicLink()) {
119349
119749
  throw new Error("Review output parent must be a real directory, not a symlink.");
119350
119750
  }
119351
- const parentStat = statSync24(parent);
119751
+ const parentStat = statSync25(parent);
119352
119752
  if (!parentStat.isDirectory() || (parentStat.mode & 63) !== 0 || process.getuid && parentStat.uid !== process.getuid()) {
119353
119753
  throw new Error("Review output parent must be an owner-only directory (mode 0700).");
119354
119754
  }
@@ -119356,8 +119756,8 @@ function assertPrivateDestination(output2) {
119356
119756
  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
119757
  throw new Error("Review output cannot be placed in agent-native discovery or Skills installation paths.");
119358
119758
  }
119359
- for (let current = parent;; current = dirname44(current)) {
119360
- if (existsSync38(join71(current, ".git"))) {
119759
+ for (let current = parent;; current = dirname45(current)) {
119760
+ if (existsSync38(join72(current, ".git"))) {
119361
119761
  throw new Error("Review output cannot be placed inside a Git worktree.");
119362
119762
  }
119363
119763
  if (current === parse13(current).root)
@@ -119393,7 +119793,7 @@ async function exportSkillVersionForReview(spec, output2, client2) {
119393
119793
  if (bytes.byteLength !== metadata2.bundleByteSize || sha256Hex(bytes) !== metadata2.bundleSha256.toLowerCase()) {
119394
119794
  throw new Error("Published bundle bytes do not match the exact version metadata.");
119395
119795
  }
119396
- const fd = openSync29(target, constants27.O_WRONLY | constants27.O_CREAT | constants27.O_EXCL | constants27.O_NOFOLLOW, 384);
119796
+ const fd = openSync29(target, constants28.O_WRONLY | constants28.O_CREAT | constants28.O_EXCL | constants28.O_NOFOLLOW, 384);
119397
119797
  try {
119398
119798
  writeFileSync33(fd, bytes);
119399
119799
  fsyncSync9(fd);
@@ -119433,12 +119833,12 @@ function registerRegistry(parent) {
119433
119833
  async function writeJson2(value, space) {
119434
119834
  const text4 = `${JSON.stringify(value, null, space)}
119435
119835
  `;
119436
- await new Promise((resolve39, reject2) => {
119836
+ await new Promise((resolve40, reject2) => {
119437
119837
  process.stdout.write(text4, (error61) => {
119438
119838
  if (error61)
119439
119839
  reject2(error61);
119440
119840
  else
119441
- resolve39();
119841
+ resolve40();
119442
119842
  });
119443
119843
  });
119444
119844
  }
@@ -119644,7 +120044,7 @@ __export(exports_publish, {
119644
120044
  import { execFileSync as execFileSync3 } from "child_process";
119645
120045
  import { existsSync as existsSync39, readFileSync as readFileSync49 } from "fs";
119646
120046
  import { hostname as hostname5 } from "os";
119647
- import { join as join72 } from "path";
120047
+ import { join as join73 } from "path";
119648
120048
  function registerPublish(parent) {
119649
120049
  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
120050
  try {
@@ -119696,7 +120096,7 @@ async function pushSkill(name, options = {}) {
119696
120096
  const packed = packSkillBundle(skill.path, { maxUnpackedBytes: MAX_UNPACKED_BYTES });
119697
120097
  await verifyPackedCanonicalHash(skill.name, packed);
119698
120098
  const versionManifest = buildVersionManifest(skill.path, packed);
119699
- const skillMdPath = join72(skill.path, "SKILL.md");
120099
+ const skillMdPath = join73(skill.path, "SKILL.md");
119700
120100
  const skillMd = existsSync39(skillMdPath) ? readFileSync49(skillMdPath, "utf-8") : undefined;
119701
120101
  const base3 = {
119702
120102
  slug: skill.name,
@@ -119935,7 +120335,7 @@ var exports_private_publications = {};
119935
120335
  __export(exports_private_publications, {
119936
120336
  registerPrivatePublications: () => registerPrivatePublications
119937
120337
  });
119938
- import { resolve as resolve39 } from "path";
120338
+ import { resolve as resolve40 } from "path";
119939
120339
  function verifyOptions(options, action) {
119940
120340
  if (options.userId === undefined !== (options.membershipId === undefined) || options.userId !== undefined && (!publicationUuid(options.userId) || !publicationUuid(options.membershipId)))
119941
120341
  throw new PrivatePublicationError("PUBLICATION_CONTEXT_REQUIRED", "Provide both observed --user-id and --membership-id UUIDs.");
@@ -119980,9 +120380,9 @@ function registerPrivatePublications(parent) {
119980
120380
  if (code2 === null)
119981
120381
  return;
119982
120382
  const context2 = options.userId ? { userId: options.userId, membershipId: options.membershipId } : undefined;
119983
- const client2 = await privatePublicationSession(options.email, code2, context2), directory2 = resolve39(options.recoveryDir);
120383
+ const client2 = await privatePublicationSession(options.email, code2, context2), directory2 = resolve40(options.recoveryDir);
119984
120384
  if (action === "publish")
119985
- await preparePrivatePublication(client2, resolve39(args2[0]), directory2, { skillId: options.skillId, expectedCurrentVersionId: options.expectedCurrentVersion ?? null, idempotencyKey: options.idempotencyKey });
120385
+ await preparePrivatePublication(client2, resolve40(args2[0]), directory2, { skillId: options.skillId, expectedCurrentVersionId: options.expectedCurrentVersion ?? null, idempotencyKey: options.idempotencyKey });
119986
120386
  const result2 = action === "publish" || action === "resume" ? await continuePrivatePublication(client2, directory2, { confirm: true, waitMs: Number(options.waitSeconds) * 1000 }) : await inspectPrivatePublication(client2, directory2, action === "cancel");
119987
120387
  print2(result2, options.json);
119988
120388
  } catch (error61) {
@@ -120084,7 +120484,7 @@ __export(exports_auth, {
120084
120484
  import { createInterface as createInterface3 } from "readline";
120085
120485
  function prompt(question) {
120086
120486
  const rl = createInterface3({ input: process.stdin, output: process.stdout });
120087
- return new Promise((resolve40) => {
120487
+ return new Promise((resolve41) => {
120088
120488
  let settled = false;
120089
120489
  const finish = (answer) => {
120090
120490
  if (settled)
@@ -120093,7 +120493,7 @@ function prompt(question) {
120093
120493
  rl.close();
120094
120494
  if (answer === null)
120095
120495
  process.exitCode = 130;
120096
- resolve40(answer);
120496
+ resolve41(answer);
120097
120497
  };
120098
120498
  rl.once("SIGINT", () => finish(null));
120099
120499
  rl.once("close", () => finish(null));
@@ -120271,7 +120671,7 @@ Skipped. Run it any time: skills setup agents`));
120271
120671
  function promptHidden(question) {
120272
120672
  const stdin = process.stdin;
120273
120673
  process.stdout.write(question);
120274
- return new Promise((resolve40) => {
120674
+ return new Promise((resolve41) => {
120275
120675
  let value = "";
120276
120676
  const done = (answer) => {
120277
120677
  stdin.off("data", onData);
@@ -120281,7 +120681,7 @@ function promptHidden(question) {
120281
120681
  `);
120282
120682
  if (answer === null)
120283
120683
  process.exitCode = 130;
120284
- resolve40(answer);
120684
+ resolve41(answer);
120285
120685
  };
120286
120686
  const onData = (chunk2) => {
120287
120687
  for (const character of chunk2.toString()) {
@@ -120837,7 +121237,7 @@ function promptInvitationProof(kind) {
120837
121237
  const label = kind === "token" ? "invitation token" : "recovery code";
120838
121238
  const character = kind === "token" ? /^[A-Za-z0-9_-]$/ : /^\d$/;
120839
121239
  const { stdin, stderr: output2 } = process, wasRaw = stdin.isRaw, wasFlowing = stdin.readableFlowing;
120840
- return new Promise((resolve40) => {
121240
+ return new Promise((resolve41) => {
120841
121241
  let value = "", settled = false, overflow = false;
120842
121242
  const finish = (answer) => {
120843
121243
  if (settled)
@@ -120854,7 +121254,7 @@ function promptInvitationProof(kind) {
120854
121254
  `);
120855
121255
  if (answer === null)
120856
121256
  process.exitCode = 130;
120857
- resolve40(answer);
121257
+ resolve41(answer);
120858
121258
  };
120859
121259
  const cancel = () => finish(null);
120860
121260
  const keypress = (text4, key) => {
@@ -121426,11 +121826,11 @@ var init_storage2 = __esm(() => {
121426
121826
  });
121427
121827
 
121428
121828
  // 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";
121829
+ import { existsSync as existsSync40, readFileSync as readFileSync50, statSync as statSync26, writeFileSync as writeFileSync34 } from "fs";
121830
+ import { join as join74 } from "path";
121431
121831
  function isDirectory2(path) {
121432
121832
  try {
121433
- return statSync25(path).isDirectory();
121833
+ return statSync26(path).isDirectory();
121434
121834
  } catch {
121435
121835
  return false;
121436
121836
  }
@@ -121438,11 +121838,11 @@ function isDirectory2(path) {
121438
121838
  function migrationNeeded(options) {
121439
121839
  if (options.rootDir)
121440
121840
  return false;
121441
- const appDir = options.homeDir ? join73(options.homeDir, ".hasna", "skills") : getDataDir();
121442
- return !(isOwnerLayoutMigrated(appDir) && isDirectory2(join73(appDir, SKILLS_CACHE_DIRNAME)));
121841
+ const appDir = options.homeDir ? join74(options.homeDir, ".hasna", "skills") : getDataDir();
121842
+ return !(isOwnerLayoutMigrated(appDir) && isDirectory2(join74(appDir, SKILLS_CACHE_DIRNAME)));
121443
121843
  }
121444
121844
  function readBaseline(skillDir) {
121445
- const markerPath = join73(skillDir, PULL_MARKER_FILE);
121845
+ const markerPath = join74(skillDir, PULL_MARKER_FILE);
121446
121846
  if (!existsSync40(markerPath))
121447
121847
  return;
121448
121848
  try {
@@ -121458,7 +121858,7 @@ function readBaseline(skillDir) {
121458
121858
  }
121459
121859
  }
121460
121860
  function readCursor(root2) {
121461
- const path = join73(root2, SYNC_CURSOR_FILE);
121861
+ const path = join74(root2, SYNC_CURSOR_FILE);
121462
121862
  if (!existsSync40(path))
121463
121863
  return { runCount: 0 };
121464
121864
  try {
@@ -121471,12 +121871,12 @@ function readCursor(root2) {
121471
121871
  function resolveCorpusRootReadOnly(options) {
121472
121872
  if (options.rootDir)
121473
121873
  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);
121874
+ const appDir = options.homeDir ? join74(options.homeDir, ".hasna", "skills") : getDataDirReadOnly();
121875
+ const cache3 = join74(appDir, SKILLS_CACHE_DIRNAME);
121476
121876
  if (isOwnerLayoutMigrated(appDir) && isDirectory2(cache3)) {
121477
121877
  return { root: cache3, migrationPending: false };
121478
121878
  }
121479
- return { root: join73(appDir, INSTALLED_SKILLS_DIRNAME), migrationPending: true };
121879
+ return { root: join74(appDir, INSTALLED_SKILLS_DIRNAME), migrationPending: true };
121480
121880
  }
121481
121881
  function remoteRowToSkill(record12) {
121482
121882
  const slug2 = typeof record12.slug === "string" ? record12.slug : typeof record12.name === "string" ? record12.name : undefined;
@@ -121610,7 +122010,7 @@ async function reconcileRegistry(options = {}) {
121610
122010
  for (const slug2 of allSlugs) {
121611
122011
  const local = locals.get(slug2);
121612
122012
  const remote = remotes.get(slug2);
121613
- const baseline = local ? readBaseline(join73(root2, slug2)) : undefined;
122013
+ const baseline = local ? readBaseline(join74(root2, slug2)) : undefined;
121614
122014
  const { state, reason: reason2 } = classifySkill(local, remote, baseline);
121615
122015
  let { action, reason: actionReason } = resolveAction(state, direction, conflict);
121616
122016
  if (state === "remote-only" && isDigestless(remote)) {
@@ -121669,7 +122069,7 @@ async function reconcileRegistry(options = {}) {
121669
122069
  try {
121670
122070
  await pushSkill(slug2, { rootDir: root2, client: client2 });
121671
122071
  const pushed = locals.get(slug2);
121672
- writePullMarker(join73(root2, slug2), {
122072
+ writePullMarker(join74(root2, slug2), {
121673
122073
  skill: slug2,
121674
122074
  ...pushed?.version ? { version: pushed.version } : {},
121675
122075
  ...pushed?.sha256 ? { contentHash: pushed.sha256 } : {},
@@ -121741,7 +122141,7 @@ async function reconcileRegistry(options = {}) {
121741
122141
  runCount: readCursor(root2).runCount + 1,
121742
122142
  summary
121743
122143
  };
121744
- writeFileSync34(join73(root2, SYNC_CURSOR_FILE), `${JSON.stringify(cursor2, null, 2)}
122144
+ writeFileSync34(join74(root2, SYNC_CURSOR_FILE), `${JSON.stringify(cursor2, null, 2)}
121745
122145
  `);
121746
122146
  return {
121747
122147
  corpusRoot: root2,