@hasna/skills 0.10.48 → 0.10.50

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/dist/index.js CHANGED
@@ -6988,7 +6988,7 @@ var require_public_api = __commonJS((exports) => {
6988
6988
  });
6989
6989
 
6990
6990
  // src/lib/registry.ts
6991
- import { existsSync as existsSync15, readFileSync as readFileSync20, readdirSync as readdirSync12 } from "fs";
6991
+ import { existsSync as existsSync15, readFileSync as readFileSync21, readdirSync as readdirSync12 } from "fs";
6992
6992
  import { join as join35 } from "path";
6993
6993
 
6994
6994
  // src/lib/config.ts
@@ -7256,13 +7256,13 @@ import {
7256
7256
  mkdirSync as mkdirSync10,
7257
7257
  mkdtempSync as mkdtempSync2,
7258
7258
  readdirSync as readdirSync11,
7259
- realpathSync as realpathSync12,
7259
+ realpathSync as realpathSync13,
7260
7260
  renameSync as renameSync6,
7261
7261
  rmSync as rmSync4,
7262
7262
  statSync as statSync11,
7263
7263
  writeFileSync as writeFileSync9
7264
7264
  } from "fs";
7265
- import { basename as basename12, dirname as dirname21, isAbsolute as isAbsolute19, join as join34, normalize as normalize4, relative as relative7, resolve as resolve20, sep as sep10 } from "path";
7265
+ import { basename as basename12, dirname as dirname21, isAbsolute as isAbsolute20, join as join34, normalize as normalize4, relative as relative7, resolve as resolve20, sep as sep10 } from "path";
7266
7266
 
7267
7267
  // src/lib/registry-data/index.ts
7268
7268
  var SKILLS = [];
@@ -8920,7 +8920,7 @@ var NATIVE_SKILL_ROOTS = [
8920
8920
  ];
8921
8921
 
8922
8922
  // src/lib/authoring-path.ts
8923
- import { lstatSync as lstatSync25, realpathSync as realpathSync11 } from "fs";
8923
+ import { lstatSync as lstatSync26, realpathSync as realpathSync12 } from "fs";
8924
8924
  import { homedir as homedir6 } from "os";
8925
8925
  import { basename as basename11, dirname as dirname20, join as join33, resolve as resolve19, sep as sep9 } from "path";
8926
8926
 
@@ -9177,6 +9177,8 @@ var BUILTIN_MODEL_SELECTIONS = new Set([
9177
9177
  "claude-opus-4-6[1m]",
9178
9178
  "claude-sonnet-4-6[1m]"
9179
9179
  ]);
9180
+ var CLAUDE_BUILTIN_THEMES = Object.freeze(["auto", "dark", "light", "dark-daltonized", "light-daltonized", "dark-ansi", "light-ansi"]);
9181
+ var BUILTIN_THEMES = new Set(CLAUDE_BUILTIN_THEMES);
9180
9182
  function canonical(value) {
9181
9183
  if (value.kind === "object")
9182
9184
  return { kind: "object", entries: value.entries.map(([key, child]) => [key, canonical(child)]).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0) };
@@ -9235,7 +9237,9 @@ function inferencePreference(key, child, version) {
9235
9237
  function settingsDigest(text, version = 1) {
9236
9238
  const value = parse(text);
9237
9239
  value.entries = value.entries.filter(([key, child]) => {
9238
- if (version !== 1 && inferencePreference(key, child, version))
9240
+ if (version === 4 && key === "theme" && child.kind === "string" && BUILTIN_THEMES.has(child.value))
9241
+ return false;
9242
+ if (version !== 1 && inferencePreference(key, child, version === 4 ? 3 : version))
9239
9243
  return false;
9240
9244
  if (key === "model") {
9241
9245
  need(child.kind === "string", "contains an invalid model selection");
@@ -9293,6 +9297,26 @@ function upgradeClaudeSettingsWitness(previous, reviewedSettingsPath) {
9293
9297
  need(settingsDigest(before, 3) === sha256, "non-preference settings changed; explicit discovery review required");
9294
9298
  return { path: previous.path, hashMode: "claude-settings-v3", sha256 };
9295
9299
  }
9300
+ function captureClaudeSettingsV4(path, budget = { remaining: 256 * 1024 * 1024 }) {
9301
+ return { path, hashMode: "claude-settings-v4", sha256: settingsDigest(readNativeSettingsWitnessFile(path, budget), 4) };
9302
+ }
9303
+ function hashClaudeSettingsReplacementV4(text, budget) {
9304
+ need(typeof text === "string", "requires settings text");
9305
+ const bytes = Buffer.byteLength(text);
9306
+ need(bytes <= CLAUDE_SETTINGS_WITNESS_LIMITS.bytes && Number.isSafeInteger(budget.remaining) && budget.remaining >= bytes, "exceeds its byte limit");
9307
+ budget.remaining -= bytes;
9308
+ return settingsDigest(text, 4);
9309
+ }
9310
+ function upgradeClaudeSettingsWitnessV4(previous, reviewedSettingsPath) {
9311
+ need(previous && Object.keys(previous).every((key) => ["path", "hashMode", "sha256"].includes(key)) && (previous.hashMode === undefined || previous.hashMode === "bytes" || previous.hashMode === "claude-settings-v1" || previous.hashMode === "claude-settings-v2" || previous.hashMode === "claude-settings-v3") && typeof previous.sha256 === "string" && /^[a-f0-9]{64}$/.test(previous.sha256), "requires an exact prior settings witness");
9312
+ const budget = { remaining: 2 * CLAUDE_SETTINGS_WITNESS_LIMITS.bytes };
9313
+ const before = readNativeSettingsWitnessFile(reviewedSettingsPath, budget), current = readNativeSettingsWitnessFile(previous.path, budget);
9314
+ const beforeDigest = previous.hashMode === undefined || previous.hashMode === "bytes" ? createHash2("sha256").update(before).digest("hex") : settingsDigest(before, previous.hashMode === "claude-settings-v1" ? 1 : previous.hashMode === "claude-settings-v2" ? 2 : 3);
9315
+ need(beforeDigest === previous.sha256, "reviewed preimage does not match the prior witness");
9316
+ const sha256 = settingsDigest(current, 4);
9317
+ need(settingsDigest(before, 4) === sha256, "non-preference settings changed; explicit discovery review required");
9318
+ return { path: previous.path, hashMode: "claude-settings-v4", sha256 };
9319
+ }
9296
9320
  function hashNativeJsonControls(text, excludedMetadata) {
9297
9321
  need(Buffer.byteLength(text) <= CLAUDE_SETTINGS_WITNESS_LIMITS.bytes, "exceeds its byte limit");
9298
9322
  const value = parse(text);
@@ -9497,14 +9521,14 @@ function assertAgentPolicyCollections(policy) {
9497
9521
  text(source.path);
9498
9522
  requireBound(source.sha256 === null || typeof source.sha256 === "string" && /^[a-f0-9]{64}$/.test(source.sha256));
9499
9523
  if (source.hashMode !== undefined)
9500
- requireBound(["bytes", "path-bytes", "claude-plugin-manifest-v1", "claude-plugin-registry", "claude-marketplace-registry", "claude-settings-v1", "claude-settings-v2", "claude-settings-v3", "claude-marketplace-registry-v2", "codex-settings-v1", "codex-settings-v2", "codex-settings-v3", "codex-settings-v4", "sumi-settings-v1"].includes(source.hashMode) && source.format === undefined && source.fields === undefined && (source.hashMode === "bytes" || source.sha256 !== null));
9524
+ requireBound(["bytes", "path-bytes", "claude-plugin-manifest-v1", "claude-plugin-registry", "claude-marketplace-registry", "claude-settings-v1", "claude-settings-v2", "claude-settings-v3", "claude-settings-v4", "claude-marketplace-registry-v2", "codex-settings-v1", "codex-settings-v2", "codex-settings-v3", "codex-settings-v4", "sumi-settings-v1"].includes(source.hashMode) && source.format === undefined && source.fields === undefined && (source.hashMode === "bytes" || source.sha256 !== null));
9501
9525
  if (source.hashMode === "claude-plugin-manifest-v1")
9502
9526
  requireBound(agent === "claude" && value.agent === "claude" && ["automatic", "reviewed"].includes(value.method) && !/[\x00-\x1f\x7f]/.test(source.path) && isAbsolute3(source.path) && resolve3(source.path) === source.path && source.path.endsWith(join7(sep2, ".claude-plugin", "plugin.json")) && source.managedPlugins === undefined);
9503
9527
  if (source.hashMode === "sumi-settings-v1")
9504
9528
  requireBound(agent === "sumi" && value.agent === "sumi" && value.method === "reviewed" && !/[\x00-\x1f\x7f]/.test(source.path) && isAbsolute3(source.path) && resolve3(source.path) === source.path && basename3(source.path) === "sumi.json");
9505
9529
  if (source.hashMode === "codex-settings-v1" || source.hashMode === "codex-settings-v2" || (source.hashMode === "codex-settings-v3" || source.hashMode === "codex-settings-v4"))
9506
9530
  requireBound(agent === "codex" && value.agent === "codex" && value.method === "reviewed" && !/[\x00-\x1f\x7f]/.test(source.path) && isAbsolute3(source.path) && resolve3(source.path) === source.path && basename3(source.path) === "config.toml");
9507
- if (source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || source.hashMode === "claude-settings-v3")
9531
+ if (source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || (source.hashMode === "claude-settings-v3" || source.hashMode === "claude-settings-v4"))
9508
9532
  requireBound(agent === "claude" && value.agent === "claude" && value.method === "reviewed" && !/[\x00-\x1f\x7f]/.test(source.path) && isAbsolute3(source.path) && resolve3(source.path) === source.path && basename3(source.path) === "settings.json");
9509
9533
  if (source.hashMode === "claude-marketplace-registry" || source.hashMode === "claude-marketplace-registry-v2")
9510
9534
  requireBound(agent === "claude" && value.agent === "claude" && value.method === "reviewed" && !/[\x00-\x1f\x7f]/.test(source.path) && isAbsolute3(source.path) && resolve3(source.path) === source.path && basename3(source.path) === "known_marketplaces.json");
@@ -9538,9 +9562,9 @@ function assertAgentPolicyCollections(policy) {
9538
9562
  }
9539
9563
 
9540
9564
  // src/lib/agent-discovery.ts
9541
- import { createHash as createHash23 } from "crypto";
9542
- import { lstatSync as lstatSync24, readFileSync as readFileSync19, readdirSync as readdirSync10, realpathSync as realpathSync10 } from "fs";
9543
- import { basename as basename10, dirname as dirname19, isAbsolute as isAbsolute18, join as join32, resolve as resolve18, sep as sep8 } from "path";
9565
+ import { createHash as createHash24 } from "crypto";
9566
+ import { lstatSync as lstatSync25, readFileSync as readFileSync20, readdirSync as readdirSync10, realpathSync as realpathSync11 } from "fs";
9567
+ import { basename as basename10, dirname as dirname19, isAbsolute as isAbsolute19, join as join32, resolve as resolve18, sep as sep8 } from "path";
9544
9568
  import { isDeepStrictEqual as isDeepStrictEqual7 } from "util";
9545
9569
 
9546
9570
  // node_modules/yaml/dist/index.js
@@ -10230,12 +10254,12 @@ function projectReviewedClaudePluginManifest(text2, reviewedSha256) {
10230
10254
  }
10231
10255
 
10232
10256
  // src/lib/plugin-discovery.ts
10233
- import { closeSync as closeSync12, constants as constants12, fstatSync as fstatSync12, lstatSync as lstatSync22, openSync as openSync12, opendirSync as opendirSync5, readSync as readSync10 } from "fs";
10234
- import { basename as basename8, dirname as dirname17, isAbsolute as isAbsolute16, join as join31, resolve as resolve16 } from "path";
10257
+ import { closeSync as closeSync13, constants as constants13, fstatSync as fstatSync13, lstatSync as lstatSync23, openSync as openSync13, opendirSync as opendirSync5, readSync as readSync10 } from "fs";
10258
+ import { basename as basename8, dirname as dirname17, isAbsolute as isAbsolute17, join as join31, resolve as resolve16 } from "path";
10235
10259
 
10236
10260
  // src/lib/plugin-admission.ts
10237
10261
  import { homedir as homedir5 } from "os";
10238
- import { isAbsolute as isAbsolute15, join as join30, resolve as resolve15 } from "path";
10262
+ import { isAbsolute as isAbsolute16, join as join30, resolve as resolve15 } from "path";
10239
10263
 
10240
10264
  // src/lib/selection-cache.ts
10241
10265
  import { createHash as createHash9, randomUUID } from "crypto";
@@ -11572,7 +11596,7 @@ function replaceSkillSession(expected, replacement, plan, options = {}, beforeCo
11572
11596
  // package.json
11573
11597
  var package_default = {
11574
11598
  name: "@hasna/skills",
11575
- version: "0.10.48",
11599
+ version: "0.10.50",
11576
11600
  description: "Skills library for AI coding agents",
11577
11601
  type: "module",
11578
11602
  bin: {
@@ -13401,7 +13425,7 @@ async function prepareSkillDependencies(skillPath, env, timeoutMs = DEFAULT_PREP
13401
13425
  }
13402
13426
 
13403
13427
  // src/lib/skillinfo.ts
13404
- import { existsSync as existsSync13, readFileSync as readFileSync18 } from "fs";
13428
+ import { existsSync as existsSync13, readFileSync as readFileSync19 } from "fs";
13405
13429
  import { join as join28 } from "path";
13406
13430
 
13407
13431
  // src/lib/codex-corpus-write.ts
@@ -13566,7 +13590,7 @@ function withCodexCorpusWrite(roots, run, options = {}) {
13566
13590
  }
13567
13591
 
13568
13592
  // src/lib/installer.ts
13569
- import { existsSync as existsSync12, readFileSync as readFileSync17, rmSync as rmSync2 } from "fs";
13593
+ import { existsSync as existsSync12, readFileSync as readFileSync18, rmSync as rmSync2 } from "fs";
13570
13594
  import { join as join27 } from "path";
13571
13595
  import { homedir as homedir4 } from "os";
13572
13596
 
@@ -13574,10 +13598,10 @@ import { homedir as homedir4 } from "os";
13574
13598
  import {
13575
13599
  cpSync as cpSync2,
13576
13600
  existsSync as existsSync10,
13577
- lstatSync as lstatSync20,
13601
+ lstatSync as lstatSync21,
13578
13602
  mkdirSync as mkdirSync7,
13579
13603
  mkdtempSync,
13580
- readFileSync as readFileSync15,
13604
+ readFileSync as readFileSync16,
13581
13605
  readdirSync as readdirSync9,
13582
13606
  renameSync as renameSync4,
13583
13607
  rmSync,
@@ -15501,10 +15525,10 @@ function upgradeCodexSettingsWitnessV4(previous, reviewedSettingsPath) {
15501
15525
  }
15502
15526
 
15503
15527
  // src/lib/agent-integration.ts
15504
- import { createHash as createHash18, randomUUID as randomUUID3 } from "crypto";
15528
+ import { createHash as createHash19, randomUUID as randomUUID3 } from "crypto";
15505
15529
  import { isDeepStrictEqual as isDeepStrictEqual6 } from "util";
15506
- import { existsSync as existsSync9, lstatSync as lstatSync19, statSync as statSync9, mkdirSync as mkdirSync6, readFileSync as readFileSync14, readdirSync as readdirSync8, opendirSync as opendirSync3, readlinkSync as readlinkSync5, realpathSync as realpathSync9, renameSync as renameSync3, rmdirSync as rmdirSync2, writeFileSync as writeFileSync6, unlinkSync as unlinkSync4, chmodSync, openSync as openSync10, closeSync as closeSync10, fsyncSync as fsyncSync4, fstatSync as fstatSync10, readSync as readSync8, constants as constants10, linkSync as linkSync2 } from "fs";
15507
- import { dirname as dirname14, join as join23, resolve as resolve13, relative as relative6, isAbsolute as isAbsolute13, sep as sep7 } from "path";
15530
+ import { existsSync as existsSync9, lstatSync as lstatSync20, statSync as statSync9, mkdirSync as mkdirSync6, readFileSync as readFileSync15, readdirSync as readdirSync8, opendirSync as opendirSync3, readlinkSync as readlinkSync6, realpathSync as realpathSync10, renameSync as renameSync3, rmdirSync as rmdirSync2, writeFileSync as writeFileSync6, unlinkSync as unlinkSync4, chmodSync, openSync as openSync11, closeSync as closeSync11, fsyncSync as fsyncSync5, fstatSync as fstatSync11, readSync as readSync8, constants as constants11, linkSync as linkSync2 } from "fs";
15531
+ import { dirname as dirname14, join as join23, resolve as resolve13, relative as relative6, isAbsolute as isAbsolute14, sep as sep7 } from "path";
15508
15532
  import { homedir as homedir2 } from "os";
15509
15533
 
15510
15534
  // src/lib/managed-policy.ts
@@ -16068,8 +16092,144 @@ function unchanged2(before) {
16068
16092
  need5(sameStat(before.stat, after.stat) && after.sha256 === before.sha256, "INPUT_CHANGED");
16069
16093
  }
16070
16094
 
16095
+ // src/cli/commands/runtime-launcher.ts
16096
+ import { createHash as createHash18 } from "crypto";
16097
+ import { closeSync as closeSync10, constants as constants10, fchmodSync, fstatSync as fstatSync10, fsyncSync as fsyncSync4, lstatSync as lstatSync19, openSync as openSync10, readFileSync as readFileSync14, readlinkSync as readlinkSync5, realpathSync as realpathSync9, symlinkSync, writeSync as writeSync2 } from "fs";
16098
+ import { isAbsolute as isAbsolute13 } from "path";
16099
+ var PINNED_LAUNCHER_SCHEMA = "hasna-skills-pinned-launcher-v1";
16100
+ var LAUNCH_CWD_VARIABLE = "HASNA_SKILLS_LAUNCH_CWD";
16101
+ var PINNED_LAUNCHER_BUN_FLAGS = ["--config=/dev/null", "--no-env-file", "--no-macros", "--no-install"];
16102
+ var PINNED_LAUNCHER_ENV_NAMES = [
16103
+ "HOME",
16104
+ "PATH",
16105
+ "TMPDIR",
16106
+ "TERM",
16107
+ "TERM_PROGRAM",
16108
+ "TERM_PROGRAM_VERSION",
16109
+ "COLORTERM",
16110
+ "LANG",
16111
+ "USER",
16112
+ "LOGNAME",
16113
+ "SHELL",
16114
+ "TZ",
16115
+ "NO_COLOR",
16116
+ "FORCE_COLOR",
16117
+ "CI",
16118
+ "COLUMNS",
16119
+ "LINES",
16120
+ "EDITOR",
16121
+ "VISUAL",
16122
+ "PAGER",
16123
+ "SSH_AUTH_SOCK",
16124
+ "DATABASE_URL",
16125
+ "TERMINAL_CWD",
16126
+ "CODEX_HOME",
16127
+ "HERMES_HOME",
16128
+ "HERMES_ENABLE_PROJECT_PLUGINS",
16129
+ "HOST",
16130
+ "PORT",
16131
+ "NODE_ENV",
16132
+ "AGENT_ID",
16133
+ "ECS_CONTAINER_METADATA_URI_V4"
16134
+ ];
16135
+ var PINNED_LAUNCHER_ENV_PREFIXES = ["HASNA", "SKILLS", "SKILL", "MCP", "XDG", "LC", "AWS"];
16136
+ var ENV_PREFIX = new RegExp(`^(${PINNED_LAUNCHER_ENV_PREFIXES.join("|")})_`);
16137
+ var ENV_EXACT = new Set(PINNED_LAUNCHER_ENV_NAMES);
16138
+ function sha2562(bytes) {
16139
+ return createHash18("sha256").update(bytes).digest("hex");
16140
+ }
16141
+ function assertLauncherPath(value, code) {
16142
+ if (typeof value !== "string" || !isAbsolute13(value) || /['\x00-\x1f\x7f]/.test(value))
16143
+ throw new Error(code);
16144
+ }
16145
+ function renderPinnedLauncher(binding) {
16146
+ assertLauncherPath(binding.runtime, "LAUNCHER_RUNTIME_PATH_INVALID");
16147
+ assertLauncherPath(binding.cwd, "LAUNCHER_CWD_PATH_INVALID");
16148
+ assertLauncherPath(binding.entry, "LAUNCHER_ENTRY_PATH_INVALID");
16149
+ const names = PINNED_LAUNCHER_ENV_NAMES.join(" ");
16150
+ const prefixes = PINNED_LAUNCHER_ENV_PREFIXES.join("|");
16151
+ return [
16152
+ "#!/bin/sh -p",
16153
+ `# ${PINNED_LAUNCHER_SCHEMA}`,
16154
+ "# Written by `skills self-update`; rewrite it with `skills self-update`, do not edit by hand.",
16155
+ "# Runs the exact Skills entry below under one exact Bun from one trusted directory with",
16156
+ "# no working-directory configuration (no bunfig.toml, no .env, no macros, no auto-install)",
16157
+ "# and only the environment names allowed here. Everything else, BUN_* and NODE_OPTIONS",
16158
+ "# included, never reaches the runtime. The CLI returns to the caller's directory itself.",
16159
+ "# `-p` keeps the caller's exported functions and shell options out of this shell.",
16160
+ "set -eu",
16161
+ `${LAUNCH_CWD_VARIABLE}=$(pwd -P 2>/dev/null || :)`,
16162
+ `export ${LAUNCH_CWD_VARIABLE}`,
16163
+ `set -- '${binding.runtime}' ${PINNED_LAUNCHER_BUN_FLAGS.join(" ")} '--cwd=${binding.cwd}' '${binding.entry}' "$@"`,
16164
+ "hasna_skills_env=$(LC_ALL=C /usr/bin/awk 'BEGIN {",
16165
+ ` n = split("${names}", exact, " ")`,
16166
+ " for (i = 1; i <= n; i++) allow[exact[i]] = 1",
16167
+ " for (name in ENVIRON) {",
16168
+ " if (name !~ /^[A-Za-z_][A-Za-z0-9_]*$/) continue",
16169
+ ` if (name == "LC_ALL" || (!(name in allow) && name !~ /^(${prefixes})_/)) continue`,
16170
+ ' value = ENVIRON[name]; quoted = ""',
16171
+ ' while ((k = index(value, "\\047")) > 0) { quoted = quoted substr(value, 1, k - 1) "\\047\\\\\\047\\047"; value = substr(value, k + 1) }',
16172
+ ' printf "\\047%s=%s\\047 ", name, quoted value',
16173
+ " }",
16174
+ "}')",
16175
+ 'eval "set -- $hasna_skills_env \\"\\$@\\""',
16176
+ 'if [ "${LC_ALL+x}" = x ]; then set -- "LC_ALL=$LC_ALL" "$@"; fi',
16177
+ 'exec /usr/bin/env -i "$@"',
16178
+ ""
16179
+ ].join(`
16180
+ `);
16181
+ }
16182
+ var COMMAND_LINE = new RegExp(`^set -- '([^']+)' ${PINNED_LAUNCHER_BUN_FLAGS.join(" ")} '--cwd=([^']+)' '([^']+)' "\\$@"$`, "m");
16183
+ function parsePinnedLauncher(text2) {
16184
+ const match = COMMAND_LINE.exec(text2);
16185
+ if (!match)
16186
+ return null;
16187
+ const binding = { runtime: match[1], cwd: match[2], entry: match[3] };
16188
+ try {
16189
+ if (renderPinnedLauncher(binding) !== text2)
16190
+ return null;
16191
+ } catch {
16192
+ return null;
16193
+ }
16194
+ return binding;
16195
+ }
16196
+ var PINNED_LAUNCHER_MAX_BYTES = 16 * 1024;
16197
+ function resolveLauncherCommand(path) {
16198
+ const physical = realpathSync9(path);
16199
+ const stat = lstatSync19(physical);
16200
+ if (stat.isFile() && stat.size <= PINNED_LAUNCHER_MAX_BYTES) {
16201
+ const text2 = readFileSync14(physical, "utf8");
16202
+ const binding = parsePinnedLauncher(text2);
16203
+ if (binding) {
16204
+ let entry;
16205
+ try {
16206
+ entry = realpathSync9(binding.entry);
16207
+ } catch {
16208
+ throw new Error("LAUNCHER_ENTRY_UNREADABLE");
16209
+ }
16210
+ if (entry !== binding.entry)
16211
+ throw new Error("LAUNCHER_ENTRY_NOT_PHYSICAL");
16212
+ return { physical, entry, pinned: { ...binding, sha256: sha2562(text2) } };
16213
+ }
16214
+ }
16215
+ return { physical, entry: physical, pinned: null };
16216
+ }
16217
+ function assertPinnedLauncherRuntimeSafe(runtime) {
16218
+ assertLauncherPath(runtime, "LAUNCHER_RUNTIME_PATH_INVALID");
16219
+ let stat;
16220
+ try {
16221
+ stat = lstatSync19(runtime);
16222
+ } catch {
16223
+ throw new Error("LAUNCHER_RUNTIME_UNSAFE");
16224
+ }
16225
+ const uid = process.getuid?.() ?? -1;
16226
+ if (!stat.isFile() || stat.isSymbolicLink() || ![0, uid].includes(stat.uid) || (stat.mode & 18) !== 0 || (stat.mode & 64) === 0) {
16227
+ throw new Error("LAUNCHER_RUNTIME_UNSAFE");
16228
+ }
16229
+ }
16230
+
16071
16231
  // src/lib/agent-integration.ts
16072
- var sha3 = (data) => createHash18("sha256").update(data).digest("hex");
16232
+ var sha3 = (data) => createHash19("sha256").update(data).digest("hex");
16073
16233
  var ROOTS = NATIVE_SKILL_ROOTS;
16074
16234
  function hasTrustedDarwinAcl(fd, allowDenyOnly = false) {
16075
16235
  try {
@@ -16120,11 +16280,11 @@ function isSystemRootAlias(path) {
16120
16280
  const target = `/private${path}`, link = `private${path}`;
16121
16281
  const identity5 = (stat) => `${stat.dev}:${stat.ino}:${stat.ctimeNs}:${stat.uid}:${stat.mode}`;
16122
16282
  try {
16123
- const before = lstatSync19(path, { bigint: true });
16124
- if (!before.isSymbolicLink() || before.uid !== 0n || readlinkSync5(path) !== link)
16283
+ const before = lstatSync20(path, { bigint: true });
16284
+ if (!before.isSymbolicLink() || before.uid !== 0n || readlinkSync6(path) !== link)
16125
16285
  return false;
16126
16286
  const directories = ["/", "/private", target].map((directory) => {
16127
- const stat = lstatSync19(directory, { bigint: true });
16287
+ const stat = lstatSync20(directory, { bigint: true });
16128
16288
  if (!stat.isDirectory() || stat.uid !== 0n)
16129
16289
  throw new Error("Untrusted system alias directory");
16130
16290
  if (directory !== "/private/tmp") {
@@ -16132,23 +16292,23 @@ function isSystemRootAlias(path) {
16132
16292
  throw new Error("Writable system alias directory");
16133
16293
  } else if ((stat.mode & 0o1000n) === 0n)
16134
16294
  throw new Error("Unprotected system temporary directory");
16135
- const fd = openSync10(directory, constants10.O_RDONLY | constants10.O_DIRECTORY | constants10.O_NOFOLLOW);
16295
+ const fd = openSync11(directory, constants11.O_RDONLY | constants11.O_DIRECTORY | constants11.O_NOFOLLOW);
16136
16296
  try {
16137
- if (identity5(fstatSync10(fd, { bigint: true })) !== identity5(stat) || !hasTrustedDarwinAcl(fd) || identity5(fstatSync10(fd, { bigint: true })) !== identity5(stat))
16297
+ if (identity5(fstatSync11(fd, { bigint: true })) !== identity5(stat) || !hasTrustedDarwinAcl(fd) || identity5(fstatSync11(fd, { bigint: true })) !== identity5(stat))
16138
16298
  throw new Error("Unverified system alias directory ACL");
16139
16299
  } finally {
16140
- closeSync10(fd);
16300
+ closeSync11(fd);
16141
16301
  }
16142
16302
  return { directory, identity: identity5(stat) };
16143
16303
  });
16144
- return realpathSync9(path) === target && readlinkSync5(path) === link && identity5(lstatSync19(path, { bigint: true })) === identity5(before) && directories.every((item) => identity5(lstatSync19(item.directory, { bigint: true })) === item.identity);
16304
+ return realpathSync10(path) === target && readlinkSync6(path) === link && identity5(lstatSync20(path, { bigint: true })) === identity5(before) && directories.every((item) => identity5(lstatSync20(item.directory, { bigint: true })) === item.identity);
16145
16305
  } catch {
16146
16306
  return false;
16147
16307
  }
16148
16308
  }
16149
16309
  function canonicalSystemPath(path) {
16150
16310
  const absolute = resolve13(path), root = `/${absolute.split(sep7)[1]}`;
16151
- if (process.platform !== "darwin" || !["/var", "/tmp", "/etc"].includes(root) || !lstatSync19(root, { throwIfNoEntry: false })?.isSymbolicLink())
16311
+ if (process.platform !== "darwin" || !["/var", "/tmp", "/etc"].includes(root) || !lstatSync20(root, { throwIfNoEntry: false })?.isSymbolicLink())
16152
16312
  return absolute;
16153
16313
  if (!isSystemRootAlias(root))
16154
16314
  throw new Error(`Refusing symlink path: ${root}`);
@@ -16157,7 +16317,7 @@ function canonicalSystemPath(path) {
16157
16317
  function assertSafePath(path) {
16158
16318
  let cursor = resolve13(path);
16159
16319
  while (true) {
16160
- if (lstatSync19(cursor, { throwIfNoEntry: false })?.isSymbolicLink() && !isSystemRootAlias(cursor))
16320
+ if (lstatSync20(cursor, { throwIfNoEntry: false })?.isSymbolicLink() && !isSystemRootAlias(cursor))
16161
16321
  throw new Error(`Refusing symlink path: ${cursor}`);
16162
16322
  const parent = dirname14(cursor);
16163
16323
  if (parent === cursor)
@@ -16167,17 +16327,17 @@ function assertSafePath(path) {
16167
16327
  }
16168
16328
  function readRootAlias(home, agent) {
16169
16329
  assertSafePath(home);
16170
- const realHome = realpathSync9(home), alias = join23(realHome, `.${agent}`);
16171
- const stat = lstatSync19(alias, { throwIfNoEntry: false, bigint: true });
16330
+ const realHome = realpathSync10(home), alias = join23(realHome, `.${agent}`);
16331
+ const stat = lstatSync20(alias, { throwIfNoEntry: false, bigint: true });
16172
16332
  if (!stat?.isSymbolicLink())
16173
16333
  throw new Error(`Agent root alias changed after planning: ${alias}`);
16174
- const link = readlinkSync5(alias), targetPath = resolve13(dirname14(alias), link);
16334
+ const link = readlinkSync6(alias), targetPath = resolve13(dirname14(alias), link);
16175
16335
  assertSafePath(targetPath);
16176
- const targetStat = lstatSync19(targetPath, { throwIfNoEntry: false });
16336
+ const targetStat = lstatSync20(targetPath, { throwIfNoEntry: false });
16177
16337
  if (!targetStat?.isDirectory())
16178
16338
  throw new Error(`Agent root alias must target an existing directory: ${alias}`);
16179
- const target = realpathSync9(targetPath), inside = relative6(realHome, target);
16180
- if (!inside || inside === ".." || inside.startsWith(`..${sep7}`) || isAbsolute13(inside))
16339
+ const target = realpathSync10(targetPath), inside = relative6(realHome, target);
16340
+ if (!inside || inside === ".." || inside.startsWith(`..${sep7}`) || isAbsolute14(inside))
16181
16341
  throw new Error(`Agent root alias target must be inside the real home: ${alias}`);
16182
16342
  return { agent, home: realHome, alias, target, link, aliasIdentity: `${stat.dev}:${stat.ino}:${stat.ctimeNs}`, targetIdentity: `${targetStat.dev}:${targetStat.ino}` };
16183
16343
  }
@@ -16186,7 +16346,7 @@ function rootAliases(home, allowed = false) {
16186
16346
  return [];
16187
16347
  const result = [];
16188
16348
  for (const agent of ["claude", "codex"])
16189
- if (lstatSync19(join23(home, `.${agent}`), { throwIfNoEntry: false })?.isSymbolicLink())
16349
+ if (lstatSync20(join23(home, `.${agent}`), { throwIfNoEntry: false })?.isSymbolicLink())
16190
16350
  result.push(readRootAlias(home, agent));
16191
16351
  if (result.some((item, index) => result.slice(index + 1).some((other) => item.target === other.target || item.target.startsWith(other.target + sep7) || other.target.startsWith(item.target + sep7))))
16192
16352
  throw new Error("Agent root alias targets must not overlap");
@@ -16203,17 +16363,17 @@ function disabledCodexSkillPaths(config, aliases) {
16203
16363
  const rows = skills.config;
16204
16364
  if (!Array.isArray(rows))
16205
16365
  return [];
16206
- 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" || !isAbsolute13(entry.path)) || entry.name !== undefined && (typeof entry.name !== "string" || !entry.name.trim())))
16366
+ 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" || !isAbsolute14(entry.path)) || entry.name !== undefined && (typeof entry.name !== "string" || !entry.name.trim())))
16207
16367
  return [];
16208
16368
  if (rows.some((entry) => entry.name !== undefined && entry.enabled !== false))
16209
16369
  return [];
16210
16370
  const settings = new Map;
16211
16371
  for (const entry of rows) {
16212
- if (typeof entry.path !== "string" || !isAbsolute13(entry.path))
16372
+ if (typeof entry.path !== "string" || !isAbsolute14(entry.path))
16213
16373
  continue;
16214
16374
  let document2;
16215
16375
  try {
16216
- document2 = realpathSync9(canonicalAgentPath(entry.path, aliases));
16376
+ document2 = realpathSync10(canonicalAgentPath(entry.path, aliases));
16217
16377
  } catch {
16218
16378
  continue;
16219
16379
  }
@@ -16234,16 +16394,16 @@ function recheckRootAliases(aliases) {
16234
16394
  }
16235
16395
  function nativeSourceDigest(path) {
16236
16396
  assertSafePath(path);
16237
- return lstatSync19(path, { throwIfNoEntry: false }) ? sha3(readNativeBytes(path, 1024 * 1024)) : null;
16397
+ return lstatSync20(path, { throwIfNoEntry: false }) ? sha3(readNativeBytes(path, 1024 * 1024)) : null;
16238
16398
  }
16239
16399
  function readNativeBytes(path, maximum = 64 * 1024 * 1024) {
16240
16400
  assertSafePath(path);
16241
- const before = lstatSync19(path);
16401
+ const before = lstatSync20(path);
16242
16402
  if (!before.isFile() || before.size > maximum)
16243
16403
  throw new Error("Unsupported or oversized native skill file");
16244
- const descriptor = openSync10(path, constants10.O_RDONLY | constants10.O_NOFOLLOW | constants10.O_NONBLOCK);
16404
+ const descriptor = openSync11(path, constants11.O_RDONLY | constants11.O_NOFOLLOW | constants11.O_NONBLOCK);
16245
16405
  try {
16246
- const opened = fstatSync10(descriptor);
16406
+ const opened = fstatSync11(descriptor);
16247
16407
  if (!opened.isFile() || opened.dev !== before.dev || opened.ino !== before.ino || opened.size !== before.size)
16248
16408
  throw new Error("Native skill file changed while reading");
16249
16409
  const bytes = Buffer.allocUnsafe(before.size + 1);
@@ -16254,19 +16414,19 @@ function readNativeBytes(path, maximum = 64 * 1024 * 1024) {
16254
16414
  break;
16255
16415
  length += count;
16256
16416
  }
16257
- const after = fstatSync10(descriptor), current = lstatSync19(path);
16417
+ const after = fstatSync11(descriptor), current = lstatSync20(path);
16258
16418
  if (current.dev !== opened.dev || current.ino !== opened.ino || current.size !== after.size || current.mtimeMs !== after.mtimeMs || current.ctimeMs !== after.ctimeMs || length !== before.size || after.size !== before.size || after.mtimeMs !== opened.mtimeMs || after.ctimeMs !== opened.ctimeMs)
16259
16419
  throw new Error("Native skill file changed while reading");
16260
16420
  return bytes.subarray(0, length);
16261
16421
  } finally {
16262
- closeSync10(descriptor);
16422
+ closeSync11(descriptor);
16263
16423
  }
16264
16424
  }
16265
16425
  function treeHash(root) {
16266
- const hash2 = createHash18("sha256");
16426
+ const hash2 = createHash19("sha256");
16267
16427
  let bytes = 0, files = 0;
16268
16428
  function visit2(path) {
16269
- const stat = lstatSync19(path);
16429
+ const stat = lstatSync20(path);
16270
16430
  if (stat.isSymbolicLink())
16271
16431
  throw new Error(`Refusing symlink in skill: ${path}`);
16272
16432
  const rel = relative6(root, path);
@@ -16295,13 +16455,13 @@ function selectNativeMigrationTargets(inventory, manifest) {
16295
16455
  const identities = new Set;
16296
16456
  const selected = [];
16297
16457
  for (const target of manifest.targets) {
16298
- if (!isAbsolute13(target.projectRoot) || resolve13(target.projectRoot) !== target.projectRoot)
16458
+ if (!isAbsolute14(target.projectRoot) || resolve13(target.projectRoot) !== target.projectRoot)
16299
16459
  throw new Error(`Native migration target project root must be an existing absolute directory: ${target.projectRoot}`);
16300
16460
  const projectRoot = canonicalSystemPath(target.projectRoot), normalized = relative6(projectRoot, resolve13(projectRoot, target.path));
16301
- if (!existsSync9(projectRoot) || !lstatSync19(projectRoot).isDirectory())
16461
+ if (!existsSync9(projectRoot) || !lstatSync20(projectRoot).isDirectory())
16302
16462
  throw new Error(`Native migration target project root must be an existing absolute directory: ${target.projectRoot}`);
16303
16463
  assertSafePath(projectRoot);
16304
- if (isAbsolute13(target.path) || target.path.includes("\\") || target.path.includes("\x00") || !normalized || normalized === ".." || normalized.startsWith(`..${sep7}`) || normalized !== target.path || !/^[0-9a-f]{64}$/.test(target.treeSha256))
16464
+ if (isAbsolute14(target.path) || target.path.includes("\\") || target.path.includes("\x00") || !normalized || normalized === ".." || normalized.startsWith(`..${sep7}`) || normalized !== target.path || !/^[0-9a-f]{64}$/.test(target.treeSha256))
16305
16465
  throw new Error(`Invalid native migration target: ${target.path}`);
16306
16466
  const identity5 = `${target.agent}\x00${canonicalSystemPath(projectRoot)}\x00${normalized}`;
16307
16467
  if (identities.has(identity5))
@@ -16344,9 +16504,9 @@ function isCodexSkillDiscoveryInput(path) {
16344
16504
  }
16345
16505
  function inventoryNativeSkills(home = homedir2(), options = {}) {
16346
16506
  home = canonicalSystemPath(home);
16347
- if (options.reviewedCacheAlias !== undefined && (!options.includeVendor || !isAbsolute13(options.reviewedCacheAlias) || resolve13(options.reviewedCacheAlias) !== options.reviewedCacheAlias))
16507
+ if (options.reviewedCacheAlias !== undefined && (!options.includeVendor || !isAbsolute14(options.reviewedCacheAlias) || resolve13(options.reviewedCacheAlias) !== options.reviewedCacheAlias))
16348
16508
  throw new Error("A reviewed cache alias requires vendor inventory and an exact absolute path");
16349
- if (options.disabledVendorPaths?.some((path) => !isAbsolute13(path) || resolve13(path) !== path))
16509
+ if (options.disabledVendorPaths?.some((path) => !isAbsolute14(path) || resolve13(path) !== path))
16350
16510
  throw new Error("Disabled vendor paths must be exact absolute paths");
16351
16511
  const reviewedCacheAlias = options.reviewedCacheAlias === undefined ? undefined : canonicalSystemPath(options.reviewedCacheAlias);
16352
16512
  const disabledVendorPaths = new Set((options.disabledVendorPaths ?? []).map(canonicalSystemPath));
@@ -16365,7 +16525,7 @@ function inventoryNativeSkills(home = homedir2(), options = {}) {
16365
16525
  roots.push(["sumi", canonicalAgentPath(join23(project, directory, name), aliases)]);
16366
16526
  }
16367
16527
  const installationInputs = options.codexInstallationInputRoots ?? [];
16368
- if (installationInputs.some((input) => resolve13(input) !== input || realpathSync9(input) !== input || roots.some(([agent, path]) => agent === "codex" && (path === input || path.startsWith(input + sep7) || input.startsWith(path + sep7)))))
16528
+ if (installationInputs.some((input) => resolve13(input) !== input || realpathSync10(input) !== input || roots.some(([agent, path]) => agent === "codex" && (path === input || path.startsWith(input + sep7) || input.startsWith(path + sep7)))))
16369
16529
  throw new Error("Native installation input overlaps an unconditional skill-loading root");
16370
16530
  const entries = [], seen = new Set;
16371
16531
  const cacheScans = new Map, maxAliasProofEntries = 1e4;
@@ -16379,13 +16539,13 @@ function inventoryNativeSkills(home = homedir2(), options = {}) {
16379
16539
  }
16380
16540
  let reviewedCacheAliasFound = false;
16381
16541
  function verifiedSiblingCacheAlias(agent, path, parent) {
16382
- const link = readlinkSync5(path), lexicalTarget = resolve13(parent, link);
16383
- if (isAbsolute13(link) ? link !== lexicalTarget : dirname14(link) !== ".")
16542
+ const link = readlinkSync6(path), lexicalTarget = resolve13(parent, link);
16543
+ if (isAbsolute14(link) ? link !== lexicalTarget : dirname14(link) !== ".")
16384
16544
  return false;
16385
16545
  const target = canonicalSystemPath(lexicalTarget);
16386
16546
  if (dirname14(target) !== parent)
16387
16547
  return false;
16388
- if (!lstatSync19(target, { throwIfNoEntry: false })?.isDirectory())
16548
+ if (!lstatSync20(target, { throwIfNoEntry: false })?.isDirectory())
16389
16549
  return false;
16390
16550
  const scan = cacheScans.get(target);
16391
16551
  if (!scan?.complete || scan.entries > maxAliasProofEntries)
@@ -16410,7 +16570,7 @@ function inventoryNativeSkills(home = homedir2(), options = {}) {
16410
16570
  return scan;
16411
16571
  if (!existsSync9(path))
16412
16572
  return scan;
16413
- const stat = lstatSync19(path);
16573
+ const stat = lstatSync20(path);
16414
16574
  if (stat.isFile()) {
16415
16575
  if (agent === "sumi" && depth === 1 && path.endsWith(".md"))
16416
16576
  throw new Error("NATIVE_SKILL_DRIFT: flat Sumi skill documents require a dedicated migration adapter");
@@ -16427,7 +16587,7 @@ function inventoryNativeSkills(home = homedir2(), options = {}) {
16427
16587
  const marker = join23(path, ".hasna-skills.json");
16428
16588
  if (existsSync9(marker)) {
16429
16589
  try {
16430
- managed = JSON.parse(readFileSync14(marker, "utf8")).managedBy === "@hasna/skills";
16590
+ managed = JSON.parse(readFileSync15(marker, "utf8")).managedBy === "@hasna/skills";
16431
16591
  } catch {}
16432
16592
  }
16433
16593
  const bridge = (!vendor || agent === "sumi") && isOwnedCliBridge(path, bridgePaths);
@@ -16459,7 +16619,7 @@ function inventoryNativeSkills(home = homedir2(), options = {}) {
16459
16619
  if (isVendor && !options.includeVendor)
16460
16620
  continue;
16461
16621
  const child = join23(path, name);
16462
- if (isVendor && lstatSync19(child, { throwIfNoEntry: false })?.isSymbolicLink()) {
16622
+ if (isVendor && lstatSync20(child, { throwIfNoEntry: false })?.isSymbolicLink()) {
16463
16623
  const target = statSync9(child, { throwIfNoEntry: false });
16464
16624
  if (target?.isFile() || pluginCache && target?.isDirectory() && verifiedSiblingCacheAlias(agent, child, path)) {
16465
16625
  scan.entries++;
@@ -16502,7 +16662,7 @@ function inventoryNativeSkills(home = homedir2(), options = {}) {
16502
16662
  }
16503
16663
  function readOptional(path) {
16504
16664
  assertSafePath(path);
16505
- return existsSync9(path) ? readFileSync14(path, "utf8") : null;
16665
+ return existsSync9(path) ? readFileSync15(path, "utf8") : null;
16506
16666
  }
16507
16667
  function jsonObject(text2, path) {
16508
16668
  if (text2 === null)
@@ -16834,23 +16994,23 @@ function projectedHookAcl(path, observed) {
16834
16994
  if (process.platform !== "darwin")
16835
16995
  return;
16836
16996
  const identity5 = (stat) => `${stat.dev}:${stat.ino}:${stat.ctimeNs}:${stat.uid}:${stat.mode}:${stat.nlink}:${stat.size}:${stat.mtimeNs}`;
16837
- const fd = openSync10(path, constants10.O_RDONLY | constants10.O_NOFOLLOW | constants10.O_NONBLOCK | (observed.isDirectory() ? constants10.O_DIRECTORY : 0));
16997
+ const fd = openSync11(path, constants11.O_RDONLY | constants11.O_NOFOLLOW | constants11.O_NONBLOCK | (observed.isDirectory() ? constants11.O_DIRECTORY : 0));
16838
16998
  try {
16839
- if (identity5(fstatSync10(fd, { bigint: true })) !== identity5(observed) || !hasTrustedDarwinAcl(fd, true) || identity5(fstatSync10(fd, { bigint: true })) !== identity5(observed) || identity5(lstatSync19(path, { bigint: true })) !== identity5(observed))
16999
+ if (identity5(fstatSync11(fd, { bigint: true })) !== identity5(observed) || !hasTrustedDarwinAcl(fd, true) || identity5(fstatSync11(fd, { bigint: true })) !== identity5(observed) || identity5(lstatSync20(path, { bigint: true })) !== identity5(observed))
16840
17000
  hookProjectionRefusal("EXECUTABLE_UNVERIFIED");
16841
17001
  } finally {
16842
- closeSync10(fd);
17002
+ closeSync11(fd);
16843
17003
  }
16844
17004
  }
16845
17005
  function projectedHookExecutable(command, expectedResolved) {
16846
17006
  try {
16847
- if (!isAbsolute13(command) || /[\0\r\n]/.test(command) || resolve13(command) !== command)
17007
+ if (!isAbsolute14(command) || /[\0\r\n]/.test(command) || resolve13(command) !== command)
16848
17008
  hookProjectionRefusal("EXECUTABLE_UNVERIFIED");
16849
17009
  command = canonicalSystemPath(command);
16850
17010
  const parents2 = (file = command) => {
16851
17011
  const result = [];
16852
17012
  for (let path = dirname14(file);; path = dirname14(path)) {
16853
- const stat = lstatSync19(path, { bigint: true });
17013
+ const stat = lstatSync20(path, { bigint: true });
16854
17014
  if (!stat.isDirectory() || (stat.mode & 0o022n) !== 0n && !(stat.uid === 0n && (stat.mode & 0o1000n) !== 0n))
16855
17015
  hookProjectionRefusal("EXECUTABLE_UNVERIFIED");
16856
17016
  projectedHookAcl(path, stat);
@@ -16860,13 +17020,22 @@ function projectedHookExecutable(command, expectedResolved) {
16860
17020
  }
16861
17021
  return result;
16862
17022
  };
16863
- const parentIdentity = parents2(), link = lstatSync19(command, { bigint: true });
17023
+ const parentIdentity = parents2(), link = lstatSync20(command, { bigint: true });
16864
17024
  if (link.uid !== BigInt(process.getuid()) || !link.isFile() && !link.isSymbolicLink())
16865
17025
  hookProjectionRefusal("EXECUTABLE_UNVERIFIED");
16866
17026
  const linkIdentity = (stat) => `${stat.dev}:${stat.ino}:${stat.mode}:${stat.uid}:${stat.ctimeNs}`;
16867
- const resolved = realpathSync9(command);
17027
+ const target = resolveLauncherCommand(command), resolved = target.entry;
16868
17028
  if (expectedResolved !== undefined && resolved !== expectedResolved)
16869
17029
  hookProjectionRefusal("EXECUTABLE_UNVERIFIED");
17030
+ let launcher, launcherParentIdentity;
17031
+ if (target.pinned) {
17032
+ launcherParentIdentity = parents2(target.physical);
17033
+ launcher = snapshot(target.physical, false);
17034
+ projectedHookAcl(launcher.file, launcher.stat);
17035
+ if (launcher.sha256 !== target.pinned.sha256 || (launcher.stat.mode & 0o100n) === 0n)
17036
+ hookProjectionRefusal("EXECUTABLE_UNVERIFIED");
17037
+ assertPinnedLauncherRuntimeSafe(target.pinned.runtime);
17038
+ }
16870
17039
  const resolvedParentIdentity = parents2(resolved);
16871
17040
  const manifest = snapshot(join23(dirname14(dirname14(resolved)), "package.json"), false, { readOnlyPackage: true });
16872
17041
  projectedHookAcl(manifest.file, manifest.stat);
@@ -16879,8 +17048,15 @@ function projectedHookExecutable(command, expectedResolved) {
16879
17048
  hookProjectionRefusal("EXECUTABLE_UNVERIFIED");
16880
17049
  const recheck = () => {
16881
17050
  try {
16882
- if (realpathSync9(command) !== resolved || linkIdentity(lstatSync19(command, { bigint: true })) !== linkIdentity(link) || !isDeepStrictEqual6(parents2(), parentIdentity) || !isDeepStrictEqual6(parents2(resolved), resolvedParentIdentity))
17051
+ const again = resolveLauncherCommand(command);
17052
+ if (again.entry !== resolved || again.physical !== target.physical || linkIdentity(lstatSync20(command, { bigint: true })) !== linkIdentity(link) || !isDeepStrictEqual6(parents2(), parentIdentity) || !isDeepStrictEqual6(parents2(resolved), resolvedParentIdentity))
16883
17053
  hookProjectionRefusal("EXECUTABLE_UNVERIFIED");
17054
+ if (launcher) {
17055
+ if (!isDeepStrictEqual6(parents2(target.physical), launcherParentIdentity))
17056
+ hookProjectionRefusal("EXECUTABLE_UNVERIFIED");
17057
+ projectedHookAcl(launcher.file, launcher.stat);
17058
+ unchanged2(launcher);
17059
+ }
16884
17060
  projectedHookAcl(cli.file, cli.stat);
16885
17061
  projectedHookAcl(manifest.file, manifest.stat);
16886
17062
  unchanged2(cli);
@@ -17002,7 +17178,7 @@ function claudeSettingsConsumers(home, path, discoveries, aliases) {
17002
17178
  const canonical6 = (value) => canonicalAgentPath(value, aliases);
17003
17179
  const containsSettings = (root) => {
17004
17180
  const distance = relative6(canonical6(root), path);
17005
- return distance === "" || distance !== ".." && !distance.startsWith(`..${sep7}`) && !isAbsolute13(distance);
17181
+ return distance === "" || distance !== ".." && !distance.startsWith(`..${sep7}`) && !isAbsolute14(distance);
17006
17182
  };
17007
17183
  return discoveries.filter((binding) => binding.agent === "claude" || binding.agent === "opencode" || canonical6(join23(home, AGENT_ADAPTERS[binding.agent].config)) === path || binding.sources.some((source) => canonical6(source.path) === path) || binding.roots.some(containsSettings) || binding.directories?.some((directory) => containsSettings(directory.path))).map((binding) => binding.agent);
17008
17184
  }
@@ -17035,7 +17211,7 @@ function planClaudeHookEventsUpdate(options) {
17035
17211
  recheckRootAliases(aliases);
17036
17212
  const path = canonicalAgentPath(join23(home, ".claude", "settings.json"), aliases);
17037
17213
  assertSafePath(path);
17038
- const before = lstatSync19(path, { throwIfNoEntry: false }) ? new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(readNativeBytes(path, 1024 * 1024)) : null;
17214
+ const before = lstatSync20(path, { throwIfNoEntry: false }) ? new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(readNativeBytes(path, 1024 * 1024)) : null;
17039
17215
  if ((before === null ? "absent" : sha3(before)) !== options.expectedSettingsSha256)
17040
17216
  throw new Error("Claude settings preimage changed");
17041
17217
  assertClaudeHookEventsReplacement(before, options.replacement, options.events);
@@ -17102,6 +17278,8 @@ function atomicWrite2(path, content) {
17102
17278
  function planAgentSettingsWitnessUpgrade(options) {
17103
17279
  if (options.targetCodexVersion !== undefined && (options.agent !== "codex" || ![2, 3, 4].includes(options.targetCodexVersion)))
17104
17280
  throw new Error("Invalid Codex witness target version");
17281
+ if (options.targetClaudeVersion !== undefined && (options.agent !== "claude" || ![3, 4].includes(options.targetClaudeVersion)))
17282
+ throw new Error("Invalid Claude witness target version");
17105
17283
  const home = resolve13(options.home ?? homedir2()), dataDir2 = options.dataDir ?? getDataDirReadOnly();
17106
17284
  const snapshot2 = readManagedSkillPolicySnapshot(dataDir2);
17107
17285
  if (!snapshot2 || sha3(snapshot2.text) !== options.expectedPolicySha256)
@@ -17149,7 +17327,7 @@ function planAgentSettingsWitnessUpgrade(options) {
17149
17327
  replaced.push(source);
17150
17328
  }
17151
17329
  }
17152
- const next = options.agent === "sumi" ? upgradeSumiSettingsWitness(previous, options.reviewedPreimage) : options.agent === "claude" ? upgradeClaudeSettingsWitness(previous, options.reviewedPreimage) : options.targetCodexVersion === 4 ? upgradeCodexSettingsWitnessV4(previous, options.reviewedPreimage) : options.targetCodexVersion === 3 ? upgradeCodexSettingsWitnessV3(previous, options.reviewedPreimage) : upgradeCodexSettingsWitness(previous, options.reviewedPreimage);
17330
+ const next = options.agent === "sumi" ? upgradeSumiSettingsWitness(previous, options.reviewedPreimage) : options.agent === "claude" ? options.targetClaudeVersion === 4 ? upgradeClaudeSettingsWitnessV4(previous, options.reviewedPreimage) : upgradeClaudeSettingsWitness(previous, options.reviewedPreimage) : options.targetCodexVersion === 4 ? upgradeCodexSettingsWitnessV4(previous, options.reviewedPreimage) : options.targetCodexVersion === 3 ? upgradeCodexSettingsWitnessV3(previous, options.reviewedPreimage) : upgradeCodexSettingsWitness(previous, options.reviewedPreimage);
17153
17331
  const rebound = [];
17154
17332
  for (const source of binding.sources) {
17155
17333
  if (!replaced.includes(source)) {
@@ -17195,7 +17373,7 @@ function applyAgentIntegrationUnlocked(plan, options = {}, assertCurrent) {
17195
17373
  const upgrade = plan.settingsWitnessUpgrade;
17196
17374
  if (!plan.managedAgentChecks || !plan.observedPolicy?.before)
17197
17375
  throw new Error("Invalid settings witness upgrade plan");
17198
- const verified = planAgentSettingsWitnessUpgrade({ agent: upgrade.agent, ...upgrade.agent === "codex" ? { targetCodexVersion: upgrade.toHashMode === "codex-settings-v4" ? 4 : upgrade.toHashMode === "codex-settings-v3" ? 3 : 2 } : {}, reviewedPreimage: upgrade.reviewedPreimage, home: plan.managedAgentChecks.home, dataDir: plan.dataDir, expectedPolicySha256: sha3(plan.observedPolicy.before), expectedSettingsSha256: upgrade.currentSettingsSha256 });
17376
+ const verified = planAgentSettingsWitnessUpgrade({ agent: upgrade.agent, ...upgrade.agent === "codex" ? { targetCodexVersion: upgrade.toHashMode === "codex-settings-v4" ? 4 : upgrade.toHashMode === "codex-settings-v3" ? 3 : 2 } : {}, ...upgrade.agent === "claude" && upgrade.toHashMode === "claude-settings-v4" ? { targetClaudeVersion: 4 } : {}, reviewedPreimage: upgrade.reviewedPreimage, home: plan.managedAgentChecks.home, dataDir: plan.dataDir, expectedPolicySha256: sha3(plan.observedPolicy.before), expectedSettingsSha256: upgrade.currentSettingsSha256 });
17199
17377
  if (JSON.stringify(verified.changes) !== JSON.stringify(plan.changes) || JSON.stringify(verified.settingsWitnessUpgrade) !== JSON.stringify(upgrade))
17200
17378
  throw new Error("Settings witness upgrade plan changed");
17201
17379
  provenDiscovery = verified.discoveryBefore[0];
@@ -17226,7 +17404,7 @@ function applyAgentIntegrationUnlocked(plan, options = {}, assertCurrent) {
17226
17404
  if (change.before !== null) {
17227
17405
  const backup = join23(backupRoot, `${index}-${sha3(change.path).slice(0, 12)}.backup`);
17228
17406
  writeFileSync6(backup, change.before, { mode: 384, flag: "wx" });
17229
- if (readFileSync14(backup, "utf8") !== change.before)
17407
+ if (readFileSync15(backup, "utf8") !== change.before)
17230
17408
  throw new Error("Native configuration preservation readback failed");
17231
17409
  backups.push(backup);
17232
17410
  }
@@ -17289,11 +17467,11 @@ function applyAgentIntegrationUnlocked(plan, options = {}, assertCurrent) {
17289
17467
  }
17290
17468
  function syncArchiveDirectory(path) {
17291
17469
  assertSafePath(path);
17292
- const descriptor = openSync10(path, constants10.O_RDONLY | constants10.O_DIRECTORY | constants10.O_NOFOLLOW | constants10.O_NONBLOCK);
17470
+ const descriptor = openSync11(path, constants11.O_RDONLY | constants11.O_DIRECTORY | constants11.O_NOFOLLOW | constants11.O_NONBLOCK);
17293
17471
  try {
17294
- fsyncSync4(descriptor);
17472
+ fsyncSync5(descriptor);
17295
17473
  } finally {
17296
- closeSync10(descriptor);
17474
+ closeSync11(descriptor);
17297
17475
  }
17298
17476
  }
17299
17477
  function writeArchiveJournal(path, value) {
@@ -17301,18 +17479,18 @@ function writeArchiveJournal(path, value) {
17301
17479
  const temporary = `${path}.skills-${randomUUID3()}`;
17302
17480
  let descriptor;
17303
17481
  try {
17304
- descriptor = openSync10(temporary, constants10.O_WRONLY | constants10.O_CREAT | constants10.O_EXCL | constants10.O_NOFOLLOW, 384);
17482
+ descriptor = openSync11(temporary, constants11.O_WRONLY | constants11.O_CREAT | constants11.O_EXCL | constants11.O_NOFOLLOW, 384);
17305
17483
  writeFileSync6(descriptor, `${JSON.stringify(value)}
17306
17484
  `);
17307
- fsyncSync4(descriptor);
17308
- closeSync10(descriptor);
17485
+ fsyncSync5(descriptor);
17486
+ closeSync11(descriptor);
17309
17487
  descriptor = undefined;
17310
17488
  renameSync3(temporary, path);
17311
17489
  syncArchiveDirectory(dirname14(path));
17312
17490
  } finally {
17313
17491
  if (descriptor !== undefined)
17314
- closeSync10(descriptor);
17315
- if (lstatSync19(temporary, { throwIfNoEntry: false }))
17492
+ closeSync11(descriptor);
17493
+ if (lstatSync20(temporary, { throwIfNoEntry: false }))
17316
17494
  unlinkSync4(temporary);
17317
17495
  }
17318
17496
  }
@@ -17358,7 +17536,7 @@ function archiveNativeSkillsUnlocked(inventory, options, assertCurrent) {
17358
17536
  const moved = [];
17359
17537
  const verifyArchive = (entry) => {
17360
17538
  assertSafePath(entry.archive);
17361
- const stat = lstatSync19(entry.archive);
17539
+ const stat = lstatSync20(entry.archive);
17362
17540
  if (entry.discoveryOnly ? !stat.isFile() : !stat.isDirectory())
17363
17541
  throw new Error("Archive type changed");
17364
17542
  if ((entry.discoveryOnly ? sha3(readNativeBytes(entry.archive)) : treeHash(entry.archive)) !== entry.hash)
@@ -17409,7 +17587,7 @@ function archiveNativeSkillsUnlocked(inventory, options, assertCurrent) {
17409
17587
  recheckRootAliases(aliases);
17410
17588
  assertSafePath(entry.source);
17411
17589
  assertSafePath(entry.archive);
17412
- if (lstatSync19(entry.source, { throwIfNoEntry: false })) {
17590
+ if (lstatSync20(entry.source, { throwIfNoEntry: false })) {
17413
17591
  entry.status = "recovery-required";
17414
17592
  entry.conflict = "source-occupied";
17415
17593
  continue;
@@ -17426,7 +17604,7 @@ function archiveNativeSkillsUnlocked(inventory, options, assertCurrent) {
17426
17604
  syncArchiveDirectory(dirname14(entry.source));
17427
17605
  unlinkSync4(entry.archive);
17428
17606
  } else {
17429
- if (lstatSync19(entry.source, { throwIfNoEntry: false })) {
17607
+ if (lstatSync20(entry.source, { throwIfNoEntry: false })) {
17430
17608
  entry.status = "recovery-required";
17431
17609
  entry.conflict = "source-occupied";
17432
17610
  continue;
@@ -17459,12 +17637,12 @@ function isInertCodexPluginCacheCopy(entry, cache, allowedHostPaths, read2) {
17459
17637
  return false;
17460
17638
  const document2 = join23(entry.path, "SKILL.md");
17461
17639
  const inside = relative6(cache, entry.path);
17462
- if (!inside || isAbsolute13(inside) || inside.split(sep7).some((segment) => segment === ".."))
17640
+ if (!inside || isAbsolute14(inside) || inside.split(sep7).some((segment) => segment === ".."))
17463
17641
  return false;
17464
17642
  assertSafePath(entry.path);
17465
- if (!lstatSync19(cache).isDirectory() || !lstatSync19(entry.path).isDirectory() || !lstatSync19(document2).isFile())
17643
+ if (!lstatSync20(cache).isDirectory() || !lstatSync20(entry.path).isDirectory() || !lstatSync20(document2).isFile())
17466
17644
  return false;
17467
- if (realpathSync9.native(cache) !== cache || realpathSync9.native(entry.path) !== entry.path || realpathSync9.native(document2) !== document2)
17645
+ if (realpathSync10.native(cache) !== cache || realpathSync10.native(entry.path) !== entry.path || realpathSync10.native(document2) !== document2)
17468
17646
  return false;
17469
17647
  if (!classifyCodexPluginCacheDocument(document2, cache, read2))
17470
17648
  return false;
@@ -17641,9 +17819,9 @@ function isSkillsOwnershipMarker(marker) {
17641
17819
  function hasSkillsOwnershipMarker(dir) {
17642
17820
  const path = join25(dir, SYNC_MARKER_FILE);
17643
17821
  try {
17644
- if (!lstatSync20(path).isFile())
17822
+ if (!lstatSync21(path).isFile())
17645
17823
  return false;
17646
- const marker = JSON.parse(readFileSync15(path, "utf8"));
17824
+ const marker = JSON.parse(readFileSync16(path, "utf8"));
17647
17825
  return isSkillsOwnershipMarker(marker);
17648
17826
  } catch {
17649
17827
  return false;
@@ -17860,7 +18038,7 @@ function writeManagedSkillDirUnlocked(dir, skillMd, options, assertCurrent) {
17860
18038
  if (dirExists && managed && hasSkillMd && !options.force && isPointerSkillMd(skillMd)) {
17861
18039
  let existingIsStub = false;
17862
18040
  try {
17863
- existingIsStub = isPointerSkillMd(readFileSync15(skillMdPath, "utf-8"));
18041
+ existingIsStub = isPointerSkillMd(readFileSync16(skillMdPath, "utf-8"));
17864
18042
  } catch {
17865
18043
  existingIsStub = false;
17866
18044
  }
@@ -17910,7 +18088,7 @@ function writeManagedSkillDirUnlocked(dir, skillMd, options, assertCurrent) {
17910
18088
  assertCurrent();
17911
18089
  renameDirectory(candidateDir, dir);
17912
18090
  assertCurrent();
17913
- if (readFileSync15(skillMdPath, "utf8") !== (skillMd.endsWith(`
18091
+ if (readFileSync16(skillMdPath, "utf8") !== (skillMd.endsWith(`
17914
18092
  `) ? skillMd : `${skillMd}
17915
18093
  `))
17916
18094
  throw new Error("Managed skill readback failed");
@@ -17954,7 +18132,7 @@ function sourceSkillMd(skillPath, name, description, kind, preferBundledDocs = f
17954
18132
  if (kind === undefined || kind === "instruction" || preferBundledDocs) {
17955
18133
  const skillMdPath = join25(skillPath, "SKILL.md");
17956
18134
  if (existsSync10(skillMdPath))
17957
- return readFileSync15(skillMdPath, "utf-8");
18135
+ return readFileSync16(skillMdPath, "utf-8");
17958
18136
  }
17959
18137
  return pointerSkillMd(name, description);
17960
18138
  }
@@ -17994,7 +18172,7 @@ function resolveSkillAlias(name) {
17994
18172
  }
17995
18173
 
17996
18174
  // src/lib/project-state.ts
17997
- import { existsSync as existsSync11, mkdirSync as mkdirSync8, readFileSync as readFileSync16, writeFileSync as writeFileSync8 } from "fs";
18175
+ import { existsSync as existsSync11, mkdirSync as mkdirSync8, readFileSync as readFileSync17, writeFileSync as writeFileSync8 } from "fs";
17998
18176
  import { join as join26 } from "path";
17999
18177
  var VALID_PIN_SOURCES = [
18000
18178
  "official",
@@ -18020,7 +18198,7 @@ function loadProjectConfig(targetDir = process.cwd()) {
18020
18198
  if (!existsSync11(path))
18021
18199
  return null;
18022
18200
  try {
18023
- return normalizeProjectConfig(JSON.parse(readFileSync16(path, "utf-8")));
18201
+ return normalizeProjectConfig(JSON.parse(readFileSync17(path, "utf-8")));
18024
18202
  } catch {
18025
18203
  return null;
18026
18204
  }
@@ -18207,7 +18385,7 @@ function createLocalSkillManifest(name, generateSkillMd) {
18207
18385
  let skillMd = "";
18208
18386
  const skillMdPath = join27(sourcePath, "SKILL.md");
18209
18387
  if (existsSync12(skillMdPath)) {
18210
- skillMd = readFileSync17(skillMdPath, "utf-8");
18388
+ skillMd = readFileSync18(skillMdPath, "utf-8");
18211
18389
  } else if (generateSkillMd) {
18212
18390
  skillMd = generateSkillMd(name) ?? "";
18213
18391
  } else {
@@ -18333,7 +18511,7 @@ function resolveAgentSkillMd(name, generateSkillMd) {
18333
18511
  const sourcePath = getSkillPath(name);
18334
18512
  const skillMdPath = join27(sourcePath, "SKILL.md");
18335
18513
  if (existsSync12(skillMdPath))
18336
- return readFileSync17(skillMdPath, "utf-8");
18514
+ return readFileSync18(skillMdPath, "utf-8");
18337
18515
  if (generateSkillMd)
18338
18516
  return generateSkillMd(name);
18339
18517
  return generateMinimalSkillMd(name);
@@ -18389,14 +18567,14 @@ function readBundledSkillVersion(name) {
18389
18567
  if (!existsSync12(pkgPath))
18390
18568
  return "unknown";
18391
18569
  try {
18392
- const pkg = JSON.parse(readFileSync17(pkgPath, "utf-8"));
18570
+ const pkg = JSON.parse(readFileSync18(pkgPath, "utf-8"));
18393
18571
  return pkg.version || "unknown";
18394
18572
  } catch {
18395
18573
  return "unknown";
18396
18574
  }
18397
18575
  }
18398
18576
  function readFileIfExists(path) {
18399
- return existsSync12(path) ? readFileSync17(path, "utf-8") : null;
18577
+ return existsSync12(path) ? readFileSync18(path, "utf-8") : null;
18400
18578
  }
18401
18579
  function loadProjectConfigCompat(targetDir) {
18402
18580
  return loadProjectConfig(targetDir);
@@ -18444,7 +18622,7 @@ function isInstructionSkillDir(skillPath, meta) {
18444
18622
  if (!existsSync13(skillMdPath))
18445
18623
  return false;
18446
18624
  try {
18447
- return parseSkillFrontmatter(readFileSync18(skillMdPath, "utf-8"))?.kind === "instruction";
18625
+ return parseSkillFrontmatter(readFileSync19(skillMdPath, "utf-8"))?.kind === "instruction";
18448
18626
  } catch {
18449
18627
  return false;
18450
18628
  }
@@ -18495,7 +18673,7 @@ function getSkillRequirements(name) {
18495
18673
  const meta = getSkill(name);
18496
18674
  let dependencies = {};
18497
18675
  try {
18498
- dependencies = JSON.parse(readFileSync18(join28(skillPath, "package.json"), "utf8")).dependencies || {};
18676
+ dependencies = JSON.parse(readFileSync19(join28(skillPath, "package.json"), "utf8")).dependencies || {};
18499
18677
  } catch {}
18500
18678
  return getSkillRequirementsFromContent(name, texts, dependencies, meta);
18501
18679
  }
@@ -18563,7 +18741,7 @@ async function runSkill(name, args, options = {}) {
18563
18741
  }
18564
18742
  let entryPoint2;
18565
18743
  try {
18566
- const pkg = JSON.parse(readFileSync18(pkgPath, "utf-8"));
18744
+ const pkg = JSON.parse(readFileSync19(pkgPath, "utf-8"));
18567
18745
  if (pkg.bin) {
18568
18746
  const binValues = Object.values(pkg.bin);
18569
18747
  entryPoint2 = binValues[0];
@@ -18666,7 +18844,7 @@ function generateSkillMd(name) {
18666
18844
  const pkgPath = join28(skillPath, "package.json");
18667
18845
  if (existsSync13(pkgPath)) {
18668
18846
  try {
18669
- const pkg = JSON.parse(readFileSync18(pkgPath, "utf-8"));
18847
+ const pkg = JSON.parse(readFileSync19(pkgPath, "utf-8"));
18670
18848
  if (pkg.bin) {
18671
18849
  const binKeys = Object.keys(pkg.bin);
18672
18850
  if (binKeys.length > 0)
@@ -18742,7 +18920,7 @@ function extractEnvVars(text2) {
18742
18920
  function readIfExists(path) {
18743
18921
  try {
18744
18922
  if (existsSync13(path)) {
18745
- return readFileSync18(path, "utf-8");
18923
+ return readFileSync19(path, "utf-8");
18746
18924
  }
18747
18925
  } catch {}
18748
18926
  return null;
@@ -18869,7 +19047,7 @@ function exactProfileSelection(spec, profile) {
18869
19047
  }
18870
19048
 
18871
19049
  // src/lib/plugin-projection.ts
18872
- import { createHash as createHash19 } from "crypto";
19050
+ import { createHash as createHash20 } from "crypto";
18873
19051
  import { posix } from "path";
18874
19052
  var PLUGIN_PROJECTION_MANIFEST = "plugin-projection.json";
18875
19053
  var PLUGIN_PROJECTION_LIMITS = Object.freeze({ files: 1024, bytes: 64 * 1024 * 1024, fileBytes: 16 * 1024 * 1024, metadataBytes: 512 * 1024, registrations: 64, history: 128 });
@@ -18880,7 +19058,7 @@ function pluginNeed(value, message) {
18880
19058
  if (!value)
18881
19059
  pluginRefusal(message);
18882
19060
  }
18883
- var pluginHash = (bytes) => createHash19("sha256").update(bytes).digest("hex");
19061
+ var pluginHash = (bytes) => createHash20("sha256").update(bytes).digest("hex");
18884
19062
  function pluginObject(value) {
18885
19063
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
18886
19064
  }
@@ -19068,16 +19246,16 @@ function buildPluginProjection(entries) {
19068
19246
  }
19069
19247
 
19070
19248
  // src/lib/plugin-projection-store.ts
19071
- import { createHash as createHash20, randomUUID as randomUUID4 } from "crypto";
19072
- import { constants as constants11, closeSync as closeSync11, fchmodSync, fstatSync as fstatSync11, fsyncSync as fsyncSync5, linkSync as linkSync3, lstatSync as lstatSync21, mkdirSync as mkdirSync9, openSync as openSync11, opendirSync as opendirSync4, readSync as readSync9, renameSync as renameSync5, rmdirSync as rmdirSync3, rmSync as rmSync3, unlinkSync as unlinkSync5, writeSync as writeSync2 } from "fs";
19073
- import { dirname as dirname16, isAbsolute as isAbsolute14, join as join29, parse as parse6, resolve as resolve14 } from "path";
19074
- var READ_FLAGS = constants11.O_RDONLY | constants11.O_NOFOLLOW | constants11.O_NONBLOCK;
19075
- var WRITE_FLAGS = constants11.O_WRONLY | constants11.O_CREAT | constants11.O_EXCL | constants11.O_NOFOLLOW | constants11.O_NONBLOCK;
19249
+ import { createHash as createHash21, randomUUID as randomUUID4 } from "crypto";
19250
+ import { constants as constants12, closeSync as closeSync12, fchmodSync as fchmodSync2, fstatSync as fstatSync12, fsyncSync as fsyncSync6, linkSync as linkSync3, lstatSync as lstatSync22, mkdirSync as mkdirSync9, openSync as openSync12, opendirSync as opendirSync4, readSync as readSync9, renameSync as renameSync5, rmdirSync as rmdirSync3, rmSync as rmSync3, unlinkSync as unlinkSync5, writeSync as writeSync3 } from "fs";
19251
+ import { dirname as dirname16, isAbsolute as isAbsolute15, join as join29, parse as parse6, resolve as resolve14 } from "path";
19252
+ var READ_FLAGS = constants12.O_RDONLY | constants12.O_NOFOLLOW | constants12.O_NONBLOCK;
19253
+ var WRITE_FLAGS = constants12.O_WRONLY | constants12.O_CREAT | constants12.O_EXCL | constants12.O_NOFOLLOW | constants12.O_NONBLOCK;
19076
19254
  var uid = () => typeof process.getuid === "function" ? BigInt(process.getuid()) : undefined;
19077
19255
  var missing = (error) => Boolean(error && typeof error === "object" && "code" in error && error.code === "ENOENT");
19078
19256
  function stat(path) {
19079
19257
  try {
19080
- return lstatSync21(path, { bigint: true });
19258
+ return lstatSync22(path, { bigint: true });
19081
19259
  } catch (error) {
19082
19260
  if (missing(error))
19083
19261
  return null;
@@ -19085,7 +19263,7 @@ function stat(path) {
19085
19263
  }
19086
19264
  }
19087
19265
  function canonical6(path) {
19088
- pluginNeed(typeof path === "string" && path.length <= 8192 && isAbsolute14(path) && resolve14(path) === path && !/[\x00-\x1f\x7f]/.test(path), "Plugin storage paths must be canonical absolute paths");
19266
+ pluginNeed(typeof path === "string" && path.length <= 8192 && isAbsolute15(path) && resolve14(path) === path && !/[\x00-\x1f\x7f]/.test(path), "Plugin storage paths must be canonical absolute paths");
19089
19267
  }
19090
19268
  function owner(stats, system = false) {
19091
19269
  const current = uid();
@@ -19153,8 +19331,8 @@ function readBytes(path, maximum, kind) {
19153
19331
  fileShape(before, maximum, kind);
19154
19332
  let fd;
19155
19333
  try {
19156
- fd = openSync11(path, READ_FLAGS);
19157
- const opened = fstatSync11(fd, { bigint: true });
19334
+ fd = openSync12(path, READ_FLAGS);
19335
+ const opened = fstatSync12(fd, { bigint: true });
19158
19336
  same3(before, opened);
19159
19337
  fileShape(opened, maximum, kind);
19160
19338
  const bytes = new Uint8Array(Number(opened.size));
@@ -19165,7 +19343,7 @@ function readBytes(path, maximum, kind) {
19165
19343
  offset += count;
19166
19344
  }
19167
19345
  pluginNeed(readSync9(fd, new Uint8Array(1), 0, 1, null) === 0, "Plugin file grew while being read");
19168
- same3(opened, fstatSync11(fd, { bigint: true }));
19346
+ same3(opened, fstatSync12(fd, { bigint: true }));
19169
19347
  same3(opened, stat(path));
19170
19348
  verifyAncestors(chain);
19171
19349
  return bytes;
@@ -19175,7 +19353,7 @@ function readBytes(path, maximum, kind) {
19175
19353
  return pluginRefusal("Cannot safely read plugin file");
19176
19354
  } finally {
19177
19355
  if (fd !== undefined)
19178
- closeSync11(fd);
19356
+ closeSync12(fd);
19179
19357
  }
19180
19358
  }
19181
19359
  function exactPaths(entries) {
@@ -19285,16 +19463,16 @@ function verifyPluginTree(root, witnesses) {
19285
19463
  function writeExclusive(path, bytes, mode) {
19286
19464
  let fd, created;
19287
19465
  try {
19288
- fd = openSync11(path, WRITE_FLAGS, mode);
19289
- fchmodSync(fd, mode);
19290
- created = fstatSync11(fd, { bigint: true });
19466
+ fd = openSync12(path, WRITE_FLAGS, mode);
19467
+ fchmodSync2(fd, mode);
19468
+ created = fstatSync12(fd, { bigint: true });
19291
19469
  let offset = 0;
19292
19470
  while (offset < bytes.byteLength) {
19293
- const count = writeSync2(fd, bytes, offset, bytes.byteLength - offset);
19471
+ const count = writeSync3(fd, bytes, offset, bytes.byteLength - offset);
19294
19472
  pluginNeed(count > 0, "Plugin file write did not progress");
19295
19473
  offset += count;
19296
19474
  }
19297
- fsyncSync5(fd);
19475
+ fsyncSync6(fd);
19298
19476
  } catch (error) {
19299
19477
  if (created) {
19300
19478
  same3(created, stat(path), true);
@@ -19303,7 +19481,7 @@ function writeExclusive(path, bytes, mode) {
19303
19481
  throw error;
19304
19482
  } finally {
19305
19483
  if (fd !== undefined)
19306
- closeSync11(fd);
19484
+ closeSync12(fd);
19307
19485
  }
19308
19486
  }
19309
19487
  function materializePluginTree(root, entries) {
@@ -19406,11 +19584,11 @@ function pluginExecutableDigest(path) {
19406
19584
  fileShape(before, maximum, "executable");
19407
19585
  let fd;
19408
19586
  try {
19409
- fd = openSync11(path, READ_FLAGS);
19410
- const opened = fstatSync11(fd, { bigint: true });
19587
+ fd = openSync12(path, READ_FLAGS);
19588
+ const opened = fstatSync12(fd, { bigint: true });
19411
19589
  same3(before, opened);
19412
19590
  fileShape(opened, maximum, "executable");
19413
- const hash2 = createHash20("sha256"), buffer = new Uint8Array(64 * 1024);
19591
+ const hash2 = createHash21("sha256"), buffer = new Uint8Array(64 * 1024);
19414
19592
  let remaining = Number(opened.size);
19415
19593
  while (remaining > 0) {
19416
19594
  const count = readSync9(fd, buffer, 0, Math.min(buffer.byteLength, remaining), null);
@@ -19419,7 +19597,7 @@ function pluginExecutableDigest(path) {
19419
19597
  remaining -= count;
19420
19598
  }
19421
19599
  pluginNeed(readSync9(fd, buffer, 0, 1, null) === 0, "Plugin executable grew during hashing");
19422
- same3(opened, fstatSync11(fd, { bigint: true }));
19600
+ same3(opened, fstatSync12(fd, { bigint: true }));
19423
19601
  same3(opened, stat(path));
19424
19602
  verifyAncestors(chain);
19425
19603
  return `sha256:${hash2.digest("hex")}`;
@@ -19429,7 +19607,7 @@ function pluginExecutableDigest(path) {
19429
19607
  return pluginRefusal("Cannot safely hash plugin executable");
19430
19608
  } finally {
19431
19609
  if (fd !== undefined)
19432
- closeSync11(fd);
19610
+ closeSync12(fd);
19433
19611
  }
19434
19612
  }
19435
19613
 
@@ -19468,7 +19646,7 @@ function validatePluginTarget(value) {
19468
19646
  for (const registration of value.registrations) {
19469
19647
  pluginKeys(registration, ["scope", "projectPath"]);
19470
19648
  pluginNeed(registration.scope === "user" || registration.scope === "project", "Unsupported plugin registration scope");
19471
- pluginNeed(registration.scope === "user" ? registration.projectPath === null : typeof registration.projectPath === "string" && isAbsolute15(registration.projectPath) && resolve15(registration.projectPath) === registration.projectPath, "Plugin scope requires its exact project path");
19649
+ pluginNeed(registration.scope === "user" ? registration.projectPath === null : typeof registration.projectPath === "string" && isAbsolute16(registration.projectPath) && resolve15(registration.projectPath) === registration.projectPath, "Plugin scope requires its exact project path");
19472
19650
  const key = JSON.stringify([registration.scope, registration.projectPath]);
19473
19651
  pluginNeed(!scopes.has(key), "Duplicate plugin registration scope");
19474
19652
  scopes.add(key);
@@ -19476,7 +19654,7 @@ function validatePluginTarget(value) {
19476
19654
  for (const key of ["native", "resolver"]) {
19477
19655
  pluginKeys(value[key], key === "native" ? ["version", "executable", "digest"] : ["executable", "digest"]);
19478
19656
  pluginText(value[key].executable);
19479
- pluginNeed(isAbsolute15(value[key].executable) && resolve15(value[key].executable) === value[key].executable, "Plugin executable must have a canonical absolute path");
19657
+ pluginNeed(isAbsolute16(value[key].executable) && resolve15(value[key].executable) === value[key].executable, "Plugin executable must have a canonical absolute path");
19480
19658
  pluginDigest(value[key].digest);
19481
19659
  }
19482
19660
  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)");
@@ -19628,7 +19806,7 @@ function pluginResolverCommand(binding) {
19628
19806
  }
19629
19807
  function root(options) {
19630
19808
  const path = options.storeRoot ?? pluginAdmissionRoot();
19631
- pluginNeed(isAbsolute15(path) && resolve15(path) === path, "Invalid plugin admission store root");
19809
+ pluginNeed(isAbsolute16(path) && resolve15(path) === path, "Invalid plugin admission store root");
19632
19810
  return path;
19633
19811
  }
19634
19812
  function pluginBindingPath(storeRoot, id) {
@@ -19833,25 +20011,25 @@ function validateManagedPluginWitnesses(value) {
19833
20011
  pluginNeed(typeof item.bindingId === "string" && /^[a-f0-9]{64}$/.test(item.bindingId) && !seen.has(item.bindingId), "Invalid or duplicate managed plugin witness");
19834
20012
  seen.add(item.bindingId);
19835
20013
  pluginText(item.storeRoot);
19836
- pluginNeed(isAbsolute16(item.storeRoot) && resolve16(item.storeRoot) === item.storeRoot, "Invalid plugin receipt store path");
20014
+ pluginNeed(isAbsolute17(item.storeRoot) && resolve16(item.storeRoot) === item.storeRoot, "Invalid plugin receipt store path");
19837
20015
  }
19838
20016
  }
19839
20017
  function safe3(path) {
19840
20018
  pluginText(path);
19841
- pluginNeed(isAbsolute16(path) && resolve16(path) === path, "Invalid plugin registry path");
20019
+ pluginNeed(isAbsolute17(path) && resolve16(path) === path, "Invalid plugin registry path");
19842
20020
  for (let at = path;; at = dirname17(at)) {
19843
- pluginNeed(!lstatSync22(at, { throwIfNoEntry: false })?.isSymbolicLink(), "Plugin registry path traverses a symlink");
20021
+ pluginNeed(!lstatSync23(at, { throwIfNoEntry: false })?.isSymbolicLink(), "Plugin registry path traverses a symlink");
19844
20022
  if (at === dirname17(at))
19845
20023
  break;
19846
20024
  }
19847
20025
  }
19848
20026
  function readRegistry(path) {
19849
20027
  safe3(path);
19850
- const initial = lstatSync22(path);
20028
+ const initial = lstatSync23(path);
19851
20029
  pluginNeed(initial.isFile() && initial.size <= 1024 * 1024, "Plugin registry is not a bounded regular file");
19852
- const fd = openSync12(path, constants12.O_RDONLY | constants12.O_NOFOLLOW | constants12.O_NONBLOCK);
20030
+ const fd = openSync13(path, constants13.O_RDONLY | constants13.O_NOFOLLOW | constants13.O_NONBLOCK);
19853
20031
  try {
19854
- const opened = fstatSync12(fd);
20032
+ const opened = fstatSync13(fd);
19855
20033
  pluginNeed(opened.isFile() && opened.ino === initial.ino && opened.dev === initial.dev, "Plugin registry changed during open");
19856
20034
  const bytes = Buffer.alloc(1024 * 1024 + 1);
19857
20035
  let length = 0;
@@ -19861,7 +20039,7 @@ function readRegistry(path) {
19861
20039
  break;
19862
20040
  length += count;
19863
20041
  }
19864
- const after = fstatSync12(fd), current = lstatSync22(path);
20042
+ const after = fstatSync13(fd), current = lstatSync23(path);
19865
20043
  safe3(path);
19866
20044
  pluginNeed(length <= 1024 * 1024 && length === opened.size && after.size === opened.size && after.mtimeMs === opened.mtimeMs && after.ctimeMs === opened.ctimeMs && current.dev === opened.dev && current.ino === opened.ino && current.mtimeMs === opened.mtimeMs && current.ctimeMs === opened.ctimeMs, "Plugin registry changed during read");
19867
20045
  let value;
@@ -19873,7 +20051,7 @@ function readRegistry(path) {
19873
20051
  pluginNeed(pluginObject(value) && value.version === 2 && pluginObject(value.plugins), "Unsupported native plugin registry schema");
19874
20052
  return { value, rawDigest: pluginHash(bytes.subarray(0, length)) };
19875
20053
  } finally {
19876
- closeSync12(fd);
20054
+ closeSync13(fd);
19877
20055
  }
19878
20056
  }
19879
20057
  function nativeVersionMatches(version, receipt) {
@@ -19934,7 +20112,7 @@ function hashManagedPluginRegistry(path, managed) {
19934
20112
  return Object.fromEntries(Object.entries(row).filter(([key]) => !["version", "installPath", "sourceProducerPath", "previousProducerPaths", "lastUpdated"].includes(key)));
19935
20113
  });
19936
20114
  safe3(cacheRoot);
19937
- const before = lstatSync22(cacheRoot);
20115
+ const before = lstatSync23(cacheRoot);
19938
20116
  pluginNeed(before.isDirectory(), "Invalid managed plugin cache root");
19939
20117
  const directory = opendirSync5(cacheRoot), names = [];
19940
20118
  try {
@@ -19957,7 +20135,7 @@ function hashManagedPluginRegistry(path, managed) {
19957
20135
  }
19958
20136
  for (const row of rows)
19959
20137
  pluginNeed(names.includes(row.version), "Managed native plugin installation is missing");
19960
- const after = lstatSync22(cacheRoot);
20138
+ const after = lstatSync23(cacheRoot);
19961
20139
  safe3(cacheRoot);
19962
20140
  pluginNeed(before.dev === after.dev && before.ino === after.ino && before.mtimeMs === after.mtimeMs && before.ctimeMs === after.ctimeMs, "Managed cache version membership changed during verification");
19963
20141
  }
@@ -19969,22 +20147,22 @@ function captureManagedPluginRegistry(path, managedPlugins) {
19969
20147
  }
19970
20148
 
19971
20149
  // src/lib/claude-marketplace-registry.ts
19972
- import { createHash as createHash21 } from "crypto";
19973
- import { closeSync as closeSync13, constants as constants13, fstatSync as fstatSync13, lstatSync as lstatSync23, openSync as openSync13, readSync as readSync11 } from "fs";
19974
- import { basename as basename9, dirname as dirname18, isAbsolute as isAbsolute17, resolve as resolve17 } from "path";
20150
+ import { createHash as createHash22 } from "crypto";
20151
+ import { closeSync as closeSync14, constants as constants14, fstatSync as fstatSync14, lstatSync as lstatSync24, openSync as openSync14, readSync as readSync11 } from "fs";
20152
+ import { basename as basename9, dirname as dirname18, isAbsolute as isAbsolute18, resolve as resolve17 } from "path";
19975
20153
  var CLAUDE_MARKETPLACE_REGISTRY_LIMITS = Object.freeze({ bytes: 1024 * 1024, rows: 1024, depth: 32, nodes: 65536, stringCharacters: 16384, pathCharacters: 4096 });
19976
20154
  function need6(value, reason) {
19977
20155
  if (!value)
19978
20156
  throw new Error(`Claude marketplace registry ${reason}`);
19979
20157
  }
19980
20158
  function absolutePath3(value) {
19981
- need6(typeof value === "string" && value.length > 0 && value.length <= CLAUDE_MARKETPLACE_REGISTRY_LIMITS.pathCharacters && !/[\x00-\x1f\x7f]/.test(value) && isAbsolute17(value) && resolve17(value) === value, "requires a normalized absolute path");
20159
+ need6(typeof value === "string" && value.length > 0 && value.length <= CLAUDE_MARKETPLACE_REGISTRY_LIMITS.pathCharacters && !/[\x00-\x1f\x7f]/.test(value) && isAbsolute18(value) && resolve17(value) === value, "requires a normalized absolute path");
19982
20160
  }
19983
20161
  var sameFile2 = (a, b) => a.dev === b.dev && a.ino === b.ino && a.mode === b.mode && a.uid === b.uid && a.gid === b.gid && a.nlink === b.nlink && a.size === b.size && a.mtimeNs === b.mtimeNs && a.ctimeNs === b.ctimeNs;
19984
20162
  function parents2(path) {
19985
20163
  const result = [];
19986
20164
  for (let at = dirname18(path);; at = dirname18(at)) {
19987
- const stat2 = lstatSync23(at, { bigint: true });
20165
+ const stat2 = lstatSync24(at, { bigint: true });
19988
20166
  need6(stat2.isDirectory() && !stat2.isSymbolicLink(), "path traverses a symlink or non-directory");
19989
20167
  result.push([at, stat2]);
19990
20168
  if (at === dirname18(at))
@@ -19995,12 +20173,12 @@ function readRegistry2(path, budget2) {
19995
20173
  absolutePath3(path);
19996
20174
  need6(basename9(path) === "known_marketplaces.json", "requires known_marketplaces.json");
19997
20175
  need6(Number.isSafeInteger(budget2.remaining) && budget2.remaining >= 0, "has an invalid byte budget");
19998
- const ancestors2 = parents2(path), initial = lstatSync23(path, { bigint: true });
20176
+ const ancestors2 = parents2(path), initial = lstatSync24(path, { bigint: true });
19999
20177
  need6(initial.isFile() && !initial.isSymbolicLink() && initial.size <= BigInt(CLAUDE_MARKETPLACE_REGISTRY_LIMITS.bytes), "is not a bounded regular file");
20000
20178
  need6(initial.size <= BigInt(budget2.remaining), "exceeds its aggregate byte limit");
20001
- const fd = openSync13(path, constants13.O_RDONLY | constants13.O_NOFOLLOW | constants13.O_NONBLOCK);
20179
+ const fd = openSync14(path, constants14.O_RDONLY | constants14.O_NOFOLLOW | constants14.O_NONBLOCK);
20002
20180
  try {
20003
- const opened = fstatSync13(fd, { bigint: true });
20181
+ const opened = fstatSync14(fd, { bigint: true });
20004
20182
  need6(opened.isFile() && sameFile2(initial, opened), "changed during open");
20005
20183
  const bytes = Buffer.alloc(Number(opened.size) + 1);
20006
20184
  let length = 0;
@@ -20010,10 +20188,10 @@ function readRegistry2(path, budget2) {
20010
20188
  break;
20011
20189
  length += count;
20012
20190
  }
20013
- const after = fstatSync13(fd, { bigint: true }), current = lstatSync23(path, { bigint: true });
20191
+ const after = fstatSync14(fd, { bigint: true }), current = lstatSync24(path, { bigint: true });
20014
20192
  need6(current.isFile() && sameFile2(opened, after) && sameFile2(after, current) && BigInt(length) === opened.size, "changed during read");
20015
20193
  for (const [ancestor, before] of ancestors2) {
20016
- const now = lstatSync23(ancestor, { bigint: true });
20194
+ const now = lstatSync24(ancestor, { bigint: true });
20017
20195
  need6(now.isDirectory() && before.dev === now.dev && before.ino === now.ino && before.mode === now.mode, "parent changed during read");
20018
20196
  }
20019
20197
  budget2.remaining -= length;
@@ -20023,7 +20201,7 @@ function readRegistry2(path, budget2) {
20023
20201
  throw new Error("Claude marketplace registry is not strict UTF-8");
20024
20202
  }
20025
20203
  } finally {
20026
- closeSync13(fd);
20204
+ closeSync14(fd);
20027
20205
  }
20028
20206
  }
20029
20207
  function parse7(text2) {
@@ -20138,19 +20316,19 @@ function captureClaudeMarketplaceRegistry(path, budget2 = { remaining: 256 * 102
20138
20316
  const value = parse7(readRegistry2(path, budget2));
20139
20317
  for (const [, row] of value.entries)
20140
20318
  normalizeRow(row);
20141
- const sha2562 = createHash21("sha256").update("hasna.skills.claude-marketplace-registry.v1\x00").update(JSON.stringify(value)).digest("hex");
20142
- return { path, hashMode: "claude-marketplace-registry", sha256: sha2562 };
20319
+ const sha2563 = createHash22("sha256").update("hasna.skills.claude-marketplace-registry.v1\x00").update(JSON.stringify(value)).digest("hex");
20320
+ return { path, hashMode: "claude-marketplace-registry", sha256: sha2563 };
20143
20321
  }
20144
20322
  function captureClaudeMarketplaceRegistryV2(path, budget2 = { remaining: 256 * 1024 * 1024 }) {
20145
20323
  const value = parse7(readRegistry2(path, budget2));
20146
20324
  for (const [, row] of value.entries)
20147
20325
  normalizeRow(row, 2);
20148
- const sha2562 = createHash21("sha256").update("hasna.skills.claude-marketplace-registry.v2\x00").update(JSON.stringify(value)).digest("hex");
20149
- return { path, hashMode: "claude-marketplace-registry-v2", sha256: sha2562 };
20326
+ const sha2563 = createHash22("sha256").update("hasna.skills.claude-marketplace-registry.v2\x00").update(JSON.stringify(value)).digest("hex");
20327
+ return { path, hashMode: "claude-marketplace-registry-v2", sha256: sha2563 };
20150
20328
  }
20151
20329
 
20152
20330
  // src/lib/codex-hook-discovery-recovery.ts
20153
- import { createHash as createHash22 } from "crypto";
20331
+ import { createHash as createHash23 } from "crypto";
20154
20332
 
20155
20333
  // src/lib/codex-hook-additions-review.ts
20156
20334
  var events = { UserPromptSubmit: ["userPromptSubmit", "user_prompt_submit"], SessionStart: ["sessionStart", "session_start"], SubagentStart: ["subagentStart", "subagent_start"] };
@@ -20158,7 +20336,7 @@ var matchedEvents = { ...events, PreToolUse: ["preToolUse", "pre_tool_use"] };
20158
20336
  var proofs = new WeakMap;
20159
20337
 
20160
20338
  // src/lib/codex-hook-discovery-recovery.ts
20161
- var sha4 = (text2) => createHash22("sha256").update(text2).digest("hex");
20339
+ var sha4 = (text2) => createHash23("sha256").update(text2).digest("hex");
20162
20340
  var fields = [...CODEX_DISCOVERY_PROJECTION_FIELDS];
20163
20341
  var proofs2 = new WeakMap;
20164
20342
  function assertCodexHookDiscoveryRecovery(binding, witness) {
@@ -20177,7 +20355,7 @@ function verifiesCodexHookDiscoverySource(binding, source, currentDigest, witnes
20177
20355
  }
20178
20356
 
20179
20357
  // src/lib/agent-discovery.ts
20180
- var digest = (text2) => createHash23("sha256").update(text2).digest("hex");
20358
+ var digest = (text2) => createHash24("sha256").update(text2).digest("hex");
20181
20359
  function parseConfig(text2, path, toml = false) {
20182
20360
  try {
20183
20361
  const value = toml ? Bun.TOML.parse(text2) : JSON.parse(text2);
@@ -20189,10 +20367,10 @@ function parseConfig(text2, path, toml = false) {
20189
20367
  }
20190
20368
  }
20191
20369
  function safe4(path) {
20192
- if (!isAbsolute18(path) || path.includes("\x00"))
20370
+ if (!isAbsolute19(path) || path.includes("\x00"))
20193
20371
  throw new Error("Expected an absolute native discovery path");
20194
20372
  for (let cursor = path;; cursor = dirname19(cursor)) {
20195
- if (lstatSync24(cursor, { throwIfNoEntry: false })?.isSymbolicLink())
20373
+ if (lstatSync25(cursor, { throwIfNoEntry: false })?.isSymbolicLink())
20196
20374
  throw new Error(`Refusing symlink native discovery input: ${cursor}`);
20197
20375
  if (dirname19(cursor) === cursor)
20198
20376
  break;
@@ -20202,12 +20380,12 @@ function read2(path, changes) {
20202
20380
  safe4(path);
20203
20381
  if (changes?.has(path))
20204
20382
  return changes.get(path);
20205
- const stat2 = lstatSync24(path, { throwIfNoEntry: false });
20383
+ const stat2 = lstatSync25(path, { throwIfNoEntry: false });
20206
20384
  if (!stat2)
20207
20385
  return null;
20208
20386
  if (!stat2.isFile() || stat2.size > 16 * 1024 * 1024)
20209
20387
  throw new Error(`Unsupported or oversized native discovery input: ${path}`);
20210
- return readFileSync19(path, "utf8");
20388
+ return readFileSync20(path, "utf8");
20211
20389
  }
20212
20390
  function projectNativeDiscoveryFields(text2, format, fields2, path) {
20213
20391
  const object6 = format === "yaml" ? parseHermesConfig(text2) : parseConfig(text2, path, format === "toml");
@@ -20242,21 +20420,21 @@ function projected(source, changes, budget2 = discoveryByteBudget()) {
20242
20420
  throw new Error(`Native discovery input changed; run skills hook install with a fresh discovery review: ${source.path}`);
20243
20421
  return changes?.has(source.path) ? (source.hashMode === "codex-settings-v4" ? hashCodexSettingsReplacementV4 : source.hashMode === "codex-settings-v3" ? hashCodexSettingsReplacementV3 : source.hashMode === "codex-settings-v2" ? hashCodexSettingsReplacementV2 : hashCodexSettingsReplacement)(changes.get(source.path), budget2) : current;
20244
20422
  }
20245
- if (source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || source.hashMode === "claude-settings-v3") {
20423
+ if (source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || (source.hashMode === "claude-settings-v3" || source.hashMode === "claude-settings-v4")) {
20246
20424
  if (source.format !== undefined || source.fields !== undefined || source.managedPlugins !== undefined || typeof source.sha256 !== "string" || !/^[a-f0-9]{64}$/.test(source.sha256))
20247
20425
  throw new Error("Claude settings witnesses require exact typed metadata");
20248
- const current = (source.hashMode === "claude-settings-v3" ? captureClaudeSettingsV3 : source.hashMode === "claude-settings-v2" ? captureClaudeSettingsV2 : captureClaudeSettings)(source.path, budget2).sha256;
20426
+ const current = (source.hashMode === "claude-settings-v4" ? captureClaudeSettingsV4 : source.hashMode === "claude-settings-v3" ? captureClaudeSettingsV3 : source.hashMode === "claude-settings-v2" ? captureClaudeSettingsV2 : captureClaudeSettings)(source.path, budget2).sha256;
20249
20427
  if (current !== source.sha256)
20250
20428
  throw new Error(`Native discovery input changed; run skills hook install with a fresh discovery review: ${source.path}`);
20251
- return changes?.has(source.path) ? (source.hashMode === "claude-settings-v3" ? hashClaudeSettingsReplacementV3 : source.hashMode === "claude-settings-v2" ? hashClaudeSettingsReplacementV2 : hashClaudeSettingsReplacement)(changes.get(source.path), budget2) : current;
20429
+ return changes?.has(source.path) ? (source.hashMode === "claude-settings-v4" ? hashClaudeSettingsReplacementV4 : source.hashMode === "claude-settings-v3" ? hashClaudeSettingsReplacementV3 : source.hashMode === "claude-settings-v2" ? hashClaudeSettingsReplacementV2 : hashClaudeSettingsReplacement)(changes.get(source.path), budget2) : current;
20252
20430
  }
20253
20431
  if (source.hashMode === "claude-marketplace-registry" || source.hashMode === "claude-marketplace-registry-v2") {
20254
20432
  if (source.format !== undefined || source.fields !== undefined || source.managedPlugins !== undefined || typeof source.sha256 !== "string" || !/^[a-f0-9]{64}$/.test(source.sha256) || changes?.has(source.path))
20255
20433
  throw new Error("Claude marketplace witnesses require an exact reviewed registry without synthetic changes");
20256
- const sha2562 = (source.hashMode === "claude-marketplace-registry-v2" ? captureClaudeMarketplaceRegistryV2 : captureClaudeMarketplaceRegistry)(source.path, budget2).sha256;
20257
- if (sha2562 !== source.sha256)
20434
+ const sha2563 = (source.hashMode === "claude-marketplace-registry-v2" ? captureClaudeMarketplaceRegistryV2 : captureClaudeMarketplaceRegistry)(source.path, budget2).sha256;
20435
+ if (sha2563 !== source.sha256)
20258
20436
  throw new Error(`Native discovery input changed; run skills hook install with a fresh discovery review: ${source.path}`);
20259
- return sha2562;
20437
+ return sha2563;
20260
20438
  }
20261
20439
  if (source.hashMode === "claude-plugin-registry") {
20262
20440
  if (source.format !== undefined || source.fields !== undefined || !source.managedPlugins || changes?.has(source.path))
@@ -20293,7 +20471,7 @@ function absentCodexSkillRoots(binding) {
20293
20471
  return [];
20294
20472
  if (binding.agent !== "codex" || !Array.isArray(controls) || controls.length > 4096)
20295
20473
  throw new Error("Invalid disabled Codex discovery proof");
20296
- if (binding.method !== "reviewed" || controls.every((control) => lstatSync24(control.pluginParent, { throwIfNoEntry: false })))
20474
+ if (binding.method !== "reviewed" || controls.every((control) => lstatSync25(control.pluginParent, { throwIfNoEntry: false })))
20297
20475
  return [];
20298
20476
  const cache = dirname19(dirname19(controls[0].pluginParent)), config = join32(dirname19(dirname19(cache)), "config.toml");
20299
20477
  const source = binding.sources.find((source2) => source2.path === config && source2.sha256 !== null && source2.format === undefined && source2.fields === undefined);
@@ -20361,7 +20539,7 @@ function absentRetiredClaudeRoots(binding) {
20361
20539
  continue;
20362
20540
  const root2 = join32(cache, ...parts.slice(0, 3));
20363
20541
  safe4(root2);
20364
- if (lstatSync24(root2, { throwIfNoEntry: false }))
20542
+ if (lstatSync25(root2, { throwIfNoEntry: false }))
20365
20543
  continue;
20366
20544
  const claude = dirname19(dirname19(cache)), settings = join32(claude, "settings.json"), registry = join32(claude, "plugins/installed_plugins.json");
20367
20545
  const full = (path) => binding.sources.find((item) => item.path === path && item.sha256 !== null && item.format === undefined && item.fields === undefined);
@@ -20380,7 +20558,7 @@ function absentRetiredClaudeRoots(binding) {
20380
20558
  if (!Array.isArray(rows) || rows.length !== 1 || rows[0]?.scope !== "user" || typeof rows[0]?.installPath !== "string")
20381
20559
  continue;
20382
20560
  const active = rows[0].installPath;
20383
- if (rows[0].version !== basename10(active) || resolve18(active) !== active || dirname19(active) !== dirname19(root2) || active === root2 || !lstatSync24(active, { throwIfNoEntry: false })?.isDirectory() || realpathSync10(active) !== active)
20561
+ if (rows[0].version !== basename10(active) || resolve18(active) !== active || dirname19(active) !== dirname19(root2) || active === root2 || !lstatSync25(active, { throwIfNoEntry: false })?.isDirectory() || realpathSync11(active) !== active)
20384
20562
  continue;
20385
20563
  const activeManifest = full(join32(active, ".claude-plugin/plugin.json"));
20386
20564
  if (!activeManifest || projected(activeManifest) !== activeManifest.sha256)
@@ -20411,7 +20589,7 @@ function verifyAgentDiscovery(binding, codexRecovery) {
20411
20589
  const projection = binding.codexRetiredMaterializations.directories;
20412
20590
  if (projection.length !== ordinary.length || projection.some((item, index) => item.path !== ordinary[index]?.path))
20413
20591
  throw new Error("Missing retired Codex directory projection");
20414
- const omitted = [...retiredRoots, ...(binding.codexRetiredMaterializations.parents ?? []).filter((parent) => !lstatSync24(parent, { throwIfNoEntry: false }))];
20592
+ const omitted = [...retiredRoots, ...(binding.codexRetiredMaterializations.parents ?? []).filter((parent) => !lstatSync25(parent, { throwIfNoEntry: false }))];
20415
20593
  if (projection.every((item) => Array.isArray(item.entries)))
20416
20594
  verifyDiscoveryDirectoryProjection(projection, omitted);
20417
20595
  else {
@@ -20425,7 +20603,7 @@ function verifyAgentDiscovery(binding, codexRecovery) {
20425
20603
  verifyDiscoveryDirectories(ordinary);
20426
20604
  verifyDiscoveryDirectories(projected2, installationRoots);
20427
20605
  }
20428
- const absentRoots = [...absentCodexSkillRoots(binding), ...absentRetiredClaudeRoots(binding), ...retiredRoots.filter((root2) => !lstatSync24(root2, { throwIfNoEntry: false }))];
20606
+ const absentRoots = [...absentCodexSkillRoots(binding), ...absentRetiredClaudeRoots(binding), ...retiredRoots.filter((root2) => !lstatSync25(root2, { throwIfNoEntry: false }))];
20429
20607
  const budget2 = discoveryByteBudget();
20430
20608
  for (const source of binding.sources) {
20431
20609
  assertMarketplaceBinding(binding, source);
@@ -20451,7 +20629,7 @@ function verifyAgentDiscovery(binding, codexRecovery) {
20451
20629
  safe4(root2);
20452
20630
  for (const root2 of absentRoots) {
20453
20631
  safe4(root2);
20454
- if (lstatSync24(root2, { throwIfNoEntry: false }))
20632
+ if (lstatSync25(root2, { throwIfNoEntry: false }))
20455
20633
  throw new Error("Retired native materialization changed during discovery verification");
20456
20634
  }
20457
20635
  }
@@ -20483,26 +20661,26 @@ function assertMarketplaceBinding(binding, source) {
20483
20661
  throw new Error("Sumi settings witnesses require explicit reviewed Sumi configuration");
20484
20662
  if ((source.hashMode === "codex-settings-v1" || source.hashMode === "codex-settings-v2" || (source.hashMode === "codex-settings-v3" || source.hashMode === "codex-settings-v4")) && (binding.agent !== "codex" || binding.method !== "reviewed" || basename10(source.path) !== "config.toml"))
20485
20663
  throw new Error("Codex settings witnesses require explicit reviewed Codex configuration");
20486
- if ((source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || source.hashMode === "claude-settings-v3") && (binding.agent !== "claude" || binding.method !== "reviewed" || basename10(source.path) !== "settings.json"))
20664
+ if ((source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || (source.hashMode === "claude-settings-v3" || source.hashMode === "claude-settings-v4")) && (binding.agent !== "claude" || binding.method !== "reviewed" || basename10(source.path) !== "settings.json"))
20487
20665
  throw new Error("Claude settings witnesses require explicit reviewed Claude configuration");
20488
20666
  if ((source.hashMode === "claude-marketplace-registry" || source.hashMode === "claude-marketplace-registry-v2") && (binding.agent !== "claude" || binding.method !== "reviewed"))
20489
20667
  throw new Error("Claude marketplace witnesses require explicit reviewed Claude discovery");
20490
20668
  }
20491
20669
  function rebindAgentDiscovery(binding, changes) {
20492
20670
  const budget2 = discoveryByteBudget();
20493
- const installationRoots = codexInstallationRoots(binding), absentRoots = [...absentCodexSkillRoots(binding), ...absentRetiredClaudeRoots(binding), ...retiredCodexRoots(binding).filter((root2) => !lstatSync24(root2, { throwIfNoEntry: false }))];
20671
+ const installationRoots = codexInstallationRoots(binding), absentRoots = [...absentCodexSkillRoots(binding), ...absentRetiredClaudeRoots(binding), ...retiredCodexRoots(binding).filter((root2) => !lstatSync25(root2, { throwIfNoEntry: false }))];
20494
20672
  const rebound = { ...binding, sources: binding.sources.map((source) => {
20495
20673
  assertMarketplaceBinding(binding, source);
20496
20674
  if (!changes.has(source.path) && (installationRoots.some((root2) => source.path.startsWith(root2 + sep8)) || absentRoots.some((root2) => source.path.startsWith(root2 + sep8)) && source.format === undefined && source.fields === undefined && source.managedPlugins === undefined && [undefined, "bytes"].includes(source.hashMode)))
20497
20675
  return source;
20498
- const sha2562 = projected(source, changes, budget2);
20499
- if (!changes.has(source.path) && sha2562 !== source.sha256)
20676
+ const sha2563 = projected(source, changes, budget2);
20677
+ if (!changes.has(source.path) && sha2563 !== source.sha256)
20500
20678
  throw new Error(`Native discovery input changed; run skills hook install with a fresh discovery review: ${source.path}`);
20501
- return { ...source, sha256: sha2562 };
20679
+ return { ...source, sha256: sha2563 };
20502
20680
  }) };
20503
20681
  for (const root2 of absentRoots) {
20504
20682
  safe4(root2);
20505
- if (lstatSync24(root2, { throwIfNoEntry: false }))
20683
+ if (lstatSync25(root2, { throwIfNoEntry: false }))
20506
20684
  throw new Error("Retired native materialization changed during discovery rebinding");
20507
20685
  }
20508
20686
  return rebound;
@@ -20557,13 +20735,13 @@ function assertProjectDiscovery(agent, directories, home, canonical7 = resolve18
20557
20735
  for (const name of ["plugin", "plugins"]) {
20558
20736
  const path = canonical7(join32(directory, ".sumi", name));
20559
20737
  safe4(path);
20560
- if (lstatSync24(path, { throwIfNoEntry: false })?.isDirectory() && readdirSync10(path).length)
20738
+ if (lstatSync25(path, { throwIfNoEntry: false })?.isDirectory() && readdirSync10(path).length)
20561
20739
  throw new Error(`NATIVE_SKILL_DRIFT: project Sumi plugins require a dedicated discovery review: ${path}`);
20562
20740
  }
20563
20741
  if (agent === "claude") {
20564
20742
  const commands = canonical7(join32(directory, ".claude/commands"));
20565
20743
  safe4(commands);
20566
- if (lstatSync24(commands, { throwIfNoEntry: false })?.isDirectory() && readdirSync10(commands).length)
20744
+ if (lstatSync25(commands, { throwIfNoEntry: false })?.isDirectory() && readdirSync10(commands).length)
20567
20745
  throw new Error("NATIVE_SKILL_DRIFT: legacy project command discovery requires a dedicated format adapter");
20568
20746
  }
20569
20747
  }
@@ -20603,7 +20781,7 @@ function resolveAgentDiscovery(options) {
20603
20781
  if (config.skills !== undefined && (!Array.isArray(config.skills) || config.skills.some((path) => typeof path !== "string")))
20604
20782
  unresolved("skills must be a string array");
20605
20783
  for (const value of config.skills ?? []) {
20606
- if (typeof value !== "string" || /[\0$]/.test(value) || !value || !(isAbsolute18(value) || value.startsWith("~/")))
20784
+ if (typeof value !== "string" || /[\0$]/.test(value) || !value || !(isAbsolute19(value) || value.startsWith("~/")))
20607
20785
  unresolved("remote or relative skill sources need a dedicated discovery adapter");
20608
20786
  roots.add(canonical7(value.startsWith("~/") ? join32(home, value.slice(2)) : value));
20609
20787
  }
@@ -20613,19 +20791,19 @@ function resolveAgentDiscovery(options) {
20613
20791
  const plugins = [join32(directory, "plugin"), join32(directory, "plugins")];
20614
20792
  for (const path of plugins) {
20615
20793
  safe4(path);
20616
- if (lstatSync24(path, { throwIfNoEntry: false })?.isDirectory())
20794
+ if (lstatSync25(path, { throwIfNoEntry: false })?.isDirectory())
20617
20795
  for (const name of readdirSync10(path).sort()) {
20618
20796
  if (name === "skills-cli.js" && path === plugins[1])
20619
20797
  continue;
20620
20798
  const target = join32(path, name);
20621
- if (!lstatSync24(target).isFile())
20799
+ if (!lstatSync25(target).isFile())
20622
20800
  unresolved("local plugin packages need a dedicated discovery adapter");
20623
20801
  witness(target);
20624
20802
  }
20625
20803
  }
20626
20804
  for (const root2 of roots) {
20627
20805
  safe4(root2);
20628
- if (lstatSync24(root2, { throwIfNoEntry: false })?.isDirectory() && readdirSync10(root2).some((name) => name.endsWith(".md")))
20806
+ if (lstatSync25(root2, { throwIfNoEntry: false })?.isDirectory() && readdirSync10(root2).some((name) => name.endsWith(".md")))
20629
20807
  unresolved("flat markdown skills require a dedicated native migration adapter");
20630
20808
  }
20631
20809
  }
@@ -20653,7 +20831,7 @@ function resolveAgentDiscovery(options) {
20653
20831
  const executable2 = Bun.which("gemini");
20654
20832
  if (executable2) {
20655
20833
  let packageRoot;
20656
- for (let directory = dirname19(realpathSync10(executable2)), depth = 0;depth < 8; directory = dirname19(directory), depth++) {
20834
+ for (let directory = dirname19(realpathSync11(executable2)), depth = 0;depth < 8; directory = dirname19(directory), depth++) {
20657
20835
  const path = join32(directory, "package.json"), raw = read2(path);
20658
20836
  if (raw !== null && parseConfig(raw, path).name === "@google/gemini-cli") {
20659
20837
  packageRoot = directory;
@@ -20667,7 +20845,7 @@ function resolveAgentDiscovery(options) {
20667
20845
  unresolved("installed Gemini package layout is not recognized");
20668
20846
  const builtinRoot = join32(packageRoot, "bundle/builtin");
20669
20847
  safe4(builtinRoot);
20670
- if (!lstatSync24(builtinRoot, { throwIfNoEntry: false })?.isDirectory())
20848
+ if (!lstatSync25(builtinRoot, { throwIfNoEntry: false })?.isDirectory())
20671
20849
  unresolved("installed Gemini builtin root is missing");
20672
20850
  for (const name of readdirSync10(builtinRoot).sort()) {
20673
20851
  const text2 = witness(join32(builtinRoot, name, "SKILL.md"));
@@ -20685,7 +20863,7 @@ function resolveAgentDiscovery(options) {
20685
20863
  verifyAgentDiscovery(retained);
20686
20864
  if (!retained.sources.some((source) => source.path === canonical7(configPath) && source.format === undefined && source.fields === undefined))
20687
20865
  unresolved("retained review is missing the full agent configuration source");
20688
- if (retained.sources.some((source) => (source.hashMode === "sumi-settings-v1" || source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || (source.hashMode === "claude-settings-v3" || (source.hashMode === "codex-settings-v1" || source.hashMode === "codex-settings-v2" || (source.hashMode === "codex-settings-v3" || source.hashMode === "codex-settings-v4")))) && source.path !== canonical7(configPath)))
20866
+ if (retained.sources.some((source) => (source.hashMode === "sumi-settings-v1" || source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || (source.hashMode === "claude-settings-v3" || source.hashMode === "claude-settings-v4" || (source.hashMode === "codex-settings-v1" || source.hashMode === "codex-settings-v2" || (source.hashMode === "codex-settings-v3" || source.hashMode === "codex-settings-v4")))) && source.path !== canonical7(configPath)))
20689
20867
  unresolved("retained settings witness names another configuration source");
20690
20868
  const covered = supersedesSettingsProjection(agent, retained.sources, canonical7(configPath)) ? sources.filter((source) => !isSupersededSettingsProjection(agent, canonical7(configPath), source)) : sources;
20691
20869
  if (covered.some((source) => !retained.sources.some((saved) => isDeepStrictEqual7(saved, source))) || [...roots].some((root2) => !retained.roots.includes(root2)) || agent === "gemini" && JSON.stringify(retained.builtinNames) !== JSON.stringify(builtinNames))
@@ -20699,7 +20877,7 @@ function resolveAgentDiscovery(options) {
20699
20877
  if (review.sources.some((source) => source.format !== undefined || source.fields !== undefined))
20700
20878
  throw new Error("Explicit discovery reviews require full source-file hashes");
20701
20879
  verifyAgentDiscovery(supplied);
20702
- if (review.sources.some((source) => (source.hashMode === "sumi-settings-v1" || source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || (source.hashMode === "claude-settings-v3" || (source.hashMode === "codex-settings-v1" || source.hashMode === "codex-settings-v2" || (source.hashMode === "codex-settings-v3" || source.hashMode === "codex-settings-v4")))) && source.path !== canonical7(configPath)))
20880
+ if (review.sources.some((source) => (source.hashMode === "sumi-settings-v1" || source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || (source.hashMode === "claude-settings-v3" || source.hashMode === "claude-settings-v4" || (source.hashMode === "codex-settings-v1" || source.hashMode === "codex-settings-v2" || (source.hashMode === "codex-settings-v3" || source.hashMode === "codex-settings-v4")))) && source.path !== canonical7(configPath)))
20703
20881
  throw new Error("Semantic settings witnesses must name the configured agent configuration source");
20704
20882
  if (!review.sources.some((source) => source.path === canonical7(configPath)))
20705
20883
  throw new Error("Discovery review must include the agent configuration source");
@@ -20708,7 +20886,7 @@ function resolveAgentDiscovery(options) {
20708
20886
  if (agent !== "claude" || source.sha256 === null || source.format !== undefined || source.fields !== undefined || source.managedPlugins !== undefined || source.hashMode !== undefined && source.hashMode !== "bytes" || basename10(source.path) !== "plugin.json" || !source.path.endsWith(join32(sep8, ".claude-plugin", "plugin.json")))
20709
20887
  return source;
20710
20888
  const pluginRoot = dirname19(dirname19(source.path)), hooksPath = join32(pluginRoot, "hooks/hooks.json");
20711
- const hookStat = lstatSync24(hooksPath, { throwIfNoEntry: false });
20889
+ const hookStat = lstatSync25(hooksPath, { throwIfNoEntry: false });
20712
20890
  const text2 = read2(source.path);
20713
20891
  if (text2 === null)
20714
20892
  throw new Error("Reviewed Claude plugin manifest is missing");
@@ -20749,7 +20927,7 @@ function resolveAgentDiscovery(options) {
20749
20927
  unresolved("plugin hooks require a separate no-skill-injection review");
20750
20928
  const commands = join32(root2, "commands");
20751
20929
  safe4(commands);
20752
- if (agent === "claude" && (manifest.commands !== undefined || lstatSync24(commands, { throwIfNoEntry: false })?.isDirectory() && readdirSync10(commands).length))
20930
+ if (agent === "claude" && (manifest.commands !== undefined || lstatSync25(commands, { throwIfNoEntry: false })?.isDirectory() && readdirSync10(commands).length))
20753
20931
  unresolved("legacy command discovery requires retirement or a dedicated format adapter");
20754
20932
  const rootSkill = witness(join32(root2, "SKILL.md"));
20755
20933
  if (rootSkill !== null)
@@ -20771,7 +20949,7 @@ function resolveAgentDiscovery(options) {
20771
20949
  const installed = registrations === null ? {} : parseConfig(registrations, join32(home, ".claude/plugins/installed_plugins.json")).plugins;
20772
20950
  const commands = canonical7(join32(home, ".claude/commands"));
20773
20951
  safe4(commands);
20774
- if (lstatSync24(commands, { throwIfNoEntry: false })?.isDirectory() && readdirSync10(commands).length)
20952
+ if (lstatSync25(commands, { throwIfNoEntry: false })?.isDirectory() && readdirSync10(commands).length)
20775
20953
  unresolved("legacy home command discovery requires a dedicated format adapter");
20776
20954
  for (const [id, enabled] of Object.entries(config.enabledPlugins ?? {})) {
20777
20955
  if (enabled === false)
@@ -20791,7 +20969,7 @@ function resolveAgentDiscovery(options) {
20791
20969
  unresolved("unsupported plugin enablement");
20792
20970
  const split = id.lastIndexOf("@"), name = id.slice(0, split), marketplace = id.slice(split + 1);
20793
20971
  const market = config.marketplaces?.[marketplace] ?? (marketplace === "personal" ? { source_type: "local", source: home } : undefined);
20794
- if (split < 1 || market?.source_type !== "local" || typeof market.source !== "string" || !isAbsolute18(market.source))
20972
+ if (split < 1 || market?.source_type !== "local" || typeof market.source !== "string" || !isAbsolute19(market.source))
20795
20973
  unresolved("enabled plugin marketplace is not an explicit local source");
20796
20974
  const catalogText = witness(join32(market.source, ".agents/plugins/marketplace.json"));
20797
20975
  if (catalogText === null)
@@ -20807,13 +20985,13 @@ function resolveAgentDiscovery(options) {
20807
20985
  if ((config.plugin?.length ?? 0) > 0 || config.skills?.urls?.length)
20808
20986
  unresolved("external plugin or remote skill source");
20809
20987
  for (const path of config.skills?.paths ?? []) {
20810
- if (typeof path !== "string" || !isAbsolute18(path))
20988
+ if (typeof path !== "string" || !isAbsolute19(path))
20811
20989
  unresolved("relative or malformed added skill root");
20812
20990
  roots.add(path);
20813
20991
  }
20814
20992
  const localPlugins = join32(home, ".config/opencode/plugins");
20815
20993
  safe4(localPlugins);
20816
- if (lstatSync24(localPlugins, { throwIfNoEntry: false }) && readdirSync10(localPlugins).some((name) => name !== "skills-cli.js"))
20994
+ if (lstatSync25(localPlugins, { throwIfNoEntry: false }) && readdirSync10(localPlugins).some((name) => name !== "skills-cli.js"))
20817
20995
  unresolved("additional local plugin hooks require review");
20818
20996
  } else if (agent === "sumi") {
20819
20997
  if ((config.plugin?.length ?? 0) > 0 || (config.plugins?.length ?? 0) > 0 || sources.some((source) => source.path !== canonical7(configPath) && source.path !== canonical7(join32(sumiConfigDirectory(home), "sumi.jsonc")) && source.sha256 !== null))
@@ -20821,7 +20999,7 @@ function resolveAgentDiscovery(options) {
20821
20999
  } else if (agent === "hermes") {
20822
21000
  for (const directory of [join32(home, ".hermes/plugins"), join32(home, ".hermes/hermes-agent")]) {
20823
21001
  safe4(directory);
20824
- if (lstatSync24(directory, { throwIfNoEntry: false }))
21002
+ if (lstatSync25(directory, { throwIfNoEntry: false }))
20825
21003
  unresolved("installed runtime/plugin discovery requires reviewed source bindings");
20826
21004
  }
20827
21005
  if (Bun.which("hermes") || Object.keys(config.plugins ?? {}).length)
@@ -20831,11 +21009,11 @@ function resolveAgentDiscovery(options) {
20831
21009
  unresolved("custom extension or skill paths");
20832
21010
  const directory = join32(home, ".gemini/extensions");
20833
21011
  safe4(directory);
20834
- if (lstatSync24(directory, { throwIfNoEntry: false }))
21012
+ if (lstatSync25(directory, { throwIfNoEntry: false }))
20835
21013
  for (const name of readdirSync10(directory)) {
20836
21014
  const root2 = join32(directory, name);
20837
21015
  safe4(root2);
20838
- if (!lstatSync24(root2)?.isDirectory())
21016
+ if (!lstatSync25(root2)?.isDirectory())
20839
21017
  continue;
20840
21018
  const raw = witness(join32(root2, "gemini-extension.json"));
20841
21019
  if (raw === null)
@@ -20868,14 +21046,14 @@ function nativeRootMatch(path) {
20868
21046
  function physicalPath(path) {
20869
21047
  let cursor = resolve19(path);
20870
21048
  const suffix = [];
20871
- while (!lstatSync25(cursor, { throwIfNoEntry: false })) {
21049
+ while (!lstatSync26(cursor, { throwIfNoEntry: false })) {
20872
21050
  suffix.unshift(basename11(cursor));
20873
21051
  const parent = dirname20(cursor);
20874
21052
  if (parent === cursor)
20875
21053
  return resolve19(path);
20876
21054
  cursor = parent;
20877
21055
  }
20878
- return resolve19(realpathSync11(cursor), ...suffix);
21056
+ return resolve19(realpathSync12(cursor), ...suffix);
20879
21057
  }
20880
21058
  function contains(root2, path) {
20881
21059
  return path === root2 || path.startsWith(root2 + sep9);
@@ -20913,7 +21091,7 @@ function configuredRoots(home, explicitHome) {
20913
21091
  continue;
20914
21092
  }
20915
21093
  const nativeHome = join33(home, agent === "opencode" ? ".config/opencode" : `.${agent}`);
20916
- if (!lstatSync25(nativeHome, { throwIfNoEntry: false }))
21094
+ if (!lstatSync26(nativeHome, { throwIfNoEntry: false }))
20917
21095
  continue;
20918
21096
  roots.push(...resolveAgentDiscovery({ home, agent, canonical: physicalPath }).roots);
20919
21097
  }
@@ -21091,14 +21269,14 @@ function physicalImportPath(path) {
21091
21269
  suffix.unshift(basename12(ancestor));
21092
21270
  ancestor = dirname21(ancestor);
21093
21271
  }
21094
- return join34(realpathSync12(ancestor), ...suffix);
21272
+ return join34(realpathSync13(ancestor), ...suffix);
21095
21273
  }
21096
21274
  function assertDisjointImportPaths(source, destination) {
21097
- const sourcePath = realpathSync12(source);
21275
+ const sourcePath = realpathSync13(source);
21098
21276
  const destinationPath = physicalImportPath(destination);
21099
21277
  const contains2 = (parent, child) => {
21100
21278
  const path = relative7(parent, child);
21101
- return path === "" || !isAbsolute19(path) && path !== ".." && !path.startsWith(`..${sep10}`);
21279
+ return path === "" || !isAbsolute20(path) && path !== ".." && !path.startsWith(`..${sep10}`);
21102
21280
  };
21103
21281
  if (contains2(sourcePath, destinationPath) || contains2(destinationPath, sourcePath)) {
21104
21282
  throw new Error("Source and destination skill directories must not overlap");
@@ -21379,7 +21557,7 @@ function safeIsDirectory(path) {
21379
21557
  }
21380
21558
  }
21381
21559
  function isSafeRelativePath2(value) {
21382
- if (!value.trim() || isAbsolute19(value))
21560
+ if (!value.trim() || isAbsolute20(value))
21383
21561
  return false;
21384
21562
  const normalized = normalize4(value).replace(/\\/g, "/");
21385
21563
  return normalized !== ".." && !normalized.startsWith("../") && !normalized.includes("/../");
@@ -21594,7 +21772,7 @@ function discoverSkillsInDir(dir, source = "custom") {
21594
21772
  continue;
21595
21773
  let content;
21596
21774
  try {
21597
- content = readFileSync20(skillMdPath, "utf-8");
21775
+ content = readFileSync21(skillMdPath, "utf-8");
21598
21776
  } catch {
21599
21777
  continue;
21600
21778
  }
@@ -21631,7 +21809,7 @@ function findExtensionSkillPath(name) {
21631
21809
  continue;
21632
21810
  let content;
21633
21811
  try {
21634
- content = readFileSync20(skillMdPath, "utf-8");
21812
+ content = readFileSync21(skillMdPath, "utf-8");
21635
21813
  } catch {
21636
21814
  continue;
21637
21815
  }
@@ -21695,8 +21873,8 @@ function getAllTags(catalog) {
21695
21873
  return Array.from(tagSet).sort();
21696
21874
  }
21697
21875
  // src/lib/run-state.ts
21698
- import { createHash as createHash24, randomBytes } from "crypto";
21699
- import { existsSync as existsSync16, mkdirSync as mkdirSync11, readFileSync as readFileSync21, readdirSync as readdirSync13, statSync as statSync12, writeFileSync as writeFileSync10 } from "fs";
21876
+ import { createHash as createHash25, randomBytes } from "crypto";
21877
+ import { existsSync as existsSync16, mkdirSync as mkdirSync11, readFileSync as readFileSync23, readdirSync as readdirSync13, statSync as statSync12, writeFileSync as writeFileSync10 } from "fs";
21700
21878
  import { extname, join as join36, relative as relative8 } from "path";
21701
21879
  function createSkillRun(params, targetDir = process.cwd()) {
21702
21880
  const now = new Date;
@@ -21768,7 +21946,7 @@ function appendRunEvent(context, event, data = {}) {
21768
21946
  const line = JSON.stringify({ ts: new Date().toISOString(), event, ...data }) + `
21769
21947
  `;
21770
21948
  const path = join36(context.runDir, "events.ndjson");
21771
- const previous = existsSync16(path) ? readFileSync21(path, "utf-8") : "";
21949
+ const previous = existsSync16(path) ? readFileSync23(path, "utf-8") : "";
21772
21950
  writeFileSync10(path, previous + line);
21773
21951
  }
21774
21952
  function listSkillRuns(targetDir = process.cwd(), limit = 50) {
@@ -21818,11 +21996,11 @@ function collectRunArtifacts(context) {
21818
21996
  const artifacts = [];
21819
21997
  for (const path of walkFiles(context.exportDir)) {
21820
21998
  const stat2 = statSync12(path);
21821
- const bytes = readFileSync21(path);
21999
+ const bytes = readFileSync23(path);
21822
22000
  artifacts.push({
21823
22001
  path: toProjectRelative(context.targetDir, path),
21824
22002
  mime: mimeForPath(path),
21825
- sha256: createHash24("sha256").update(bytes).digest("hex"),
22003
+ sha256: createHash25("sha256").update(bytes).digest("hex"),
21826
22004
  sizeBytes: stat2.size
21827
22005
  });
21828
22006
  }
@@ -21833,7 +22011,7 @@ function readRunRecord(runDir) {
21833
22011
  if (!existsSync16(path))
21834
22012
  return null;
21835
22013
  try {
21836
- return JSON.parse(readFileSync21(path, "utf-8"));
22014
+ return JSON.parse(readFileSync23(path, "utf-8"));
21837
22015
  } catch {
21838
22016
  return null;
21839
22017
  }
@@ -41241,7 +41419,7 @@ function clone2(value) {
41241
41419
  return value === undefined ? undefined : JSON.parse(JSON.stringify(value));
41242
41420
  }
41243
41421
  // src/lib/canonical-json.ts
41244
- import { createHash as createHash25 } from "crypto";
41422
+ import { createHash as createHash26 } from "crypto";
41245
41423
  function canonicalJson2(value, maximumBytes = 2 * 1024 * 1024) {
41246
41424
  return canonicalJsonAtDepth(value, maximumBytes, 64);
41247
41425
  }
@@ -41285,7 +41463,7 @@ function canonicalJsonAtDepth(value, maximumBytes, maximumDepth) {
41285
41463
  return visit3(value, 0);
41286
41464
  }
41287
41465
  function canonicalJsonSha256(value, maximumBytes) {
41288
- return createHash25("sha256").update(canonicalJson2(value, maximumBytes)).digest("hex");
41466
+ return createHash26("sha256").update(canonicalJson2(value, maximumBytes)).digest("hex");
41289
41467
  }
41290
41468
 
41291
41469
  // src/lib/remote-recurring-contract.ts
@@ -43348,7 +43526,7 @@ async function createRemoteSkillsClient(env = process.env) {
43348
43526
  return connection ? new RemoteSkillsClient(connection.apiKey, connection.apiOrigin) : null;
43349
43527
  }
43350
43528
  // src/lib/scheduler.ts
43351
- import { existsSync as existsSync17, readFileSync as readFileSync23, writeFileSync as writeFileSync11, mkdirSync as mkdirSync12 } from "fs";
43529
+ import { existsSync as existsSync17, readFileSync as readFileSync25, writeFileSync as writeFileSync11, mkdirSync as mkdirSync12 } from "fs";
43352
43530
  import { join as join37 } from "path";
43353
43531
  function getSchedulesPath(targetDir = process.cwd()) {
43354
43532
  return join37(targetDir, ".skills", "schedules.json");
@@ -43357,7 +43535,7 @@ function loadSchedules(targetDir = process.cwd()) {
43357
43535
  const path = getSchedulesPath(targetDir);
43358
43536
  if (existsSync17(path)) {
43359
43537
  try {
43360
- return JSON.parse(readFileSync23(path, "utf-8"));
43538
+ return JSON.parse(readFileSync25(path, "utf-8"));
43361
43539
  } catch {}
43362
43540
  }
43363
43541
  return { version: 1, schedules: [] };
@@ -43552,7 +43730,7 @@ function recordScheduleRun(id, status, targetDir) {
43552
43730
  saveSchedules(data, targetDir);
43553
43731
  }
43554
43732
  // src/lib/revision.ts
43555
- import { createHash as createHash26 } from "crypto";
43733
+ import { createHash as createHash27 } from "crypto";
43556
43734
  var REVISION_ID_PATTERN = /^[0-9a-f]{64}$/;
43557
43735
  function revisionIdOf(content) {
43558
43736
  const canonicalContent = {
@@ -43574,13 +43752,13 @@ function revisionIdOf(content) {
43574
43752
  canonicalContent.replacementSlug = content.replacementSlug ?? null;
43575
43753
  }
43576
43754
  const canonical7 = JSON.stringify(canonicalContent);
43577
- return createHash26("sha256").update(canonical7).digest("hex");
43755
+ return createHash27("sha256").update(canonical7).digest("hex");
43578
43756
  }
43579
43757
  function revisionIdOfRecord(record8) {
43580
43758
  return revisionIdOf(record8);
43581
43759
  }
43582
43760
  // src/lib/pull.ts
43583
- import { existsSync as existsSync18, mkdirSync as mkdirSync13, mkdtempSync as mkdtempSync3, readFileSync as readFileSync25, renameSync as renameSync7, rmSync as rmSync5, writeFileSync as writeFileSync12 } from "fs";
43761
+ import { existsSync as existsSync18, mkdirSync as mkdirSync13, mkdtempSync as mkdtempSync3, readFileSync as readFileSync26, renameSync as renameSync7, rmSync as rmSync5, writeFileSync as writeFileSync12 } from "fs";
43584
43762
  import { dirname as dirname22, join as join38 } from "path";
43585
43763
 
43586
43764
  // src/lib/skill-bundles.ts
@@ -43780,7 +43958,7 @@ function reconcileTombstone(slug2, corpusOptions) {
43780
43958
  }
43781
43959
  function readPullMarker(dir) {
43782
43960
  try {
43783
- return JSON.parse(readFileSync25(join38(dir, PULL_MARKER_FILE), "utf-8"));
43961
+ return JSON.parse(readFileSync26(join38(dir, PULL_MARKER_FILE), "utf-8"));
43784
43962
  } catch {
43785
43963
  return null;
43786
43964
  }
@@ -44017,7 +44195,7 @@ function splitNameVersion(raw) {
44017
44195
  return version2 ? { name, version: version2 } : { name };
44018
44196
  }
44019
44197
  // src/lib/recurring-surface.ts
44020
- import { isAbsolute as isAbsolute20 } from "path";
44198
+ import { isAbsolute as isAbsolute21 } from "path";
44021
44199
 
44022
44200
  // src/lib/remote-invitation-recovery.ts
44023
44201
  class InvitationEmailInputError extends Error {
@@ -44115,7 +44293,7 @@ async function requestInvitationEmail(origin, action, input2) {
44115
44293
  }
44116
44294
 
44117
44295
  // src/lib/remote-private-publications.ts
44118
- import { createHash as createHash27 } from "crypto";
44296
+ import { createHash as createHash28 } from "crypto";
44119
44297
  var PRIVATE_PUBLICATION_MAX_BYTES = 16 * 1024 * 1024;
44120
44298
  var failures2 = {
44121
44299
  INVALID_REQUEST: [400, "The publication request is invalid."],
@@ -44162,7 +44340,7 @@ var hash3 = (v) => typeof v === "string" && /^[a-f0-9]{64}$/.test(v);
44162
44340
  var record9 = (v) => !!v && typeof v === "object" && !Array.isArray(v);
44163
44341
  var exact = (v, keys) => record9(v) && Object.keys(v).sort().join(",") === keys.sort().join(",");
44164
44342
  var date5 = (v) => typeof v === "string" && /^\d{4}-\d\d-\d\dT[0-9:.]+(?:Z|[+-](?:[01]\d|2[0-3]):[0-5]\d)$/.test(v) && Number.isFinite(Date.parse(v));
44165
- var publicationSha256 = (bytes) => createHash27("sha256").update(bytes).digest("hex");
44343
+ var publicationSha256 = (bytes) => createHash28("sha256").update(bytes).digest("hex");
44166
44344
  function checkedPublicationDeclaration(value) {
44167
44345
  if (!exact(value, ["idempotencyKey", "version", "expectedCurrentVersionId", "manifestText", "archiveSha256", "archiveByteSize"]) || !publicationUuid(value.idempotencyKey) || !(value.expectedCurrentVersionId === null || publicationUuid(value.expectedCurrentVersionId)) || typeof value.version !== "string" || !value.version || value.version.length > 128 || /[\p{Cc}\p{Cs}]/u.test(value.version) || typeof value.manifestText !== "string" || Buffer.byteLength(value.manifestText) > 16384 || !hash3(value.archiveSha256) || !Number.isSafeInteger(value.archiveByteSize) || Number(value.archiveByteSize) < 1 || Number(value.archiveByteSize) > PRIVATE_PUBLICATION_MAX_BYTES)
44168
44346
  return bad();
@@ -44676,7 +44854,7 @@ var stateSchema = exports_external.object({
44676
44854
  var uuid13 = exports_external.string().regex(/^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/);
44677
44855
  var context = { userId: uuid13.optional(), membershipId: uuid13.optional() };
44678
44856
  var page2 = { limit: exports_external.number().int().min(1).max(100).optional(), cursor: exports_external.string().min(1).max(2048).optional() };
44679
- var directory = exports_external.string().max(4096).refine(isAbsolute20, "Use an absolute recovery directory");
44857
+ var directory = exports_external.string().max(4096).refine(isAbsolute21, "Use an absolute recovery directory");
44680
44858
  var email4 = exports_external.string().trim().toLowerCase().email().max(254);
44681
44859
  var code = exports_external.string().regex(/^\d{6}$/);
44682
44860
  var recurringSurfaceSchemas = {
@@ -46028,11 +46206,11 @@ function isApiMode(env = process.env) {
46028
46206
  }
46029
46207
  }
46030
46208
  // src/lib/native-storage.ts
46031
- import { createHash as createHash28, createHmac as createHmac2 } from "crypto";
46209
+ import { createHash as createHash29, createHmac as createHmac2 } from "crypto";
46032
46210
  import {
46033
46211
  existsSync as existsSync20,
46034
46212
  mkdirSync as mkdirSync16,
46035
- readFileSync as readFileSync26,
46213
+ readFileSync as readFileSync27,
46036
46214
  readdirSync as readdirSync14,
46037
46215
  statSync as statSync13,
46038
46216
  writeFileSync as writeFileSync14
@@ -46199,12 +46377,12 @@ function exportSkillsLocalSnapshot(targetDir = process.cwd(), options = {}) {
46199
46377
  const files = [];
46200
46378
  if (existsSync20(projectStateDir)) {
46201
46379
  for (const filePath of walkFiles2(projectStateDir)) {
46202
- const bytes = readFileSync26(filePath);
46380
+ const bytes = readFileSync27(filePath);
46203
46381
  const relativePath = toPosix(relative10(targetDir, filePath));
46204
46382
  files.push({
46205
46383
  path: relativePath,
46206
46384
  sizeBytes: bytes.byteLength,
46207
- sha256: createHash28("sha256").update(bytes).digest("hex"),
46385
+ sha256: createHash29("sha256").update(bytes).digest("hex"),
46208
46386
  ...options.includeFileContents ? { contentBase64: Buffer.from(bytes).toString("base64") } : {}
46209
46387
  });
46210
46388
  }
@@ -46229,7 +46407,7 @@ function importSkillsLocalSnapshot(snapshot2, targetDir = process.cwd(), options
46229
46407
  continue;
46230
46408
  }
46231
46409
  const bytes = Buffer.from(file2.contentBase64, "base64");
46232
- const hash4 = createHash28("sha256").update(bytes).digest("hex");
46410
+ const hash4 = createHash29("sha256").update(bytes).digest("hex");
46233
46411
  if (hash4 !== file2.sha256) {
46234
46412
  throw new Error(`Snapshot file checksum mismatch: ${file2.path}`);
46235
46413
  }
@@ -46561,7 +46739,7 @@ function toIsoString(value) {
46561
46739
  return Number.isNaN(date6.getTime()) ? value : date6.toISOString();
46562
46740
  }
46563
46741
  function sha256Hex2(value) {
46564
- return createHash28("sha256").update(value).digest("hex");
46742
+ return createHash29("sha256").update(value).digest("hex");
46565
46743
  }
46566
46744
  function normalizeHeaders(headers) {
46567
46745
  const result = {};
@@ -46613,15 +46791,15 @@ function toArrayBuffer(bytes) {
46613
46791
  return buffer;
46614
46792
  }
46615
46793
  // src/lib/station-snapshot.ts
46616
- import { createHash as createHash29 } from "crypto";
46794
+ import { createHash as createHash30 } from "crypto";
46617
46795
  import {
46618
46796
  copyFileSync,
46619
46797
  mkdirSync as mkdirSync17,
46620
- readFileSync as readFileSync27,
46798
+ readFileSync as readFileSync28,
46621
46799
  statSync as statSync15,
46622
46800
  writeFileSync as writeFileSync15
46623
46801
  } from "fs";
46624
- import { dirname as dirname26, isAbsolute as isAbsolute21, relative as relative11, resolve as resolve21, sep as sep13 } from "path";
46802
+ import { dirname as dirname26, isAbsolute as isAbsolute22, relative as relative11, resolve as resolve21, sep as sep13 } from "path";
46625
46803
 
46626
46804
  // src/lib/portable-snapshot-filter.ts
46627
46805
  import { readdirSync as readdirSync15, statSync as statSync14 } from "fs";
@@ -46788,7 +46966,7 @@ function validateStationId(stationId) {
46788
46966
  }
46789
46967
  }
46790
46968
  function sha256File(filePath) {
46791
- return createHash29("sha256").update(readFileSync27(filePath)).digest("hex");
46969
+ return createHash30("sha256").update(readFileSync28(filePath)).digest("hex");
46792
46970
  }
46793
46971
  function scanHome(definition, homesRoot) {
46794
46972
  const homePath = homePathFor(definition, homesRoot);
@@ -46887,7 +47065,7 @@ function writeStationSnapshot(options) {
46887
47065
  for (const plan of plans) {
46888
47066
  const destination = resolve21(repoRoot, plan.destination);
46889
47067
  const destinationRelative = relative11(repoRoot, destination);
46890
- if (destinationRelative.startsWith("..") || destinationRelative.startsWith(sep13) || isAbsolute21(destinationRelative)) {
47068
+ if (destinationRelative.startsWith("..") || destinationRelative.startsWith(sep13) || isAbsolute22(destinationRelative)) {
46891
47069
  throw new StationSnapshotError("DESTINATION_ESCAPE", `destination escapes repo root: ${plan.destination}`);
46892
47070
  }
46893
47071
  let existingDigest = null;
@@ -46939,12 +47117,12 @@ function writeStationSnapshot(options) {
46939
47117
  };
46940
47118
  }
46941
47119
  // src/lib/station-hydrate.ts
46942
- import { createHash as createHash30 } from "crypto";
47120
+ import { createHash as createHash31 } from "crypto";
46943
47121
  import {
46944
47122
  copyFileSync as copyFileSync2,
46945
47123
  mkdirSync as mkdirSync18,
46946
47124
  readdirSync as readdirSync16,
46947
- readFileSync as readFileSync28,
47125
+ readFileSync as readFileSync29,
46948
47126
  statSync as statSync16,
46949
47127
  writeFileSync as writeFileSync16
46950
47128
  } from "fs";
@@ -46963,7 +47141,7 @@ function readSnapshotManifest(repoRoot, stationId) {
46963
47141
  const manifestPath = join42(snapshotRoot, "sync-manifest.json");
46964
47142
  let manifest;
46965
47143
  try {
46966
- manifest = JSON.parse(readFileSync28(manifestPath, "utf8"));
47144
+ manifest = JSON.parse(readFileSync29(manifestPath, "utf8"));
46967
47145
  } catch (error61) {
46968
47146
  fail2("MANIFEST_UNREADABLE", `cannot read snapshot manifest: ${manifestPath}: ${error61.message}`);
46969
47147
  }
@@ -47099,7 +47277,7 @@ function planStationHydration(stationId, repoRoot) {
47099
47277
  for (const copy of copies) {
47100
47278
  let isStub = false;
47101
47279
  try {
47102
- isStub = isPointerSkillMd(readFileSync28(copy.fullPath, "utf8"));
47280
+ isStub = isPointerSkillMd(readFileSync29(copy.fullPath, "utf8"));
47103
47281
  } catch {
47104
47282
  isStub = false;
47105
47283
  }
@@ -47145,7 +47323,7 @@ function skillSha256(skill) {
47145
47323
  return sha256File(skill.files[0].winner.fullPath);
47146
47324
  }
47147
47325
  const joined = skill.files.map((file2) => sha256File(file2.winner.fullPath));
47148
- return createHash30("sha256").update(joined.sort().join(`
47326
+ return createHash31("sha256").update(joined.sort().join(`
47149
47327
  `)).digest("hex");
47150
47328
  }
47151
47329
  function writeStationHydration(options) {
@@ -47237,23 +47415,23 @@ function writeStationHydration(options) {
47237
47415
  };
47238
47416
  }
47239
47417
  // src/lib/private-publication-recovery.ts
47240
- import { constants as constants14, closeSync as closeSync14, fsyncSync as fsyncSync6, fstatSync as fstatSync14, lstatSync as lstatSync26, mkdirSync as mkdirSync19, openSync as openSync14, readSync as readSync12, realpathSync as realpathSync13, renameSync as renameSync8, unlinkSync as unlinkSync6, writeFileSync as writeFileSync17 } from "fs";
47241
- import { dirname as dirname28, isAbsolute as isAbsolute22, join as join43, resolve as resolve23 } from "path";
47418
+ import { constants as constants15, closeSync as closeSync15, fsyncSync as fsyncSync7, fstatSync as fstatSync15, lstatSync as lstatSync27, mkdirSync as mkdirSync19, openSync as openSync15, readSync as readSync12, realpathSync as realpathSync14, renameSync as renameSync8, unlinkSync as unlinkSync6, writeFileSync as writeFileSync17 } from "fs";
47419
+ import { dirname as dirname28, isAbsolute as isAbsolute23, join as join43, resolve as resolve23 } from "path";
47242
47420
  import { randomUUID as randomUUID5 } from "crypto";
47243
47421
  var fail3 = () => {
47244
47422
  throw new PrivatePublicationError("PUBLICATION_RECOVERY_INVALID", "The recovery directory is invalid or changed. Preserve it and inspect the existing intent; do not start a replacement automatically.");
47245
47423
  };
47246
47424
  function safeDirectory(directory2) {
47247
- if (!isAbsolute22(directory2) || directory2 !== resolve23(directory2) || realpathSync13(directory2) !== directory2)
47425
+ if (!isAbsolute23(directory2) || directory2 !== resolve23(directory2) || realpathSync14(directory2) !== directory2)
47248
47426
  return fail3();
47249
47427
  for (let path = directory2;; path = dirname28(path)) {
47250
- const stat2 = lstatSync26(path);
47428
+ const stat2 = lstatSync27(path);
47251
47429
  if (!stat2.isDirectory() || stat2.isSymbolicLink())
47252
47430
  return fail3();
47253
47431
  if (path === dirname28(path))
47254
47432
  break;
47255
47433
  }
47256
- const own2 = lstatSync26(directory2);
47434
+ const own2 = lstatSync27(directory2);
47257
47435
  if ((own2.mode & 63) !== 0 || process.getuid && own2.uid !== process.getuid())
47258
47436
  return fail3();
47259
47437
  return { dev: own2.dev, ino: own2.ino };
@@ -47265,9 +47443,9 @@ function unchangedDirectory(directory2, identity5) {
47265
47443
  }
47266
47444
  function readOwned(directory2, name, max) {
47267
47445
  const identity5 = safeDirectory(directory2), file2 = join43(directory2, name);
47268
- const fd = openSync14(file2, constants14.O_RDONLY | constants14.O_NOFOLLOW);
47446
+ const fd = openSync15(file2, constants15.O_RDONLY | constants15.O_NOFOLLOW);
47269
47447
  try {
47270
- const stat2 = fstatSync14(fd);
47448
+ const stat2 = fstatSync15(fd);
47271
47449
  if (!stat2.isFile() || stat2.nlink !== 1 || stat2.size > max || stat2.size < 1 || (stat2.mode & 63) !== 0 || process.getuid && stat2.uid !== process.getuid())
47272
47450
  return fail3();
47273
47451
  const buffer = Buffer.alloc(Math.min(max, stat2.size) + 1);
@@ -47278,22 +47456,22 @@ function readOwned(directory2, name, max) {
47278
47456
  break;
47279
47457
  length += count;
47280
47458
  }
47281
- const bytes = buffer.subarray(0, length), after = fstatSync14(fd);
47459
+ const bytes = buffer.subarray(0, length), after = fstatSync15(fd);
47282
47460
  unchangedDirectory(directory2, identity5);
47283
47461
  if (bytes.length !== stat2.size || stat2.size !== after.size || stat2.mtimeMs !== after.mtimeMs || stat2.ctimeMs !== after.ctimeMs)
47284
47462
  return fail3();
47285
47463
  return bytes;
47286
47464
  } finally {
47287
- closeSync14(fd);
47465
+ closeSync15(fd);
47288
47466
  }
47289
47467
  }
47290
47468
  function writeOwned(directory2, name, bytes) {
47291
- const fd = openSync14(join43(directory2, name), constants14.O_WRONLY | constants14.O_CREAT | constants14.O_EXCL | constants14.O_NOFOLLOW, 384);
47469
+ const fd = openSync15(join43(directory2, name), constants15.O_WRONLY | constants15.O_CREAT | constants15.O_EXCL | constants15.O_NOFOLLOW, 384);
47292
47470
  try {
47293
47471
  writeFileSync17(fd, bytes);
47294
- fsyncSync6(fd);
47472
+ fsyncSync7(fd);
47295
47473
  } finally {
47296
- closeSync14(fd);
47474
+ closeSync15(fd);
47297
47475
  }
47298
47476
  }
47299
47477
  function save(directory2, value) {
@@ -47302,11 +47480,11 @@ function save(directory2, value) {
47302
47480
  `);
47303
47481
  unchangedDirectory(directory2, identity5);
47304
47482
  renameSync8(join43(directory2, temporary), join43(directory2, "receipt.json"));
47305
- const fd = openSync14(directory2, constants14.O_RDONLY | constants14.O_NOFOLLOW);
47483
+ const fd = openSync15(directory2, constants15.O_RDONLY | constants15.O_NOFOLLOW);
47306
47484
  try {
47307
- fsyncSync6(fd);
47485
+ fsyncSync7(fd);
47308
47486
  } finally {
47309
- closeSync14(fd);
47487
+ closeSync15(fd);
47310
47488
  }
47311
47489
  }
47312
47490
  function bind(client2, receipt) {
@@ -47317,20 +47495,20 @@ async function locked(directory2, action) {
47317
47495
  const identity5 = safeDirectory(directory2), file2 = join43(directory2, "operation.lock");
47318
47496
  let fd;
47319
47497
  try {
47320
- fd = openSync14(file2, constants14.O_WRONLY | constants14.O_CREAT | constants14.O_EXCL | constants14.O_NOFOLLOW, 384);
47498
+ fd = openSync15(file2, constants15.O_WRONLY | constants15.O_CREAT | constants15.O_EXCL | constants15.O_NOFOLLOW, 384);
47321
47499
  } catch {
47322
47500
  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.");
47323
47501
  }
47324
- const lock = fstatSync14(fd);
47502
+ const lock = fstatSync15(fd);
47325
47503
  try {
47326
47504
  writeFileSync17(fd, JSON.stringify({ pid: process.pid }) + `
47327
47505
  `);
47328
- fsyncSync6(fd);
47506
+ fsyncSync7(fd);
47329
47507
  return await action();
47330
47508
  } finally {
47331
- closeSync14(fd);
47509
+ closeSync15(fd);
47332
47510
  unchangedDirectory(directory2, identity5);
47333
- const now = lstatSync26(file2);
47511
+ const now = lstatSync27(file2);
47334
47512
  if (now.dev !== lock.dev || now.ino !== lock.ino || !now.isFile() || now.isSymbolicLink())
47335
47513
  fail3();
47336
47514
  unlinkSync6(file2);
@@ -47382,15 +47560,15 @@ async function preparePrivatePublication(client2, sourceDirectory, recoveryDirec
47382
47560
  phase: "prepared",
47383
47561
  intent: null
47384
47562
  };
47385
- if (!isAbsolute22(recoveryDirectory) || resolve23(recoveryDirectory) !== recoveryDirectory || realpathSync13(dirname28(recoveryDirectory)) !== dirname28(recoveryDirectory))
47563
+ if (!isAbsolute23(recoveryDirectory) || resolve23(recoveryDirectory) !== recoveryDirectory || realpathSync14(dirname28(recoveryDirectory)) !== dirname28(recoveryDirectory))
47386
47564
  return fail3();
47387
47565
  mkdirSync19(recoveryDirectory, { mode: 448 });
47388
47566
  safeDirectory(recoveryDirectory);
47389
- const parent = openSync14(dirname28(recoveryDirectory), constants14.O_RDONLY | constants14.O_NOFOLLOW);
47567
+ const parent = openSync15(dirname28(recoveryDirectory), constants15.O_RDONLY | constants15.O_NOFOLLOW);
47390
47568
  try {
47391
- fsyncSync6(parent);
47569
+ fsyncSync7(parent);
47392
47570
  } finally {
47393
- closeSync14(parent);
47571
+ closeSync15(parent);
47394
47572
  }
47395
47573
  writeOwned(recoveryDirectory, "bundle.tgz", packed.bytes);
47396
47574
  save(recoveryDirectory, receipt);
@@ -47473,7 +47651,7 @@ async function inspectLocked(client2, directory2, cancel) {
47473
47651
  return privatePublicationResult(directory2, receipt);
47474
47652
  }
47475
47653
  // src/lib/skill-context.ts
47476
- import { createHash as createHash31 } from "crypto";
47654
+ import { createHash as createHash32 } from "crypto";
47477
47655
  import { resolve as resolve24 } from "path";
47478
47656
  function words(value) {
47479
47657
  return new Set(value.toLowerCase().match(/[a-z0-9]+/g) ?? []);
@@ -47566,7 +47744,7 @@ ${content}`;
47566
47744
  `);
47567
47745
  const receipt = {
47568
47746
  schemaVersion: 1,
47569
- id: createHash31("sha256").update(JSON.stringify({ profile: profile.profileRevision, sessionId, selections, omitted })).digest("hex"),
47747
+ id: createHash32("sha256").update(JSON.stringify({ profile: profile.profileRevision, sessionId, selections, omitted })).digest("hex"),
47570
47748
  profileId: profile.profileId,
47571
47749
  profileRevision: profile.profileRevision,
47572
47750
  authority: profile.authority,
@@ -47582,9 +47760,9 @@ ${content}`;
47582
47760
  return { context: context2, selections, omitted, receipt };
47583
47761
  }
47584
47762
  // src/lib/session-reconciliation.ts
47585
- import { createHash as createHash32 } from "crypto";
47763
+ import { createHash as createHash33 } from "crypto";
47586
47764
  var SESSION_RECONCILIATION_PLAN_TTL_MS = 5 * 60 * 1000;
47587
- var digest3 = (value) => createHash32("sha256").update(JSON.stringify(value)).digest("hex");
47765
+ var digest3 = (value) => createHash33("sha256").update(JSON.stringify(value)).digest("hex");
47588
47766
  function exactTimestamp(value) {
47589
47767
  const parsed = value === undefined ? Number.NaN : Date.parse(value);
47590
47768
  if (!Number.isFinite(parsed) || new Date(parsed).toISOString() !== value) {
@@ -47702,6 +47880,7 @@ export {
47702
47880
  upgradeCodexSettingsWitnessV4,
47703
47881
  upgradeCodexSettingsWitnessV3,
47704
47882
  upgradeCodexSettingsWitness,
47883
+ upgradeClaudeSettingsWitnessV4,
47705
47884
  upgradeClaudeSettingsWitness,
47706
47885
  updateSkillRun,
47707
47886
  unsetConfig,
@@ -47893,6 +48072,7 @@ export {
47893
48072
  captureCodexSettingsV2,
47894
48073
  captureCodexSettings,
47895
48074
  captureCodexNativeSkillCatalog,
48075
+ captureClaudeSettingsV4,
47896
48076
  captureClaudeSettingsV3,
47897
48077
  captureClaudeSettingsV2,
47898
48078
  captureClaudeSettings,