@hasna/skills 0.10.44 → 0.10.46

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/bin/mcp.js CHANGED
@@ -20019,7 +20019,7 @@ var package_default;
20019
20019
  var init_package = __esm(() => {
20020
20020
  package_default = {
20021
20021
  name: "@hasna/skills",
20022
- version: "0.10.44",
20022
+ version: "0.10.46",
20023
20023
  description: "Skills library for AI coding agents",
20024
20024
  type: "module",
20025
20025
  bin: {
@@ -38209,8 +38209,323 @@ var init_agent_adapters = __esm(() => {
38209
38209
  INTEGRATION_AGENTS = ["claude", "codex", "gemini", "opencode", "cursor", "hermes", "sumi"];
38210
38210
  });
38211
38211
 
38212
+ // src/lib/claude-settings-witness.ts
38213
+ import { createHash as createHash2 } from "crypto";
38214
+ import { closeSync as closeSync5, constants as constants2, fstatSync as fstatSync5, lstatSync as lstatSync5, openSync as openSync5, readSync as readSync2 } from "fs";
38215
+ import { basename as basename3, dirname as dirname4, isAbsolute as isAbsolute3, resolve as resolve2 } from "path";
38216
+ function need(value, reason) {
38217
+ if (!value)
38218
+ throw new Error(`Claude settings witness ${reason}`);
38219
+ }
38220
+ function absolutePath(value) {
38221
+ need(typeof value === "string" && value.length > 0 && value.length <= CLAUDE_SETTINGS_WITNESS_LIMITS.pathCharacters && !/[\x00-\x1f\x7f]/.test(value) && isAbsolute3(value) && resolve2(value) === value, "requires a normalized absolute path");
38222
+ }
38223
+ function parents(path) {
38224
+ const result = [];
38225
+ for (let at = dirname4(path);; at = dirname4(at)) {
38226
+ const stat = lstatSync5(at, { bigint: true });
38227
+ need(stat.isDirectory() && !stat.isSymbolicLink(), "path traverses a symlink or non-directory");
38228
+ result.push([at, stat]);
38229
+ if (at === dirname4(at))
38230
+ return result;
38231
+ }
38232
+ }
38233
+ function readNativeSettingsWitnessFile(path, budget, filename = "settings.json") {
38234
+ absolutePath(path);
38235
+ need(basename3(path) === filename, `requires ${filename}`);
38236
+ need(Number.isSafeInteger(budget.remaining) && budget.remaining >= 0, "has an invalid byte budget");
38237
+ const ancestors = parents(path), initial = lstatSync5(path, { bigint: true });
38238
+ need(initial.isFile() && !initial.isSymbolicLink() && initial.size <= BigInt(CLAUDE_SETTINGS_WITNESS_LIMITS.bytes), "is not a bounded regular file");
38239
+ need(initial.size <= BigInt(budget.remaining), "exceeds its aggregate byte limit");
38240
+ const fd = openSync5(path, constants2.O_RDONLY | constants2.O_NOFOLLOW | constants2.O_NONBLOCK);
38241
+ try {
38242
+ const opened = fstatSync5(fd, { bigint: true });
38243
+ need(opened.isFile() && sameFile(initial, opened), "changed during open");
38244
+ const bytes = Buffer.alloc(Number(opened.size) + 1);
38245
+ let length = 0;
38246
+ while (length < bytes.length) {
38247
+ const count = readSync2(fd, bytes, length, bytes.length - length, null);
38248
+ if (!count)
38249
+ break;
38250
+ length += count;
38251
+ }
38252
+ const after = fstatSync5(fd, { bigint: true }), current = lstatSync5(path, { bigint: true });
38253
+ need(current.isFile() && sameFile(opened, after) && sameFile(after, current) && BigInt(length) === opened.size, "changed during read");
38254
+ for (const [ancestor, before] of ancestors) {
38255
+ const now = lstatSync5(ancestor, { bigint: true });
38256
+ need(now.isDirectory() && before.dev === now.dev && before.ino === now.ino && before.mode === now.mode, "parent changed during read");
38257
+ }
38258
+ budget.remaining -= length;
38259
+ try {
38260
+ return new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(bytes.subarray(0, length));
38261
+ } catch {
38262
+ throw new Error("Claude settings witness is not strict UTF-8");
38263
+ }
38264
+ } finally {
38265
+ closeSync5(fd);
38266
+ }
38267
+ }
38268
+ function parse6(text) {
38269
+ let at = 0, nodes = 0;
38270
+ const numberPattern = /-?(?:0|[1-9][0-9]*)(?:\.[0-9]+)?(?:[eE][+-]?[0-9]+)?/y;
38271
+ const space = () => {
38272
+ while (at < text.length && /[\x20\t\r\n]/.test(text[at]))
38273
+ at++;
38274
+ };
38275
+ function string5() {
38276
+ need(text[at] === '"', "contains invalid JSON");
38277
+ const start = at++;
38278
+ while (at < text.length) {
38279
+ const character = text[at++];
38280
+ if (character === '"') {
38281
+ let value2;
38282
+ try {
38283
+ value2 = JSON.parse(text.slice(start, at));
38284
+ } catch {
38285
+ throw new Error("Claude settings witness contains invalid JSON string");
38286
+ }
38287
+ need(value2.length <= CLAUDE_SETTINGS_WITNESS_LIMITS.stringCharacters, "exceeds its string limit");
38288
+ return value2;
38289
+ }
38290
+ if (character === "\\")
38291
+ at++;
38292
+ }
38293
+ throw new Error("Claude settings witness contains an unterminated JSON string");
38294
+ }
38295
+ function value(depth) {
38296
+ need(depth <= CLAUDE_SETTINGS_WITNESS_LIMITS.depth && ++nodes <= CLAUDE_SETTINGS_WITNESS_LIMITS.nodes, "exceeds its nesting or node limit");
38297
+ space();
38298
+ const character = text[at];
38299
+ if (character === '"')
38300
+ return { kind: "string", value: string5() };
38301
+ if (character === "{" || character === "[") {
38302
+ at++;
38303
+ space();
38304
+ const object4 = character === "{", end = object4 ? "}" : "]", entries = [], items = [], keys = new Set;
38305
+ if (text[at] !== end)
38306
+ while (true) {
38307
+ if (object4) {
38308
+ space();
38309
+ const key = string5();
38310
+ need(!keys.has(key), "contains a duplicate JSON key");
38311
+ keys.add(key);
38312
+ space();
38313
+ need(text[at++] === ":", "contains invalid JSON");
38314
+ entries.push([key, value(depth + 1)]);
38315
+ } else
38316
+ items.push(value(depth + 1));
38317
+ space();
38318
+ if (text[at] === end)
38319
+ break;
38320
+ need(text[at++] === ",", "contains invalid JSON");
38321
+ }
38322
+ at++;
38323
+ return object4 ? { kind: "object", entries } : { kind: "array", items };
38324
+ }
38325
+ for (const literal3 of ["true", "false", "null"])
38326
+ if (text.startsWith(literal3, at)) {
38327
+ at += literal3.length;
38328
+ return { kind: "literal", value: literal3 };
38329
+ }
38330
+ numberPattern.lastIndex = at;
38331
+ const number5 = numberPattern.exec(text);
38332
+ need(number5, "contains invalid JSON");
38333
+ at += number5[0].length;
38334
+ return { kind: "number", value: number5[0] };
38335
+ }
38336
+ const root = value(0);
38337
+ space();
38338
+ need(at === text.length && root.kind === "object", "requires a JSON object without trailing content");
38339
+ need(root.entries.length <= CLAUDE_SETTINGS_WITNESS_LIMITS.rows, "exceeds its settings field limit");
38340
+ return root;
38341
+ }
38342
+ function canonical(value) {
38343
+ if (value.kind === "object")
38344
+ return { kind: "object", entries: value.entries.map(([key, child]) => [key, canonical(child)]).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0) };
38345
+ if (value.kind === "array")
38346
+ return { kind: "array", items: value.items.map(canonical) };
38347
+ return value;
38348
+ }
38349
+ function inferencePreference(key, child, version2) {
38350
+ if (key === "skipDangerousModePermissionPrompt") {
38351
+ need(child.kind === "literal" && (child.value === "true" || child.value === "false"), "contains an invalid dialog acknowledgment");
38352
+ return false;
38353
+ }
38354
+ if (key === "effortLevel") {
38355
+ need(child.kind === "string" && PERSISTED_EFFORT_LEVELS.has(child.value), "contains an invalid persisted effort level");
38356
+ return true;
38357
+ }
38358
+ if (key !== "modelSettings")
38359
+ return false;
38360
+ need(child.kind === "object", "requires an object of model preferences");
38361
+ child.entries = child.entries.filter(([model, preferences]) => {
38362
+ if (version2 === 2 && !BUILTIN_MODEL_SELECTIONS.has(model) || preferences.kind !== "object" || preferences.entries.length !== 1 || preferences.entries[0][0] !== "effortLevel")
38363
+ return true;
38364
+ const effort = preferences.entries[0][1];
38365
+ need(effort.kind === "string" && PERSISTED_EFFORT_LEVELS.has(effort.value), "contains an invalid persisted model effort level");
38366
+ return false;
38367
+ });
38368
+ return child.entries.length === 0;
38369
+ }
38370
+ function settingsDigest(text, version2 = 1) {
38371
+ const value = parse6(text);
38372
+ value.entries = value.entries.filter(([key, child]) => {
38373
+ if (version2 !== 1 && inferencePreference(key, child, version2))
38374
+ return false;
38375
+ if (key === "model") {
38376
+ need(child.kind === "string", "contains an invalid model selection");
38377
+ return !BUILTIN_MODEL_SELECTIONS.has(child.value);
38378
+ }
38379
+ if (BOOLEAN_PREFERENCES.has(key)) {
38380
+ need(child.kind === "literal" && (child.value === "true" || child.value === "false"), "contains an invalid display preference");
38381
+ return false;
38382
+ }
38383
+ if (Object.hasOwn(ENUM_PREFERENCES, key)) {
38384
+ need(child.kind === "string" && ENUM_PREFERENCES[key].includes(child.value), "contains an invalid display preference");
38385
+ return false;
38386
+ }
38387
+ return true;
38388
+ });
38389
+ return createHash2("sha256").update(`hasna.skills.claude-settings.v${version2}\x00`).update(JSON.stringify(canonical(value))).digest("hex");
38390
+ }
38391
+ function hashClaudeSettingsReplacement(text, budget) {
38392
+ need(typeof text === "string", "requires settings text");
38393
+ const bytes = Buffer.byteLength(text);
38394
+ need(bytes <= CLAUDE_SETTINGS_WITNESS_LIMITS.bytes && Number.isSafeInteger(budget.remaining) && budget.remaining >= bytes, "exceeds its byte limit");
38395
+ budget.remaining -= bytes;
38396
+ return settingsDigest(text);
38397
+ }
38398
+ function captureClaudeSettings(path, budget = { remaining: 256 * 1024 * 1024 }) {
38399
+ return { path, hashMode: "claude-settings-v1", sha256: settingsDigest(readNativeSettingsWitnessFile(path, budget)) };
38400
+ }
38401
+ function captureClaudeSettingsV2(path, budget = { remaining: 256 * 1024 * 1024 }) {
38402
+ return { path, hashMode: "claude-settings-v2", sha256: settingsDigest(readNativeSettingsWitnessFile(path, budget), 2) };
38403
+ }
38404
+ function hashClaudeSettingsReplacementV2(text, budget) {
38405
+ need(typeof text === "string", "requires settings text");
38406
+ const bytes = Buffer.byteLength(text);
38407
+ need(bytes <= CLAUDE_SETTINGS_WITNESS_LIMITS.bytes && Number.isSafeInteger(budget.remaining) && budget.remaining >= bytes, "exceeds its byte limit");
38408
+ budget.remaining -= bytes;
38409
+ return settingsDigest(text, 2);
38410
+ }
38411
+ function captureClaudeSettingsV3(path, budget = { remaining: 256 * 1024 * 1024 }) {
38412
+ return { path, hashMode: "claude-settings-v3", sha256: settingsDigest(readNativeSettingsWitnessFile(path, budget), 3) };
38413
+ }
38414
+ function hashClaudeSettingsReplacementV3(text, budget) {
38415
+ need(typeof text === "string", "requires settings text");
38416
+ const bytes = Buffer.byteLength(text);
38417
+ need(bytes <= CLAUDE_SETTINGS_WITNESS_LIMITS.bytes && Number.isSafeInteger(budget.remaining) && budget.remaining >= bytes, "exceeds its byte limit");
38418
+ budget.remaining -= bytes;
38419
+ return settingsDigest(text, 3);
38420
+ }
38421
+ function hashNativeJsonControls(text, excludedMetadata) {
38422
+ need(Buffer.byteLength(text) <= CLAUDE_SETTINGS_WITNESS_LIMITS.bytes, "exceeds its byte limit");
38423
+ const value = parse6(text);
38424
+ value.entries = value.entries.filter(([key, child]) => {
38425
+ if (key !== excludedMetadata)
38426
+ return true;
38427
+ need(child.kind === "string" && child.value.length <= 128, "has invalid version metadata");
38428
+ return false;
38429
+ });
38430
+ return createHash2("sha256").update("hasna.skills.native-json-controls.v1\x00").update(JSON.stringify(canonical(value))).digest("hex");
38431
+ }
38432
+ function hashSumiNativeJsonControls(text) {
38433
+ need(Buffer.byteLength(text) <= CLAUDE_SETTINGS_WITNESS_LIMITS.bytes, "exceeds its byte limit");
38434
+ const value = parse6(text);
38435
+ value.entries = value.entries.filter(([key, child]) => {
38436
+ if (key === "$schema" || key === "username") {
38437
+ need(child.kind === "string", "has invalid Sumi display metadata");
38438
+ return false;
38439
+ }
38440
+ if (key !== "experimental")
38441
+ return true;
38442
+ need(child.kind === "object", "requires Sumi experimental controls to be an object");
38443
+ child.entries = child.entries.filter(([name, option]) => {
38444
+ if (name !== "statusline" && name !== "compact_tools")
38445
+ return true;
38446
+ need(option.kind === "literal" && (option.value === "true" || option.value === "false"), "has invalid Sumi display preference");
38447
+ return false;
38448
+ });
38449
+ return child.entries.length > 0;
38450
+ });
38451
+ return createHash2("sha256").update("hasna.skills.sumi-settings.v1\x00").update(JSON.stringify(value)).digest("hex");
38452
+ }
38453
+ var CLAUDE_SETTINGS_WITNESS_LIMITS, sameFile = (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, BOOLEAN_PREFERENCES, ENUM_PREFERENCES, BUILTIN_MODEL_SELECTIONS, PERSISTED_EFFORT_LEVELS;
38454
+ var init_claude_settings_witness = __esm(() => {
38455
+ CLAUDE_SETTINGS_WITNESS_LIMITS = Object.freeze({ bytes: 1024 * 1024, rows: 1024, depth: 32, nodes: 65536, stringCharacters: 16384, pathCharacters: 4096 });
38456
+ BOOLEAN_PREFERENCES = new Set([
38457
+ "autoScrollEnabled",
38458
+ "axScreenReader",
38459
+ "emojiCompletionEnabled",
38460
+ "prefersReducedMotion",
38461
+ "showTurnDuration",
38462
+ "spinnerTipsEnabled",
38463
+ "syntaxHighlightingDisabled",
38464
+ "terminalProgressBarEnabled",
38465
+ "terminalTitleFromRename",
38466
+ "verbose",
38467
+ "wheelScrollAccelerationEnabled"
38468
+ ]);
38469
+ ENUM_PREFERENCES = Object.freeze({
38470
+ editorMode: ["normal", "vim"],
38471
+ tui: ["default", "fullscreen"],
38472
+ viewMode: ["default", "verbose", "focus"]
38473
+ });
38474
+ BUILTIN_MODEL_SELECTIONS = new Set([
38475
+ "default",
38476
+ "best",
38477
+ "fable",
38478
+ "fable[1m]",
38479
+ "sonnet",
38480
+ "sonnet[1m]",
38481
+ "opus",
38482
+ "opus[1m]",
38483
+ "haiku",
38484
+ "opusplan",
38485
+ "claude-fable-5-1",
38486
+ "claude-fable-5",
38487
+ "claude-fable-5[1m]",
38488
+ "claude-opus-5",
38489
+ "claude-sonnet-5",
38490
+ "claude-haiku-4-5-20251001",
38491
+ "claude-opus-4-6",
38492
+ "claude-sonnet-4-5",
38493
+ "claude-sonnet-4-5-20250929",
38494
+ "claude-opus-4-8",
38495
+ "claude-opus-4-8[1m]",
38496
+ "claude-opus-4-7",
38497
+ "claude-sonnet-4-6",
38498
+ "claude-opus-4-5-20251101",
38499
+ "claude-opus-4-5",
38500
+ "claude-haiku-4-5",
38501
+ "claude-fable-5-1[1m]",
38502
+ "claude-opus-5[1m]",
38503
+ "claude-opus-4-7[1m]",
38504
+ "claude-opus-4-6[1m]",
38505
+ "claude-sonnet-4-6[1m]"
38506
+ ]);
38507
+ PERSISTED_EFFORT_LEVELS = new Set(["low", "medium", "high", "xhigh"]);
38508
+ });
38509
+
38510
+ // src/lib/sumi-settings-witness.ts
38511
+ function hashSumiSettingsReplacement(text, limits) {
38512
+ const bytes = Buffer.byteLength(text);
38513
+ if (bytes > CLAUDE_SETTINGS_WITNESS_LIMITS.bytes || !Number.isSafeInteger(limits.remaining) || limits.remaining < bytes)
38514
+ throw new Error("Sumi settings witness exceeds its byte limit");
38515
+ limits.remaining -= bytes;
38516
+ return hashSumiNativeJsonControls(text);
38517
+ }
38518
+ function captureSumiSettings(path, limits = budget()) {
38519
+ return { path, hashMode: "sumi-settings-v1", sha256: hashSumiNativeJsonControls(readNativeSettingsWitnessFile(path, limits, "sumi.json")) };
38520
+ }
38521
+ var SUMI_DISCOVERY_PROJECTION_FIELDS, budget = () => ({ remaining: 256 * 1024 * 1024 });
38522
+ var init_sumi_settings_witness = __esm(() => {
38523
+ init_claude_settings_witness();
38524
+ SUMI_DISCOVERY_PROJECTION_FIELDS = ["skills", "plugin", "plugins", "permissions"];
38525
+ });
38526
+
38212
38527
  // src/lib/agent-policy-limits.ts
38213
- import { basename as basename3, isAbsolute as isAbsolute3, resolve as resolve2 } from "path";
38528
+ import { basename as basename4, isAbsolute as isAbsolute4, resolve as resolve3 } from "path";
38214
38529
  function object4(value) {
38215
38530
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
38216
38531
  }
@@ -38263,7 +38578,7 @@ function assertAgentPolicyCollections(policy) {
38263
38578
  text(control.pluginId, 1024);
38264
38579
  text(control.namespace, 64);
38265
38580
  text(control.pluginParent);
38266
- requireBound(isAbsolute3(control.pluginParent) && resolve2(control.pluginParent) === control.pluginParent && /^[a-f0-9]{64}$/.test(control.manifestSha256));
38581
+ requireBound(isAbsolute4(control.pluginParent) && resolve3(control.pluginParent) === control.pluginParent && /^[a-f0-9]{64}$/.test(control.manifestSha256));
38267
38582
  if (control.remotePluginId !== undefined)
38268
38583
  requireBound(typeof control.remotePluginId === "string" && /^[A-Za-z0-9_~-]{1,1024}$/.test(control.remotePluginId));
38269
38584
  if (control.skillsOnly !== undefined)
@@ -38281,7 +38596,7 @@ function assertAgentPolicyCollections(policy) {
38281
38596
  text(control.pluginId, 1024);
38282
38597
  text(control.namespace, 64);
38283
38598
  text(control.pluginParent);
38284
- requireBound(!ids.has(control.pluginId) && isAbsolute3(control.pluginParent) && resolve2(control.pluginParent) === control.pluginParent && ["local", "git", "npm"].includes(control.sourceType) && typeof control.sourceSha256 === "string" && /^[a-f0-9]{64}$/.test(control.sourceSha256));
38599
+ requireBound(!ids.has(control.pluginId) && isAbsolute4(control.pluginParent) && resolve3(control.pluginParent) === control.pluginParent && ["local", "git", "npm"].includes(control.sourceType) && typeof control.sourceSha256 === "string" && /^[a-f0-9]{64}$/.test(control.sourceSha256));
38285
38600
  ids.add(control.pluginId);
38286
38601
  }
38287
38602
  }
@@ -38306,15 +38621,15 @@ function assertAgentPolicyCollections(policy) {
38306
38621
  requireBound(object4(value));
38307
38622
  text(value.agent, 128);
38308
38623
  if (value.codexRetiredMaterializations !== undefined) {
38309
- const proof = record3(value.codexRetiredMaterializations, 3), roots = array3(proof.roots, AGENT_POLICY_LIMITS.discoveryRoots), parents = proof.parents === undefined ? [] : array3(proof.parents, AGENT_POLICY_LIMITS.discoveryRoots);
38310
- requireBound(agent === "codex" && value.agent === "codex" && value.method === "reviewed" && Object.keys(proof).every((key) => ["roots", "parents", "directories"].includes(key)) && roots.length + parents.length > 0 && new Set(roots).size === roots.length && new Set(parents).size === parents.length);
38624
+ const proof = record3(value.codexRetiredMaterializations, 3), roots = array3(proof.roots, AGENT_POLICY_LIMITS.discoveryRoots), parents2 = proof.parents === undefined ? [] : array3(proof.parents, AGENT_POLICY_LIMITS.discoveryRoots);
38625
+ requireBound(agent === "codex" && value.agent === "codex" && value.method === "reviewed" && Object.keys(proof).every((key) => ["roots", "parents", "directories"].includes(key)) && roots.length + parents2.length > 0 && new Set(roots).size === roots.length && new Set(parents2).size === parents2.length);
38311
38626
  for (const root of roots) {
38312
38627
  text(root);
38313
- requireBound(isAbsolute3(root) && resolve2(root) === root);
38628
+ requireBound(isAbsolute4(root) && resolve3(root) === root);
38314
38629
  }
38315
- for (const parent of parents) {
38630
+ for (const parent of parents2) {
38316
38631
  text(parent);
38317
- requireBound(isAbsolute3(parent) && resolve2(parent) === parent);
38632
+ requireBound(isAbsolute4(parent) && resolve3(parent) === parent);
38318
38633
  }
38319
38634
  for (const directory of array3(proof.directories, AGENT_POLICY_LIMITS.discoveryDirectories)) {
38320
38635
  requireBound(object4(directory));
@@ -38334,7 +38649,7 @@ function assertAgentPolicyCollections(policy) {
38334
38649
  text(input2.namespace, 64);
38335
38650
  text(input2.pluginParent);
38336
38651
  text(input2.sourceRoot);
38337
- requireBound(!ids.has(input2.pluginId) && [input2.pluginParent, input2.sourceRoot].every((path) => isAbsolute3(path) && resolve2(path) === path) && typeof input2.sourceSha256 === "string" && /^[a-f0-9]{64}$/.test(input2.sourceSha256));
38652
+ requireBound(!ids.has(input2.pluginId) && [input2.pluginParent, input2.sourceRoot].every((path) => isAbsolute4(path) && resolve3(path) === path) && typeof input2.sourceSha256 === "string" && /^[a-f0-9]{64}$/.test(input2.sourceSha256));
38338
38653
  ids.add(input2.pluginId);
38339
38654
  }
38340
38655
  if (proof.directories !== undefined)
@@ -38351,13 +38666,15 @@ function assertAgentPolicyCollections(policy) {
38351
38666
  text(source.path);
38352
38667
  requireBound(source.sha256 === null || typeof source.sha256 === "string" && /^[a-f0-9]{64}$/.test(source.sha256));
38353
38668
  if (source.hashMode !== undefined)
38354
- requireBound(["bytes", "path-bytes", "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"].includes(source.hashMode) && source.format === undefined && source.fields === undefined && (source.hashMode === "bytes" || source.sha256 !== null));
38669
+ requireBound(["bytes", "path-bytes", "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));
38670
+ if (source.hashMode === "sumi-settings-v1")
38671
+ requireBound(agent === "sumi" && value.agent === "sumi" && value.method === "reviewed" && !/[\x00-\x1f\x7f]/.test(source.path) && isAbsolute4(source.path) && resolve3(source.path) === source.path && basename4(source.path) === "sumi.json");
38355
38672
  if (source.hashMode === "codex-settings-v1" || source.hashMode === "codex-settings-v2" || (source.hashMode === "codex-settings-v3" || source.hashMode === "codex-settings-v4"))
38356
- requireBound(agent === "codex" && value.agent === "codex" && value.method === "reviewed" && !/[\x00-\x1f\x7f]/.test(source.path) && isAbsolute3(source.path) && resolve2(source.path) === source.path && basename3(source.path) === "config.toml");
38673
+ requireBound(agent === "codex" && value.agent === "codex" && value.method === "reviewed" && !/[\x00-\x1f\x7f]/.test(source.path) && isAbsolute4(source.path) && resolve3(source.path) === source.path && basename4(source.path) === "config.toml");
38357
38674
  if (source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || source.hashMode === "claude-settings-v3")
38358
- requireBound(agent === "claude" && value.agent === "claude" && value.method === "reviewed" && !/[\x00-\x1f\x7f]/.test(source.path) && isAbsolute3(source.path) && resolve2(source.path) === source.path && basename3(source.path) === "settings.json");
38675
+ requireBound(agent === "claude" && value.agent === "claude" && value.method === "reviewed" && !/[\x00-\x1f\x7f]/.test(source.path) && isAbsolute4(source.path) && resolve3(source.path) === source.path && basename4(source.path) === "settings.json");
38359
38676
  if (source.hashMode === "claude-marketplace-registry" || source.hashMode === "claude-marketplace-registry-v2")
38360
- requireBound(agent === "claude" && value.agent === "claude" && value.method === "reviewed" && !/[\x00-\x1f\x7f]/.test(source.path) && isAbsolute3(source.path) && resolve2(source.path) === source.path && basename3(source.path) === "known_marketplaces.json");
38677
+ requireBound(agent === "claude" && value.agent === "claude" && value.method === "reviewed" && !/[\x00-\x1f\x7f]/.test(source.path) && isAbsolute4(source.path) && resolve3(source.path) === source.path && basename4(source.path) === "known_marketplaces.json");
38361
38678
  if (source.hashMode === "claude-plugin-registry") {
38362
38679
  requireBound(agent === "claude");
38363
38680
  const managed = array3(source.managedPlugins, 64);
@@ -45285,7 +45602,7 @@ var require_public_api = __commonJS((exports) => {
45285
45602
  }
45286
45603
  return doc2;
45287
45604
  }
45288
- function parse6(src, reviver, options) {
45605
+ function parse7(src, reviver, options) {
45289
45606
  let _reviver = undefined;
45290
45607
  if (typeof reviver === "function") {
45291
45608
  _reviver = reviver;
@@ -45326,7 +45643,7 @@ var require_public_api = __commonJS((exports) => {
45326
45643
  return value.toString(options);
45327
45644
  return new Document.Document(value, _replacer, options).toString(options);
45328
45645
  }
45329
- exports.parse = parse6;
45646
+ exports.parse = parse7;
45330
45647
  exports.parseAllDocuments = parseAllDocuments;
45331
45648
  exports.parseDocument = parseDocument;
45332
45649
  exports.stringify = stringify;
@@ -45382,7 +45699,7 @@ var init_dist = __esm(() => {
45382
45699
  });
45383
45700
 
45384
45701
  // src/lib/agent-hermes.ts
45385
- import { dirname as dirname4, isAbsolute as isAbsolute4, join as join10, resolve as resolve3 } from "path";
45702
+ import { dirname as dirname5, isAbsolute as isAbsolute5, join as join10, resolve as resolve4 } from "path";
45386
45703
  function object5(value) {
45387
45704
  return Boolean(value && typeof value === "object" && (Object.getPrototypeOf(value) === Object.prototype || Object.getPrototypeOf(value) === null));
45388
45705
  }
@@ -45416,7 +45733,7 @@ function assertHermesEnvironment(home) {
45416
45733
  throw new Error(`NATIVE_SKILL_DRIFT: Hermes ${variable} requires a dedicated discovery adapter; unset it before using this adapter`);
45417
45734
  }
45418
45735
  const selected = process.env.HERMES_HOME?.trim();
45419
- if (selected && (!isAbsolute4(selected) || resolve3(selected) !== join10(resolve3(home), ".hermes")))
45736
+ if (selected && (!isAbsolute5(selected) || resolve4(selected) !== join10(resolve4(home), ".hermes")))
45420
45737
  throw new Error("NATIVE_SKILL_DRIFT: custom Hermes homes/profiles require their own reviewed bridge");
45421
45738
  if (process.env.HERMES_ENABLE_PROJECT_PLUGINS?.trim() && !["0", "false", "no", "off"].includes(process.env.HERMES_ENABLE_PROJECT_PLUGINS.trim().toLowerCase()))
45422
45739
  throw new Error("NATIVE_SKILL_DRIFT: Hermes project plugins require a dedicated discovery review");
@@ -45426,189 +45743,189 @@ var init_agent_hermes = __esm(() => {
45426
45743
  });
45427
45744
 
45428
45745
  // src/lib/agent-discovery-directories.ts
45429
- import { createHash as createHash2 } from "crypto";
45430
- import { lstatSync as lstatSync5, opendirSync } from "fs";
45431
- import { dirname as dirname5, isAbsolute as isAbsolute5, join as join11, resolve as resolve4 } from "path";
45432
- function need(value, message) {
45746
+ import { createHash as createHash3 } from "crypto";
45747
+ import { lstatSync as lstatSync6, opendirSync } from "fs";
45748
+ import { dirname as dirname6, isAbsolute as isAbsolute6, join as join11, resolve as resolve5 } from "path";
45749
+ function need2(value, message) {
45433
45750
  if (!value)
45434
45751
  throw new Error(message);
45435
45752
  }
45436
45753
  function safe(path) {
45437
- need(typeof path === "string" && path.length <= AGENT_POLICY_LIMITS.pathCharacters && isAbsolute5(path) && resolve4(path) === path && !path.includes("\x00"), "Expected a canonical absolute discovery directory path");
45438
- for (let cursor = path;; cursor = dirname5(cursor)) {
45439
- need(!lstatSync5(cursor, { throwIfNoEntry: false })?.isSymbolicLink(), "Refusing symlink native discovery directory");
45440
- if (dirname5(cursor) === cursor)
45754
+ need2(typeof path === "string" && path.length <= AGENT_POLICY_LIMITS.pathCharacters && isAbsolute6(path) && resolve5(path) === path && !path.includes("\x00"), "Expected a canonical absolute discovery directory path");
45755
+ for (let cursor = path;; cursor = dirname6(cursor)) {
45756
+ need2(!lstatSync6(cursor, { throwIfNoEntry: false })?.isSymbolicLink(), "Refusing symlink native discovery directory");
45757
+ if (dirname6(cursor) === cursor)
45441
45758
  break;
45442
45759
  }
45443
45760
  }
45444
45761
  function same(before, after) {
45445
45762
  return Boolean(after && after.isDirectory() && before.dev === after.dev && before.ino === after.ino && before.mtimeMs === after.mtimeMs && before.ctimeMs === after.ctimeMs);
45446
45763
  }
45447
- function capture(path, budget, excludedRoots, omittedRoots = [], rows) {
45764
+ function capture(path, budget2, excludedRoots, omittedRoots = [], rows) {
45448
45765
  safe(path);
45449
45766
  if (omittedRoots.some((root2) => path === root2 || path.startsWith(root2 + "/")))
45450
45767
  return { path, sha256: null };
45451
- const root = lstatSync5(path, { throwIfNoEntry: false });
45768
+ const root = lstatSync6(path, { throwIfNoEntry: false });
45452
45769
  if (!root)
45453
45770
  return { path, sha256: null };
45454
- need(root.isDirectory(), "Unsupported native discovery directory input");
45455
- const hash2 = createHash2("sha256");
45771
+ need2(root.isDirectory(), "Unsupported native discovery directory input");
45772
+ const hash2 = createHash3("sha256");
45456
45773
  function walk(current, relative3, before, depth) {
45457
- need(depth <= 64, "Native discovery directory depth limit exceeded");
45774
+ need2(depth <= 64, "Native discovery directory depth limit exceeded");
45458
45775
  const names = [], directory = opendirSync(current);
45459
45776
  try {
45460
45777
  for (let entry = directory.readSync();entry; entry = directory.readSync()) {
45461
- need(++budget.entries <= AGENT_POLICY_LIMITS.discoveryDirectoryEntries, "Native discovery directory entry limit exceeded");
45778
+ need2(++budget2.entries <= AGENT_POLICY_LIMITS.discoveryDirectoryEntries, "Native discovery directory entry limit exceeded");
45462
45779
  names.push(entry.name);
45463
45780
  }
45464
45781
  } finally {
45465
45782
  directory.closeSync();
45466
45783
  }
45467
- need(new Set(names).size === names.length, "Ambiguous native discovery directory names");
45784
+ need2(new Set(names).size === names.length, "Ambiguous native discovery directory names");
45468
45785
  for (const name of names.sort()) {
45469
45786
  const child = join11(current, name), childRelative = relative3 ? `${relative3}/${name}` : name;
45470
45787
  if (omittedRoots.includes(child))
45471
45788
  continue;
45472
- need(child.length <= AGENT_POLICY_LIMITS.pathCharacters, "Native discovery directory path limit exceeded");
45473
- const stat = lstatSync5(child);
45474
- need(stat.isFile() || stat.isDirectory(), "Refusing symlink or special native discovery directory member");
45789
+ need2(child.length <= AGENT_POLICY_LIMITS.pathCharacters, "Native discovery directory path limit exceeded");
45790
+ const stat = lstatSync6(child);
45791
+ need2(stat.isFile() || stat.isDirectory(), "Refusing symlink or special native discovery directory member");
45475
45792
  const row = JSON.stringify([childRelative, stat.isDirectory() ? "directory" : "file"]) + `
45476
45793
  `;
45477
- budget.bytes += Buffer.byteLength(row);
45478
- need(budget.bytes <= AGENT_POLICY_LIMITS.discoveryDirectoryBytes, "Native discovery directory metadata limit exceeded");
45794
+ budget2.bytes += Buffer.byteLength(row);
45795
+ need2(budget2.bytes <= AGENT_POLICY_LIMITS.discoveryDirectoryBytes, "Native discovery directory metadata limit exceeded");
45479
45796
  hash2.update(row);
45480
45797
  rows?.push(row);
45481
45798
  if (stat.isDirectory() && !excludedRoots.includes(child))
45482
45799
  walk(child, childRelative, stat, depth + 1);
45483
45800
  }
45484
- need(same(before, lstatSync5(current, { throwIfNoEntry: false })), "Native discovery directory changed while reading");
45801
+ need2(same(before, lstatSync6(current, { throwIfNoEntry: false })), "Native discovery directory changed while reading");
45485
45802
  }
45486
45803
  walk(path, "", root, 0);
45487
45804
  safe(path);
45488
45805
  return { path, sha256: hash2.digest("hex") };
45489
45806
  }
45490
45807
  function captureDiscoveryDirectoryProjection(paths, omittedRoots) {
45491
- need(Array.isArray(paths) && paths.length <= AGENT_POLICY_LIMITS.discoveryDirectories && new Set(paths).size === paths.length, "Invalid projected discovery directory collection");
45492
- need(omittedRoots.length <= AGENT_POLICY_LIMITS.discoveryRoots && new Set(omittedRoots).size === omittedRoots.length, "Invalid inactive discovery roots");
45808
+ need2(Array.isArray(paths) && paths.length <= AGENT_POLICY_LIMITS.discoveryDirectories && new Set(paths).size === paths.length, "Invalid projected discovery directory collection");
45809
+ need2(omittedRoots.length <= AGENT_POLICY_LIMITS.discoveryRoots && new Set(omittedRoots).size === omittedRoots.length, "Invalid inactive discovery roots");
45493
45810
  for (const root of omittedRoots)
45494
45811
  safe(root);
45495
- const budget = { entries: 0, bytes: 0 };
45812
+ const budget2 = { entries: 0, bytes: 0 };
45496
45813
  return paths.map((path) => {
45497
45814
  const entries = [];
45498
- return { ...capture(path, budget, [], omittedRoots, entries), entries };
45815
+ return { ...capture(path, budget2, [], omittedRoots, entries), entries };
45499
45816
  });
45500
45817
  }
45501
45818
  function verifyDiscoveryDirectoryProjection(directories, omittedRoots) {
45502
- need(directories.length <= AGENT_POLICY_LIMITS.discoveryDirectories, "Invalid projected discovery directory collection");
45819
+ need2(directories.length <= AGENT_POLICY_LIMITS.discoveryDirectories, "Invalid projected discovery directory collection");
45503
45820
  let count = 0, bytes = 0;
45504
45821
  const expected = directories.map((directory) => {
45505
45822
  safe(directory.path);
45506
- need(Array.isArray(directory.entries), "Missing reviewed directory membership inventory");
45507
- const hash2 = createHash2("sha256");
45823
+ need2(Array.isArray(directory.entries), "Missing reviewed directory membership inventory");
45824
+ const hash2 = createHash3("sha256");
45508
45825
  const kept = [];
45509
45826
  for (const row of directory.entries) {
45510
- need(typeof row === "string" && ++count <= AGENT_POLICY_LIMITS.discoveryDirectoryEntries, "Invalid reviewed directory membership rows");
45827
+ need2(typeof row === "string" && ++count <= AGENT_POLICY_LIMITS.discoveryDirectoryEntries, "Invalid reviewed directory membership rows");
45511
45828
  bytes += Buffer.byteLength(row);
45512
- need(bytes <= AGENT_POLICY_LIMITS.discoveryDirectoryBytes, "Reviewed directory membership byte limit exceeded");
45829
+ need2(bytes <= AGENT_POLICY_LIMITS.discoveryDirectoryBytes, "Reviewed directory membership byte limit exceeded");
45513
45830
  const value = JSON.parse(row);
45514
- need(Array.isArray(value) && value.length === 2 && typeof value[0] === "string" && value[0] && !isAbsolute5(value[0]) && !value[0].split("/").some((part) => !part || part === "." || part === "..") && ["file", "directory"].includes(value[1]) && row === JSON.stringify(value) + `
45831
+ need2(Array.isArray(value) && value.length === 2 && typeof value[0] === "string" && value[0] && !isAbsolute6(value[0]) && !value[0].split("/").some((part) => !part || part === "." || part === "..") && ["file", "directory"].includes(value[1]) && row === JSON.stringify(value) + `
45515
45832
  `, "Invalid reviewed directory member");
45516
45833
  hash2.update(row);
45517
45834
  const path = join11(directory.path, value[0]);
45518
45835
  if (!omittedRoots.some((root) => path === root || path.startsWith(root + "/")))
45519
45836
  kept.push(row);
45520
45837
  }
45521
- need(directory.sha256 === null ? directory.entries.length === 0 : hash2.digest("hex") === directory.sha256, "Reviewed directory inventory does not match its fingerprint");
45838
+ need2(directory.sha256 === null ? directory.entries.length === 0 : hash2.digest("hex") === directory.sha256, "Reviewed directory inventory does not match its fingerprint");
45522
45839
  const absent = omittedRoots.some((root) => directory.path === root || directory.path.startsWith(root + "/"));
45523
- return { path: directory.path, sha256: absent || directory.sha256 === null ? null : createHash2("sha256").update(kept.join("")).digest("hex") };
45840
+ return { path: directory.path, sha256: absent || directory.sha256 === null ? null : createHash3("sha256").update(kept.join("")).digest("hex") };
45524
45841
  });
45525
45842
  const current = captureDiscoveryDirectoryProjection(directories.map((item) => item.path), omittedRoots);
45526
- need(current.every((item, index) => item.sha256 === expected[index].sha256), "Native discovery directory membership changed outside retired Codex roots");
45843
+ need2(current.every((item, index) => item.sha256 === expected[index].sha256), "Native discovery directory membership changed outside retired Codex roots");
45527
45844
  }
45528
45845
  function captureDiscoveryDirectories(paths, excludedRoots = []) {
45529
- need(Array.isArray(paths) && paths.length <= AGENT_POLICY_LIMITS.discoveryDirectories && new Set(paths).size === paths.length, "Invalid native discovery directory collection");
45530
- const budget = { entries: 0, bytes: 0 };
45846
+ need2(Array.isArray(paths) && paths.length <= AGENT_POLICY_LIMITS.discoveryDirectories && new Set(paths).size === paths.length, "Invalid native discovery directory collection");
45847
+ const budget2 = { entries: 0, bytes: 0 };
45531
45848
  for (const root of excludedRoots)
45532
45849
  safe(root);
45533
- return paths.map((path) => capture(path, budget, excludedRoots));
45850
+ return paths.map((path) => capture(path, budget2, excludedRoots));
45534
45851
  }
45535
45852
  function verifyDiscoveryDirectories(directories, excludedRoots = []) {
45536
- need(Array.isArray(directories) && directories.length <= AGENT_POLICY_LIMITS.discoveryDirectories, "Invalid native discovery directory collection");
45853
+ need2(Array.isArray(directories) && directories.length <= AGENT_POLICY_LIMITS.discoveryDirectories, "Invalid native discovery directory collection");
45537
45854
  for (const directory of directories)
45538
- need(directory && typeof directory === "object" && (directory.sha256 === null || typeof directory.sha256 === "string" && /^[a-f0-9]{64}$/.test(directory.sha256)), "Invalid native discovery directory digest");
45855
+ need2(directory && typeof directory === "object" && (directory.sha256 === null || typeof directory.sha256 === "string" && /^[a-f0-9]{64}$/.test(directory.sha256)), "Invalid native discovery directory digest");
45539
45856
  const current = captureDiscoveryDirectories(directories.map((directory) => directory.path), excludedRoots);
45540
45857
  for (let i = 0;i < directories.length; i++)
45541
- need(current[i].sha256 === directories[i].sha256, `Native discovery directory membership changed; run skills hook install with a fresh discovery review: ${directories[i].path}`);
45858
+ need2(current[i].sha256 === directories[i].sha256, `Native discovery directory membership changed; run skills hook install with a fresh discovery review: ${directories[i].path}`);
45542
45859
  }
45543
45860
  var init_agent_discovery_directories = __esm(() => {
45544
45861
  init_agent_policy_limits();
45545
45862
  });
45546
45863
 
45547
45864
  // src/lib/agent-discovery-bytes.ts
45548
- import { createHash as createHash3 } from "crypto";
45549
- import { closeSync as closeSync5, constants as constants2, fstatSync as fstatSync5, lstatSync as lstatSync6, openSync as openSync5, readSync as readSync2 } from "fs";
45550
- import { dirname as dirname6, isAbsolute as isAbsolute6, resolve as resolve5 } from "path";
45865
+ import { createHash as createHash4 } from "crypto";
45866
+ import { closeSync as closeSync6, constants as constants3, fstatSync as fstatSync6, lstatSync as lstatSync7, openSync as openSync6, readSync as readSync3 } from "fs";
45867
+ import { dirname as dirname7, isAbsolute as isAbsolute7, resolve as resolve6 } from "path";
45551
45868
  function discoveryByteBudget() {
45552
45869
  return { remaining: AGENT_POLICY_LIMITS.discoveryRawTotalBytes };
45553
45870
  }
45554
45871
  function safe2(path) {
45555
- if (typeof path !== "string" || !isAbsolute6(path) || path !== resolve5(path) || path.length > AGENT_POLICY_LIMITS.pathCharacters || path.includes("\x00"))
45872
+ if (typeof path !== "string" || !isAbsolute7(path) || path !== resolve6(path) || path.length > AGENT_POLICY_LIMITS.pathCharacters || path.includes("\x00"))
45556
45873
  throw new Error("Expected a canonical absolute raw discovery path");
45557
- for (let cursor = path;; cursor = dirname6(cursor)) {
45558
- if (lstatSync6(cursor, { throwIfNoEntry: false })?.isSymbolicLink())
45874
+ for (let cursor = path;; cursor = dirname7(cursor)) {
45875
+ if (lstatSync7(cursor, { throwIfNoEntry: false })?.isSymbolicLink())
45559
45876
  throw new Error("Refusing symlink raw discovery input");
45560
- if (dirname6(cursor) === cursor)
45877
+ if (dirname7(cursor) === cursor)
45561
45878
  break;
45562
45879
  }
45563
45880
  }
45564
45881
  function same2(left, right) {
45565
45882
  return left.dev === right.dev && left.ino === right.ino && left.size === right.size && left.mtimeMs === right.mtimeMs && left.ctimeMs === right.ctimeMs;
45566
45883
  }
45567
- function consume(budget, bytes) {
45568
- if (bytes > budget.remaining)
45884
+ function consume(budget2, bytes) {
45885
+ if (bytes > budget2.remaining)
45569
45886
  throw new Error("Raw discovery aggregate byte limit exceeded");
45570
- budget.remaining -= bytes;
45887
+ budget2.remaining -= bytes;
45571
45888
  }
45572
- function hashRawDiscoveryFile(path, budget, changes) {
45889
+ function hashRawDiscoveryFile(path, budget2, changes) {
45573
45890
  safe2(path);
45574
45891
  if (changes?.has(path)) {
45575
45892
  const text2 = changes.get(path), bytes = Buffer.byteLength(text2);
45576
45893
  if (bytes > AGENT_POLICY_LIMITS.discoveryRawSourceBytes)
45577
45894
  throw new Error("Raw discovery file byte limit exceeded");
45578
- consume(budget, bytes);
45579
- return createHash3("sha256").update(text2).digest("hex");
45895
+ consume(budget2, bytes);
45896
+ return createHash4("sha256").update(text2).digest("hex");
45580
45897
  }
45581
- const initial = lstatSync6(path, { throwIfNoEntry: false });
45898
+ const initial = lstatSync7(path, { throwIfNoEntry: false });
45582
45899
  if (!initial)
45583
45900
  return null;
45584
45901
  if (!initial.isFile() || initial.size > AGENT_POLICY_LIMITS.discoveryRawSourceBytes)
45585
45902
  throw new Error("Unsupported or oversized raw discovery input");
45586
- if (initial.size > budget.remaining)
45903
+ if (initial.size > budget2.remaining)
45587
45904
  throw new Error("Raw discovery aggregate byte limit exceeded");
45588
- const fd = openSync5(path, constants2.O_RDONLY | constants2.O_NOFOLLOW | constants2.O_NONBLOCK);
45905
+ const fd = openSync6(path, constants3.O_RDONLY | constants3.O_NOFOLLOW | constants3.O_NONBLOCK);
45589
45906
  try {
45590
- const opened = fstatSync5(fd);
45907
+ const opened = fstatSync6(fd);
45591
45908
  if (!opened.isFile() || !same2(initial, opened))
45592
45909
  throw new Error("Raw discovery input changed during open");
45593
- const hash2 = createHash3("sha256"), buffer = Buffer.alloc(64 * 1024);
45910
+ const hash2 = createHash4("sha256"), buffer = Buffer.alloc(64 * 1024);
45594
45911
  let bytes = 0;
45595
45912
  while (true) {
45596
- const count = readSync2(fd, buffer, 0, Math.min(buffer.length, AGENT_POLICY_LIMITS.discoveryRawSourceBytes - bytes + 1), null);
45913
+ const count = readSync3(fd, buffer, 0, Math.min(buffer.length, AGENT_POLICY_LIMITS.discoveryRawSourceBytes - bytes + 1), null);
45597
45914
  if (!count)
45598
45915
  break;
45599
45916
  bytes += count;
45600
45917
  if (bytes > AGENT_POLICY_LIMITS.discoveryRawSourceBytes)
45601
45918
  throw new Error("Raw discovery file byte limit exceeded");
45602
- consume(budget, count);
45919
+ consume(budget2, count);
45603
45920
  hash2.update(buffer.subarray(0, count));
45604
45921
  }
45605
- const final = fstatSync5(fd), current = lstatSync6(path, { throwIfNoEntry: false });
45922
+ const final = fstatSync6(fd), current = lstatSync7(path, { throwIfNoEntry: false });
45606
45923
  safe2(path);
45607
45924
  if (!current?.isFile() || !same2(opened, final) || !same2(final, current) || bytes !== final.size)
45608
45925
  throw new Error("Raw discovery input changed during read");
45609
45926
  return hash2.digest("hex");
45610
45927
  } finally {
45611
- closeSync5(fd);
45928
+ closeSync6(fd);
45612
45929
  }
45613
45930
  }
45614
45931
  var init_agent_discovery_bytes = __esm(() => {
@@ -45616,9 +45933,9 @@ var init_agent_discovery_bytes = __esm(() => {
45616
45933
  });
45617
45934
 
45618
45935
  // src/lib/agent-discovery-path-bytes.ts
45619
- import { createHash as createHash4 } from "crypto";
45620
- import { lstatSync as lstatSync7, readlinkSync } from "fs";
45621
- import { dirname as dirname7, isAbsolute as isAbsolute7, join as join12, parse as parse6, resolve as resolve6, sep as sep3 } from "path";
45936
+ import { createHash as createHash5 } from "crypto";
45937
+ import { lstatSync as lstatSync8, readlinkSync } from "fs";
45938
+ import { dirname as dirname8, isAbsolute as isAbsolute8, join as join12, parse as parse7, resolve as resolve7, sep as sep3 } from "path";
45622
45939
  function identity2(stat, mutable = false) {
45623
45940
  return {
45624
45941
  dev: String(stat.dev),
@@ -45629,14 +45946,14 @@ function identity2(stat, mutable = false) {
45629
45946
  ...mutable ? { size: String(stat.size), mtimeNs: String(stat.mtimeNs), ctimeNs: String(stat.ctimeNs) } : {}
45630
45947
  };
45631
45948
  }
45632
- function canonical(path) {
45633
- if (typeof path !== "string" || !isAbsolute7(path) || path !== resolve6(path) || path.length > AGENT_POLICY_LIMITS.pathCharacters || path.includes("\x00") || Buffer.from(path).toString("utf8") !== path)
45949
+ function canonical2(path) {
45950
+ if (typeof path !== "string" || !isAbsolute8(path) || path !== resolve7(path) || path.length > AGENT_POLICY_LIMITS.pathCharacters || path.includes("\x00") || Buffer.from(path).toString("utf8") !== path)
45634
45951
  throw new Error("Expected a canonical absolute discovery path");
45635
45952
  }
45636
45953
  function trace(path) {
45637
- canonical(path);
45954
+ canonical2(path);
45638
45955
  const rows = [], paths = [];
45639
- let metadataBytes = 0, steps = 0, links = 0, cursor = parse6(path).root, pending = path.slice(cursor.length).split(sep3);
45956
+ let metadataBytes = 0, steps = 0, links = 0, cursor = parse7(path).root, pending = path.slice(cursor.length).split(sep3);
45640
45957
  function record4(path2, row) {
45641
45958
  const value = { path: path2, ...row };
45642
45959
  metadataBytes += Buffer.byteLength(JSON.stringify(value));
@@ -45646,7 +45963,7 @@ function trace(path) {
45646
45963
  paths.push(path2);
45647
45964
  }
45648
45965
  function root() {
45649
- const stat = lstatSync7(cursor, { bigint: true });
45966
+ const stat = lstatSync8(cursor, { bigint: true });
45650
45967
  if (!stat.isDirectory())
45651
45968
  throw new Error("Unsupported discovery path root");
45652
45969
  record4(cursor, { type: "directory", ...identity2(stat) });
@@ -45659,13 +45976,13 @@ function trace(path) {
45659
45976
  if (!component || component === ".")
45660
45977
  continue;
45661
45978
  if (component === "..") {
45662
- cursor = dirname7(cursor);
45979
+ cursor = dirname8(cursor);
45663
45980
  continue;
45664
45981
  }
45665
45982
  const candidate = join12(cursor, component);
45666
45983
  if (candidate.length > AGENT_POLICY_LIMITS.pathCharacters)
45667
45984
  throw new Error("Discovery resolved path length limit exceeded");
45668
- const stat = lstatSync7(candidate, { bigint: true, throwIfNoEntry: false });
45985
+ const stat = lstatSync8(candidate, { bigint: true, throwIfNoEntry: false });
45669
45986
  if (!stat) {
45670
45987
  record4(candidate, { type: "missing", remaining: pending });
45671
45988
  return { rows, paths, file: null, missing: candidate, metadataBytes };
@@ -45673,17 +45990,17 @@ function trace(path) {
45673
45990
  if (stat.isSymbolicLink()) {
45674
45991
  if (++links > AGENT_POLICY_LIMITS.discoveryPathLinks || stat.size > BigInt(AGENT_POLICY_LIMITS.pathCharacters))
45675
45992
  throw new Error("Discovery path link limit exceeded");
45676
- const rawTarget = readlinkSync(candidate, { encoding: "buffer" }), target = rawTarget.toString("utf8"), after = lstatSync7(candidate, { bigint: true });
45993
+ const rawTarget = readlinkSync(candidate, { encoding: "buffer" }), target = rawTarget.toString("utf8"), after = lstatSync8(candidate, { bigint: true });
45677
45994
  if (!rawTarget.equals(Buffer.from(target, "utf8")))
45678
45995
  throw new Error("Unsupported non-UTF8 discovery link target");
45679
45996
  if (!target || target.includes("\x00") || Buffer.byteLength(target) > AGENT_POLICY_LIMITS.pathCharacters || !after.isSymbolicLink() || JSON.stringify(identity2(stat, true)) !== JSON.stringify(identity2(after, true)))
45680
45997
  throw new Error("Discovery link changed during read");
45681
45998
  record4(candidate, { type: "link", target, ...identity2(stat, true) });
45682
- if (isAbsolute7(target)) {
45683
- cursor = parse6(target).root;
45999
+ if (isAbsolute8(target)) {
46000
+ cursor = parse7(target).root;
45684
46001
  root();
45685
46002
  }
45686
- const remainder = isAbsolute7(target) ? target.slice(parse6(target).root.length) : target;
46003
+ const remainder = isAbsolute8(target) ? target.slice(parse7(target).root.length) : target;
45687
46004
  pending = [...remainder.split(sep3), ...pending];
45688
46005
  if (pending.length + steps > AGENT_POLICY_LIMITS.discoveryPathSteps)
45689
46006
  throw new Error("Discovery path step limit exceeded");
@@ -45703,7 +46020,7 @@ function trace(path) {
45703
46020
  }
45704
46021
  throw new Error("Unsupported directory discovery path input");
45705
46022
  }
45706
- function hashDiscoveryPathFile(path, budget, changes) {
46023
+ function hashDiscoveryPathFile(path, budget2, changes) {
45707
46024
  const before = trace(path);
45708
46025
  let createsMissingPath = false;
45709
46026
  if (before.missing !== null && changes) {
@@ -45716,17 +46033,17 @@ function hashDiscoveryPathFile(path, budget, changes) {
45716
46033
  }
45717
46034
  if (createsMissingPath || changes?.has(path) || before.paths.some((path2) => changes?.has(path2)))
45718
46035
  throw new Error("Discovery path witness intersects a planned write; use bytes mode for owned configuration");
45719
- const remaining = budget.pathMetadataRemaining ?? AGENT_POLICY_LIMITS.discoveryPathTotalMetadataBytes;
46036
+ const remaining = budget2.pathMetadataRemaining ?? AGENT_POLICY_LIMITS.discoveryPathTotalMetadataBytes;
45720
46037
  if (before.metadataBytes > remaining)
45721
46038
  throw new Error("Discovery path aggregate metadata limit exceeded");
45722
- budget.pathMetadataRemaining = remaining - before.metadataBytes;
45723
- const content = before.file === null ? null : hashRawDiscoveryFile(before.file, budget);
46039
+ budget2.pathMetadataRemaining = remaining - before.metadataBytes;
46040
+ const content = before.file === null ? null : hashRawDiscoveryFile(before.file, budget2);
45724
46041
  if (before.file !== null && content === null)
45725
46042
  throw new Error("Discovery path input changed during read");
45726
46043
  const after = trace(path);
45727
46044
  if (JSON.stringify(before.rows) !== JSON.stringify(after.rows) || before.file !== after.file)
45728
46045
  throw new Error("Discovery path input changed during read");
45729
- return createHash4("sha256").update(JSON.stringify({ version: 1, path, rows: before.rows, content })).digest("hex");
46046
+ return createHash5("sha256").update(JSON.stringify({ version: 1, path, rows: before.rows, content })).digest("hex");
45730
46047
  }
45731
46048
  var init_agent_discovery_path_bytes = __esm(() => {
45732
46049
  init_agent_policy_limits();
@@ -45734,7 +46051,7 @@ var init_agent_discovery_path_bytes = __esm(() => {
45734
46051
  });
45735
46052
 
45736
46053
  // src/lib/skill-bundle.ts
45737
- import { createHash as createHash5 } from "crypto";
46054
+ import { createHash as createHash6 } from "crypto";
45738
46055
  import { readFileSync as readFileSync9, readdirSync as readdirSync4, statSync as statSync6 } from "fs";
45739
46056
  import { join as join13, relative as relative3 } from "path";
45740
46057
  import { createGunzip } from "zlib";
@@ -45766,7 +46083,7 @@ function ownBytes(view) {
45766
46083
  return out;
45767
46084
  }
45768
46085
  function sha256Hex(bytes) {
45769
- return createHash5("sha256").update(bytes).digest("hex");
46086
+ return createHash6("sha256").update(bytes).digest("hex");
45770
46087
  }
45771
46088
  function collectSkillBundleEntries(dir) {
45772
46089
  const entries = [];
@@ -45944,7 +46261,7 @@ async function inspectSkillBundle(bundle, options = {}) {
45944
46261
  parser2.push(chunk);
45945
46262
  bytesSinceYield += chunk.byteLength;
45946
46263
  if (bytesSinceYield >= 256 * 1024) {
45947
- await new Promise((resolve7) => setTimeout(resolve7, 0));
46264
+ await new Promise((resolve8) => setTimeout(resolve8, 0));
45948
46265
  bytesSinceYield = 0;
45949
46266
  check2();
45950
46267
  }
@@ -46301,21 +46618,21 @@ var init_profile_limits = __esm(() => {
46301
46618
  });
46302
46619
 
46303
46620
  // src/lib/selection-cache.ts
46304
- import { createHash as createHash6, randomUUID } from "crypto";
46621
+ import { createHash as createHash7, randomUUID } from "crypto";
46305
46622
  import { spawnSync as spawnSync2 } from "child_process";
46306
- import { closeSync as closeSync6, constants as constants3, fstatSync as fstatSync6, fsyncSync, linkSync, lstatSync as lstatSync8, mkdirSync as mkdirSync3, openSync as openSync6, readFileSync as readFileSync10, readlinkSync as readlinkSync2, readSync as readSync3, renameSync, unlinkSync, writeFileSync as writeFileSync3 } from "fs";
46623
+ import { closeSync as closeSync7, constants as constants4, fstatSync as fstatSync7, fsyncSync, linkSync, lstatSync as lstatSync9, mkdirSync as mkdirSync3, openSync as openSync7, readFileSync as readFileSync10, readlinkSync as readlinkSync2, readSync as readSync4, renameSync, unlinkSync, writeFileSync as writeFileSync3 } from "fs";
46307
46624
  import { hostname as hostname3 } from "os";
46308
- import { dirname as dirname8, join as join14, parse as parse7, resolve as resolve7 } from "path";
46625
+ import { dirname as dirname9, join as join14, parse as parse8, resolve as resolve8 } from "path";
46309
46626
  import { isDeepStrictEqual } from "util";
46310
46627
  function selectionCacheRoot(options = {}) {
46311
- return resolve7(options.cacheDir ?? join14(getDataDirReadOnly(), "selection-cache"));
46628
+ return resolve8(options.cacheDir ?? join14(getDataDirReadOnly(), "selection-cache"));
46312
46629
  }
46313
46630
  function selectionKey(selection) {
46314
46631
  validateSelection(selection);
46315
46632
  return hash2([selection.authority, selection.workspaceId, selection.slug, selection.version, selection.bundleDigest]);
46316
46633
  }
46317
46634
  function hash2(value) {
46318
- return createHash6("sha256").update(JSON.stringify(value)).digest("hex");
46635
+ return createHash7("sha256").update(JSON.stringify(value)).digest("hex");
46319
46636
  }
46320
46637
  function validateSelection(selection) {
46321
46638
  if (!selection || !/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(selection.slug) || !isValidSkillVersion(selection.version) || !/^sha256:[a-f0-9]{64}$/.test(selection.bundleDigest) || typeof selection.workspaceId !== "string" || !selection.workspaceId.trim() || typeof selection.profileRevision !== "string" || !selection.profileRevision.trim()) {
@@ -46355,14 +46672,14 @@ function selectionBundlePath(selection, options = {}) {
46355
46672
  return join14(selectionCacheRoot(options), "objects", hash2(selection.authority), hash2(selection.workspaceId), `${selection.bundleDigest.slice(7)}.tar.gz`);
46356
46673
  }
46357
46674
  function assertRegularPath(path, createParents = false) {
46358
- const absolute = resolve7(path);
46359
- const root = parse7(absolute).root;
46675
+ const absolute = resolve8(path);
46676
+ const root = parse8(absolute).root;
46360
46677
  let cursor = root;
46361
46678
  const segments = absolute.slice(root.length).split("/");
46362
46679
  for (let index = 0;index < segments.length; index++) {
46363
46680
  cursor = join14(cursor, segments[index]);
46364
46681
  try {
46365
- const stat = lstatSync8(cursor);
46682
+ const stat = lstatSync9(cursor);
46366
46683
  if (stat.isSymbolicLink() || index < segments.length - 1 && !stat.isDirectory()) {
46367
46684
  throw new SkillSelectionError("UNSAFE_CACHE_PATH", "Skills cache paths must not traverse symlinks or non-directories.");
46368
46685
  }
@@ -46378,20 +46695,20 @@ function readRegularFile(path, limit) {
46378
46695
  assertRegularPath(path);
46379
46696
  let fd;
46380
46697
  try {
46381
- fd = openSync6(path, constants3.O_RDONLY | constants3.O_NOFOLLOW | constants3.O_NONBLOCK);
46698
+ fd = openSync7(path, constants4.O_RDONLY | constants4.O_NOFOLLOW | constants4.O_NONBLOCK);
46382
46699
  } catch (error61) {
46383
46700
  if (error61.code === "ENOENT")
46384
46701
  return null;
46385
46702
  throw error61;
46386
46703
  }
46387
46704
  try {
46388
- const stat = fstatSync6(fd);
46705
+ const stat = fstatSync7(fd);
46389
46706
  if (!stat.isFile() || stat.size > limit)
46390
46707
  throw new SkillSelectionError("INVALID_CACHE_FILE", "The Skills cache contains an invalid or oversized file.");
46391
46708
  const bytes = Buffer.alloc(stat.size + 1);
46392
46709
  let size = 0;
46393
46710
  while (size < bytes.length) {
46394
- const read = readSync3(fd, bytes, size, bytes.length - size, null);
46711
+ const read = readSync4(fd, bytes, size, bytes.length - size, null);
46395
46712
  if (!read)
46396
46713
  break;
46397
46714
  size += read;
@@ -46400,7 +46717,7 @@ function readRegularFile(path, limit) {
46400
46717
  throw new SkillSelectionError("INVALID_CACHE_FILE", "The Skills cache file grew during its bounded read.");
46401
46718
  return bytes.subarray(0, size);
46402
46719
  } finally {
46403
- closeSync6(fd);
46720
+ closeSync7(fd);
46404
46721
  }
46405
46722
  }
46406
46723
  function writeSelectionJson(path, value) {
@@ -46412,19 +46729,19 @@ function writeSelectionJson(path, value) {
46412
46729
  }
46413
46730
  function atomicWrite(path, bytes, mode, durable = false) {
46414
46731
  assertRegularPath(path, true);
46415
- const temporary = join14(dirname8(path), `.selection-${randomUUID()}.tmp`);
46732
+ const temporary = join14(dirname9(path), `.selection-${randomUUID()}.tmp`);
46416
46733
  try {
46417
- const fd = openSync6(temporary, constants3.O_WRONLY | constants3.O_CREAT | constants3.O_EXCL | constants3.O_NOFOLLOW, mode);
46734
+ const fd = openSync7(temporary, constants4.O_WRONLY | constants4.O_CREAT | constants4.O_EXCL | constants4.O_NOFOLLOW, mode);
46418
46735
  try {
46419
46736
  writeFileSync3(fd, bytes);
46420
46737
  if (durable)
46421
46738
  fsyncSync(fd);
46422
46739
  } finally {
46423
- closeSync6(fd);
46740
+ closeSync7(fd);
46424
46741
  }
46425
46742
  renameSync(temporary, path);
46426
46743
  if (durable)
46427
- syncDirectory(dirname8(path));
46744
+ syncDirectory(dirname9(path));
46428
46745
  } finally {
46429
46746
  try {
46430
46747
  unlinkSync(temporary);
@@ -46528,7 +46845,7 @@ function assertFreshCachedProfile(receipt, options = {}) {
46528
46845
  }
46529
46846
  }
46530
46847
  function projectSelectionLockPath(projectDir) {
46531
- return join14(resolve7(projectDir), ".skills", SELECTION_LOCK_FILE);
46848
+ return join14(resolve8(projectDir), ".skills", SELECTION_LOCK_FILE);
46532
46849
  }
46533
46850
  function readProjectSelection(projectDir) {
46534
46851
  const receipt = readSelectionJson(projectSelectionLockPath(projectDir));
@@ -46636,14 +46953,14 @@ function localLockIdentity() {
46636
46953
  }
46637
46954
  function readSessionLock(sessionId, options) {
46638
46955
  const path = `${sessionReceiptPath(sessionId, options)}.write-lock`;
46639
- const before = lstatSync8(path, { throwIfNoEntry: false });
46956
+ const before = lstatSync9(path, { throwIfNoEntry: false });
46640
46957
  if (!before)
46641
46958
  return null;
46642
46959
  if (!before.isFile() || ![1, 2].includes(before.nlink) || (before.mode & 63) !== 0 || process.getuid && before.uid !== process.getuid()) {
46643
46960
  throw new SkillSelectionError("SESSION_WRITE_LOCKED", "The session lock is not a private regular file; recovery requires review.");
46644
46961
  }
46645
46962
  const bytes = readRegularFile(path, SESSION_LOCK_MAX_BYTES);
46646
- const after = lstatSync8(path, { throwIfNoEntry: false });
46963
+ const after = lstatSync9(path, { throwIfNoEntry: false });
46647
46964
  if (!bytes || !after?.isFile() || before.dev !== after.dev || before.ino !== after.ino || before.mtimeMs !== after.mtimeMs || before.mode !== after.mode || before.uid !== after.uid || before.gid !== after.gid || before.nlink !== after.nlink) {
46648
46965
  throw new SkillSelectionError("SESSION_WRITE_LOCKED", "The session lock changed during inspection; recovery requires review.");
46649
46966
  }
@@ -46660,7 +46977,7 @@ function readSessionLock(sessionId, options) {
46660
46977
  if (after.nlink === 2) {
46661
46978
  stagingPath = `${path}.${marker.operationId}.prepared`;
46662
46979
  assertRegularPath(stagingPath);
46663
- const staged = lstatSync8(stagingPath, { throwIfNoEntry: false });
46980
+ const staged = lstatSync9(stagingPath, { throwIfNoEntry: false });
46664
46981
  if (marker.publication !== "hard-link-v1" || !staged?.isFile() || staged.dev !== after.dev || staged.ino !== after.ino || staged.nlink !== 2 || staged.mode !== after.mode || staged.uid !== after.uid || staged.gid !== after.gid) {
46665
46982
  throw new SkillSelectionError("SESSION_WRITE_LOCKED", "The session lock has an unbound publication link; recovery requires review.");
46666
46983
  }
@@ -46671,33 +46988,33 @@ function publishSessionLock(path, marker) {
46671
46988
  const stagingPath = `${path}.${marker.operationId}.prepared`;
46672
46989
  const bytes = Buffer.from(`${JSON.stringify({ ...marker, publication: "hard-link-v1" })}
46673
46990
  `);
46674
- const fd = openSync6(stagingPath, constants3.O_WRONLY | constants3.O_CREAT | constants3.O_EXCL | constants3.O_NOFOLLOW, 384);
46675
- const stat = fstatSync6(fd);
46991
+ const fd = openSync7(stagingPath, constants4.O_WRONLY | constants4.O_CREAT | constants4.O_EXCL | constants4.O_NOFOLLOW, 384);
46992
+ const stat = fstatSync7(fd);
46676
46993
  let published = false, handedOff = false;
46677
46994
  try {
46678
46995
  writeFileSync3(fd, bytes);
46679
46996
  fsyncSync(fd);
46680
46997
  linkSync(stagingPath, path);
46681
46998
  published = true;
46682
- syncDirectory(dirname8(path));
46683
- const staged = lstatSync8(stagingPath);
46999
+ syncDirectory(dirname9(path));
47000
+ const staged = lstatSync9(stagingPath);
46684
47001
  if (!staged.isFile() || staged.dev !== stat.dev || staged.ino !== stat.ino) {
46685
47002
  throw new SkillSelectionError("SESSION_WRITE_LOCK_CHANGED", "The initialized lock staging inode changed before publication completed.");
46686
47003
  }
46687
47004
  unlinkSync(stagingPath);
46688
- syncDirectory(dirname8(path));
47005
+ syncDirectory(dirname9(path));
46689
47006
  handedOff = true;
46690
47007
  return { path, stagingPath, fd, dev: stat.dev, ino: stat.ino };
46691
47008
  } finally {
46692
47009
  if (!handedOff) {
46693
47010
  try {
46694
47011
  for (const target of [...published ? [path] : [], stagingPath]) {
46695
- const current = lstatSync8(target, { throwIfNoEntry: false });
47012
+ const current = lstatSync9(target, { throwIfNoEntry: false });
46696
47013
  if (current?.isFile() && current.dev === stat.dev && current.ino === stat.ino)
46697
47014
  unlinkSync(target);
46698
47015
  }
46699
47016
  } finally {
46700
- closeSync6(fd);
47017
+ closeSync7(fd);
46701
47018
  }
46702
47019
  }
46703
47020
  }
@@ -46719,25 +47036,25 @@ function archiveSessionLock(lock, receipt, explicitLocalHost) {
46719
47036
  const guardPath = `${lock.path}.recovery-guard`;
46720
47037
  let guardFd;
46721
47038
  try {
46722
- guardFd = openSync6(guardPath, constants3.O_WRONLY | constants3.O_CREAT | constants3.O_EXCL | constants3.O_NOFOLLOW, 384);
47039
+ guardFd = openSync7(guardPath, constants4.O_WRONLY | constants4.O_CREAT | constants4.O_EXCL | constants4.O_NOFOLLOW, 384);
46723
47040
  } catch (error61) {
46724
47041
  if (error61.code === "EEXIST")
46725
47042
  return null;
46726
47043
  throw error61;
46727
47044
  }
46728
- const guardStat = fstatSync6(guardFd);
47045
+ const guardStat = fstatSync7(guardFd);
46729
47046
  try {
46730
47047
  writeFileSync3(guardFd, `${JSON.stringify({ schemaVersion: 1, pid: process.pid, operationId: randomUUID() })}
46731
47048
  `);
46732
47049
  fsyncSync(guardFd);
46733
- const cacheOptions = { cacheDir: dirname8(dirname8(lock.path)) };
47050
+ const cacheOptions = { cacheDir: dirname9(dirname9(lock.path)) };
46734
47051
  const current = readSessionLock(lock.marker.sessionId, cacheOptions);
46735
47052
  if (!current || current.dev !== lock.dev || current.ino !== lock.ino || current.sha256 !== lock.sha256 || current.mtimeMs !== lock.mtimeMs || !writerIsGone(current, explicitLocalHost))
46736
47053
  return null;
46737
47054
  const currentReceipt = readSkillSessionSnapshotIfExists(lock.marker.sessionId, cacheOptions);
46738
47055
  if (currentReceipt?.sha256 !== receipt?.sha256 || currentReceipt?.generation !== receipt?.generation)
46739
47056
  return null;
46740
- const directory = join14(dirname8(dirname8(lock.path)), "session-lock-recoveries", randomUUID());
47057
+ const directory = join14(dirname9(dirname9(lock.path)), "session-lock-recoveries", randomUUID());
46741
47058
  const archivePath = join14(directory, "original.write-lock");
46742
47059
  const recordPath = join14(directory, "recovery.json");
46743
47060
  assertRegularPath(archivePath, true);
@@ -46754,7 +47071,7 @@ function archiveSessionLock(lock, receipt, explicitLocalHost) {
46754
47071
  })}
46755
47072
  `));
46756
47073
  syncDirectory(directory);
46757
- syncDirectory(dirname8(directory));
47074
+ syncDirectory(dirname9(directory));
46758
47075
  const finalLock = readSessionLock(lock.marker.sessionId, cacheOptions);
46759
47076
  if (!finalLock || finalLock.dev !== lock.dev || finalLock.ino !== lock.ino || finalLock.sha256 !== lock.sha256 || readSkillSessionSnapshotIfExists(lock.marker.sessionId, cacheOptions)?.sha256 !== receipt?.sha256)
46760
47077
  return null;
@@ -46769,11 +47086,11 @@ function archiveSessionLock(lock, receipt, explicitLocalHost) {
46769
47086
  archivedPaths.push(publicationPath);
46770
47087
  }
46771
47088
  syncDirectory(directory);
46772
- syncDirectory(dirname8(lock.path));
47089
+ syncDirectory(dirname9(lock.path));
46773
47090
  for (const path of archivedPaths) {
46774
- const before = lstatSync8(path, { throwIfNoEntry: false });
47091
+ const before = lstatSync9(path, { throwIfNoEntry: false });
46775
47092
  const bytes = readRegularFile(path, SESSION_LOCK_MAX_BYTES);
46776
- const after = lstatSync8(path, { throwIfNoEntry: false });
47093
+ const after = lstatSync9(path, { throwIfNoEntry: false });
46777
47094
  if (!before?.isFile() || before.dev !== lock.dev || before.ino !== lock.ino || before.nlink !== archivedPaths.length || before.mtimeMs !== lock.mtimeMs || (before.mode & 63) !== 0 || process.getuid && before.uid !== process.getuid() || !bytes || sha256Hex(bytes) !== lock.sha256 || !after?.isFile() || before.dev !== after.dev || before.ino !== after.ino || before.mtimeMs !== after.mtimeMs || before.mode !== after.mode || before.uid !== after.uid || before.gid !== after.gid || before.nlink !== after.nlink) {
46778
47095
  throw new Error("Archived lock ownership or bytes changed");
46779
47096
  }
@@ -46785,8 +47102,8 @@ function archiveSessionLock(lock, receipt, explicitLocalHost) {
46785
47102
  }
46786
47103
  return archivePath;
46787
47104
  } finally {
46788
- closeSync6(guardFd);
46789
- const current = lstatSync8(guardPath, { throwIfNoEntry: false });
47105
+ closeSync7(guardFd);
47106
+ const current = lstatSync9(guardPath, { throwIfNoEntry: false });
46790
47107
  if (current?.isFile() && current.dev === guardStat.dev && current.ino === guardStat.ino)
46791
47108
  unlinkSync(guardPath);
46792
47109
  }
@@ -46798,7 +47115,7 @@ function withSessionWriteLocks(sessionIds, options, action) {
46798
47115
  const owned = [];
46799
47116
  const assertOwned = () => {
46800
47117
  for (const lock of owned) {
46801
- const current = lstatSync8(lock.path, { throwIfNoEntry: false });
47118
+ const current = lstatSync9(lock.path, { throwIfNoEntry: false });
46802
47119
  if (!current?.isFile() || current.dev !== lock.dev || current.ino !== lock.ino) {
46803
47120
  throw new SkillSelectionError("SESSION_WRITE_LOCK_CHANGED", "A session write lock changed during the operation; no replacement is permitted.");
46804
47121
  }
@@ -46842,12 +47159,12 @@ function withSessionWriteLocks(sessionIds, options, action) {
46842
47159
  for (const lock of owned.reverse()) {
46843
47160
  try {
46844
47161
  for (const path of [lock.path, lock.stagingPath]) {
46845
- const current = lstatSync8(path, { throwIfNoEntry: false });
47162
+ const current = lstatSync9(path, { throwIfNoEntry: false });
46846
47163
  if (current?.isFile() && current.dev === lock.dev && current.ino === lock.ino)
46847
47164
  unlinkSync(path);
46848
47165
  }
46849
47166
  } finally {
46850
- closeSync6(lock.fd);
47167
+ closeSync7(lock.fd);
46851
47168
  }
46852
47169
  }
46853
47170
  }
@@ -46895,21 +47212,21 @@ function writeSkillSession(receipt, expected, options = {}) {
46895
47212
  }
46896
47213
  function syncDirectory(path) {
46897
47214
  assertRegularPath(path);
46898
- const fd = openSync6(path, constants3.O_RDONLY | constants3.O_DIRECTORY | constants3.O_NOFOLLOW);
47215
+ const fd = openSync7(path, constants4.O_RDONLY | constants4.O_DIRECTORY | constants4.O_NOFOLLOW);
46899
47216
  try {
46900
47217
  fsyncSync(fd);
46901
47218
  } finally {
46902
- closeSync6(fd);
47219
+ closeSync7(fd);
46903
47220
  }
46904
47221
  }
46905
47222
  function archiveBytes(path, bytes) {
46906
47223
  assertRegularPath(path, true);
46907
- const fd = openSync6(path, constants3.O_WRONLY | constants3.O_CREAT | constants3.O_EXCL | constants3.O_NOFOLLOW, 384);
47224
+ const fd = openSync7(path, constants4.O_WRONLY | constants4.O_CREAT | constants4.O_EXCL | constants4.O_NOFOLLOW, 384);
46908
47225
  try {
46909
47226
  writeFileSync3(fd, bytes);
46910
47227
  fsyncSync(fd);
46911
47228
  } finally {
46912
- closeSync6(fd);
47229
+ closeSync7(fd);
46913
47230
  }
46914
47231
  }
46915
47232
  var SkillSelectionError, MAX_CACHED_PROFILE_AGE_MS, SELECTION_LOCK_FILE = "selection.lock.json", SESSION_LOCK_MAX_BYTES = 4096, SESSION_LOCK_MIN_AGE_MS = 30000;
@@ -46938,7 +47255,7 @@ __export(exports_remote_files, {
46938
47255
  decodeRemoteFiles: () => decodeRemoteFiles,
46939
47256
  MAX_REMOTE_FILE_BYTES: () => MAX_REMOTE_FILE_BYTES
46940
47257
  });
46941
- import { createHash as createHash7 } from "crypto";
47258
+ import { createHash as createHash8 } from "crypto";
46942
47259
  function describeRemoteFiles(files) {
46943
47260
  if (files.length > 10)
46944
47261
  throw new Error("At most 10 input files are supported");
@@ -46955,7 +47272,7 @@ function describeRemoteFiles(files) {
46955
47272
  });
46956
47273
  }
46957
47274
  function sha256(bytes) {
46958
- return createHash7("sha256").update(bytes).digest("hex");
47275
+ return createHash8("sha256").update(bytes).digest("hex");
46959
47276
  }
46960
47277
  async function readBoundedResponse(response, maximum) {
46961
47278
  if (!Number.isSafeInteger(maximum) || maximum < 0 || maximum > MAX_REMOTE_FILE_BYTES)
@@ -47210,11 +47527,11 @@ function capturePreparationProcess(child, platform = process.platform, signalGro
47210
47527
  }
47211
47528
 
47212
47529
  // src/lib/dependency-preparation.ts
47213
- import { constants as constants4, closeSync as closeSync7, fstatSync as fstatSync7, lstatSync as lstatSync9, mkdirSync as mkdirSync4, openSync as openSync7, readFileSync as readFileSync11, readdirSync as readdirSync5, rmdirSync, unlinkSync as unlinkSync2, ftruncateSync, writeSync } from "fs";
47530
+ import { constants as constants5, closeSync as closeSync8, fstatSync as fstatSync8, lstatSync as lstatSync10, mkdirSync as mkdirSync4, openSync as openSync8, readFileSync as readFileSync11, readdirSync as readdirSync5, rmdirSync, unlinkSync as unlinkSync2, ftruncateSync, writeSync } from "fs";
47214
47531
  import { join as join15 } from "path";
47215
47532
  function hasDependencyPreparationMarker(skillPath) {
47216
47533
  try {
47217
- lstatSync9(join15(skillPath, DEPENDENCY_PREPARATION_MARKER));
47534
+ lstatSync10(join15(skillPath, DEPENDENCY_PREPARATION_MARKER));
47218
47535
  return true;
47219
47536
  } catch (error61) {
47220
47537
  return error61.code !== "ENOENT";
@@ -47233,21 +47550,21 @@ function claimPreparation(skillPath) {
47233
47550
  }
47234
47551
  let fd;
47235
47552
  try {
47236
- if (!lstatSync9(marker).isDirectory() || lstatSync9(marker).isSymbolicLink())
47553
+ if (!lstatSync10(marker).isDirectory() || lstatSync10(marker).isSymbolicLink())
47237
47554
  return;
47238
47555
  if (!created) {
47239
47556
  if (readdirSync5(marker).some((name) => name !== "state.json"))
47240
47557
  return;
47241
- if (!lstatSync9(state).isFile() || lstatSync9(state).isSymbolicLink() || lstatSync9(state).size > 1024)
47558
+ if (!lstatSync10(state).isFile() || lstatSync10(state).isSymbolicLink() || lstatSync10(state).size > 1024)
47242
47559
  return;
47243
47560
  const previous = JSON.parse(readFileSync11(state, "utf8"));
47244
47561
  if (previous.version !== 1 || previous.status !== "failed" || Object.keys(previous).length !== 2)
47245
47562
  return;
47246
47563
  }
47247
47564
  mkdirSync4(active, { mode: 448 });
47248
- fd = openSync7(state, constants4.O_RDWR | constants4.O_NOFOLLOW | (created ? constants4.O_CREAT | constants4.O_EXCL : 0), 384);
47249
- if (!fstatSync7(fd).isFile()) {
47250
- closeSync7(fd);
47565
+ fd = openSync8(state, constants5.O_RDWR | constants5.O_NOFOLLOW | (created ? constants5.O_CREAT | constants5.O_EXCL : 0), 384);
47566
+ if (!fstatSync8(fd).isFile()) {
47567
+ closeSync8(fd);
47251
47568
  return;
47252
47569
  }
47253
47570
  const descriptor = fd;
@@ -47259,7 +47576,7 @@ function claimPreparation(skillPath) {
47259
47576
  record4("pending");
47260
47577
  return { abandon() {
47261
47578
  try {
47262
- closeSync7(descriptor);
47579
+ closeSync8(descriptor);
47263
47580
  } catch {}
47264
47581
  }, finish(success2) {
47265
47582
  try {
@@ -47267,7 +47584,7 @@ function claimPreparation(skillPath) {
47267
47584
  unlinkSync2(state);
47268
47585
  else
47269
47586
  record4("failed");
47270
- closeSync7(descriptor);
47587
+ closeSync8(descriptor);
47271
47588
  fd = undefined;
47272
47589
  rmdirSync(active);
47273
47590
  if (success2)
@@ -47275,7 +47592,7 @@ function claimPreparation(skillPath) {
47275
47592
  return true;
47276
47593
  } catch {
47277
47594
  try {
47278
- closeSync7(descriptor);
47595
+ closeSync8(descriptor);
47279
47596
  } catch {}
47280
47597
  return false;
47281
47598
  }
@@ -47283,7 +47600,7 @@ function claimPreparation(skillPath) {
47283
47600
  } catch {
47284
47601
  if (fd !== undefined)
47285
47602
  try {
47286
- closeSync7(fd);
47603
+ closeSync8(fd);
47287
47604
  } catch {}
47288
47605
  return;
47289
47606
  }
@@ -47443,283 +47760,6 @@ function isCodexLocalStdioMcpServer(name, server) {
47443
47760
  }
47444
47761
  }
47445
47762
 
47446
- // src/lib/claude-settings-witness.ts
47447
- import { createHash as createHash8 } from "crypto";
47448
- import { closeSync as closeSync8, constants as constants5, fstatSync as fstatSync8, lstatSync as lstatSync10, openSync as openSync8, readSync as readSync4 } from "fs";
47449
- import { basename as basename4, dirname as dirname9, isAbsolute as isAbsolute8, resolve as resolve8 } from "path";
47450
- function need2(value, reason) {
47451
- if (!value)
47452
- throw new Error(`Claude settings witness ${reason}`);
47453
- }
47454
- function absolutePath(value) {
47455
- need2(typeof value === "string" && value.length > 0 && value.length <= CLAUDE_SETTINGS_WITNESS_LIMITS.pathCharacters && !/[\x00-\x1f\x7f]/.test(value) && isAbsolute8(value) && resolve8(value) === value, "requires a normalized absolute path");
47456
- }
47457
- function parents(path) {
47458
- const result = [];
47459
- for (let at = dirname9(path);; at = dirname9(at)) {
47460
- const stat = lstatSync10(at, { bigint: true });
47461
- need2(stat.isDirectory() && !stat.isSymbolicLink(), "path traverses a symlink or non-directory");
47462
- result.push([at, stat]);
47463
- if (at === dirname9(at))
47464
- return result;
47465
- }
47466
- }
47467
- function readNativeSettingsWitnessFile(path, budget, filename = "settings.json") {
47468
- absolutePath(path);
47469
- need2(basename4(path) === filename, `requires ${filename}`);
47470
- need2(Number.isSafeInteger(budget.remaining) && budget.remaining >= 0, "has an invalid byte budget");
47471
- const ancestors = parents(path), initial = lstatSync10(path, { bigint: true });
47472
- need2(initial.isFile() && !initial.isSymbolicLink() && initial.size <= BigInt(CLAUDE_SETTINGS_WITNESS_LIMITS.bytes), "is not a bounded regular file");
47473
- need2(initial.size <= BigInt(budget.remaining), "exceeds its aggregate byte limit");
47474
- const fd = openSync8(path, constants5.O_RDONLY | constants5.O_NOFOLLOW | constants5.O_NONBLOCK);
47475
- try {
47476
- const opened = fstatSync8(fd, { bigint: true });
47477
- need2(opened.isFile() && sameFile(initial, opened), "changed during open");
47478
- const bytes = Buffer.alloc(Number(opened.size) + 1);
47479
- let length = 0;
47480
- while (length < bytes.length) {
47481
- const count = readSync4(fd, bytes, length, bytes.length - length, null);
47482
- if (!count)
47483
- break;
47484
- length += count;
47485
- }
47486
- const after = fstatSync8(fd, { bigint: true }), current = lstatSync10(path, { bigint: true });
47487
- need2(current.isFile() && sameFile(opened, after) && sameFile(after, current) && BigInt(length) === opened.size, "changed during read");
47488
- for (const [ancestor, before] of ancestors) {
47489
- const now = lstatSync10(ancestor, { bigint: true });
47490
- need2(now.isDirectory() && before.dev === now.dev && before.ino === now.ino && before.mode === now.mode, "parent changed during read");
47491
- }
47492
- budget.remaining -= length;
47493
- try {
47494
- return new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(bytes.subarray(0, length));
47495
- } catch {
47496
- throw new Error("Claude settings witness is not strict UTF-8");
47497
- }
47498
- } finally {
47499
- closeSync8(fd);
47500
- }
47501
- }
47502
- function parse8(text2) {
47503
- let at = 0, nodes = 0;
47504
- const numberPattern = /-?(?:0|[1-9][0-9]*)(?:\.[0-9]+)?(?:[eE][+-]?[0-9]+)?/y;
47505
- const space = () => {
47506
- while (at < text2.length && /[\x20\t\r\n]/.test(text2[at]))
47507
- at++;
47508
- };
47509
- function string5() {
47510
- need2(text2[at] === '"', "contains invalid JSON");
47511
- const start = at++;
47512
- while (at < text2.length) {
47513
- const character = text2[at++];
47514
- if (character === '"') {
47515
- let value2;
47516
- try {
47517
- value2 = JSON.parse(text2.slice(start, at));
47518
- } catch {
47519
- throw new Error("Claude settings witness contains invalid JSON string");
47520
- }
47521
- need2(value2.length <= CLAUDE_SETTINGS_WITNESS_LIMITS.stringCharacters, "exceeds its string limit");
47522
- return value2;
47523
- }
47524
- if (character === "\\")
47525
- at++;
47526
- }
47527
- throw new Error("Claude settings witness contains an unterminated JSON string");
47528
- }
47529
- function value(depth) {
47530
- need2(depth <= CLAUDE_SETTINGS_WITNESS_LIMITS.depth && ++nodes <= CLAUDE_SETTINGS_WITNESS_LIMITS.nodes, "exceeds its nesting or node limit");
47531
- space();
47532
- const character = text2[at];
47533
- if (character === '"')
47534
- return { kind: "string", value: string5() };
47535
- if (character === "{" || character === "[") {
47536
- at++;
47537
- space();
47538
- const object7 = character === "{", end = object7 ? "}" : "]", entries = [], items = [], keys = new Set;
47539
- if (text2[at] !== end)
47540
- while (true) {
47541
- if (object7) {
47542
- space();
47543
- const key = string5();
47544
- need2(!keys.has(key), "contains a duplicate JSON key");
47545
- keys.add(key);
47546
- space();
47547
- need2(text2[at++] === ":", "contains invalid JSON");
47548
- entries.push([key, value(depth + 1)]);
47549
- } else
47550
- items.push(value(depth + 1));
47551
- space();
47552
- if (text2[at] === end)
47553
- break;
47554
- need2(text2[at++] === ",", "contains invalid JSON");
47555
- }
47556
- at++;
47557
- return object7 ? { kind: "object", entries } : { kind: "array", items };
47558
- }
47559
- for (const literal3 of ["true", "false", "null"])
47560
- if (text2.startsWith(literal3, at)) {
47561
- at += literal3.length;
47562
- return { kind: "literal", value: literal3 };
47563
- }
47564
- numberPattern.lastIndex = at;
47565
- const number5 = numberPattern.exec(text2);
47566
- need2(number5, "contains invalid JSON");
47567
- at += number5[0].length;
47568
- return { kind: "number", value: number5[0] };
47569
- }
47570
- const root = value(0);
47571
- space();
47572
- need2(at === text2.length && root.kind === "object", "requires a JSON object without trailing content");
47573
- need2(root.entries.length <= CLAUDE_SETTINGS_WITNESS_LIMITS.rows, "exceeds its settings field limit");
47574
- return root;
47575
- }
47576
- function canonical2(value) {
47577
- if (value.kind === "object")
47578
- return { kind: "object", entries: value.entries.map(([key, child]) => [key, canonical2(child)]).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0) };
47579
- if (value.kind === "array")
47580
- return { kind: "array", items: value.items.map(canonical2) };
47581
- return value;
47582
- }
47583
- function inferencePreference(key, child, version2) {
47584
- if (key === "skipDangerousModePermissionPrompt") {
47585
- need2(child.kind === "literal" && (child.value === "true" || child.value === "false"), "contains an invalid dialog acknowledgment");
47586
- return false;
47587
- }
47588
- if (key === "effortLevel") {
47589
- need2(child.kind === "string" && PERSISTED_EFFORT_LEVELS.has(child.value), "contains an invalid persisted effort level");
47590
- return true;
47591
- }
47592
- if (key !== "modelSettings")
47593
- return false;
47594
- need2(child.kind === "object", "requires an object of model preferences");
47595
- child.entries = child.entries.filter(([model, preferences]) => {
47596
- if (version2 === 2 && !BUILTIN_MODEL_SELECTIONS.has(model) || preferences.kind !== "object" || preferences.entries.length !== 1 || preferences.entries[0][0] !== "effortLevel")
47597
- return true;
47598
- const effort = preferences.entries[0][1];
47599
- need2(effort.kind === "string" && PERSISTED_EFFORT_LEVELS.has(effort.value), "contains an invalid persisted model effort level");
47600
- return false;
47601
- });
47602
- return child.entries.length === 0;
47603
- }
47604
- function settingsDigest(text2, version2 = 1) {
47605
- const value = parse8(text2);
47606
- value.entries = value.entries.filter(([key, child]) => {
47607
- if (version2 !== 1 && inferencePreference(key, child, version2))
47608
- return false;
47609
- if (key === "model") {
47610
- need2(child.kind === "string", "contains an invalid model selection");
47611
- return !BUILTIN_MODEL_SELECTIONS.has(child.value);
47612
- }
47613
- if (BOOLEAN_PREFERENCES.has(key)) {
47614
- need2(child.kind === "literal" && (child.value === "true" || child.value === "false"), "contains an invalid display preference");
47615
- return false;
47616
- }
47617
- if (Object.hasOwn(ENUM_PREFERENCES, key)) {
47618
- need2(child.kind === "string" && ENUM_PREFERENCES[key].includes(child.value), "contains an invalid display preference");
47619
- return false;
47620
- }
47621
- return true;
47622
- });
47623
- return createHash8("sha256").update(`hasna.skills.claude-settings.v${version2}\x00`).update(JSON.stringify(canonical2(value))).digest("hex");
47624
- }
47625
- function hashClaudeSettingsReplacement(text2, budget) {
47626
- need2(typeof text2 === "string", "requires settings text");
47627
- const bytes = Buffer.byteLength(text2);
47628
- need2(bytes <= CLAUDE_SETTINGS_WITNESS_LIMITS.bytes && Number.isSafeInteger(budget.remaining) && budget.remaining >= bytes, "exceeds its byte limit");
47629
- budget.remaining -= bytes;
47630
- return settingsDigest(text2);
47631
- }
47632
- function captureClaudeSettings(path, budget = { remaining: 256 * 1024 * 1024 }) {
47633
- return { path, hashMode: "claude-settings-v1", sha256: settingsDigest(readNativeSettingsWitnessFile(path, budget)) };
47634
- }
47635
- function captureClaudeSettingsV2(path, budget = { remaining: 256 * 1024 * 1024 }) {
47636
- return { path, hashMode: "claude-settings-v2", sha256: settingsDigest(readNativeSettingsWitnessFile(path, budget), 2) };
47637
- }
47638
- function hashClaudeSettingsReplacementV2(text2, budget) {
47639
- need2(typeof text2 === "string", "requires settings text");
47640
- const bytes = Buffer.byteLength(text2);
47641
- need2(bytes <= CLAUDE_SETTINGS_WITNESS_LIMITS.bytes && Number.isSafeInteger(budget.remaining) && budget.remaining >= bytes, "exceeds its byte limit");
47642
- budget.remaining -= bytes;
47643
- return settingsDigest(text2, 2);
47644
- }
47645
- function captureClaudeSettingsV3(path, budget = { remaining: 256 * 1024 * 1024 }) {
47646
- return { path, hashMode: "claude-settings-v3", sha256: settingsDigest(readNativeSettingsWitnessFile(path, budget), 3) };
47647
- }
47648
- function hashClaudeSettingsReplacementV3(text2, budget) {
47649
- need2(typeof text2 === "string", "requires settings text");
47650
- const bytes = Buffer.byteLength(text2);
47651
- need2(bytes <= CLAUDE_SETTINGS_WITNESS_LIMITS.bytes && Number.isSafeInteger(budget.remaining) && budget.remaining >= bytes, "exceeds its byte limit");
47652
- budget.remaining -= bytes;
47653
- return settingsDigest(text2, 3);
47654
- }
47655
- function hashNativeJsonControls(text2, excludedMetadata) {
47656
- need2(Buffer.byteLength(text2) <= CLAUDE_SETTINGS_WITNESS_LIMITS.bytes, "exceeds its byte limit");
47657
- const value = parse8(text2);
47658
- value.entries = value.entries.filter(([key, child]) => {
47659
- if (key !== excludedMetadata)
47660
- return true;
47661
- need2(child.kind === "string" && child.value.length <= 128, "has invalid version metadata");
47662
- return false;
47663
- });
47664
- return createHash8("sha256").update("hasna.skills.native-json-controls.v1\x00").update(JSON.stringify(canonical2(value))).digest("hex");
47665
- }
47666
- var CLAUDE_SETTINGS_WITNESS_LIMITS, sameFile = (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, BOOLEAN_PREFERENCES, ENUM_PREFERENCES, BUILTIN_MODEL_SELECTIONS, PERSISTED_EFFORT_LEVELS;
47667
- var init_claude_settings_witness = __esm(() => {
47668
- CLAUDE_SETTINGS_WITNESS_LIMITS = Object.freeze({ bytes: 1024 * 1024, rows: 1024, depth: 32, nodes: 65536, stringCharacters: 16384, pathCharacters: 4096 });
47669
- BOOLEAN_PREFERENCES = new Set([
47670
- "autoScrollEnabled",
47671
- "axScreenReader",
47672
- "emojiCompletionEnabled",
47673
- "prefersReducedMotion",
47674
- "showTurnDuration",
47675
- "spinnerTipsEnabled",
47676
- "syntaxHighlightingDisabled",
47677
- "terminalProgressBarEnabled",
47678
- "terminalTitleFromRename",
47679
- "verbose",
47680
- "wheelScrollAccelerationEnabled"
47681
- ]);
47682
- ENUM_PREFERENCES = Object.freeze({
47683
- editorMode: ["normal", "vim"],
47684
- tui: ["default", "fullscreen"],
47685
- viewMode: ["default", "verbose", "focus"]
47686
- });
47687
- BUILTIN_MODEL_SELECTIONS = new Set([
47688
- "default",
47689
- "best",
47690
- "fable",
47691
- "fable[1m]",
47692
- "sonnet",
47693
- "sonnet[1m]",
47694
- "opus",
47695
- "opus[1m]",
47696
- "haiku",
47697
- "opusplan",
47698
- "claude-fable-5-1",
47699
- "claude-fable-5",
47700
- "claude-fable-5[1m]",
47701
- "claude-opus-5",
47702
- "claude-sonnet-5",
47703
- "claude-haiku-4-5-20251001",
47704
- "claude-opus-4-6",
47705
- "claude-sonnet-4-5",
47706
- "claude-sonnet-4-5-20250929",
47707
- "claude-opus-4-8",
47708
- "claude-opus-4-8[1m]",
47709
- "claude-opus-4-7",
47710
- "claude-sonnet-4-6",
47711
- "claude-opus-4-5-20251101",
47712
- "claude-opus-4-5",
47713
- "claude-haiku-4-5",
47714
- "claude-fable-5-1[1m]",
47715
- "claude-opus-5[1m]",
47716
- "claude-opus-4-7[1m]",
47717
- "claude-opus-4-6[1m]",
47718
- "claude-sonnet-4-6[1m]"
47719
- ]);
47720
- PERSISTED_EFFORT_LEVELS = new Set(["low", "medium", "high", "xhigh"]);
47721
- });
47722
-
47723
47763
  // src/lib/codex-native-compatibility.ts
47724
47764
  function supportsCodexNativeCapability(version2, capability) {
47725
47765
  return typeof version2 === "string" && Object.hasOwn(MEASURED_CODEX_CAPABILITIES, version2) && MEASURED_CODEX_CAPABILITIES[version2].includes(capability);
@@ -48060,8 +48100,8 @@ function numericTokens(text2) {
48060
48100
  }
48061
48101
  return result;
48062
48102
  }
48063
- function canonical3(value, depth = 0, budget = { remaining: 65536 }) {
48064
- need3(depth <= 32 && --budget.remaining >= 0);
48103
+ function canonical3(value, depth = 0, budget2 = { remaining: 65536 }) {
48104
+ need3(depth <= 32 && --budget2.remaining >= 0);
48065
48105
  if (value === null)
48066
48106
  return ["null"];
48067
48107
  if (typeof value === "string")
@@ -48077,13 +48117,13 @@ function canonical3(value, depth = 0, budget = { remaining: 65536 }) {
48077
48117
  return ["date", value.toISOString()];
48078
48118
  }
48079
48119
  if (Array.isArray(value))
48080
- return ["array", value.map((child) => canonical3(child, depth + 1, budget))];
48120
+ return ["array", value.map((child) => canonical3(child, depth + 1, budget2))];
48081
48121
  need3(value && typeof value === "object");
48082
- return ["object", Object.entries(value).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0).map(([key, child]) => [key, canonical3(child, depth + 1, budget)])];
48122
+ return ["object", Object.entries(value).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0).map(([key, child]) => [key, canonical3(child, depth + 1, budget2)])];
48083
48123
  }
48084
- function hashCodexSettingsReplacement(text2, budget = { remaining: 256 * 1024 * 1024 }) {
48085
- need3(Buffer.byteLength(text2) <= 1024 * 1024 && budget.remaining >= Buffer.byteLength(text2));
48086
- budget.remaining -= Buffer.byteLength(text2);
48124
+ function hashCodexSettingsReplacement(text2, budget2 = { remaining: 256 * 1024 * 1024 }) {
48125
+ need3(Buffer.byteLength(text2) <= 1024 * 1024 && budget2.remaining >= Buffer.byteLength(text2));
48126
+ budget2.remaining -= Buffer.byteLength(text2);
48087
48127
  let config2;
48088
48128
  try {
48089
48129
  config2 = Bun.TOML.parse(text2);
@@ -48102,8 +48142,8 @@ function hashCodexSettingsReplacement(text2, budget = { remaining: 256 * 1024 *
48102
48142
  }
48103
48143
  return sha(`hasna.skills.codex-settings.v1\x00${JSON.stringify([canonical3(config2), numericTokens(text2)])}`);
48104
48144
  }
48105
- function captureCodexSettings(path, budget = { remaining: 256 * 1024 * 1024 }) {
48106
- const text2 = readNativeSettingsWitnessFile(path, budget, "config.toml");
48145
+ function captureCodexSettings(path, budget2 = { remaining: 256 * 1024 * 1024 }) {
48146
+ const text2 = readNativeSettingsWitnessFile(path, budget2, "config.toml");
48107
48147
  return { path, hashMode: "codex-settings-v1", sha256: hashCodexSettingsReplacement(text2) };
48108
48148
  }
48109
48149
  var sha = (text2) => createHash9("sha256").update(text2).digest("hex"), EFFORT, VERBOSITY;
@@ -48230,8 +48270,8 @@ function numericTokens2(text2) {
48230
48270
  }
48231
48271
  return result.sort();
48232
48272
  }
48233
- function canonical4(value, depth = 0, budget = { remaining: 65536 }) {
48234
- need4(depth <= 32 && --budget.remaining >= 0);
48273
+ function canonical4(value, depth = 0, budget2 = { remaining: 65536 }) {
48274
+ need4(depth <= 32 && --budget2.remaining >= 0);
48235
48275
  if (value === null)
48236
48276
  return ["null"];
48237
48277
  if (typeof value === "string")
@@ -48247,9 +48287,9 @@ function canonical4(value, depth = 0, budget = { remaining: 65536 }) {
48247
48287
  return ["date", value.toISOString()];
48248
48288
  }
48249
48289
  if (Array.isArray(value))
48250
- return ["array", value.map((child) => canonical4(child, depth + 1, budget))];
48290
+ return ["array", value.map((child) => canonical4(child, depth + 1, budget2))];
48251
48291
  need4(isRecord3(value));
48252
- return ["object", Object.entries(value).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0).map(([key, child]) => [key, canonical4(child, depth + 1, budget)])];
48292
+ return ["object", Object.entries(value).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0).map(([key, child]) => [key, canonical4(child, depth + 1, budget2)])];
48253
48293
  }
48254
48294
  function normalize2(config2, version2 = 2) {
48255
48295
  if (isRecord3(config2.hooks)) {
@@ -48425,30 +48465,30 @@ function settingsDigest2(text2, version2 = 2) {
48425
48465
  normalize2(projected.config, version2);
48426
48466
  return sha2(`hasna.skills.codex-settings.v${version2}\x00${JSON.stringify([canonical4(projected.config), numericTokens2(projected.numericSource)])}`);
48427
48467
  }
48428
- function hashCodexSettingsReplacementV2(text2, budget = { remaining: 256 * 1024 * 1024 }) {
48429
- need4(Buffer.byteLength(text2) <= 1024 * 1024 && budget.remaining >= Buffer.byteLength(text2));
48430
- budget.remaining -= Buffer.byteLength(text2);
48468
+ function hashCodexSettingsReplacementV2(text2, budget2 = { remaining: 256 * 1024 * 1024 }) {
48469
+ need4(Buffer.byteLength(text2) <= 1024 * 1024 && budget2.remaining >= Buffer.byteLength(text2));
48470
+ budget2.remaining -= Buffer.byteLength(text2);
48431
48471
  return settingsDigest2(text2);
48432
48472
  }
48433
- function captureCodexSettingsV2(path, budget = { remaining: 256 * 1024 * 1024 }) {
48434
- const text2 = readNativeSettingsWitnessFile(path, budget, "config.toml");
48473
+ function captureCodexSettingsV2(path, budget2 = { remaining: 256 * 1024 * 1024 }) {
48474
+ const text2 = readNativeSettingsWitnessFile(path, budget2, "config.toml");
48435
48475
  return { path, hashMode: "codex-settings-v2", sha256: settingsDigest2(text2) };
48436
48476
  }
48437
- function hashCodexSettingsReplacementV3(text2, budget = { remaining: 256 * 1024 * 1024 }) {
48438
- need4(Buffer.byteLength(text2) <= 1024 * 1024 && budget.remaining >= Buffer.byteLength(text2));
48439
- budget.remaining -= Buffer.byteLength(text2);
48477
+ function hashCodexSettingsReplacementV3(text2, budget2 = { remaining: 256 * 1024 * 1024 }) {
48478
+ need4(Buffer.byteLength(text2) <= 1024 * 1024 && budget2.remaining >= Buffer.byteLength(text2));
48479
+ budget2.remaining -= Buffer.byteLength(text2);
48440
48480
  return settingsDigest2(text2, 3);
48441
48481
  }
48442
- function captureCodexSettingsV3(path, budget = { remaining: 256 * 1024 * 1024 }) {
48443
- return { path, hashMode: "codex-settings-v3", sha256: settingsDigest2(readNativeSettingsWitnessFile(path, budget, "config.toml"), 3) };
48482
+ function captureCodexSettingsV3(path, budget2 = { remaining: 256 * 1024 * 1024 }) {
48483
+ return { path, hashMode: "codex-settings-v3", sha256: settingsDigest2(readNativeSettingsWitnessFile(path, budget2, "config.toml"), 3) };
48444
48484
  }
48445
- function hashCodexSettingsReplacementV4(text2, budget = { remaining: 256 * 1024 * 1024 }) {
48446
- need4(Buffer.byteLength(text2) <= 1024 * 1024 && budget.remaining >= Buffer.byteLength(text2));
48447
- budget.remaining -= Buffer.byteLength(text2);
48485
+ function hashCodexSettingsReplacementV4(text2, budget2 = { remaining: 256 * 1024 * 1024 }) {
48486
+ need4(Buffer.byteLength(text2) <= 1024 * 1024 && budget2.remaining >= Buffer.byteLength(text2));
48487
+ budget2.remaining -= Buffer.byteLength(text2);
48448
48488
  return settingsDigest2(text2, 4);
48449
48489
  }
48450
- function captureCodexSettingsV4(path, budget = { remaining: 256 * 1024 * 1024 }) {
48451
- return { path, hashMode: "codex-settings-v4", sha256: settingsDigest2(readNativeSettingsWitnessFile(path, budget, "config.toml"), 4) };
48490
+ function captureCodexSettingsV4(path, budget2 = { remaining: 256 * 1024 * 1024 }) {
48491
+ return { path, hashMode: "codex-settings-v4", sha256: settingsDigest2(readNativeSettingsWitnessFile(path, budget2, "config.toml"), 4) };
48452
48492
  }
48453
48493
  var sha2 = (text2) => createHash10("sha256").update(text2).digest("hex"), EFFORT2, VERBOSITY2, MODEL, CODEX_DISCOVERY_PROJECTION_FIELDS, INFERENCE;
48454
48494
  var init_codex_settings_witness = __esm(() => {
@@ -48653,6 +48693,7 @@ var init_codex_hook_trust_files = () => {};
48653
48693
 
48654
48694
  // src/lib/agent-integration.ts
48655
48695
  var init_agent_integration = __esm(() => {
48696
+ init_sumi_settings_witness();
48656
48697
  init_codex_corpus_write();
48657
48698
  init_codex_plugin_skill_controls();
48658
48699
  init_codex_native_skill_policy();
@@ -50047,13 +50088,13 @@ function parents2(path) {
50047
50088
  return result;
50048
50089
  }
50049
50090
  }
50050
- function readRegistry2(path, budget) {
50091
+ function readRegistry2(path, budget2) {
50051
50092
  absolutePath2(path);
50052
50093
  need6(basename7(path) === "known_marketplaces.json", "requires known_marketplaces.json");
50053
- need6(Number.isSafeInteger(budget.remaining) && budget.remaining >= 0, "has an invalid byte budget");
50094
+ need6(Number.isSafeInteger(budget2.remaining) && budget2.remaining >= 0, "has an invalid byte budget");
50054
50095
  const ancestors2 = parents2(path), initial = lstatSync17(path, { bigint: true });
50055
50096
  need6(initial.isFile() && !initial.isSymbolicLink() && initial.size <= BigInt(CLAUDE_MARKETPLACE_REGISTRY_LIMITS.bytes), "is not a bounded regular file");
50056
- need6(initial.size <= BigInt(budget.remaining), "exceeds its aggregate byte limit");
50097
+ need6(initial.size <= BigInt(budget2.remaining), "exceeds its aggregate byte limit");
50057
50098
  const fd = openSync13(path, constants10.O_RDONLY | constants10.O_NOFOLLOW | constants10.O_NONBLOCK);
50058
50099
  try {
50059
50100
  const opened = fstatSync13(fd, { bigint: true });
@@ -50072,7 +50113,7 @@ function readRegistry2(path, budget) {
50072
50113
  const now = lstatSync17(ancestor, { bigint: true });
50073
50114
  need6(now.isDirectory() && before.dev === now.dev && before.ino === now.ino && before.mode === now.mode, "parent changed during read");
50074
50115
  }
50075
- budget.remaining -= length;
50116
+ budget2.remaining -= length;
50076
50117
  try {
50077
50118
  return new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(bytes.subarray(0, length));
50078
50119
  } catch {
@@ -50189,15 +50230,15 @@ function normalizeRow(row, version2 = 1) {
50189
50230
  need6(Number.isFinite(millis) && new Date(millis).toISOString() === updated, "contains an invalid recognized update timestamp");
50190
50231
  row.entries = row.entries.map(([key, value]) => [key, key === "lastUpdated" ? { kind: "validated-update-time" } : value]);
50191
50232
  }
50192
- function captureClaudeMarketplaceRegistry(path, budget = { remaining: 256 * 1024 * 1024 }) {
50193
- const value = parse10(readRegistry2(path, budget));
50233
+ function captureClaudeMarketplaceRegistry(path, budget2 = { remaining: 256 * 1024 * 1024 }) {
50234
+ const value = parse10(readRegistry2(path, budget2));
50194
50235
  for (const [, row] of value.entries)
50195
50236
  normalizeRow(row);
50196
50237
  const sha2562 = createHash14("sha256").update("hasna.skills.claude-marketplace-registry.v1\x00").update(JSON.stringify(value)).digest("hex");
50197
50238
  return { path, hashMode: "claude-marketplace-registry", sha256: sha2562 };
50198
50239
  }
50199
- function captureClaudeMarketplaceRegistryV2(path, budget = { remaining: 256 * 1024 * 1024 }) {
50200
- const value = parse10(readRegistry2(path, budget));
50240
+ function captureClaudeMarketplaceRegistryV2(path, budget2 = { remaining: 256 * 1024 * 1024 }) {
50241
+ const value = parse10(readRegistry2(path, budget2));
50201
50242
  for (const [, row] of value.entries)
50202
50243
  normalizeRow(row, 2);
50203
50244
  const sha2562 = createHash14("sha256").update("hasna.skills.claude-marketplace-registry.v2\x00").update(JSON.stringify(value)).digest("hex");
@@ -50289,33 +50330,45 @@ function projectNativeDiscoveryFields(text2, format, fields2, path) {
50289
50330
  throw new Error("Expected native discovery configuration object");
50290
50331
  return digest(JSON.stringify(Object.fromEntries(fields2.map((field2) => [field2, object7[field2] ?? null]))));
50291
50332
  }
50292
- function isSupersededCodexProjection(agent, configPath, source) {
50333
+ function isSupersededSettingsProjection(agent, configPath, source) {
50334
+ if (agent === "sumi")
50335
+ return source.path === configPath && source.format === "json" && isDeepStrictEqual4(source.fields, [...SUMI_DISCOVERY_PROJECTION_FIELDS]);
50293
50336
  return agent === "codex" && source.path === configPath && source.format === "toml" && isDeepStrictEqual4(source.fields, [...CODEX_DISCOVERY_PROJECTION_FIELDS]);
50294
50337
  }
50295
- function supersedesCodexProjection(sources, configPath) {
50296
- return sources.some((source) => source.path === configPath && (source.hashMode === "codex-settings-v2" || (source.hashMode === "codex-settings-v3" || source.hashMode === "codex-settings-v4")));
50338
+ function supersedesSettingsProjection(agent, sources, configPath) {
50339
+ if (agent === "sumi")
50340
+ return sources.some((source) => source.path === configPath && source.hashMode === "sumi-settings-v1");
50341
+ return agent === "codex" && sources.some((source) => source.path === configPath && (source.hashMode === "codex-settings-v2" || (source.hashMode === "codex-settings-v3" || source.hashMode === "codex-settings-v4")));
50297
50342
  }
50298
- function projected(source, changes, budget = discoveryByteBudget()) {
50343
+ function projected(source, changes, budget2 = discoveryByteBudget()) {
50344
+ if (source.hashMode === "sumi-settings-v1") {
50345
+ if (source.format !== undefined || source.fields !== undefined || source.managedPlugins !== undefined || typeof source.sha256 !== "string" || !/^[a-f0-9]{64}$/.test(source.sha256))
50346
+ throw new Error("Sumi settings witnesses require exact typed metadata");
50347
+ const current = captureSumiSettings(source.path, budget2).sha256;
50348
+ if (current !== source.sha256)
50349
+ throw new Error(`Native discovery input changed; run skills hook install with a fresh discovery review: ${source.path}`);
50350
+ return changes?.has(source.path) ? hashSumiSettingsReplacement(changes.get(source.path), budget2) : current;
50351
+ }
50299
50352
  if (source.hashMode === "codex-settings-v1" || source.hashMode === "codex-settings-v2" || (source.hashMode === "codex-settings-v3" || source.hashMode === "codex-settings-v4")) {
50300
50353
  if (source.format !== undefined || source.fields !== undefined || source.managedPlugins !== undefined || typeof source.sha256 !== "string" || !/^[a-f0-9]{64}$/.test(source.sha256))
50301
50354
  throw new Error("Codex settings witnesses require exact typed metadata");
50302
- const current = (source.hashMode === "codex-settings-v4" ? captureCodexSettingsV4 : source.hashMode === "codex-settings-v3" ? captureCodexSettingsV3 : source.hashMode === "codex-settings-v2" ? captureCodexSettingsV2 : captureCodexSettings)(source.path, budget).sha256;
50355
+ const current = (source.hashMode === "codex-settings-v4" ? captureCodexSettingsV4 : source.hashMode === "codex-settings-v3" ? captureCodexSettingsV3 : source.hashMode === "codex-settings-v2" ? captureCodexSettingsV2 : captureCodexSettings)(source.path, budget2).sha256;
50303
50356
  if (current !== source.sha256)
50304
50357
  throw new Error(`Native discovery input changed; run skills hook install with a fresh discovery review: ${source.path}`);
50305
- 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), budget) : current;
50358
+ 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;
50306
50359
  }
50307
50360
  if (source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || source.hashMode === "claude-settings-v3") {
50308
50361
  if (source.format !== undefined || source.fields !== undefined || source.managedPlugins !== undefined || typeof source.sha256 !== "string" || !/^[a-f0-9]{64}$/.test(source.sha256))
50309
50362
  throw new Error("Claude settings witnesses require exact typed metadata");
50310
- const current = (source.hashMode === "claude-settings-v3" ? captureClaudeSettingsV3 : source.hashMode === "claude-settings-v2" ? captureClaudeSettingsV2 : captureClaudeSettings)(source.path, budget).sha256;
50363
+ const current = (source.hashMode === "claude-settings-v3" ? captureClaudeSettingsV3 : source.hashMode === "claude-settings-v2" ? captureClaudeSettingsV2 : captureClaudeSettings)(source.path, budget2).sha256;
50311
50364
  if (current !== source.sha256)
50312
50365
  throw new Error(`Native discovery input changed; run skills hook install with a fresh discovery review: ${source.path}`);
50313
- return changes?.has(source.path) ? (source.hashMode === "claude-settings-v3" ? hashClaudeSettingsReplacementV3 : source.hashMode === "claude-settings-v2" ? hashClaudeSettingsReplacementV2 : hashClaudeSettingsReplacement)(changes.get(source.path), budget) : current;
50366
+ return changes?.has(source.path) ? (source.hashMode === "claude-settings-v3" ? hashClaudeSettingsReplacementV3 : source.hashMode === "claude-settings-v2" ? hashClaudeSettingsReplacementV2 : hashClaudeSettingsReplacement)(changes.get(source.path), budget2) : current;
50314
50367
  }
50315
50368
  if (source.hashMode === "claude-marketplace-registry" || source.hashMode === "claude-marketplace-registry-v2") {
50316
50369
  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))
50317
50370
  throw new Error("Claude marketplace witnesses require an exact reviewed registry without synthetic changes");
50318
- const sha2562 = (source.hashMode === "claude-marketplace-registry-v2" ? captureClaudeMarketplaceRegistryV2 : captureClaudeMarketplaceRegistry)(source.path, budget).sha256;
50371
+ const sha2562 = (source.hashMode === "claude-marketplace-registry-v2" ? captureClaudeMarketplaceRegistryV2 : captureClaudeMarketplaceRegistry)(source.path, budget2).sha256;
50319
50372
  if (sha2562 !== source.sha256)
50320
50373
  throw new Error(`Native discovery input changed; run skills hook install with a fresh discovery review: ${source.path}`);
50321
50374
  return sha2562;
@@ -50333,8 +50386,8 @@ function projected(source, changes, budget = discoveryByteBudget()) {
50333
50386
  if (source.format !== undefined || source.fields !== undefined)
50334
50387
  throw new Error("Raw discovery witnesses cannot project configuration fields");
50335
50388
  if (source.hashMode === "path-bytes")
50336
- return hashDiscoveryPathFile(source.path, budget, changes);
50337
- return hashRawDiscoveryFile(source.path, budget, changes);
50389
+ return hashDiscoveryPathFile(source.path, budget2, changes);
50390
+ return hashRawDiscoveryFile(source.path, budget2, changes);
50338
50391
  }
50339
50392
  const text2 = read(source.path, changes);
50340
50393
  if (text2 === null)
@@ -50466,7 +50519,7 @@ function verifyAgentDiscovery(binding, codexRecovery) {
50466
50519
  verifyDiscoveryDirectories(projected2, installationRoots);
50467
50520
  }
50468
50521
  const absentRoots = [...absentCodexSkillRoots(binding), ...absentRetiredClaudeRoots(binding), ...retiredRoots.filter((root) => !lstatSync18(root, { throwIfNoEntry: false }))];
50469
- const budget = discoveryByteBudget();
50522
+ const budget2 = discoveryByteBudget();
50470
50523
  for (const source of binding.sources) {
50471
50524
  assertMarketplaceBinding(binding, source);
50472
50525
  if (source.hashMode === "claude-plugin-registry" && binding.agent !== "claude")
@@ -50483,7 +50536,7 @@ function verifyAgentDiscovery(binding, codexRecovery) {
50483
50536
  safe4(source.path);
50484
50537
  continue;
50485
50538
  }
50486
- const current = projected(source, undefined, budget);
50539
+ const current = projected(source, undefined, budget2);
50487
50540
  if (current !== source.sha256 && !verifiesCodexHookDiscoverySource(binding, source, current, codexRecovery))
50488
50541
  throw new Error(`Native discovery input changed; run skills hook install with a fresh discovery review: ${source.path}`);
50489
50542
  }
@@ -50517,6 +50570,8 @@ function codexInstallationRoots(binding) {
50517
50570
  });
50518
50571
  }
50519
50572
  function assertMarketplaceBinding(binding, source) {
50573
+ if (source.hashMode === "sumi-settings-v1" && (binding.agent !== "sumi" || binding.method !== "reviewed" || basename8(source.path) !== "sumi.json"))
50574
+ throw new Error("Sumi settings witnesses require explicit reviewed Sumi configuration");
50520
50575
  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" || basename8(source.path) !== "config.toml"))
50521
50576
  throw new Error("Codex settings witnesses require explicit reviewed Codex configuration");
50522
50577
  if ((source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || source.hashMode === "claude-settings-v3") && (binding.agent !== "claude" || binding.method !== "reviewed" || basename8(source.path) !== "settings.json"))
@@ -50541,7 +50596,7 @@ function resolveAgentDiscovery(options) {
50541
50596
  if (agent === "hermes")
50542
50597
  assertHermesEnvironment(home);
50543
50598
  const configPath = agentDiscoveryConfigPath(home, agent);
50544
- const configText = witness(configPath, agent === "hermes" ? "yaml" : agent === "codex" ? "toml" : "json", agent === "hermes" ? ["skills", "plugins", "hooks"] : agent === "claude" ? ["enabledPlugins", "extraKnownMarketplaces"] : agent === "codex" ? [...CODEX_DISCOVERY_PROJECTION_FIELDS] : agent === "gemini" ? ["skills", "extensions", "security"] : agent === "opencode" ? ["plugin", "skills"] : agent === "sumi" ? ["skills", "plugin", "plugins", "permissions"] : ["version"]);
50599
+ const configText = witness(configPath, agent === "hermes" ? "yaml" : agent === "codex" ? "toml" : "json", agent === "hermes" ? ["skills", "plugins", "hooks"] : agent === "claude" ? ["enabledPlugins", "extraKnownMarketplaces"] : agent === "codex" ? [...CODEX_DISCOVERY_PROJECTION_FIELDS] : agent === "gemini" ? ["skills", "extensions", "security"] : agent === "opencode" ? ["plugin", "skills"] : agent === "sumi" ? [...SUMI_DISCOVERY_PROJECTION_FIELDS] : ["version"]);
50545
50600
  const config2 = configText === null ? {} : agent === "hermes" ? parseHermesConfig(configText) : parseConfig(configText, configPath, agent === "codex");
50546
50601
  const unresolved = (detail) => {
50547
50602
  throw new Error(`Native discovery is unresolved (${agent}: ${detail}); provide a reviewed --discovery-inputs file`);
@@ -50638,9 +50693,9 @@ function resolveAgentDiscovery(options) {
50638
50693
  verifyAgentDiscovery(retained);
50639
50694
  if (!retained.sources.some((source) => source.path === canonical6(configPath) && source.format === undefined && source.fields === undefined))
50640
50695
  unresolved("retained review is missing the full agent configuration source");
50641
- if (retained.sources.some((source) => (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 !== canonical6(configPath)))
50696
+ 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 !== canonical6(configPath)))
50642
50697
  unresolved("retained settings witness names another configuration source");
50643
- const covered = supersedesCodexProjection(retained.sources, canonical6(configPath)) ? sources.filter((source) => !isSupersededCodexProjection(agent, canonical6(configPath), source)) : sources;
50698
+ const covered = supersedesSettingsProjection(agent, retained.sources, canonical6(configPath)) ? sources.filter((source) => !isSupersededSettingsProjection(agent, canonical6(configPath), source)) : sources;
50644
50699
  if (covered.some((source) => !retained.sources.some((saved) => isDeepStrictEqual4(saved, source))) || [...roots].some((root) => !retained.roots.includes(root)) || agent === "gemini" && JSON.stringify(retained.builtinNames) !== JSON.stringify(builtinNames))
50645
50700
  unresolved("retained review is missing current runtime discovery coverage");
50646
50701
  return retained;
@@ -50655,11 +50710,11 @@ function resolveAgentDiscovery(options) {
50655
50710
  if (review.sources.some((source) => source.format !== undefined || source.fields !== undefined))
50656
50711
  throw new Error("Explicit discovery reviews require full source-file hashes");
50657
50712
  verifyAgentDiscovery(supplied);
50658
- if (review.sources.some((source) => (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 !== canonical6(configPath)))
50659
- throw new Error("Semantic settings witnesses must name the configured Claude configuration source");
50713
+ 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 !== canonical6(configPath)))
50714
+ throw new Error("Semantic settings witnesses must name the configured agent configuration source");
50660
50715
  if (!review.sources.some((source) => source.path === canonical6(configPath)))
50661
50716
  throw new Error("Discovery review must include the agent configuration source");
50662
- const reviewedSources = supersedesCodexProjection(review.sources, canonical6(configPath)) ? sources.filter((source) => !isSupersededCodexProjection(agent, canonical6(configPath), source)) : sources;
50717
+ const reviewedSources = supersedesSettingsProjection(agent, review.sources, canonical6(configPath)) ? sources.filter((source) => !isSupersededSettingsProjection(agent, canonical6(configPath), source)) : sources;
50663
50718
  return { ...supplied, roots: [...new Set([...roots, ...supplied.roots])].sort(), sources: [...reviewedSources, ...review.sources], ...agent === "gemini" ? { builtinNames } : {} };
50664
50719
  }
50665
50720
  function plugin(root) {
@@ -50776,6 +50831,7 @@ function resolveAgentDiscovery(options) {
50776
50831
  }
50777
50832
  var digest = (text2) => createHash16("sha256").update(text2).digest("hex");
50778
50833
  var init_agent_discovery = __esm(() => {
50834
+ init_sumi_settings_witness();
50779
50835
  init_agent_policy_limits();
50780
50836
  init_agent_hermes();
50781
50837
  init_agent_discovery_directories();
@@ -52077,7 +52133,7 @@ function parseRecurringResult(action, value, input2, identity3) {
52077
52133
  }
52078
52134
  return result;
52079
52135
  }
52080
- var RecurringInputError, RemoteRecurringUnavailableError, RemoteRecurringReadError, RemoteRecurringUnconfirmedError, failures, RemoteRecurringError, uuid3, instant2, integer2, digest2, list, inputs, capabilityNames, budget, period, preview, consent, refusal2, occurrence, revocation, page = (item) => exports_external.object({ contractVersion: exports_external.literal(1), items: exports_external.array(item).max(100), nextCursor: exports_external.string().min(1).max(2048).nullable() }), results;
52136
+ var RecurringInputError, RemoteRecurringUnavailableError, RemoteRecurringReadError, RemoteRecurringUnconfirmedError, failures, RemoteRecurringError, uuid3, instant2, integer2, digest2, list, inputs, capabilityNames, budget2, period, preview, consent, refusal2, occurrence, revocation, page = (item) => exports_external.object({ contractVersion: exports_external.literal(1), items: exports_external.array(item).max(100), nextCursor: exports_external.string().min(1).max(2048).nullable() }), results;
52081
52137
  var init_remote_recurring = __esm(() => {
52082
52138
  init_v4();
52083
52139
  init_canonical_json();
@@ -52163,7 +52219,7 @@ var init_remote_recurring = __esm(() => {
52163
52219
  occurrences: "recurring.occurrences",
52164
52220
  revoke: "recurring.revoke"
52165
52221
  };
52166
- budget = exports_external.object({ reservedCredits: integer2, settledCredits: integer2, admittedOccurrences: integer2 });
52222
+ budget2 = exports_external.object({ reservedCredits: integer2, settledCredits: integer2, admittedOccurrences: integer2 });
52167
52223
  period = exports_external.object({ startsAt: instant2, endsAt: instant2 });
52168
52224
  preview = exports_external.object({
52169
52225
  contractVersion: exports_external.literal(1),
@@ -52185,8 +52241,8 @@ var init_remote_recurring = __esm(() => {
52185
52241
  state: exports_external.enum(["active", "revoked", "expired"]),
52186
52242
  activatedAt: instant2,
52187
52243
  revokedAt: instant2.nullable(),
52188
- total: budget,
52189
- currentPeriod: budget.extend(period.shape).nullable(),
52244
+ total: budget2,
52245
+ currentPeriod: budget2.extend(period.shape).nullable(),
52190
52246
  nextDueAt: instant2.nullable()
52191
52247
  });
52192
52248
  refusal2 = exports_external.enum([
@@ -54144,7 +54200,7 @@ function checkedPublicationView(value, skillId, intentId, declaration) {
54144
54200
  return invalid4();
54145
54201
  return Object.freeze({ ...value });
54146
54202
  }
54147
- async function boundedJson(url2, init, token, mutation, budget2 = 15000, signal) {
54203
+ async function boundedJson(url2, init, token, mutation, budget3 = 15000, signal) {
54148
54204
  const controller = new AbortController;
54149
54205
  let reader;
54150
54206
  let response;
@@ -54199,7 +54255,7 @@ async function boundedJson(url2, init, token, mutation, budget2 = 15000, signal)
54199
54255
  controller.abort();
54200
54256
  reject(timeout);
54201
54257
  };
54202
- timer = setTimeout(abort, Math.max(1, Math.min(15000, budget2)));
54258
+ timer = setTimeout(abort, Math.max(1, Math.min(15000, budget3)));
54203
54259
  signal?.addEventListener("abort", abort, { once: true });
54204
54260
  })]);
54205
54261
  } catch (error61) {