@hasna/skills 0.10.20 → 0.10.23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/sdk/index.js CHANGED
@@ -9004,7 +9004,7 @@ var require_client = __commonJS((exports) => {
9004
9004
  var require_config = __commonJS((exports) => {
9005
9005
  var { homedir: homedir7 } = __require("os");
9006
9006
  var { sep: sep9, join: join4 } = __require("path");
9007
- var { createHash: createHash20 } = __require("crypto");
9007
+ var { createHash: createHash21 } = __require("crypto");
9008
9008
  var { readFile: readFile$1 } = __require("fs/promises");
9009
9009
  var { IniSectionType } = require_dist_cjs();
9010
9010
  var { normalizeProvider } = require_client();
@@ -9159,7 +9159,7 @@ var require_config = __commonJS((exports) => {
9159
9159
  var DEFAULT_PROFILE = "default";
9160
9160
  var getProfileName = (init) => init.profile || process.env[ENV_PROFILE] || DEFAULT_PROFILE;
9161
9161
  var getSSOTokenFilepath = (id2) => {
9162
- const hasher = createHash20("sha1");
9162
+ const hasher = createHash21("sha1");
9163
9163
  const cacheName = hasher.update(id2).digest("hex");
9164
9164
  return join4(getHomeDir(), ".aws", "sso", "cache", `${cacheName}.json`);
9165
9165
  };
@@ -10511,7 +10511,7 @@ var require_endpoints = __commonJS((exports) => {
10511
10511
 
10512
10512
  // node_modules/@smithy/core/dist-cjs/submodules/serde/index.js
10513
10513
  var require_serde = __commonJS((exports) => {
10514
- var { createHmac: createHmac2, createHash: createHash20, getRandomValues } = __require("crypto");
10514
+ var { createHmac: createHmac2, createHash: createHash21, getRandomValues } = __require("crypto");
10515
10515
  var { hasOwn: hasOwn2, HttpResponse } = require_transport();
10516
10516
  exports.hasOwn = hasOwn2;
10517
10517
  var { ReadStream, lstatSync: lstatSync23, fstatSync: fstatSync4 } = __require("fs");
@@ -11416,7 +11416,7 @@ var require_serde = __commonJS((exports) => {
11416
11416
  return Promise.resolve(this.hash.digest());
11417
11417
  }
11418
11418
  reset() {
11419
- this.hash = this.secret ? createHmac2(this.algorithmIdentifier, castSourceData(this.secret)) : createHash20(this.algorithmIdentifier);
11419
+ this.hash = this.secret ? createHmac2(this.algorithmIdentifier, castSourceData(this.secret)) : createHash21(this.algorithmIdentifier);
11420
11420
  }
11421
11421
  }
11422
11422
  function castSourceData(toCast, encoding) {
@@ -12155,7 +12155,7 @@ var require_checksum = __commonJS((exports) => {
12155
12155
  var { createReadStream } = __require("fs");
12156
12156
  var { Writable } = __require("stream");
12157
12157
  var { toUint8Array, concatBytes } = require_serde();
12158
- var { createHash: createHash20, createHmac: createHmac2 } = __require("crypto");
12158
+ var { createHash: createHash21, createHmac: createHmac2 } = __require("crypto");
12159
12159
  var zlib = __require("zlib");
12160
12160
  async function blobReader(blob, onChunk, chunkSize = 1024 * 1024) {
12161
12161
  const size = blob.size;
@@ -12320,7 +12320,7 @@ var require_checksum = __commonJS((exports) => {
12320
12320
  }
12321
12321
  var hasNativeCrypto$1 = (() => {
12322
12322
  try {
12323
- createHash20("md5");
12323
+ createHash21("md5");
12324
12324
  return true;
12325
12325
  } catch {
12326
12326
  return false;
@@ -12330,7 +12330,7 @@ var require_checksum = __commonJS((exports) => {
12330
12330
  function buildNativeClass$2() {
12331
12331
  return class Md5Node2 {
12332
12332
  digestLength = 16;
12333
- hash = createHash20("md5");
12333
+ hash = createHash21("md5");
12334
12334
  update(data) {
12335
12335
  this.hash.update(toUint8Array(data));
12336
12336
  }
@@ -12339,7 +12339,7 @@ var require_checksum = __commonJS((exports) => {
12339
12339
  return new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength);
12340
12340
  }
12341
12341
  reset() {
12342
- this.hash = createHash20("md5");
12342
+ this.hash = createHash21("md5");
12343
12343
  }
12344
12344
  };
12345
12345
  }
@@ -12629,7 +12629,7 @@ var require_checksum = __commonJS((exports) => {
12629
12629
  ]);
12630
12630
  var hasNativeCrypto = (() => {
12631
12631
  try {
12632
- createHash20("sha256");
12632
+ createHash21("sha256");
12633
12633
  return true;
12634
12634
  } catch {
12635
12635
  return false;
@@ -12669,7 +12669,7 @@ var require_checksum = __commonJS((exports) => {
12669
12669
  this.finished = false;
12670
12670
  }
12671
12671
  createHash() {
12672
- return this.secret ? createHmac2("sha256", toBuffer(this.secret)) : createHash20("sha256");
12672
+ return this.secret ? createHmac2("sha256", toBuffer(this.secret)) : createHash21("sha256");
12673
12673
  }
12674
12674
  };
12675
12675
  }
@@ -14538,8 +14538,8 @@ var require_protocols = __commonJS((exports) => {
14538
14538
  class Fields {
14539
14539
  entries = {};
14540
14540
  encoding;
14541
- constructor({ fields = [], encoding = "utf-8" }) {
14542
- fields.forEach(this.setField.bind(this));
14541
+ constructor({ fields: fields2 = [], encoding = "utf-8" }) {
14542
+ fields2.forEach(this.setField.bind(this));
14543
14543
  this.encoding = encoding;
14544
14544
  }
14545
14545
  setField(field2) {
@@ -18166,7 +18166,7 @@ ${toHex(hashedRequest)}`;
18166
18166
  return hash2.digest();
18167
18167
  };
18168
18168
  var getCanonicalHeaders = ({ headers }, unsignableHeaders, signableHeaders) => {
18169
- const canonical5 = {};
18169
+ const canonical6 = {};
18170
18170
  for (const headerName of Object.keys(headers).sort()) {
18171
18171
  if (headers[headerName] == undefined) {
18172
18172
  continue;
@@ -18177,9 +18177,9 @@ ${toHex(hashedRequest)}`;
18177
18177
  continue;
18178
18178
  }
18179
18179
  }
18180
- canonical5[canonicalHeaderName] = headers[headerName].trim().replace(/\s+/g, " ");
18180
+ canonical6[canonicalHeaderName] = headers[headerName].trim().replace(/\s+/g, " ");
18181
18181
  }
18182
- return canonical5;
18182
+ return canonical6;
18183
18183
  };
18184
18184
  var getPayloadHash = async ({ headers, body }, hashConstructor) => {
18185
18185
  for (const headerName in headers) {
@@ -21700,12 +21700,12 @@ var require_protocols2 = __commonJS((exports) => {
21700
21700
  return expandToDecimal(numericString) === expandToDecimal(String(value));
21701
21701
  }
21702
21702
  const normalized = numericString.replace(/(\.\d*?)0+$/, "$1").replace(/\.$/, "");
21703
- const canonical5 = String(value);
21704
- if (normalized === canonical5) {
21703
+ const canonical6 = String(value);
21704
+ if (normalized === canonical6) {
21705
21705
  return true;
21706
21706
  }
21707
- if (/[eE]/.test(canonical5)) {
21708
- return normalized === expandToDecimal(canonical5);
21707
+ if (/[eE]/.test(canonical6)) {
21708
+ return normalized === expandToDecimal(canonical6);
21709
21709
  }
21710
21710
  return false;
21711
21711
  }
@@ -29443,7 +29443,7 @@ var require_signin = __commonJS((exports) => {
29443
29443
  });
29444
29444
 
29445
29445
  // node_modules/@aws-sdk/credential-provider-ini/node_modules/@aws-sdk/credential-provider-login/dist-es/LoginCredentialsFetcher.js
29446
- import { createHash as createHash20, createPrivateKey, createPublicKey, sign } from "crypto";
29446
+ import { createHash as createHash21, createPrivateKey, createPublicKey, sign } from "crypto";
29447
29447
  import { promises as fs2 } from "fs";
29448
29448
  import { homedir as homedir7 } from "os";
29449
29449
  import { dirname as dirname21, join as join33 } from "path";
@@ -29615,7 +29615,7 @@ var init_LoginCredentialsFetcher = __esm(() => {
29615
29615
  getTokenFilePath() {
29616
29616
  const directory = process.env.AWS_LOGIN_CACHE_DIRECTORY ?? join33(homedir7(), ".aws", "login", "cache");
29617
29617
  const loginSessionBytes = Buffer.from(this.loginSession, "utf8");
29618
- const loginSessionSha256 = createHash20("sha256").update(loginSessionBytes).digest("hex");
29618
+ const loginSessionSha256 = createHash21("sha256").update(loginSessionBytes).digest("hex");
29619
29619
  return join33(directory, `${loginSessionSha256}.json`);
29620
29620
  }
29621
29621
  derToRawSignature(derSignature) {
@@ -32373,7 +32373,7 @@ var init_event_sink = __esm(() => {
32373
32373
  // package.json
32374
32374
  var package_default = {
32375
32375
  name: "@hasna/skills",
32376
- version: "0.10.20",
32376
+ version: "0.10.23",
32377
32377
  description: "Skills library for AI coding agents",
32378
32378
  type: "module",
32379
32379
  bin: {
@@ -37455,7 +37455,7 @@ async function reconcileSkillSession(input, options = {}) {
37455
37455
  return { applied: true, plan, planDigest, ...result };
37456
37456
  }
37457
37457
  // src/lib/selected-run.ts
37458
- import { createHash as createHash19 } from "crypto";
37458
+ import { createHash as createHash20 } from "crypto";
37459
37459
  import { spawn as spawn2 } from "child_process";
37460
37460
  import { mkdirSync as mkdirSync10, mkdtempSync as mkdtempSync3, writeFileSync as writeFileSync9, realpathSync as realpathSync11 } from "fs";
37461
37461
  import { dirname as dirname20, join as join32, resolve as resolve18 } from "path";
@@ -38009,6 +38009,25 @@ function hashNativeJsonControls(text, excludedMetadata) {
38009
38009
  import { basename as basename3, dirname as dirname5, join as join10, relative as relative3, resolve as resolve4, sep as sep2 } from "path";
38010
38010
  import { lstatSync as lstatSync6, readdirSync as readdirSync3, readlinkSync as readlinkSync2, realpathSync as realpathSync5 } from "fs";
38011
38011
 
38012
+ // src/lib/codex-native-compatibility.ts
38013
+ var MEASURED_CODEX_CAPABILITIES = {
38014
+ "codex-cli 0.153.0": ["hooks"],
38015
+ "codex-cli 0.154.0": ["hooks"],
38016
+ "codex-cli 0.155.0": ["hooks"],
38017
+ "codex-cli 0.155.1": ["hooks"],
38018
+ "codex-cli 0.156.1": ["hooks"],
38019
+ "codex-cli 0.157.0": ["hooks"],
38020
+ "codex-cli 0.157.1": ["hooks"],
38021
+ "codex-cli 0.158.0": ["hooks"],
38022
+ "codex-cli 0.159.0": ["hooks"],
38023
+ "codex-cli 0.159.2": ["hooks", "qualified-skill-catalog"],
38024
+ "codex-cli 0.160.0": ["hooks", "qualified-skill-catalog"]
38025
+ };
38026
+ function supportsCodexNativeCapability(version, capability) {
38027
+ return typeof version === "string" && Object.hasOwn(MEASURED_CODEX_CAPABILITIES, version) && MEASURED_CODEX_CAPABILITIES[version].includes(capability);
38028
+ }
38029
+ var SUPPORTED_CODEX_HOOK_VERSIONS = Object.freeze(Object.keys(MEASURED_CODEX_CAPABILITIES).filter((version) => supportsCodexNativeCapability(version, "hooks")));
38030
+
38012
38031
  // src/lib/codex-native-skill-catalog.ts
38013
38032
  import { realpathSync as realpathSync4 } from "fs";
38014
38033
  import { isAbsolute as isAbsolute5, normalize } from "path";
@@ -38018,7 +38037,6 @@ import { execFile, spawn } from "child_process";
38018
38037
  import { realpathSync as realpathSync3, statSync as statSync3 } from "fs";
38019
38038
  import { isAbsolute as isAbsolute4 } from "path";
38020
38039
  import { promisify } from "util";
38021
- var SUPPORTED_CODEX_HOOK_VERSIONS = ["codex-cli 0.153.0", "codex-cli 0.154.0", "codex-cli 0.155.0", "codex-cli 0.155.1", "codex-cli 0.156.1", "codex-cli 0.157.0", "codex-cli 0.157.1", "codex-cli 0.158.0", "codex-cli 0.159.0", "codex-cli 0.159.2"];
38022
38040
  async function connectCodexHookRpc(options) {
38023
38041
  const timeoutMs = options.timeoutMs ?? 20000;
38024
38042
  if (!Number.isSafeInteger(timeoutMs) || timeoutMs < 100 || timeoutMs > 20000)
@@ -38036,7 +38054,7 @@ async function connectCodexHookRpc(options) {
38036
38054
  } catch {
38037
38055
  throw new Error("CODEX_HOOK_TRUST_NATIVE_UNAVAILABLE");
38038
38056
  }
38039
- if (!SUPPORTED_CODEX_HOOK_VERSIONS.includes(version))
38057
+ if (!supportsCodexNativeCapability(version, "hooks"))
38040
38058
  throw new Error("CODEX_HOOK_TRUST_NATIVE_UNSUPPORTED_VERSION");
38041
38059
  const current = statSync3(binary);
38042
38060
  if (realpathSync3(found) !== binary || ["dev", "ino", "size", "mtimeMs", "ctimeMs"].some((k) => stat[k] !== current[k]))
@@ -38161,12 +38179,12 @@ var MAX_SKILLS = 4096;
38161
38179
  var MAX_NAME_BYTES = 1024;
38162
38180
  var MAX_PATH_BYTES = 16384;
38163
38181
  var MAX_PLUGIN_ID_BYTES = 1024;
38164
- var SUPPORTED_NAME_CONTROL_VERSIONS = new Set(["codex-cli 0.159.2"]);
38165
38182
  function refuse2() {
38166
38183
  throw new Error("CODEX_NATIVE_SKILL_CATALOG_INVALID");
38167
38184
  }
38168
38185
  var object2 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
38169
38186
  var scalar = (value, max) => typeof value === "string" && value.length > 0 && value.trim() === value && Buffer.byteLength(value, "utf8") <= max && !/[\u0000-\u001f\u007f]/u.test(value);
38187
+ var remotePluginIdentifier = (value) => typeof value === "string" && /^[A-Za-z0-9_~-]{1,1024}$/.test(value);
38170
38188
  var absolutePath2 = (value) => scalar(value, MAX_PATH_BYTES) && isAbsolute5(value);
38171
38189
  function projectCodexNativeSkillCatalog(response, cwd) {
38172
38190
  if (!absolutePath2(cwd) || !object2(response) || !Array.isArray(response.data) || response.data.length !== 1)
@@ -38194,7 +38212,11 @@ function projectCodexInstalledPlugins(response) {
38194
38212
  for (const value of marketplace.plugins) {
38195
38213
  if (!object2(value) || !scalar(value.id, MAX_PLUGIN_ID_BYTES) || !scalar(value.name, MAX_NAME_BYTES) || value.id !== `${value.name}@${marketplace.name}`)
38196
38214
  refuse2();
38197
- plugins.push({ ...value, marketplace: marketplace.name });
38215
+ plugins.push({
38216
+ ...value,
38217
+ marketplace: marketplace.name,
38218
+ sourceType: object2(value.source) && value.source.type === "remote" ? "remote" : undefined
38219
+ });
38198
38220
  }
38199
38221
  }
38200
38222
  return projectCodexInstalledPluginEntries(plugins);
@@ -38204,13 +38226,21 @@ function projectCodexInstalledPluginEntries(value) {
38204
38226
  refuse2();
38205
38227
  const ids = new Set;
38206
38228
  return value.map((item) => {
38207
- if (!object2(item) || !scalar(item.id, MAX_PLUGIN_ID_BYTES) || !scalar(item.name, MAX_NAME_BYTES) || typeof item.installed !== "boolean" || typeof item.enabled !== "boolean" || item.localVersion !== null && !scalar(item.localVersion, MAX_NAME_BYTES))
38229
+ if (!object2(item) || !scalar(item.id, MAX_PLUGIN_ID_BYTES) || !scalar(item.name, MAX_NAME_BYTES) || typeof item.installed !== "boolean" || typeof item.enabled !== "boolean" || item.localVersion !== null && !scalar(item.localVersion, MAX_NAME_BYTES) || item.remotePluginId !== undefined && item.remotePluginId !== null && !remotePluginIdentifier(item.remotePluginId) || item.sourceType !== undefined && item.sourceType !== "remote")
38208
38230
  refuse2();
38209
38231
  const at = item.id.lastIndexOf("@");
38210
38232
  if (at < 1 || item.id.slice(0, at) !== item.name || at === item.id.length - 1 || ids.has(item.id))
38211
38233
  refuse2();
38212
38234
  ids.add(item.id);
38213
- return { id: item.id, name: item.name, installed: item.installed, enabled: item.enabled, localVersion: item.localVersion ?? null };
38235
+ return {
38236
+ id: item.id,
38237
+ name: item.name,
38238
+ installed: item.installed,
38239
+ enabled: item.enabled,
38240
+ localVersion: item.localVersion ?? null,
38241
+ ...item.sourceType === "remote" ? { sourceType: "remote" } : {},
38242
+ ...item.remotePluginId == null ? {} : { remotePluginId: item.remotePluginId }
38243
+ };
38214
38244
  });
38215
38245
  }
38216
38246
  async function captureCodexNativeSkillCatalog(options, connect = connectCodexHookRpc) {
@@ -38223,7 +38253,7 @@ async function captureCodexNativeSkillCatalog(options, connect = connectCodexHoo
38223
38253
  ...options.timeoutMs === undefined ? {} : { timeoutMs: options.timeoutMs }
38224
38254
  });
38225
38255
  try {
38226
- if (!SUPPORTED_NAME_CONTROL_VERSIONS.has(rpc.version))
38256
+ if (!supportsCodexNativeCapability(rpc.version, "qualified-skill-catalog"))
38227
38257
  throw new Error("CODEX_NATIVE_SKILL_CATALOG_UNSUPPORTED_VERSION");
38228
38258
  const response = await rpc.request("skills/list", { cwds: [options.cwd], forceReload: true });
38229
38259
  const installed = await rpc.request("plugin/installed", { cwds: [options.cwd] });
@@ -38281,6 +38311,21 @@ var CODEX_DEFAULT_AGENT_PLUGIN_VERSION = "1.0.0";
38281
38311
  function refuse3() {
38282
38312
  throw new Error("CODEX_NATIVE_SKILL_IDENTITY_UNSUPPORTED: review native plugin names and hook controls");
38283
38313
  }
38314
+ function remoteInstallationMatches(parent, remotePluginId, read) {
38315
+ try {
38316
+ if (!remotePluginIdentifier(remotePluginId) || !lstatSync6(parent).isDirectory() || realpathSync5(parent) !== parent)
38317
+ return false;
38318
+ const path = join10(parent, ".codex-remote-plugin-install.json"), stat = lstatSync6(path, { throwIfNoEntry: false });
38319
+ if (!stat?.isFile() || stat.isSymbolicLink() || stat.size > 16384)
38320
+ return false;
38321
+ const text = read(path);
38322
+ hashNativeJsonControls(text);
38323
+ const value = JSON.parse(text);
38324
+ return Boolean(value && typeof value === "object" && !Array.isArray(value) && Object.keys(value).length === 2 && value.schema_version === 1 && value.remote_plugin_id === remotePluginId);
38325
+ } catch {
38326
+ return false;
38327
+ }
38328
+ }
38284
38329
  function appControls(path, read) {
38285
38330
  const text = read(path);
38286
38331
  let value, sha2562;
@@ -38302,6 +38347,42 @@ function appControls(path, read) {
38302
38347
  }
38303
38348
  return sha2562;
38304
38349
  }
38350
+ function mcpControls(path, read) {
38351
+ const text = read(path);
38352
+ let value, sha2562;
38353
+ try {
38354
+ sha2562 = hashNativeJsonControls(text);
38355
+ value = JSON.parse(text);
38356
+ } catch {
38357
+ refuse3();
38358
+ }
38359
+ const object3 = (v) => Boolean(v && typeof v === "object" && !Array.isArray(v));
38360
+ const textField = (v, empty = false) => typeof v === "string" && (empty || Boolean(v.trim())) && Buffer.byteLength(v) <= 16384 && !/[\x00-\x1f\x7f]/.test(v);
38361
+ const envName = (v) => typeof v === "string" && /^[A-Za-z_][A-Za-z0-9_]{0,255}$/.test(v);
38362
+ if (!object3(value) || Object.keys(value).length !== 1 || !object3(value.mcpServers))
38363
+ refuse3();
38364
+ const servers = Object.entries(value.mcpServers);
38365
+ if (!servers.length || servers.length > 256)
38366
+ refuse3();
38367
+ for (const [name, server] of servers) {
38368
+ if (!identifier3(name) || !object3(server) || !Object.keys(server).every((key) => ["command", "args", "cwd", "env_vars"].includes(key)) || !textField(server.command) || server.args !== undefined && (!Array.isArray(server.args) || server.args.length > 256 || !server.args.every((arg) => textField(arg, true))) || server.cwd !== undefined && !textField(server.cwd))
38369
+ refuse3();
38370
+ if (server.env_vars !== undefined) {
38371
+ if (!Array.isArray(server.env_vars) || server.env_vars.length > 256)
38372
+ refuse3();
38373
+ const names = server.env_vars.map((entry) => {
38374
+ if (envName(entry))
38375
+ return entry;
38376
+ if (!object3(entry) || !Object.keys(entry).every((key) => ["name", "source"].includes(key)) || !envName(entry.name) || entry.source !== undefined && entry.source !== "local")
38377
+ refuse3();
38378
+ return entry.name;
38379
+ });
38380
+ if (new Set(names).size !== names.length)
38381
+ refuse3();
38382
+ }
38383
+ }
38384
+ return sha2562;
38385
+ }
38305
38386
  function rootControls(root, read) {
38306
38387
  const manifestPath = join10(root, ".codex-plugin/plugin.json"), manifestFile = lstatSync6(manifestPath, { throwIfNoEntry: false });
38307
38388
  if (!lstatSync6(join10(root, ".codex-plugin"), { throwIfNoEntry: false })?.isDirectory() || !manifestFile?.isFile() || manifestFile.size > 1024 * 1024)
@@ -38319,15 +38400,21 @@ function rootControls(root, read) {
38319
38400
  const cacheVersion = basename3(root), declaredVersion = manifest.version === undefined ? "" : typeof manifest.version === "string" ? manifest.version.trim() : null;
38320
38401
  if (declaredVersion === null || (declaredVersion ? declaredVersion !== cacheVersion : cacheVersion !== CODEX_DEFAULT_AGENT_PLUGIN_VERSION))
38321
38402
  refuse3();
38322
- if (manifest.hooks !== undefined || manifest.mcpServers !== undefined || manifest.commands !== undefined || manifest.apps !== undefined && manifest.apps !== "./.app.json" || ["hooks", ".mcp.json"].some((path) => lstatSync6(join10(root, path), { throwIfNoEntry: false })))
38403
+ if (manifest.hooks !== undefined || manifest.commands !== undefined || manifest.mcpServers !== undefined && manifest.mcpServers !== "./.mcp.json" || manifest.apps !== undefined && manifest.apps !== "./.app.json" || lstatSync6(join10(root, "hooks"), { throwIfNoEntry: false }))
38404
+ refuse3();
38405
+ const mcp = join10(root, ".mcp.json"), mcpPresent = lstatSync6(mcp, { throwIfNoEntry: false });
38406
+ if (mcpPresent && (!mcpPresent.isFile() || mcpPresent.isSymbolicLink() || mcpPresent.size > 1024 * 1024 || realpathSync5(mcp) !== mcp))
38407
+ refuse3();
38408
+ if (Boolean(mcpPresent) !== (manifest.mcpServers !== undefined))
38323
38409
  refuse3();
38410
+ const mcpSha256 = mcpPresent ? mcpControls(mcp, read) : undefined;
38324
38411
  const app = join10(root, ".app.json"), present = lstatSync6(app, { throwIfNoEntry: false });
38325
38412
  if (present && (!present.isFile() || present.isSymbolicLink() || present.size > 1024 * 1024))
38326
38413
  refuse3();
38327
38414
  if (manifest.apps !== undefined && !present)
38328
38415
  refuse3();
38329
38416
  const appSha256 = present ? appControls(app, read) : undefined;
38330
- return { namespace: manifest.name, manifestSha256, ...appSha256 ? { appSha256 } : {} };
38417
+ return { namespace: manifest.name, manifestSha256, ...appSha256 ? { appSha256 } : {}, ...mcpSha256 ? { mcpSha256 } : {} };
38331
38418
  }
38332
38419
  function identity(document, cache, read) {
38333
38420
  if (!document.startsWith(cache + sep2) || !document.endsWith(sep2 + "SKILL.md"))
@@ -38370,6 +38457,10 @@ function reviewedCodexPluginCapabilitiesUnchanged(cache, controls, read) {
38370
38457
  for (const parent of new Set(controls.map((control) => control.pluginParent))) {
38371
38458
  if (!parent.startsWith(cache + sep2) || !lstatSync6(parent, { throwIfNoEntry: false })?.isDirectory())
38372
38459
  return false;
38460
+ for (const control of controls.filter((control2) => control2.pluginParent === parent)) {
38461
+ if (control.remotePluginId !== undefined && !remoteInstallationMatches(parent, control.remotePluginId, read))
38462
+ return false;
38463
+ }
38373
38464
  const names = readdirSync3(parent);
38374
38465
  entries += names.length;
38375
38466
  if (entries > 4096)
@@ -38386,7 +38477,7 @@ function reviewedCodexPluginCapabilitiesUnchanged(cache, controls, read) {
38386
38477
  if (!stat.isDirectory() || ![".codex-plugin/plugin.json", ".app.json", "hooks", ".mcp.json"].some((path) => lstatSync6(join10(root, path), { throwIfNoEntry: false })))
38387
38478
  continue;
38388
38479
  const parsed = rootControls(root, read);
38389
- if (!controls.some((control) => control.pluginParent === parent && control.namespace === parsed.namespace && control.manifestSha256 === parsed.manifestSha256 && control.appSha256 === parsed.appSha256))
38480
+ if (!controls.some((control) => control.pluginParent === parent && control.namespace === parsed.namespace && control.manifestSha256 === parsed.manifestSha256 && control.appSha256 === parsed.appSha256 && control.mcpSha256 === parsed.mcpSha256))
38390
38481
  return false;
38391
38482
  }
38392
38483
  }
@@ -38396,7 +38487,7 @@ function reviewedCodexPluginCapabilitiesUnchanged(cache, controls, read) {
38396
38487
  }
38397
38488
  }
38398
38489
  function reviewCodexPluginSkillControls(catalog, documents, cache, cwd, read, rules) {
38399
- if (catalog?.version !== "codex-cli 0.159.2" || catalog.cwd !== cwd)
38490
+ if (!supportsCodexNativeCapability(catalog?.version, "qualified-skill-catalog") || catalog.cwd !== cwd)
38400
38491
  refuse3();
38401
38492
  const skills = projectCodexNativeSkillCatalog({ data: [{ cwd, errors: [], skills: catalog.skills }] }, cwd);
38402
38493
  const allowed = new Set(documents), result = [];
@@ -38423,22 +38514,30 @@ function reviewCodexPluginSkillControls(catalog, documents, cache, cwd, read, ru
38423
38514
  const listed = skills.filter((skill) => skill.path === document);
38424
38515
  if (listed.length > 1)
38425
38516
  refuse3();
38517
+ let remotePluginId;
38426
38518
  if (listed.length === 1) {
38427
38519
  if (listed[0].name !== parsed.name || listed[0].pluginId !== expectedPluginId)
38428
38520
  refuse3();
38429
38521
  } else {
38430
- const installed = installedPlugins.filter((plugin) => plugin.id === expectedPluginId && plugin.name === pluginName);
38431
- if (installed.length !== 1 || !installed[0].installed || !installed[0].enabled || !installed[0].localVersion)
38522
+ const installed = installedPlugins.filter((plugin2) => plugin2.id === expectedPluginId && plugin2.name === pluginName);
38523
+ if (installed.length !== 1 || !installed[0].installed || !installed[0].enabled)
38432
38524
  refuse3();
38433
- if (installed[0].localVersion !== basename3(dirname5(dirname5(dirname5(document)))))
38434
- continue;
38525
+ const plugin = installed[0];
38526
+ if (plugin.localVersion !== null) {
38527
+ if (plugin.localVersion !== basename3(dirname5(dirname5(dirname5(document)))))
38528
+ continue;
38529
+ } else {
38530
+ if (plugin.sourceType !== "remote" || !plugin.remotePluginId || !remoteInstallationMatches(parsed.pluginParent, plugin.remotePluginId, read) || !lstatSync6(document).isFile() || realpathSync5(document) !== document)
38531
+ refuse3();
38532
+ remotePluginId = plugin.remotePluginId;
38533
+ }
38435
38534
  const exactPathDeny = Array.isArray(rules) && rules.some((rule) => rule?.path === document && rule?.enabled === false);
38436
38535
  if (!exactPathDeny || !isCodexNativeSkillDisabled({ name: parsed.name, path: document, pluginId: expectedPluginId, enabled: true }, rules))
38437
38536
  refuse3();
38438
38537
  }
38439
- result.push({ ...parsed, pluginId: expectedPluginId });
38538
+ result.push({ ...parsed, pluginId: expectedPluginId, ...remotePluginId ? { remotePluginId } : {} });
38440
38539
  }
38441
- if (!result.length || new Set(result.map((item) => item.name)).size !== result.length)
38540
+ if (!result.length && documents.some((document) => document.startsWith(cache + sep2)) || new Set(result.map((item) => item.name)).size !== result.length)
38442
38541
  refuse3();
38443
38542
  return result;
38444
38543
  }
@@ -38451,8 +38550,8 @@ function isReviewedCodexPluginSkillDisabled(document, cache, controls, rules, re
38451
38550
  } catch {
38452
38551
  return false;
38453
38552
  }
38454
- const reviewed = controls.find((item) => item.name === parsed.name && item.namespace === parsed.namespace && item.pluginParent === parsed.pluginParent && item.manifestSha256 === parsed.manifestSha256 && item.appSha256 === parsed.appSha256);
38455
- if (!reviewed)
38553
+ const reviewed = controls.find((item) => item.name === parsed.name && item.namespace === parsed.namespace && item.pluginParent === parsed.pluginParent && item.manifestSha256 === parsed.manifestSha256 && item.appSha256 === parsed.appSha256 && item.mcpSha256 === parsed.mcpSha256);
38554
+ if (!reviewed || reviewed.remotePluginId !== undefined && !remoteInstallationMatches(reviewed.pluginParent, reviewed.remotePluginId, read))
38456
38555
  return false;
38457
38556
  return isCodexNativeSkillDisabled({ name: parsed.name, path: document, pluginId: reviewed.pluginId, enabled: true }, rules);
38458
38557
  }
@@ -38471,7 +38570,7 @@ enabled = false
38471
38570
  return text;
38472
38571
  }
38473
38572
 
38474
- // src/lib/codex-settings-witness.ts
38573
+ // src/lib/codex-settings-witness-v1.ts
38475
38574
  import { createHash as createHash6 } from "crypto";
38476
38575
  var sha = (text) => createHash6("sha256").update(text).digest("hex");
38477
38576
  var EFFORT = new Set(["none", "minimal", "low", "medium", "high", "xhigh"]);
@@ -38565,15 +38664,162 @@ function captureCodexSettings(path, budget = { remaining: 256 * 1024 * 1024 }) {
38565
38664
  const text = readNativeSettingsWitnessFile(path, budget, "config.toml");
38566
38665
  return { path, hashMode: "codex-settings-v1", sha256: hashCodexSettingsReplacement(text) };
38567
38666
  }
38667
+
38668
+ // src/lib/codex-settings-witness.ts
38669
+ import { createHash as createHash7 } from "crypto";
38670
+ var sha2 = (text) => createHash7("sha256").update(text).digest("hex");
38671
+ var EFFORT2 = new Set(["none", "minimal", "low", "medium", "high", "xhigh"]);
38672
+ var VERBOSITY2 = new Set(["low", "medium", "high"]);
38673
+ var MODEL = /^[A-Za-z0-9][A-Za-z0-9._:/-]{0,127}$/;
38674
+ var CODEX_DISCOVERY_PROJECTION_FIELDS = ["plugins", "marketplaces", "skills"];
38675
+ var INFERENCE = ["model", "model_reasoning_effort", "model_verbosity"];
38676
+ function need3(value) {
38677
+ if (!value)
38678
+ throw new Error("Invalid Codex settings witness");
38679
+ }
38680
+ function isRecord(value) {
38681
+ return Boolean(value && typeof value === "object" && !Array.isArray(value));
38682
+ }
38683
+ function isDate(value) {
38684
+ return value instanceof Date;
38685
+ }
38686
+ function numericTokens2(text) {
38687
+ const result = [];
38688
+ for (let at = 0;at < text.length; ) {
38689
+ const char = text[at];
38690
+ if (char === "#") {
38691
+ while (at < text.length && text[at] !== `
38692
+ `)
38693
+ at++;
38694
+ continue;
38695
+ }
38696
+ if (char === '"' || char === "'") {
38697
+ const quote = char, triple = text.slice(at, at + 3) === quote.repeat(3);
38698
+ at += triple ? 3 : 1;
38699
+ while (at < text.length) {
38700
+ if (quote === '"' && text[at] === "\\") {
38701
+ at += 2;
38702
+ continue;
38703
+ }
38704
+ if (text.slice(at, at + (triple ? 3 : 1)) === quote.repeat(triple ? 3 : 1)) {
38705
+ at += triple ? 3 : 1;
38706
+ break;
38707
+ }
38708
+ at++;
38709
+ }
38710
+ continue;
38711
+ }
38712
+ if (/[0-9+-]/.test(char)) {
38713
+ const start = at;
38714
+ while (at < text.length && !/[\s,\]{}#=]/.test(text[at]))
38715
+ at++;
38716
+ if (at > start) {
38717
+ result.push(text.slice(start, at));
38718
+ continue;
38719
+ }
38720
+ }
38721
+ at++;
38722
+ }
38723
+ return result.sort();
38724
+ }
38725
+ function canonical3(value, depth = 0, budget = { remaining: 65536 }) {
38726
+ need3(depth <= 32 && --budget.remaining >= 0);
38727
+ if (value === null)
38728
+ return ["null"];
38729
+ if (typeof value === "string")
38730
+ return ["string", value];
38731
+ if (typeof value === "boolean")
38732
+ return ["boolean", value];
38733
+ if (typeof value === "number") {
38734
+ need3(Number.isFinite(value));
38735
+ return ["number", String(value)];
38736
+ }
38737
+ if (isDate(value)) {
38738
+ need3(Number.isFinite(value.getTime()));
38739
+ return ["date", value.toISOString()];
38740
+ }
38741
+ if (Array.isArray(value))
38742
+ return ["array", value.map((child) => canonical3(child, depth + 1, budget))];
38743
+ need3(isRecord(value));
38744
+ return ["object", Object.entries(value).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0).map(([key, child]) => [key, canonical3(child, depth + 1, budget)])];
38745
+ }
38746
+ function normalize2(config) {
38747
+ if (isRecord(config.hooks)) {
38748
+ delete config.hooks.state;
38749
+ if (!Object.keys(config.hooks).length)
38750
+ delete config.hooks;
38751
+ }
38752
+ if (isRecord(config.skills) && Array.isArray(config.skills.config)) {
38753
+ const skills = config.skills;
38754
+ const retained = skills.config.filter((entry) => !disablesOneSkill(entry));
38755
+ if (retained.length !== skills.config.length) {
38756
+ if (retained.length)
38757
+ skills.config = retained;
38758
+ else
38759
+ delete skills.config;
38760
+ }
38761
+ if (!Object.keys(skills).length)
38762
+ delete config.skills;
38763
+ }
38764
+ inference(config);
38765
+ if (isRecord(config.profiles)) {
38766
+ for (const profile of Object.values(config.profiles))
38767
+ if (isRecord(profile))
38768
+ inference(profile);
38769
+ }
38770
+ }
38771
+ function disablesOneSkill(entry) {
38772
+ if (!isRecord(entry) || entry.enabled !== false)
38773
+ return false;
38774
+ const keys2 = Object.keys(entry);
38775
+ if (!keys2.every((key) => key === "path" || key === "name" || key === "enabled"))
38776
+ return false;
38777
+ const selector = ["path", "name"].filter((key) => Object.hasOwn(entry, key));
38778
+ return selector.length === 1 && typeof entry[selector[0]] === "string" && entry[selector[0]].length > 0;
38779
+ }
38780
+ function inference(target) {
38781
+ for (const key of INFERENCE)
38782
+ if (Object.hasOwn(target, key)) {
38783
+ const value = target[key];
38784
+ if (key === "model")
38785
+ need3(typeof value === "string" && MODEL.test(value));
38786
+ else
38787
+ need3(typeof value === "string" && (key === "model_reasoning_effort" ? EFFORT2.has(value) : VERBOSITY2.has(value)));
38788
+ delete target[key];
38789
+ }
38790
+ }
38791
+ function settingsDigest2(text) {
38792
+ let config;
38793
+ try {
38794
+ config = Bun.TOML.parse(text);
38795
+ } catch {
38796
+ throw new Error("Invalid Codex settings witness");
38797
+ }
38798
+ need3(isRecord(config));
38799
+ normalize2(config);
38800
+ return sha2(`hasna.skills.codex-settings.v2\x00${JSON.stringify([canonical3(config), numericTokens2(text)])}`);
38801
+ }
38802
+ function hashCodexSettingsReplacementV2(text, budget = { remaining: 256 * 1024 * 1024 }) {
38803
+ need3(Buffer.byteLength(text) <= 1024 * 1024 && budget.remaining >= Buffer.byteLength(text));
38804
+ budget.remaining -= Buffer.byteLength(text);
38805
+ return settingsDigest2(text);
38806
+ }
38807
+ function captureCodexSettingsV2(path, budget = { remaining: 256 * 1024 * 1024 }) {
38808
+ const text = readNativeSettingsWitnessFile(path, budget, "config.toml");
38809
+ return { path, hashMode: "codex-settings-v2", sha256: settingsDigest2(text) };
38810
+ }
38811
+ function readCodexSettingsPreimage(path, budget = { remaining: 2 * 1024 * 1024 }) {
38812
+ return readNativeSettingsWitnessFile(path, budget, "config.toml");
38813
+ }
38568
38814
  function upgradeCodexSettingsWitness(previous, reviewedSettingsPath) {
38569
- need2(previous && Object.keys(previous).every((key) => ["path", "hashMode", "sha256"].includes(key)) && (previous.hashMode === undefined || previous.hashMode === "bytes") && /^[a-f0-9]{64}$/.test(previous.sha256));
38815
+ need3(previous && Object.keys(previous).every((key) => ["path", "hashMode", "sha256"].includes(key)) && (previous.hashMode === undefined || previous.hashMode === "bytes" || previous.hashMode === "codex-settings-v1") && /^[a-f0-9]{64}$/.test(previous.sha256));
38570
38816
  const budget = { remaining: 2 * 1024 * 1024 };
38571
38817
  const before = readNativeSettingsWitnessFile(reviewedSettingsPath, budget, "config.toml"), current = readNativeSettingsWitnessFile(previous.path, budget, "config.toml");
38572
- need2(sha(before) === previous.sha256);
38573
- const sha2562 = hashCodexSettingsReplacement(current);
38574
- if (hashCodexSettingsReplacement(before) !== sha2562)
38818
+ need3((previous.hashMode === "codex-settings-v1" ? hashCodexSettingsReplacement(before) : sha2(before)) === previous.sha256);
38819
+ const sha2562 = settingsDigest2(current);
38820
+ if (settingsDigest2(before) !== sha2562)
38575
38821
  throw new Error("Codex non-preference settings changed; explicit discovery review required");
38576
- return { path: previous.path, hashMode: "codex-settings-v1", sha256: sha2562 };
38822
+ return { path: previous.path, hashMode: "codex-settings-v2", sha256: sha2562 };
38577
38823
  }
38578
38824
 
38579
38825
  // src/lib/native-discovery-roots.ts
@@ -38596,7 +38842,8 @@ var NATIVE_SKILL_ROOTS = [
38596
38842
  ];
38597
38843
 
38598
38844
  // src/lib/agent-integration.ts
38599
- import { createHash as createHash17, randomUUID as randomUUID3 } from "crypto";
38845
+ import { createHash as createHash18, randomUUID as randomUUID3 } from "crypto";
38846
+ import { isDeepStrictEqual as isDeepStrictEqual5 } from "util";
38600
38847
  import { existsSync as existsSync6, lstatSync as lstatSync19, statSync as statSync6, mkdirSync as mkdirSync5, readFileSync as readFileSync14, readdirSync as readdirSync8, opendirSync as opendirSync5, readlinkSync as readlinkSync4, realpathSync as realpathSync7, renameSync as renameSync3, rmdirSync as rmdirSync3, writeFileSync as writeFileSync4, unlinkSync as unlinkSync4, chmodSync, openSync as openSync16, closeSync as closeSync16, fsyncSync as fsyncSync4, fstatSync as fstatSync16, readSync as readSync11, constants as constants12, linkSync as linkSync2 } from "fs";
38601
38848
  import { dirname as dirname15, join as join22, resolve as resolve15, relative as relative4, isAbsolute as isAbsolute17, sep as sep5 } from "path";
38602
38849
  import { homedir as homedir3 } from "os";
@@ -38655,12 +38902,16 @@ function assertAgentPolicyCollections(policy) {
38655
38902
  }
38656
38903
  if (bridge.codexPluginSkills !== undefined)
38657
38904
  for (const control of array(bridge.codexPluginSkills, 4096)) {
38658
- requireBound(object3(control) && Object.keys(control).every((key) => ["name", "pluginId", "namespace", "pluginParent", "manifestSha256", "appSha256"].includes(key)));
38905
+ requireBound(object3(control) && Object.keys(control).every((key) => ["name", "pluginId", "namespace", "pluginParent", "manifestSha256", "appSha256", "mcpSha256", "remotePluginId"].includes(key)));
38659
38906
  text(control.name, 129);
38660
38907
  text(control.pluginId, 1024);
38661
38908
  text(control.namespace, 64);
38662
38909
  text(control.pluginParent);
38663
38910
  requireBound(isAbsolute6(control.pluginParent) && resolve5(control.pluginParent) === control.pluginParent && /^[a-f0-9]{64}$/.test(control.manifestSha256));
38911
+ if (control.remotePluginId !== undefined)
38912
+ requireBound(typeof control.remotePluginId === "string" && /^[A-Za-z0-9_~-]{1,1024}$/.test(control.remotePluginId));
38913
+ if (control.mcpSha256 !== undefined)
38914
+ requireBound(typeof control.mcpSha256 === "string" && /^[a-f0-9]{64}$/.test(control.mcpSha256));
38664
38915
  if (control.appSha256 !== undefined)
38665
38916
  requireBound(typeof control.appSha256 === "string" && /^[a-f0-9]{64}$/.test(control.appSha256));
38666
38917
  }
@@ -38683,8 +38934,8 @@ function assertAgentPolicyCollections(policy) {
38683
38934
  text(source.path);
38684
38935
  requireBound(source.sha256 === null || typeof source.sha256 === "string" && /^[a-f0-9]{64}$/.test(source.sha256));
38685
38936
  if (source.hashMode !== undefined)
38686
- 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"].includes(source.hashMode) && source.format === undefined && source.fields === undefined && (source.hashMode === "bytes" || source.sha256 !== null));
38687
- if (source.hashMode === "codex-settings-v1")
38937
+ 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"].includes(source.hashMode) && source.format === undefined && source.fields === undefined && (source.hashMode === "bytes" || source.sha256 !== null));
38938
+ if (source.hashMode === "codex-settings-v1" || source.hashMode === "codex-settings-v2")
38688
38939
  requireBound(agent === "codex" && value.agent === "codex" && value.method === "reviewed" && !/[\x00-\x1f\x7f]/.test(source.path) && isAbsolute6(source.path) && resolve5(source.path) === source.path && basename4(source.path) === "config.toml");
38689
38940
  if (source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || source.hashMode === "claude-settings-v3")
38690
38941
  requireBound(agent === "claude" && value.agent === "claude" && value.method === "reviewed" && !/[\x00-\x1f\x7f]/.test(source.path) && isAbsolute6(source.path) && resolve5(source.path) === source.path && basename4(source.path) === "settings.json");
@@ -38798,7 +39049,7 @@ function requiresCliSkillLoading(dataDir2 = getDataDirReadOnly()) {
38798
39049
  }
38799
39050
 
38800
39051
  // src/lib/agent-bridge.ts
38801
- import { createHash as createHash7 } from "crypto";
39052
+ import { createHash as createHash8 } from "crypto";
38802
39053
  import { lstatSync as lstatSync8, readFileSync as readFileSync9, readdirSync as readdirSync4 } from "fs";
38803
39054
  import { join as join12 } from "path";
38804
39055
  var CLI_BRIDGE_NAME = "skills-cli";
@@ -38817,7 +39068,7 @@ Use the Skills CLI as the skill authority for this station.
38817
39068
 
38818
39069
  This bridge contains no skill payloads. Do not copy skill content into agent-native skill directories or load other native skill copies. If a Skills command refuses authority, selection, integrity, or native drift, report that refusal and use its repair guidance; do not substitute bundled or stale local content. Explicit local draft authoring remains available.
38819
39070
  `;
38820
- var CLI_BRIDGE_DIGEST = createHash7("sha256").update(markdown).digest("hex");
39071
+ var CLI_BRIDGE_DIGEST = createHash8("sha256").update(markdown).digest("hex");
38821
39072
  var CLI_BRIDGE_FILES = Object.freeze({
38822
39073
  "SKILL.md": markdown,
38823
39074
  ".hasna-skills.json": `${JSON.stringify({ managedBy: "@hasna/skills", kind: "cli-bridge", version: CLI_BRIDGE_VERSION, protocol: "selection-v1", contentSha256: CLI_BRIDGE_DIGEST }, null, 2)}
@@ -38841,7 +39092,7 @@ function isOwnedCliBridge(path, expectedPaths) {
38841
39092
  }
38842
39093
 
38843
39094
  // src/lib/agent-discovery.ts
38844
- import { createHash as createHash16 } from "crypto";
39095
+ import { createHash as createHash17 } from "crypto";
38845
39096
  import { lstatSync as lstatSync18, readFileSync as readFileSync13, readdirSync as readdirSync7, realpathSync as realpathSync6 } from "fs";
38846
39097
  import { basename as basename7, dirname as dirname14, isAbsolute as isAbsolute16, join as join21, resolve as resolve14, sep as sep4 } from "path";
38847
39098
  import { isDeepStrictEqual as isDeepStrictEqual3 } from "util";
@@ -39100,17 +39351,17 @@ if (failed) process.exitCode = 2;
39100
39351
  }
39101
39352
 
39102
39353
  // src/lib/agent-discovery-directories.ts
39103
- import { createHash as createHash8 } from "crypto";
39354
+ import { createHash as createHash9 } from "crypto";
39104
39355
  import { lstatSync as lstatSync10, opendirSync as opendirSync2 } from "fs";
39105
39356
  import { dirname as dirname7, isAbsolute as isAbsolute8, join as join14, resolve as resolve7 } from "path";
39106
- function need3(value, message) {
39357
+ function need4(value, message) {
39107
39358
  if (!value)
39108
39359
  throw new Error(message);
39109
39360
  }
39110
39361
  function safe(path) {
39111
- need3(typeof path === "string" && path.length <= AGENT_POLICY_LIMITS.pathCharacters && isAbsolute8(path) && resolve7(path) === path && !path.includes("\x00"), "Expected a canonical absolute discovery directory path");
39362
+ need4(typeof path === "string" && path.length <= AGENT_POLICY_LIMITS.pathCharacters && isAbsolute8(path) && resolve7(path) === path && !path.includes("\x00"), "Expected a canonical absolute discovery directory path");
39112
39363
  for (let cursor = path;; cursor = dirname7(cursor)) {
39113
- need3(!lstatSync10(cursor, { throwIfNoEntry: false })?.isSymbolicLink(), "Refusing symlink native discovery directory");
39364
+ need4(!lstatSync10(cursor, { throwIfNoEntry: false })?.isSymbolicLink(), "Refusing symlink native discovery directory");
39114
39365
  if (dirname7(cursor) === cursor)
39115
39366
  break;
39116
39367
  }
@@ -39123,55 +39374,55 @@ function capture(path, budget) {
39123
39374
  const root = lstatSync10(path, { throwIfNoEntry: false });
39124
39375
  if (!root)
39125
39376
  return { path, sha256: null };
39126
- need3(root.isDirectory(), "Unsupported native discovery directory input");
39127
- const hash2 = createHash8("sha256");
39377
+ need4(root.isDirectory(), "Unsupported native discovery directory input");
39378
+ const hash2 = createHash9("sha256");
39128
39379
  function walk2(current, relative4, before, depth) {
39129
- need3(depth <= 64, "Native discovery directory depth limit exceeded");
39380
+ need4(depth <= 64, "Native discovery directory depth limit exceeded");
39130
39381
  const names = [], directory = opendirSync2(current);
39131
39382
  try {
39132
39383
  for (let entry = directory.readSync();entry; entry = directory.readSync()) {
39133
- need3(++budget.entries <= AGENT_POLICY_LIMITS.discoveryDirectoryEntries, "Native discovery directory entry limit exceeded");
39384
+ need4(++budget.entries <= AGENT_POLICY_LIMITS.discoveryDirectoryEntries, "Native discovery directory entry limit exceeded");
39134
39385
  names.push(entry.name);
39135
39386
  }
39136
39387
  } finally {
39137
39388
  directory.closeSync();
39138
39389
  }
39139
- need3(new Set(names).size === names.length, "Ambiguous native discovery directory names");
39390
+ need4(new Set(names).size === names.length, "Ambiguous native discovery directory names");
39140
39391
  for (const name of names.sort()) {
39141
39392
  const child = join14(current, name), childRelative = relative4 ? `${relative4}/${name}` : name;
39142
- need3(child.length <= AGENT_POLICY_LIMITS.pathCharacters, "Native discovery directory path limit exceeded");
39393
+ need4(child.length <= AGENT_POLICY_LIMITS.pathCharacters, "Native discovery directory path limit exceeded");
39143
39394
  const stat = lstatSync10(child);
39144
- need3(stat.isFile() || stat.isDirectory(), "Refusing symlink or special native discovery directory member");
39395
+ need4(stat.isFile() || stat.isDirectory(), "Refusing symlink or special native discovery directory member");
39145
39396
  const row = JSON.stringify([childRelative, stat.isDirectory() ? "directory" : "file"]) + `
39146
39397
  `;
39147
39398
  budget.bytes += Buffer.byteLength(row);
39148
- need3(budget.bytes <= AGENT_POLICY_LIMITS.discoveryDirectoryBytes, "Native discovery directory metadata limit exceeded");
39399
+ need4(budget.bytes <= AGENT_POLICY_LIMITS.discoveryDirectoryBytes, "Native discovery directory metadata limit exceeded");
39149
39400
  hash2.update(row);
39150
39401
  if (stat.isDirectory())
39151
39402
  walk2(child, childRelative, stat, depth + 1);
39152
39403
  }
39153
- need3(same(before, lstatSync10(current, { throwIfNoEntry: false })), "Native discovery directory changed while reading");
39404
+ need4(same(before, lstatSync10(current, { throwIfNoEntry: false })), "Native discovery directory changed while reading");
39154
39405
  }
39155
39406
  walk2(path, "", root, 0);
39156
39407
  safe(path);
39157
39408
  return { path, sha256: hash2.digest("hex") };
39158
39409
  }
39159
39410
  function captureDiscoveryDirectories(paths) {
39160
- need3(Array.isArray(paths) && paths.length <= AGENT_POLICY_LIMITS.discoveryDirectories && new Set(paths).size === paths.length, "Invalid native discovery directory collection");
39411
+ need4(Array.isArray(paths) && paths.length <= AGENT_POLICY_LIMITS.discoveryDirectories && new Set(paths).size === paths.length, "Invalid native discovery directory collection");
39161
39412
  const budget = { entries: 0, bytes: 0 };
39162
39413
  return paths.map((path) => capture(path, budget));
39163
39414
  }
39164
39415
  function verifyDiscoveryDirectories(directories) {
39165
- need3(Array.isArray(directories) && directories.length <= AGENT_POLICY_LIMITS.discoveryDirectories, "Invalid native discovery directory collection");
39416
+ need4(Array.isArray(directories) && directories.length <= AGENT_POLICY_LIMITS.discoveryDirectories, "Invalid native discovery directory collection");
39166
39417
  for (const directory of directories)
39167
- need3(directory && typeof directory === "object" && (directory.sha256 === null || typeof directory.sha256 === "string" && /^[a-f0-9]{64}$/.test(directory.sha256)), "Invalid native discovery directory digest");
39418
+ need4(directory && typeof directory === "object" && (directory.sha256 === null || typeof directory.sha256 === "string" && /^[a-f0-9]{64}$/.test(directory.sha256)), "Invalid native discovery directory digest");
39168
39419
  const current = captureDiscoveryDirectories(directories.map((directory) => directory.path));
39169
39420
  for (let i = 0;i < directories.length; i++)
39170
- need3(current[i].sha256 === directories[i].sha256, `Native discovery directory membership changed; run skills hook install with a fresh discovery review: ${directories[i].path}`);
39421
+ need4(current[i].sha256 === directories[i].sha256, `Native discovery directory membership changed; run skills hook install with a fresh discovery review: ${directories[i].path}`);
39171
39422
  }
39172
39423
 
39173
39424
  // src/lib/agent-discovery-bytes.ts
39174
- import { createHash as createHash9 } from "crypto";
39425
+ import { createHash as createHash10 } from "crypto";
39175
39426
  import { closeSync as closeSync11, constants as constants7, fstatSync as fstatSync11, lstatSync as lstatSync11, openSync as openSync11, readSync as readSync6 } from "fs";
39176
39427
  import { dirname as dirname8, isAbsolute as isAbsolute9, resolve as resolve8 } from "path";
39177
39428
  function discoveryByteBudget() {
@@ -39202,7 +39453,7 @@ function hashRawDiscoveryFile(path, budget, changes) {
39202
39453
  if (bytes > AGENT_POLICY_LIMITS.discoveryRawSourceBytes)
39203
39454
  throw new Error("Raw discovery file byte limit exceeded");
39204
39455
  consume(budget, bytes);
39205
- return createHash9("sha256").update(text2).digest("hex");
39456
+ return createHash10("sha256").update(text2).digest("hex");
39206
39457
  }
39207
39458
  const initial = lstatSync11(path, { throwIfNoEntry: false });
39208
39459
  if (!initial)
@@ -39216,7 +39467,7 @@ function hashRawDiscoveryFile(path, budget, changes) {
39216
39467
  const opened = fstatSync11(fd);
39217
39468
  if (!opened.isFile() || !same2(initial, opened))
39218
39469
  throw new Error("Raw discovery input changed during open");
39219
- const hash2 = createHash9("sha256"), buffer = Buffer.alloc(64 * 1024);
39470
+ const hash2 = createHash10("sha256"), buffer = Buffer.alloc(64 * 1024);
39220
39471
  let bytes = 0;
39221
39472
  while (true) {
39222
39473
  const count = readSync6(fd, buffer, 0, Math.min(buffer.length, AGENT_POLICY_LIMITS.discoveryRawSourceBytes - bytes + 1), null);
@@ -39239,7 +39490,7 @@ function hashRawDiscoveryFile(path, budget, changes) {
39239
39490
  }
39240
39491
 
39241
39492
  // src/lib/agent-discovery-path-bytes.ts
39242
- import { createHash as createHash10 } from "crypto";
39493
+ import { createHash as createHash11 } from "crypto";
39243
39494
  import { lstatSync as lstatSync12, readlinkSync as readlinkSync3 } from "fs";
39244
39495
  import { dirname as dirname9, isAbsolute as isAbsolute10, join as join15, parse as parse3, resolve as resolve9, sep as sep3 } from "path";
39245
39496
  function identity3(stat, mutable = false) {
@@ -39252,12 +39503,12 @@ function identity3(stat, mutable = false) {
39252
39503
  ...mutable ? { size: String(stat.size), mtimeNs: String(stat.mtimeNs), ctimeNs: String(stat.ctimeNs) } : {}
39253
39504
  };
39254
39505
  }
39255
- function canonical3(path) {
39506
+ function canonical4(path) {
39256
39507
  if (typeof path !== "string" || !isAbsolute10(path) || path !== resolve9(path) || path.length > AGENT_POLICY_LIMITS.pathCharacters || path.includes("\x00") || Buffer.from(path).toString("utf8") !== path)
39257
39508
  throw new Error("Expected a canonical absolute discovery path");
39258
39509
  }
39259
39510
  function trace(path) {
39260
- canonical3(path);
39511
+ canonical4(path);
39261
39512
  const rows = [], paths = [];
39262
39513
  let metadataBytes = 0, steps = 0, links = 0, cursor = parse3(path).root, pending = path.slice(cursor.length).split(sep3);
39263
39514
  function record3(path2, row) {
@@ -39349,7 +39600,7 @@ function hashDiscoveryPathFile(path, budget, changes) {
39349
39600
  const after = trace(path);
39350
39601
  if (JSON.stringify(before.rows) !== JSON.stringify(after.rows) || before.file !== after.file)
39351
39602
  throw new Error("Discovery path input changed during read");
39352
- return createHash10("sha256").update(JSON.stringify({ version: 1, path, rows: before.rows, content })).digest("hex");
39603
+ return createHash11("sha256").update(JSON.stringify({ version: 1, path, rows: before.rows, content })).digest("hex");
39353
39604
  }
39354
39605
 
39355
39606
  // src/lib/plugin-discovery.ts
@@ -39361,7 +39612,7 @@ import { homedir as homedir2 } from "os";
39361
39612
  import { isAbsolute as isAbsolute13, join as join19, resolve as resolve11 } from "path";
39362
39613
 
39363
39614
  // src/lib/plugin-projection.ts
39364
- import { createHash as createHash11 } from "crypto";
39615
+ import { createHash as createHash12 } from "crypto";
39365
39616
  import { posix as posix2 } from "path";
39366
39617
  var PLUGIN_PROJECTION_MANIFEST = "plugin-projection.json";
39367
39618
  var PLUGIN_PROJECTION_LIMITS = Object.freeze({ files: 1024, bytes: 64 * 1024 * 1024, fileBytes: 16 * 1024 * 1024, metadataBytes: 512 * 1024, registrations: 64, history: 128 });
@@ -39372,7 +39623,7 @@ function pluginNeed(value, message) {
39372
39623
  if (!value)
39373
39624
  pluginRefusal(message);
39374
39625
  }
39375
- var pluginHash = (bytes) => createHash11("sha256").update(bytes).digest("hex");
39626
+ var pluginHash = (bytes) => createHash12("sha256").update(bytes).digest("hex");
39376
39627
  function pluginObject(value) {
39377
39628
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
39378
39629
  }
@@ -39560,7 +39811,7 @@ function buildPluginProjection(entries) {
39560
39811
  }
39561
39812
 
39562
39813
  // src/lib/plugin-projection-store.ts
39563
- import { createHash as createHash12, randomUUID as randomUUID2 } from "crypto";
39814
+ import { createHash as createHash13, randomUUID as randomUUID2 } from "crypto";
39564
39815
  import { constants as constants8, closeSync as closeSync12, fchmodSync, fstatSync as fstatSync12, fsyncSync as fsyncSync2, linkSync, lstatSync as lstatSync13, mkdirSync as mkdirSync4, openSync as openSync12, opendirSync as opendirSync3, readSync as readSync7, renameSync as renameSync2, rmdirSync as rmdirSync2, rmSync, unlinkSync as unlinkSync3, writeSync as writeSync2 } from "fs";
39565
39816
  import { dirname as dirname10, isAbsolute as isAbsolute11, join as join16, parse as parse5, resolve as resolve10 } from "path";
39566
39817
  var READ_FLAGS = constants8.O_RDONLY | constants8.O_NOFOLLOW | constants8.O_NONBLOCK;
@@ -39576,7 +39827,7 @@ function stat(path) {
39576
39827
  return pluginRefusal("Cannot inspect plugin filesystem entry");
39577
39828
  }
39578
39829
  }
39579
- function canonical4(path) {
39830
+ function canonical5(path) {
39580
39831
  pluginNeed(typeof path === "string" && path.length <= 8192 && isAbsolute11(path) && resolve10(path) === path && !/[\x00-\x1f\x7f]/.test(path), "Plugin storage paths must be canonical absolute paths");
39581
39832
  }
39582
39833
  function owner(stats, system = false) {
@@ -39587,7 +39838,7 @@ function same3(left, right, identityOnly = false) {
39587
39838
  pluginNeed(right && left.dev === right.dev && left.ino === right.ino && left.mode === right.mode && left.uid === right.uid && left.gid === right.gid && (identityOnly || left.size === right.size && left.nlink === right.nlink && left.mtimeNs === right.mtimeNs && left.ctimeNs === right.ctimeNs), "Plugin filesystem entry changed during access");
39588
39839
  }
39589
39840
  function ancestors(path, create = false) {
39590
- canonical4(path);
39841
+ canonical5(path);
39591
39842
  const result = [], parent = dirname10(path), filesystemRoot = parse5(parent).root;
39592
39843
  let current = filesystemRoot;
39593
39844
  for (const segment of ["", ...parent.slice(filesystemRoot.length).split("/").filter(Boolean)]) {
@@ -39902,7 +40153,7 @@ function pluginExecutableDigest(path) {
39902
40153
  const opened = fstatSync12(fd, { bigint: true });
39903
40154
  same3(before, opened);
39904
40155
  fileShape(opened, maximum, "executable");
39905
- const hash2 = createHash12("sha256"), buffer = new Uint8Array(64 * 1024);
40156
+ const hash2 = createHash13("sha256"), buffer = new Uint8Array(64 * 1024);
39906
40157
  let remaining = Number(opened.size);
39907
40158
  while (remaining > 0) {
39908
40159
  const count = readSync7(fd, buffer, 0, Math.min(buffer.byteLength, remaining), null);
@@ -39927,7 +40178,7 @@ function pluginExecutableDigest(path) {
39927
40178
 
39928
40179
  // src/lib/skill-validation.ts
39929
40180
  import { existsSync as existsSync5, lstatSync as lstatSync14, readFileSync as readFileSync12, readdirSync as readdirSync6, statSync as statSync5 } from "fs";
39930
- import { isAbsolute as isAbsolute12, join as join18, normalize as normalize2 } from "path";
40181
+ import { isAbsolute as isAbsolute12, join as join18, normalize as normalize3 } from "path";
39931
40182
 
39932
40183
  // src/lib/hosted-skill-set.ts
39933
40184
  import { existsSync as existsSync4, readFileSync as readFileSync11, readdirSync as readdirSync5, statSync as statSync4 } from "fs";
@@ -40033,7 +40284,7 @@ function sortMessages(messages) {
40033
40284
  function isSafeRelativePath(value) {
40034
40285
  if (!value.trim() || isAbsolute12(value))
40035
40286
  return false;
40036
- const normalized = normalize2(value).replace(/\\/g, "/");
40287
+ const normalized = normalize3(value).replace(/\\/g, "/");
40037
40288
  return normalized !== ".." && !normalized.startsWith("../") && !normalized.includes("/../");
40038
40289
  }
40039
40290
  function validateRuntimeEntry(skillPath, entrypoint, issues, warnings) {
@@ -40897,23 +41148,23 @@ function captureManagedPluginRegistry(path, managedPlugins) {
40897
41148
  }
40898
41149
 
40899
41150
  // src/lib/claude-marketplace-registry.ts
40900
- import { createHash as createHash13 } from "crypto";
41151
+ import { createHash as createHash14 } from "crypto";
40901
41152
  import { closeSync as closeSync14, constants as constants10, fstatSync as fstatSync14, lstatSync as lstatSync16, openSync as openSync14, readSync as readSync9 } from "fs";
40902
41153
  import { basename as basename6, dirname as dirname12, isAbsolute as isAbsolute15, resolve as resolve13 } from "path";
40903
41154
  var CLAUDE_MARKETPLACE_REGISTRY_LIMITS = Object.freeze({ bytes: 1024 * 1024, rows: 1024, depth: 32, nodes: 65536, stringCharacters: 16384, pathCharacters: 4096 });
40904
- function need4(value, reason) {
41155
+ function need5(value, reason) {
40905
41156
  if (!value)
40906
41157
  throw new Error(`Claude marketplace registry ${reason}`);
40907
41158
  }
40908
41159
  function absolutePath3(value) {
40909
- need4(typeof value === "string" && value.length > 0 && value.length <= CLAUDE_MARKETPLACE_REGISTRY_LIMITS.pathCharacters && !/[\x00-\x1f\x7f]/.test(value) && isAbsolute15(value) && resolve13(value) === value, "requires a normalized absolute path");
41160
+ need5(typeof value === "string" && value.length > 0 && value.length <= CLAUDE_MARKETPLACE_REGISTRY_LIMITS.pathCharacters && !/[\x00-\x1f\x7f]/.test(value) && isAbsolute15(value) && resolve13(value) === value, "requires a normalized absolute path");
40910
41161
  }
40911
41162
  var sameFile2 = (a, b) => a.dev === b.dev && a.ino === b.ino && a.mode === b.mode && a.uid === b.uid && a.gid === b.gid && a.nlink === b.nlink && a.size === b.size && a.mtimeNs === b.mtimeNs && a.ctimeNs === b.ctimeNs;
40912
41163
  function parents2(path) {
40913
41164
  const result = [];
40914
41165
  for (let at = dirname12(path);; at = dirname12(at)) {
40915
41166
  const stat2 = lstatSync16(at, { bigint: true });
40916
- need4(stat2.isDirectory() && !stat2.isSymbolicLink(), "path traverses a symlink or non-directory");
41167
+ need5(stat2.isDirectory() && !stat2.isSymbolicLink(), "path traverses a symlink or non-directory");
40917
41168
  result.push([at, stat2]);
40918
41169
  if (at === dirname12(at))
40919
41170
  return result;
@@ -40921,15 +41172,15 @@ function parents2(path) {
40921
41172
  }
40922
41173
  function readRegistry2(path, budget) {
40923
41174
  absolutePath3(path);
40924
- need4(basename6(path) === "known_marketplaces.json", "requires known_marketplaces.json");
40925
- need4(Number.isSafeInteger(budget.remaining) && budget.remaining >= 0, "has an invalid byte budget");
41175
+ need5(basename6(path) === "known_marketplaces.json", "requires known_marketplaces.json");
41176
+ need5(Number.isSafeInteger(budget.remaining) && budget.remaining >= 0, "has an invalid byte budget");
40926
41177
  const ancestors2 = parents2(path), initial = lstatSync16(path, { bigint: true });
40927
- need4(initial.isFile() && !initial.isSymbolicLink() && initial.size <= BigInt(CLAUDE_MARKETPLACE_REGISTRY_LIMITS.bytes), "is not a bounded regular file");
40928
- need4(initial.size <= BigInt(budget.remaining), "exceeds its aggregate byte limit");
41178
+ need5(initial.isFile() && !initial.isSymbolicLink() && initial.size <= BigInt(CLAUDE_MARKETPLACE_REGISTRY_LIMITS.bytes), "is not a bounded regular file");
41179
+ need5(initial.size <= BigInt(budget.remaining), "exceeds its aggregate byte limit");
40929
41180
  const fd = openSync14(path, constants10.O_RDONLY | constants10.O_NOFOLLOW | constants10.O_NONBLOCK);
40930
41181
  try {
40931
41182
  const opened = fstatSync14(fd, { bigint: true });
40932
- need4(opened.isFile() && sameFile2(initial, opened), "changed during open");
41183
+ need5(opened.isFile() && sameFile2(initial, opened), "changed during open");
40933
41184
  const bytes = Buffer.alloc(Number(opened.size) + 1);
40934
41185
  let length = 0;
40935
41186
  while (length < bytes.length) {
@@ -40939,10 +41190,10 @@ function readRegistry2(path, budget) {
40939
41190
  length += count;
40940
41191
  }
40941
41192
  const after = fstatSync14(fd, { bigint: true }), current = lstatSync16(path, { bigint: true });
40942
- need4(current.isFile() && sameFile2(opened, after) && sameFile2(after, current) && BigInt(length) === opened.size, "changed during read");
41193
+ need5(current.isFile() && sameFile2(opened, after) && sameFile2(after, current) && BigInt(length) === opened.size, "changed during read");
40943
41194
  for (const [ancestor, before] of ancestors2) {
40944
41195
  const now = lstatSync16(ancestor, { bigint: true });
40945
- need4(now.isDirectory() && before.dev === now.dev && before.ino === now.ino && before.mode === now.mode, "parent changed during read");
41196
+ need5(now.isDirectory() && before.dev === now.dev && before.ino === now.ino && before.mode === now.mode, "parent changed during read");
40946
41197
  }
40947
41198
  budget.remaining -= length;
40948
41199
  try {
@@ -40962,7 +41213,7 @@ function parse6(text2) {
40962
41213
  at++;
40963
41214
  };
40964
41215
  function string() {
40965
- need4(text2[at] === '"', "contains invalid JSON");
41216
+ need5(text2[at] === '"', "contains invalid JSON");
40966
41217
  const start = at++;
40967
41218
  while (at < text2.length) {
40968
41219
  const character = text2[at++];
@@ -40973,7 +41224,7 @@ function parse6(text2) {
40973
41224
  } catch {
40974
41225
  throw new Error("Claude marketplace registry contains invalid JSON string");
40975
41226
  }
40976
- need4(value2.length <= CLAUDE_MARKETPLACE_REGISTRY_LIMITS.stringCharacters, "exceeds its string limit");
41227
+ need5(value2.length <= CLAUDE_MARKETPLACE_REGISTRY_LIMITS.stringCharacters, "exceeds its string limit");
40977
41228
  return value2;
40978
41229
  }
40979
41230
  if (character === "\\")
@@ -40982,7 +41233,7 @@ function parse6(text2) {
40982
41233
  throw new Error("Claude marketplace registry contains an unterminated JSON string");
40983
41234
  }
40984
41235
  function value(depth) {
40985
- need4(depth <= CLAUDE_MARKETPLACE_REGISTRY_LIMITS.depth && ++nodes <= CLAUDE_MARKETPLACE_REGISTRY_LIMITS.nodes, "exceeds its nesting or node limit");
41236
+ need5(depth <= CLAUDE_MARKETPLACE_REGISTRY_LIMITS.depth && ++nodes <= CLAUDE_MARKETPLACE_REGISTRY_LIMITS.nodes, "exceeds its nesting or node limit");
40986
41237
  space();
40987
41238
  const character = text2[at];
40988
41239
  if (character === '"')
@@ -40996,17 +41247,17 @@ function parse6(text2) {
40996
41247
  if (object5) {
40997
41248
  space();
40998
41249
  const key = string();
40999
- need4(!keys2.has(key), "contains a duplicate JSON key");
41250
+ need5(!keys2.has(key), "contains a duplicate JSON key");
41000
41251
  keys2.add(key);
41001
41252
  space();
41002
- need4(text2[at++] === ":", "contains invalid JSON");
41253
+ need5(text2[at++] === ":", "contains invalid JSON");
41003
41254
  entries.push([key, value(depth + 1)]);
41004
41255
  } else
41005
41256
  items.push(value(depth + 1));
41006
41257
  space();
41007
41258
  if (text2[at] === end)
41008
41259
  break;
41009
- need4(text2[at++] === ",", "contains invalid JSON");
41260
+ need5(text2[at++] === ",", "contains invalid JSON");
41010
41261
  }
41011
41262
  at++;
41012
41263
  return object5 ? { kind: "object", entries } : { kind: "array", items };
@@ -41018,14 +41269,14 @@ function parse6(text2) {
41018
41269
  }
41019
41270
  numberPattern.lastIndex = at;
41020
41271
  const number = numberPattern.exec(text2);
41021
- need4(number, "contains invalid JSON");
41272
+ need5(number, "contains invalid JSON");
41022
41273
  at += number[0].length;
41023
41274
  return { kind: "number", value: number[0] };
41024
41275
  }
41025
41276
  const root2 = value(0);
41026
41277
  space();
41027
- need4(at === text2.length && root2.kind === "object", "requires a JSON object without trailing content");
41028
- need4(root2.entries.length <= CLAUDE_MARKETPLACE_REGISTRY_LIMITS.rows, "exceeds its marketplace row limit");
41278
+ need5(at === text2.length && root2.kind === "object", "requires a JSON object without trailing content");
41279
+ need5(root2.entries.length <= CLAUDE_MARKETPLACE_REGISTRY_LIMITS.rows, "exceeds its marketplace row limit");
41029
41280
  return root2;
41030
41281
  }
41031
41282
  function exactKeys2(value, keys2) {
@@ -41033,7 +41284,7 @@ function exactKeys2(value, keys2) {
41033
41284
  }
41034
41285
  var field = (object5, key) => object5.entries.find(([name]) => name === key)?.[1];
41035
41286
  function textField(value) {
41036
- need4(value?.kind === "string" && value.value.length > 0 && !/[\x00-\x1f\x7f]/.test(value.value), "contains an invalid recognized field");
41287
+ need5(value?.kind === "string" && value.value.length > 0 && !/[\x00-\x1f\x7f]/.test(value.value), "contains an invalid recognized field");
41037
41288
  return value.value;
41038
41289
  }
41039
41290
  function normalizeRow(row, version = 1) {
@@ -41041,7 +41292,7 @@ function normalizeRow(row, version = 1) {
41041
41292
  if (version !== 2 || !exactKeys2(row, ["source", "installLocation", "lastUpdated", "autoUpdate"]))
41042
41293
  return;
41043
41294
  const autoUpdate = field(row, "autoUpdate");
41044
- need4(autoUpdate?.kind === "literal" && (autoUpdate.value === "true" || autoUpdate.value === "false"), "contains an invalid automatic-update preference");
41295
+ need5(autoUpdate?.kind === "literal" && (autoUpdate.value === "true" || autoUpdate.value === "false"), "contains an invalid automatic-update preference");
41045
41296
  }
41046
41297
  const source = field(row, "source");
41047
41298
  if (source?.kind !== "object")
@@ -41057,34 +41308,34 @@ function normalizeRow(row, version = 1) {
41057
41308
  absolutePath3(sourceLocation);
41058
41309
  absolutePath3(textField(field(row, "installLocation")));
41059
41310
  const updated = textField(field(row, "lastUpdated"));
41060
- need4(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/.test(updated), "contains an invalid recognized update timestamp");
41311
+ need5(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/.test(updated), "contains an invalid recognized update timestamp");
41061
41312
  const millis = Date.parse(updated);
41062
- need4(Number.isFinite(millis) && new Date(millis).toISOString() === updated, "contains an invalid recognized update timestamp");
41313
+ need5(Number.isFinite(millis) && new Date(millis).toISOString() === updated, "contains an invalid recognized update timestamp");
41063
41314
  row.entries = row.entries.map(([key, value]) => [key, key === "lastUpdated" ? { kind: "validated-update-time" } : value]);
41064
41315
  }
41065
41316
  function captureClaudeMarketplaceRegistry(path, budget = { remaining: 256 * 1024 * 1024 }) {
41066
41317
  const value = parse6(readRegistry2(path, budget));
41067
41318
  for (const [, row] of value.entries)
41068
41319
  normalizeRow(row);
41069
- const sha2562 = createHash13("sha256").update("hasna.skills.claude-marketplace-registry.v1\x00").update(JSON.stringify(value)).digest("hex");
41320
+ const sha2562 = createHash14("sha256").update("hasna.skills.claude-marketplace-registry.v1\x00").update(JSON.stringify(value)).digest("hex");
41070
41321
  return { path, hashMode: "claude-marketplace-registry", sha256: sha2562 };
41071
41322
  }
41072
41323
  function captureClaudeMarketplaceRegistryV2(path, budget = { remaining: 256 * 1024 * 1024 }) {
41073
41324
  const value = parse6(readRegistry2(path, budget));
41074
41325
  for (const [, row] of value.entries)
41075
41326
  normalizeRow(row, 2);
41076
- const sha2562 = createHash13("sha256").update("hasna.skills.claude-marketplace-registry.v2\x00").update(JSON.stringify(value)).digest("hex");
41327
+ const sha2562 = createHash14("sha256").update("hasna.skills.claude-marketplace-registry.v2\x00").update(JSON.stringify(value)).digest("hex");
41077
41328
  return { path, hashMode: "claude-marketplace-registry-v2", sha256: sha2562 };
41078
41329
  }
41079
41330
 
41080
41331
  // src/lib/codex-hook-discovery-recovery.ts
41081
- import { createHash as createHash15 } from "crypto";
41332
+ import { createHash as createHash16 } from "crypto";
41082
41333
 
41083
41334
  // src/lib/codex-hook-trust-files.ts
41084
41335
  import { closeSync as closeSync15, constants as constants11, fstatSync as fstatSync15, fsyncSync as fsyncSync3, lstatSync as lstatSync17, openSync as openSync15, readSync as readSync10, writeFileSync as writeFileSync3 } from "fs";
41085
- import { createHash as createHash14 } from "crypto";
41336
+ import { createHash as createHash15 } from "crypto";
41086
41337
  import { dirname as dirname13 } from "path";
41087
- function need5(value, code) {
41338
+ function need6(value, code) {
41088
41339
  if (!value)
41089
41340
  throw new Error(`CODEX_HOOK_TRUST_${code}`);
41090
41341
  }
@@ -41092,8 +41343,8 @@ var sameStat = (a, b) => ["dev", "ino", "uid", "nlink", "mode", "size", "mtimeNs
41092
41343
  function safeParents(file) {
41093
41344
  for (let p = dirname13(file);; p = dirname13(p)) {
41094
41345
  const s = lstatSync17(p);
41095
- need5(s.isDirectory() && !s.isSymbolicLink(), "UNSAFE_PARENT");
41096
- need5((s.mode & 18) === 0 || s.uid === 0 && (s.mode & 512) !== 0, "UNSAFE_PARENT");
41346
+ need6(s.isDirectory() && !s.isSymbolicLink(), "UNSAFE_PARENT");
41347
+ need6((s.mode & 18) === 0 || s.uid === 0 && (s.mode & 512) !== 0, "UNSAFE_PARENT");
41097
41348
  if (dirname13(p) === p)
41098
41349
  break;
41099
41350
  }
@@ -41102,12 +41353,12 @@ function snapshot(file, privateFile = false, options = {}) {
41102
41353
  const readOnlyPackage = options.readOnlyPackage === true && !privateFile;
41103
41354
  safeParents(file);
41104
41355
  const initial = lstatSync17(file, { bigint: true });
41105
- need5(initial.isFile() && initial.uid === BigInt(process.getuid()) && (initial.nlink === 1n || readOnlyPackage && initial.nlink > 1n) && (initial.mode & 0o022n) === 0n && (!privateFile || (initial.mode & 0o777n) === 0o600n), "UNSAFE_FILE");
41106
- need5(initial.size <= 8n * 1024n * 1024n, "FILE_BOUND");
41356
+ need6(initial.isFile() && initial.uid === BigInt(process.getuid()) && (initial.nlink === 1n || readOnlyPackage && initial.nlink > 1n) && (initial.mode & 0o022n) === 0n && (!privateFile || (initial.mode & 0o777n) === 0o600n), "UNSAFE_FILE");
41357
+ need6(initial.size <= 8n * 1024n * 1024n, "FILE_BOUND");
41107
41358
  const fd = openSync15(file, constants11.O_RDONLY | constants11.O_NOFOLLOW | constants11.O_NONBLOCK);
41108
41359
  try {
41109
41360
  const before = fstatSync15(fd, { bigint: true });
41110
- need5(sameStat(initial, before), "INPUT_CHANGED");
41361
+ need6(sameStat(initial, before), "INPUT_CHANGED");
41111
41362
  const bytes = Buffer.alloc(Number(before.size) + 1);
41112
41363
  let length = 0;
41113
41364
  while (length < bytes.length) {
@@ -41116,16 +41367,16 @@ function snapshot(file, privateFile = false, options = {}) {
41116
41367
  break;
41117
41368
  length += n2;
41118
41369
  }
41119
- need5(length === Number(before.size) && sameStat(before, fstatSync15(fd, { bigint: true })) && sameStat(before, lstatSync17(file, { bigint: true })), "INPUT_CHANGED");
41370
+ need6(length === Number(before.size) && sameStat(before, fstatSync15(fd, { bigint: true })) && sameStat(before, lstatSync17(file, { bigint: true })), "INPUT_CHANGED");
41120
41371
  const content = bytes.subarray(0, length), text2 = new TextDecoder("utf-8", { fatal: true }).decode(content);
41121
- return { file, privateFile, readOnlyPackage, text: text2, bytes: content, stat: before, sha256: createHash14("sha256").update(content).digest("hex") };
41372
+ return { file, privateFile, readOnlyPackage, text: text2, bytes: content, stat: before, sha256: createHash15("sha256").update(content).digest("hex") };
41122
41373
  } finally {
41123
41374
  closeSync15(fd);
41124
41375
  }
41125
41376
  }
41126
41377
  function unchanged2(before) {
41127
41378
  const after = snapshot(before.file, before.privateFile, before.readOnlyPackage ? { readOnlyPackage: true } : {});
41128
- need5(sameStat(before.stat, after.stat) && after.sha256 === before.sha256, "INPUT_CHANGED");
41379
+ need6(sameStat(before.stat, after.stat) && after.sha256 === before.sha256, "INPUT_CHANGED");
41129
41380
  }
41130
41381
 
41131
41382
  // src/lib/codex-hook-additions-review.ts
@@ -41134,11 +41385,12 @@ var matchedEvents = { ...events, PreToolUse: ["preToolUse", "pre_tool_use"] };
41134
41385
  var proofs = new WeakMap;
41135
41386
 
41136
41387
  // src/lib/codex-hook-discovery-recovery.ts
41137
- var sha2 = (text2) => createHash15("sha256").update(text2).digest("hex");
41388
+ var sha3 = (text2) => createHash16("sha256").update(text2).digest("hex");
41389
+ var fields = [...CODEX_DISCOVERY_PROJECTION_FIELDS];
41138
41390
  var proofs2 = new WeakMap;
41139
41391
  function assertCodexHookDiscoveryRecovery(binding, witness) {
41140
41392
  const proof = proofs2.get(witness);
41141
- need5(!!proof && binding.agent === "codex" && witness.discoverySha256 === sha2(JSON.stringify(binding)), "RECONCILE_DISCOVERY_RECOVERY_CHANGED");
41393
+ need6(!!proof && binding.agent === "codex" && witness.discoverySha256 === sha3(JSON.stringify(binding)), "RECONCILE_DISCOVERY_RECOVERY_CHANGED");
41142
41394
  unchanged2(proof.before);
41143
41395
  unchanged2(proof.current);
41144
41396
  proof.recheckAdditions();
@@ -41147,12 +41399,12 @@ function verifiesCodexHookDiscoverySource(binding, source, currentDigest, witnes
41147
41399
  if (!witness || source.path !== witness.configPath || source.hashMode !== "bytes")
41148
41400
  return false;
41149
41401
  assertCodexHookDiscoveryRecovery(binding, witness);
41150
- need5(source.sha256 === witness.beforeSha256 && currentDigest === witness.currentSha256, "RECONCILE_DISCOVERY_RECOVERY_CHANGED");
41402
+ need6(source.sha256 === witness.beforeSha256 && currentDigest === witness.currentSha256, "RECONCILE_DISCOVERY_RECOVERY_CHANGED");
41151
41403
  return true;
41152
41404
  }
41153
41405
 
41154
41406
  // src/lib/agent-discovery.ts
41155
- var digest2 = (text2) => createHash16("sha256").update(text2).digest("hex");
41407
+ var digest2 = (text2) => createHash17("sha256").update(text2).digest("hex");
41156
41408
  function parseConfig(text2, path, toml = false) {
41157
41409
  try {
41158
41410
  const value = toml ? Bun.TOML.parse(text2) : JSON.parse(text2);
@@ -41184,14 +41436,26 @@ function read2(path, changes) {
41184
41436
  throw new Error(`Unsupported or oversized native discovery input: ${path}`);
41185
41437
  return readFileSync13(path, "utf8");
41186
41438
  }
41439
+ function projectNativeDiscoveryFields(text2, format, fields2, path) {
41440
+ const object5 = format === "yaml" ? parseHermesConfig(text2) : parseConfig(text2, path, format === "toml");
41441
+ if (!object5 || typeof object5 !== "object" || Array.isArray(object5))
41442
+ throw new Error("Expected native discovery configuration object");
41443
+ return digest2(JSON.stringify(Object.fromEntries(fields2.map((field2) => [field2, object5[field2] ?? null]))));
41444
+ }
41445
+ function isSupersededCodexProjection(agent, configPath, source) {
41446
+ return agent === "codex" && source.path === configPath && source.format === "toml" && isDeepStrictEqual3(source.fields, [...CODEX_DISCOVERY_PROJECTION_FIELDS]);
41447
+ }
41448
+ function supersedesCodexProjection(sources, configPath) {
41449
+ return sources.some((source) => source.path === configPath && source.hashMode === "codex-settings-v2");
41450
+ }
41187
41451
  function projected(source, changes, budget = discoveryByteBudget()) {
41188
- if (source.hashMode === "codex-settings-v1") {
41452
+ if (source.hashMode === "codex-settings-v1" || source.hashMode === "codex-settings-v2") {
41189
41453
  if (source.format !== undefined || source.fields !== undefined || source.managedPlugins !== undefined || typeof source.sha256 !== "string" || !/^[a-f0-9]{64}$/.test(source.sha256))
41190
41454
  throw new Error("Codex settings witnesses require exact typed metadata");
41191
- const current = captureCodexSettings(source.path, budget).sha256;
41455
+ const current = (source.hashMode === "codex-settings-v2" ? captureCodexSettingsV2 : captureCodexSettings)(source.path, budget).sha256;
41192
41456
  if (current !== source.sha256)
41193
41457
  throw new Error(`Native discovery input changed; run skills hook install with a fresh discovery review: ${source.path}`);
41194
- return changes?.has(source.path) ? hashCodexSettingsReplacement(changes.get(source.path), budget) : current;
41458
+ return changes?.has(source.path) ? (source.hashMode === "codex-settings-v2" ? hashCodexSettingsReplacementV2 : hashCodexSettingsReplacement)(changes.get(source.path), budget) : current;
41195
41459
  }
41196
41460
  if (source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || source.hashMode === "claude-settings-v3") {
41197
41461
  if (source.format !== undefined || source.fields !== undefined || source.managedPlugins !== undefined || typeof source.sha256 !== "string" || !/^[a-f0-9]{64}$/.test(source.sha256))
@@ -41230,10 +41494,7 @@ function projected(source, changes, budget = discoveryByteBudget()) {
41230
41494
  return null;
41231
41495
  if (!source.format)
41232
41496
  return digest2(text2);
41233
- const object5 = source.format === "yaml" ? parseHermesConfig(text2) : parseConfig(text2, source.path, source.format === "toml");
41234
- if (!object5 || typeof object5 !== "object" || Array.isArray(object5))
41235
- throw new Error("Expected native discovery configuration object");
41236
- return digest2(JSON.stringify(Object.fromEntries((source.fields ?? []).map((field2) => [field2, object5[field2] ?? null]))));
41497
+ return projectNativeDiscoveryFields(text2, source.format, source.fields ?? [], source.path);
41237
41498
  }
41238
41499
  function verifyAgentDiscovery(binding, codexRecovery) {
41239
41500
  if (codexRecovery)
@@ -41261,7 +41522,7 @@ function verifyAgentDiscovery(binding, codexRecovery) {
41261
41522
  safe4(root2);
41262
41523
  }
41263
41524
  function assertMarketplaceBinding(binding, source) {
41264
- if (source.hashMode === "codex-settings-v1" && (binding.agent !== "codex" || binding.method !== "reviewed" || basename7(source.path) !== "config.toml"))
41525
+ if ((source.hashMode === "codex-settings-v1" || source.hashMode === "codex-settings-v2") && (binding.agent !== "codex" || binding.method !== "reviewed" || basename7(source.path) !== "config.toml"))
41265
41526
  throw new Error("Codex settings witnesses require explicit reviewed Codex configuration");
41266
41527
  if ((source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || source.hashMode === "claude-settings-v3") && (binding.agent !== "claude" || binding.method !== "reviewed" || basename7(source.path) !== "settings.json"))
41267
41528
  throw new Error("Claude settings witnesses require explicit reviewed Claude configuration");
@@ -41290,8 +41551,8 @@ function captureDiscoveryPathSources(paths) {
41290
41551
  const budget = discoveryByteBudget();
41291
41552
  return paths.map((path) => ({ path, hashMode: "path-bytes", sha256: hashDiscoveryPathFile(path, budget) }));
41292
41553
  }
41293
- function assertProjectDiscovery(agent, directories, home, canonical5 = resolve14, reviewed) {
41294
- const homeConfigPath = canonical5(agentDiscoveryConfigPath(home, agent));
41554
+ function assertProjectDiscovery(agent, directories, home, canonical6 = resolve14, reviewed) {
41555
+ const homeConfigPath = canonical6(agentDiscoveryConfigPath(home, agent));
41295
41556
  for (const directory of directories) {
41296
41557
  const isHome = resolve14(directory) === resolve14(home);
41297
41558
  if (agent === "hermes") {
@@ -41302,7 +41563,7 @@ function assertProjectDiscovery(agent, directories, home, canonical5 = resolve14
41302
41563
  continue;
41303
41564
  const paths = agent === "claude" ? [...isHome ? [] : [".claude/settings.json"], ".claude/settings.local.json"] : agent === "codex" ? [".codex/config.toml"] : agent === "gemini" ? [".gemini/settings.json"] : agent === "opencode" ? ["opencode.json", "opencode.jsonc", ".opencode/opencode.json", ".opencode/opencode.jsonc"] : [".cursor/hooks.json"];
41304
41565
  for (const suffix of paths) {
41305
- const path = canonical5(join21(directory, suffix)), raw = read2(path);
41566
+ const path = canonical6(join21(directory, suffix)), raw = read2(path);
41306
41567
  if (raw === null)
41307
41568
  continue;
41308
41569
  const isRootAliasedHomeConfig = agent === "claude" && suffix === ".claude/settings.json" || agent === "codex" && suffix === ".codex/config.toml";
@@ -41318,14 +41579,14 @@ function assertProjectDiscovery(agent, directories, home, canonical5 = resolve14
41318
41579
  const managed = reviewed.sources.flatMap((source) => source.hashMode === "claude-plugin-registry" ? source.managedPlugins ?? [] : []);
41319
41580
  if (exact && projected(exact) === exact.sha256 && managed.length) {
41320
41581
  const bindings = managed.map((item) => readPluginBinding(item.storeRoot, item.bindingId));
41321
- admittedPlugins = Object.entries(config.enabledPlugins).every(([id2, enabled]) => typeof enabled === "boolean" && bindings.some((binding) => binding.target.pluginId === id2 && binding.target.registrations.some((scope) => scope.scope === "project" && scope.projectPath === canonical5(directory))));
41582
+ admittedPlugins = Object.entries(config.enabledPlugins).every(([id2, enabled]) => typeof enabled === "boolean" && bindings.some((binding) => binding.target.pluginId === id2 && binding.target.registrations.some((scope) => scope.scope === "project" && scope.projectPath === canonical6(directory))));
41322
41583
  }
41323
41584
  }
41324
41585
  if (keys2.some((key) => config[key] !== undefined && !(key === "enabledPlugins" && admittedPlugins)) || config.disableAllHooks === true || config.disableBundledSkills === false || config.hooksConfig?.enabled === false || config.permission?.skill !== undefined || config.permissions?.deny?.some((rule) => typeof rule === "string" && /^Skill(?:\(|$)/.test(rule)))
41325
41586
  throw new Error(`NATIVE_SKILL_DRIFT: higher-precedence project skill or hook configuration requires review: ${path}`);
41326
41587
  }
41327
41588
  if (agent === "claude") {
41328
- const commands = canonical5(join21(directory, ".claude/commands"));
41589
+ const commands = canonical6(join21(directory, ".claude/commands"));
41329
41590
  safe4(commands);
41330
41591
  if (lstatSync18(commands, { throwIfNoEntry: false })?.isDirectory() && readdirSync7(commands).length)
41331
41592
  throw new Error("NATIVE_SKILL_DRIFT: legacy project command discovery requires a dedicated format adapter");
@@ -41336,10 +41597,10 @@ function agentDiscoveryConfigPath(home, agent) {
41336
41597
  return join21(home, agent === "hermes" ? ".hermes/config.yaml" : agent === "opencode" ? ".config/opencode/opencode.json" : `.${agent}/${agent === "codex" ? "config.toml" : agent === "cursor" ? "hooks.json" : "settings.json"}`);
41337
41598
  }
41338
41599
  function resolveAgentDiscovery(options) {
41339
- const canonical5 = options.canonical ?? resolve14, home = resolve14(options.home), agent = options.agent;
41600
+ const canonical6 = options.canonical ?? resolve14, home = resolve14(options.home), agent = options.agent;
41340
41601
  const sources = [], roots = new Set, builtinNames = [];
41341
- const witness = (path, format, fields) => {
41342
- const source = { path: canonical5(path), sha256: null, ...format ? { format, fields } : {} };
41602
+ const witness = (path, format, fields2) => {
41603
+ const source = { path: canonical6(path), sha256: null, ...format ? { format, fields: fields2 } : {} };
41343
41604
  source.sha256 = projected(source);
41344
41605
  sources.push(source);
41345
41606
  return read2(source.path);
@@ -41347,7 +41608,7 @@ function resolveAgentDiscovery(options) {
41347
41608
  if (agent === "hermes")
41348
41609
  assertHermesEnvironment(home);
41349
41610
  const configPath = agentDiscoveryConfigPath(home, agent);
41350
- const configText = witness(configPath, agent === "hermes" ? "yaml" : agent === "codex" ? "toml" : "json", agent === "hermes" ? ["skills", "plugins", "hooks"] : agent === "claude" ? ["enabledPlugins", "extraKnownMarketplaces"] : agent === "codex" ? ["plugins", "marketplaces", "skills"] : agent === "gemini" ? ["skills", "extensions", "security"] : agent === "opencode" ? ["plugin", "skills"] : ["version"]);
41611
+ 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"] : ["version"]);
41351
41612
  const config = configText === null ? {} : agent === "hermes" ? parseHermesConfig(configText) : parseConfig(configText, configPath, agent === "codex");
41352
41613
  const unresolved = (detail) => {
41353
41614
  throw new Error(`Native discovery is unresolved (${agent}: ${detail}); provide a reviewed --discovery-inputs file`);
@@ -41406,11 +41667,12 @@ function resolveAgentDiscovery(options) {
41406
41667
  if (retained.agent !== agent || retained.method !== "reviewed")
41407
41668
  unresolved("invalid retained review");
41408
41669
  verifyAgentDiscovery(retained);
41409
- if (!retained.sources.some((source) => source.path === canonical5(configPath) && source.format === undefined && source.fields === undefined))
41670
+ if (!retained.sources.some((source) => source.path === canonical6(configPath) && source.format === undefined && source.fields === undefined))
41410
41671
  unresolved("retained review is missing the full agent configuration source");
41411
- 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.path !== canonical5(configPath)))
41672
+ 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.path !== canonical6(configPath)))
41412
41673
  unresolved("retained settings witness names another configuration source");
41413
- if (sources.some((source) => !retained.sources.some((saved) => isDeepStrictEqual3(saved, source))) || [...roots].some((root2) => !retained.roots.includes(root2)) || agent === "gemini" && JSON.stringify(retained.builtinNames) !== JSON.stringify(builtinNames))
41674
+ const covered = supersedesCodexProjection(retained.sources, canonical6(configPath)) ? sources.filter((source) => !isSupersededCodexProjection(agent, canonical6(configPath), source)) : sources;
41675
+ if (covered.some((source) => !retained.sources.some((saved) => isDeepStrictEqual3(saved, source))) || [...roots].some((root2) => !retained.roots.includes(root2)) || agent === "gemini" && JSON.stringify(retained.builtinNames) !== JSON.stringify(builtinNames))
41414
41676
  unresolved("retained review is missing current runtime discovery coverage");
41415
41677
  return retained;
41416
41678
  }
@@ -41424,14 +41686,15 @@ function resolveAgentDiscovery(options) {
41424
41686
  if (review.sources.some((source) => source.format !== undefined || source.fields !== undefined))
41425
41687
  throw new Error("Explicit discovery reviews require full source-file hashes");
41426
41688
  verifyAgentDiscovery(supplied);
41427
- 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.path !== canonical5(configPath)))
41689
+ 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.path !== canonical6(configPath)))
41428
41690
  throw new Error("Semantic settings witnesses must name the configured Claude configuration source");
41429
- if (!review.sources.some((source) => source.path === canonical5(configPath)))
41691
+ if (!review.sources.some((source) => source.path === canonical6(configPath)))
41430
41692
  throw new Error("Discovery review must include the agent configuration source");
41431
- return { ...supplied, roots: [...new Set([...roots, ...supplied.roots])].sort(), sources: [...sources, ...review.sources], ...agent === "gemini" ? { builtinNames } : {} };
41693
+ const reviewedSources = supersedesCodexProjection(review.sources, canonical6(configPath)) ? sources.filter((source) => !isSupersededCodexProjection(agent, canonical6(configPath), source)) : sources;
41694
+ return { ...supplied, roots: [...new Set([...roots, ...supplied.roots])].sort(), sources: [...reviewedSources, ...review.sources], ...agent === "gemini" ? { builtinNames } : {} };
41432
41695
  }
41433
41696
  function plugin(root2) {
41434
- root2 = canonical5(root2);
41697
+ root2 = canonical6(root2);
41435
41698
  safe4(root2);
41436
41699
  const manifestPath = join21(root2, agent === "claude" ? ".claude-plugin/plugin.json" : ".codex-plugin/plugin.json");
41437
41700
  const raw = witness(manifestPath);
@@ -41463,7 +41726,7 @@ function resolveAgentDiscovery(options) {
41463
41726
  if (agent === "claude") {
41464
41727
  const registrations = witness(join21(home, ".claude/plugins/installed_plugins.json"));
41465
41728
  const installed = registrations === null ? {} : parseConfig(registrations, join21(home, ".claude/plugins/installed_plugins.json")).plugins;
41466
- const commands = canonical5(join21(home, ".claude/commands"));
41729
+ const commands = canonical6(join21(home, ".claude/commands"));
41467
41730
  safe4(commands);
41468
41731
  if (lstatSync18(commands, { throwIfNoEntry: false })?.isDirectory() && readdirSync7(commands).length)
41469
41732
  unresolved("legacy home command discovery requires a dedicated format adapter");
@@ -41537,7 +41800,7 @@ function resolveAgentDiscovery(options) {
41537
41800
  roots.add(join21(root2, "skills"));
41538
41801
  }
41539
41802
  }
41540
- return { agent, roots: [...roots].sort(), sources, method: "automatic", ...agent === "gemini" ? { builtinNames } : {}, ...agent === "hermes" ? { directories: captureDiscoveryDirectories([join21(home, ".hermes/plugins"), join21(home, ".hermes/hermes-agent")].map((path) => canonical5(path))) } : {} };
41803
+ return { agent, roots: [...roots].sort(), sources, method: "automatic", ...agent === "gemini" ? { builtinNames } : {}, ...agent === "hermes" ? { directories: captureDiscoveryDirectories([join21(home, ".hermes/plugins"), join21(home, ".hermes/hermes-agent")].map((path) => canonical6(path))) } : {} };
41541
41804
  }
41542
41805
 
41543
41806
  // src/lib/agent-adapters.ts
@@ -41716,10 +41979,10 @@ function inlineRowsAsTables(value, newline) {
41716
41979
  for (const row of rows) {
41717
41980
  if (!row.startsWith("{") || !row.endsWith("}"))
41718
41981
  return null;
41719
- const fields = splitTopLevel(row.slice(1, -1), ",");
41720
- if (!fields)
41982
+ const fields2 = splitTopLevel(row.slice(1, -1), ",");
41983
+ if (!fields2)
41721
41984
  return null;
41722
- const lines = fields.map((field2) => field2.trim()).filter(Boolean);
41985
+ const lines = fields2.map((field2) => field2.trim()).filter(Boolean);
41723
41986
  if (lines.some((line) => !/^(?:path|name|enabled)\s*=/.test(line)))
41724
41987
  return null;
41725
41988
  const keys2 = lines.map((line) => line.slice(0, line.indexOf("=")).trim());
@@ -41875,7 +42138,7 @@ function disableCodexBundledSkills(text2) {
41875
42138
  }
41876
42139
 
41877
42140
  // src/lib/agent-integration.ts
41878
- var sha3 = (data) => createHash17("sha256").update(data).digest("hex");
42141
+ var sha4 = (data) => createHash18("sha256").update(data).digest("hex");
41879
42142
  var ROOTS = NATIVE_SKILL_ROOTS;
41880
42143
  function assertSafePath(path) {
41881
42144
  let cursor = resolve15(path);
@@ -41982,7 +42245,7 @@ function readNativeBytes(path, maximum = 64 * 1024 * 1024) {
41982
42245
  }
41983
42246
  }
41984
42247
  function treeHash(root2) {
41985
- const hash2 = createHash17("sha256");
42248
+ const hash2 = createHash18("sha256");
41986
42249
  let bytes = 0, files = 0;
41987
42250
  function visit2(path) {
41988
42251
  const stat2 = lstatSync19(path);
@@ -42367,7 +42630,7 @@ function planAgentIntegration(options) {
42367
42630
  const observedNativeSources = [];
42368
42631
  const codexPluginSkills = options.codexNativeCatalog ? reviewCodexPluginSkillControls(options.codexNativeCatalog, nativeSkills.filter((entry) => entry.agent === "codex" && entry.vendor).map((entry) => join22(entry.path, "SKILL.md")), canonicalAgentPath(join22(home, ".codex/plugins/cache"), aliases), resolve15(options.projectDir ?? home), (path) => {
42369
42632
  const bytes = readNativeBytes(path, 1024 * 1024);
42370
- observedNativeSources.push({ path, sha256: sha3(bytes) });
42633
+ observedNativeSources.push({ path, sha256: sha4(bytes) });
42371
42634
  return new TextDecoder("utf-8", { fatal: true }).decode(bytes);
42372
42635
  }, codexConfig.skills?.config ?? []) : policy.bridge?.codexPluginSkills ?? [];
42373
42636
  const changes = [];
@@ -42395,7 +42658,7 @@ function planAgentIntegration(options) {
42395
42658
  throw new Error("Refusing to overwrite an unrecognized Hermes supervisor");
42396
42659
  if (supervisorBefore !== supervisorAfter)
42397
42660
  changes.push({ path: supervisorPath, before: supervisorBefore, after: supervisorAfter });
42398
- const supervisor = { path: supervisorPath, runtime: process.execPath, sha256: sha3(supervisorAfter) };
42661
+ const supervisor = { path: supervisorPath, runtime: process.execPath, sha256: sha4(supervisorAfter) };
42399
42662
  const after2 = configureHermesHooks(before, supervisor, previous);
42400
42663
  if (before !== after2)
42401
42664
  changes.push({ path, before, after: after2 });
@@ -42442,12 +42705,12 @@ function planAgentIntegration(options) {
42442
42705
  agents: [...new Set([...priorAgents, ...options.agents])].sort(),
42443
42706
  home: resolve15(home),
42444
42707
  includeVendor: true,
42445
- ...options.agents.includes("hermes") ? { supervisors: { ...policy.bridge?.supervisors, hermes: { path: join22(dataDir2, "agent-hooks", "hermes.js"), runtime: process.execPath, sha256: sha3(renderHermesSupervisor(bindings.get("hermes").command, bindings.get("hermes").profileId)) } } } : {},
42708
+ ...options.agents.includes("hermes") ? { supervisors: { ...policy.bridge?.supervisors, hermes: { path: join22(dataDir2, "agent-hooks", "hermes.js"), runtime: process.execPath, sha256: sha4(renderHermesSupervisor(bindings.get("hermes").command, bindings.get("hermes").profileId)) } } } : {},
42446
42709
  commands: { ...policy.bridge?.commands, ...Object.fromEntries([...bindings].map(([agent, binding]) => [agent, binding.command])) },
42447
42710
  profiles: Object.fromEntries([...new Set([...priorAgents, ...options.agents])].sort().map((agent) => [agent, bindings.get(agent)?.profileId ?? policy.bridge?.profiles?.[agent] ?? policy.profileId])),
42448
42711
  disabledBuiltins: options.agents.includes("codex") ? nativeSkills.filter((entry) => entry.agent === "codex" && entry.vendor && entry.path.startsWith(canonicalAgentPath(join22(home, ".codex", "skills", ".system"), aliases) + sep5)).map((entry) => ({ path: entry.path, hash: entry.hash })) : policy.bridge?.disabledBuiltins ?? [],
42449
42712
  rootAliases: aliases,
42450
- ...codexPluginSkills.length ? { codexPluginSkills, codexPluginSkillReview: options.codexNativeCatalog ? { version: options.codexNativeCatalog.version, cwd: options.codexNativeCatalog.cwd, catalogSha256: sha3(JSON.stringify({ version: options.codexNativeCatalog.version, cwd: options.codexNativeCatalog.cwd, skills: projectCodexNativeSkillCatalog({ data: [{ cwd: options.codexNativeCatalog.cwd, errors: [], skills: options.codexNativeCatalog.skills }] }, options.codexNativeCatalog.cwd), ...options.codexNativeCatalog.plugins === undefined ? {} : { plugins: projectCodexInstalledPluginEntries(options.codexNativeCatalog.plugins) } })), configSha256: changes.find((change) => change.path === canonicalAgentPath(join22(home, ".codex/config.toml"), aliases))?.before === null ? null : sha3(readOptional(canonicalAgentPath(join22(home, ".codex/config.toml"), aliases)) ?? "") } : policy.bridge?.codexPluginSkillReview } : {},
42713
+ ...codexPluginSkills.length ? { codexPluginSkills, codexPluginSkillReview: options.codexNativeCatalog ? { version: options.codexNativeCatalog.version, cwd: options.codexNativeCatalog.cwd, catalogSha256: sha4(JSON.stringify({ version: options.codexNativeCatalog.version, cwd: options.codexNativeCatalog.cwd, skills: projectCodexNativeSkillCatalog({ data: [{ cwd: options.codexNativeCatalog.cwd, errors: [], skills: options.codexNativeCatalog.skills }] }, options.codexNativeCatalog.cwd), ...options.codexNativeCatalog.plugins === undefined ? {} : { plugins: projectCodexInstalledPluginEntries(options.codexNativeCatalog.plugins) } })), configSha256: changes.find((change) => change.path === canonicalAgentPath(join22(home, ".codex/config.toml"), aliases))?.before === null ? null : sha4(readOptional(canonicalAgentPath(join22(home, ".codex/config.toml"), aliases)) ?? "") } : policy.bridge?.codexPluginSkillReview } : {},
42451
42714
  discovery: { ...policy.bridge?.discovery, ...Object.fromEntries(discoveryAfter.map((binding) => [binding.agent, binding])) }
42452
42715
  } };
42453
42716
  const serializedPolicy = serializeManagedSkillPolicy(nextPolicy);
@@ -42463,12 +42726,12 @@ function planClaudePreToolUseHookUpdate(options) {
42463
42726
  return planClaudeHookEventsUpdate({ ...options, events: ["PreToolUse"] });
42464
42727
  }
42465
42728
  function claudeSettingsConsumers(home, path, discoveries, aliases) {
42466
- const canonical5 = (value) => canonicalAgentPath(value, aliases);
42729
+ const canonical6 = (value) => canonicalAgentPath(value, aliases);
42467
42730
  const containsSettings = (root2) => {
42468
- const distance = relative4(canonical5(root2), path);
42731
+ const distance = relative4(canonical6(root2), path);
42469
42732
  return distance === "" || distance !== ".." && !distance.startsWith(`..${sep5}`) && !isAbsolute17(distance);
42470
42733
  };
42471
- return discoveries.filter((binding) => binding.agent === "claude" || binding.agent === "opencode" || canonical5(join22(home, AGENT_ADAPTERS[binding.agent].config)) === path || binding.sources.some((source) => canonical5(source.path) === path) || binding.roots.some(containsSettings) || binding.directories?.some((directory) => containsSettings(directory.path))).map((binding) => binding.agent);
42734
+ return discoveries.filter((binding) => binding.agent === "claude" || binding.agent === "opencode" || canonical6(join22(home, AGENT_ADAPTERS[binding.agent].config)) === path || binding.sources.some((source) => canonical6(source.path) === path) || binding.roots.some(containsSettings) || binding.directories?.some((directory) => containsSettings(directory.path))).map((binding) => binding.agent);
42472
42735
  }
42473
42736
  function verifyCoordinatedDiscovery(binding, home, aliases) {
42474
42737
  try {
@@ -42500,7 +42763,7 @@ function planClaudeHookEventsUpdate(options) {
42500
42763
  const path = canonicalAgentPath(join22(home, ".claude", "settings.json"), aliases);
42501
42764
  assertSafePath(path);
42502
42765
  const before = lstatSync19(path, { throwIfNoEntry: false }) ? new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(readNativeBytes(path, 1024 * 1024)) : null;
42503
- if ((before === null ? "absent" : sha3(before)) !== options.expectedSettingsSha256)
42766
+ if ((before === null ? "absent" : sha4(before)) !== options.expectedSettingsSha256)
42504
42767
  throw new Error("Claude settings preimage changed");
42505
42768
  assertClaudeHookEventsReplacement(before, options.replacement, options.events);
42506
42769
  const agents = bridge.agents;
@@ -42566,7 +42829,7 @@ function atomicWrite2(path, content) {
42566
42829
  function planAgentSettingsWitnessUpgrade(options) {
42567
42830
  const home = resolve15(options.home ?? homedir3()), dataDir2 = options.dataDir ?? getDataDirReadOnly();
42568
42831
  const snapshot2 = readManagedSkillPolicySnapshot(dataDir2);
42569
- if (!snapshot2 || sha3(snapshot2.text) !== options.expectedPolicySha256)
42832
+ if (!snapshot2 || sha4(snapshot2.text) !== options.expectedPolicySha256)
42570
42833
  throw new Error("Managed policy preimage changed");
42571
42834
  const policy = snapshot2.value, aliases = policy.bridge?.rootAliases ?? [];
42572
42835
  recheckRootAliases(aliases);
@@ -42575,7 +42838,7 @@ function planAgentSettingsWitnessUpgrade(options) {
42575
42838
  throw new Error("Settings witness upgrade requires an existing reviewed native binding");
42576
42839
  const configPath = canonicalAgentPath(join22(home, options.agent === "claude" ? ".claude/settings.json" : ".codex/config.toml"), aliases);
42577
42840
  const settings = readOptional(configPath);
42578
- if (settings === null || sha3(settings) !== options.expectedSettingsSha256)
42841
+ if (settings === null || sha4(settings) !== options.expectedSettingsSha256)
42579
42842
  throw new Error("Native settings preimage changed");
42580
42843
  const sources = binding.sources.filter((source) => source.path === configPath && source.format === undefined && source.fields === undefined);
42581
42844
  if (sources.length !== 1)
@@ -42583,15 +42846,40 @@ function planAgentSettingsWitnessUpgrade(options) {
42583
42846
  const previous = sources[0];
42584
42847
  if (typeof previous.sha256 !== "string")
42585
42848
  throw new Error("Settings witness upgrade requires a preserved settings preimage");
42849
+ const replaced = [previous];
42850
+ if (options.agent === "codex") {
42851
+ if (previous.hashMode !== undefined && previous.hashMode !== "bytes" && previous.hashMode !== "codex-settings-v1")
42852
+ throw new Error("Codex settings witness upgrade requires a preserved raw or codex-settings-v1 configuration witness");
42853
+ const preimage = readCodexSettingsPreimage(options.reviewedPreimage);
42854
+ for (const source of binding.sources) {
42855
+ if (source === previous || source.path !== configPath)
42856
+ continue;
42857
+ const fields2 = source.fields;
42858
+ if (source.hashMode !== undefined || source.format !== "toml" || !Array.isArray(fields2) || !isDeepStrictEqual5(fields2, [...CODEX_DISCOVERY_PROJECTION_FIELDS]) || typeof source.sha256 !== "string")
42859
+ throw new Error("Codex settings witness upgrade found an unrecognized configuration witness");
42860
+ if (projectNativeDiscoveryFields(preimage, "toml", fields2, configPath) !== source.sha256)
42861
+ throw new Error("Reviewed preimage does not explain the Codex discovery projection witness");
42862
+ replaced.push(source);
42863
+ }
42864
+ }
42586
42865
  const next = options.agent === "claude" ? upgradeClaudeSettingsWitness(previous, options.reviewedPreimage) : upgradeCodexSettingsWitness(previous, options.reviewedPreimage);
42587
- const replacement = { ...binding, sources: binding.sources.map((source) => source === previous ? next : source) };
42866
+ const rebound = [];
42867
+ for (const source of binding.sources) {
42868
+ if (!replaced.includes(source)) {
42869
+ rebound.push(source);
42870
+ continue;
42871
+ }
42872
+ if (source === replaced[0])
42873
+ rebound.push(next);
42874
+ }
42875
+ const replacement = { ...binding, sources: rebound };
42588
42876
  verifyAgentDiscovery(replacement);
42589
42877
  const after = serializeManagedSkillPolicy({ ...policy, bridge: { ...policy.bridge, discovery: { ...policy.bridge.discovery, [options.agent]: replacement } } });
42590
- return { dataDir: dataDir2, profileId: policy.profileId, changes: [{ path: join22(dataDir2, "agent-policy.json"), before: snapshot2.text, after }], nativeSkills: [], observedPolicy: { path: join22(dataDir2, "agent-policy.json"), before: snapshot2.text }, observedSettings: { path: configPath, before: settings }, discoveryBefore: [replacement], discoveryAfter: [replacement], rootAliases: aliases, managedAgentChecks: { home, agents: [options.agent] }, settingsWitnessUpgrade: { agent: options.agent, path: configPath, fromHashMode: previous.hashMode ?? "bytes", fromSha256: previous.sha256, toHashMode: next.hashMode, toSha256: next.sha256, reviewedPreimage: options.reviewedPreimage, currentSettingsSha256: options.expectedSettingsSha256 } };
42878
+ return { dataDir: dataDir2, profileId: policy.profileId, changes: [{ path: join22(dataDir2, "agent-policy.json"), before: snapshot2.text, after }], nativeSkills: [], observedPolicy: { path: join22(dataDir2, "agent-policy.json"), before: snapshot2.text }, observedSettings: { path: configPath, before: settings }, discoveryBefore: [replacement], discoveryAfter: [replacement], rootAliases: aliases, managedAgentChecks: { home, agents: [options.agent] }, settingsWitnessUpgrade: { agent: options.agent, path: configPath, fromHashMode: previous.hashMode ?? "bytes", fromSha256: previous.sha256, toHashMode: next.hashMode, toSha256: next.sha256, reviewedPreimage: options.reviewedPreimage, currentSettingsSha256: options.expectedSettingsSha256, replacedWitnesses: replaced.map((source) => ({ hashMode: source.hashMode ?? "bytes", sha256: source.sha256 })) } };
42591
42879
  }
42592
42880
  function applyAgentIntegration(plan) {
42593
42881
  for (const source of plan.observedNativeSources ?? [])
42594
- if (sha3(readNativeBytes(source.path, 1024 * 1024)) !== source.sha256)
42882
+ if (sha4(readNativeBytes(source.path, 1024 * 1024)) !== source.sha256)
42595
42883
  throw new Error("Native identity source changed after planning");
42596
42884
  if (plan.observedSettings && readOptional(plan.observedSettings.path) !== plan.observedSettings.before)
42597
42885
  throw new Error("Native settings changed after witness planning");
@@ -42611,7 +42899,7 @@ function applyAgentIntegration(plan) {
42611
42899
  const upgrade = plan.settingsWitnessUpgrade;
42612
42900
  if (!plan.managedAgentChecks || !plan.observedPolicy?.before)
42613
42901
  throw new Error("Invalid settings witness upgrade plan");
42614
- const verified = planAgentSettingsWitnessUpgrade({ agent: upgrade.agent, reviewedPreimage: upgrade.reviewedPreimage, home: plan.managedAgentChecks.home, dataDir: plan.dataDir, expectedPolicySha256: sha3(plan.observedPolicy.before), expectedSettingsSha256: upgrade.currentSettingsSha256 });
42902
+ const verified = planAgentSettingsWitnessUpgrade({ agent: upgrade.agent, reviewedPreimage: upgrade.reviewedPreimage, home: plan.managedAgentChecks.home, dataDir: plan.dataDir, expectedPolicySha256: sha4(plan.observedPolicy.before), expectedSettingsSha256: upgrade.currentSettingsSha256 });
42615
42903
  if (JSON.stringify(verified.changes) !== JSON.stringify(plan.changes) || JSON.stringify(verified.settingsWitnessUpgrade) !== JSON.stringify(upgrade))
42616
42904
  throw new Error("Settings witness upgrade plan changed");
42617
42905
  provenDiscovery = verified.discoveryBefore[0];
@@ -42639,7 +42927,7 @@ function applyAgentIntegration(plan) {
42639
42927
  chmodSync(backupRoot, 448);
42640
42928
  for (const [index, change] of plan.changes.entries())
42641
42929
  if (change.before !== null) {
42642
- const backup = join22(backupRoot, `${index}-${sha3(change.path).slice(0, 12)}.backup`);
42930
+ const backup = join22(backupRoot, `${index}-${sha4(change.path).slice(0, 12)}.backup`);
42643
42931
  writeFileSync4(backup, change.before, { mode: 384, flag: "wx" });
42644
42932
  if (readFileSync14(backup, "utf8") !== change.before)
42645
42933
  throw new Error("Native configuration preservation readback failed");
@@ -42658,7 +42946,7 @@ function applyAgentIntegration(plan) {
42658
42946
  }
42659
42947
  recheckRootAliases(aliases);
42660
42948
  for (const source of plan.observedNativeSources ?? [])
42661
- if (sha3(readNativeBytes(source.path, 1024 * 1024)) !== source.sha256)
42949
+ if (sha4(readNativeBytes(source.path, 1024 * 1024)) !== source.sha256)
42662
42950
  throw new Error("Native identity source changed during application");
42663
42951
  if (plan.observedSettings && readOptional(plan.observedSettings.path) !== plan.observedSettings.before)
42664
42952
  throw new Error("Native settings changed during witness application");
@@ -42670,7 +42958,7 @@ function applyAgentIntegration(plan) {
42670
42958
  }
42671
42959
  for (const agent of plan.managedAgentChecks?.agents ?? [])
42672
42960
  assertManagedAgentBridge(agent, { home: plan.managedAgentChecks.home, dataDir: plan.dataDir, projectDir: plan.managedAgentChecks.home });
42673
- atomicWrite2(join22(backupRoot, "receipt.json"), JSON.stringify({ version: 1, changes: written.map((change) => ({ path: change.path, beforeHash: change.before === null ? null : sha3(change.before), afterHash: sha3(change.after) })), backups, ...aliases.length ? { rootAliases: aliases } : {} }) + `
42961
+ atomicWrite2(join22(backupRoot, "receipt.json"), JSON.stringify({ version: 1, changes: written.map((change) => ({ path: change.path, beforeHash: change.before === null ? null : sha4(change.before), afterHash: sha4(change.after) })), backups, ...aliases.length ? { rootAliases: aliases } : {} }) + `
42674
42962
  `);
42675
42963
  } catch (error) {
42676
42964
  for (const change of written.reverse()) {
@@ -42749,8 +43037,8 @@ function archiveNativeSkills(inventory, options) {
42749
43037
  const operationId = randomUUID3(), archiveRoot = join22(options.dataDir ?? getDataDir(), "migration", operationId, "native"), receiptPath = join22(archiveRoot, "receipt.json");
42750
43038
  const entries = selected.map((entry, index) => ({
42751
43039
  source: entry.vendor ? join22(entry.path, "SKILL.md") : entry.path,
42752
- archive: join22(archiveRoot, `${index}-${sha3(entry.path).slice(0, 12)}`),
42753
- hash: entry.vendor ? sha3(readNativeBytes(join22(entry.path, "SKILL.md"))) : entry.hash,
43040
+ archive: join22(archiveRoot, `${index}-${sha4(entry.path).slice(0, 12)}`),
43041
+ hash: entry.vendor ? sha4(readNativeBytes(join22(entry.path, "SKILL.md"))) : entry.hash,
42754
43042
  ...entry.vendor ? { discoveryOnly: true } : {},
42755
43043
  status: "planned"
42756
43044
  }));
@@ -42761,7 +43049,7 @@ function archiveNativeSkills(inventory, options) {
42761
43049
  const stat2 = lstatSync19(entry.archive);
42762
43050
  if (entry.discoveryOnly ? !stat2.isFile() : !stat2.isDirectory())
42763
43051
  throw new Error("Archive type changed");
42764
- if ((entry.discoveryOnly ? sha3(readNativeBytes(entry.archive)) : treeHash(entry.archive)) !== entry.hash)
43052
+ if ((entry.discoveryOnly ? sha4(readNativeBytes(entry.archive)) : treeHash(entry.archive)) !== entry.hash)
42765
43053
  throw new Error("Archive bytes changed");
42766
43054
  };
42767
43055
  assertSafePath(archiveRoot);
@@ -42881,7 +43169,7 @@ function assertManagedAgentBridgeWithDiscovery(agent, options = {}, provenDiscov
42881
43169
  throw new Error("NATIVE_SKILL_DRIFT: the hook selection profile differs from its managed binding; restart the native client after reviewing skills hook install");
42882
43170
  if (agent === "hermes") {
42883
43171
  const supervisor = binding.supervisors?.hermes;
42884
- if (supervisor?.path !== join22(dataDir2, "agent-hooks", "hermes.js") || supervisor?.sha256 !== sha3(renderHermesSupervisor(command, profile)))
43172
+ if (supervisor?.path !== join22(dataDir2, "agent-hooks", "hermes.js") || supervisor?.sha256 !== sha4(renderHermesSupervisor(command, profile)))
42885
43173
  throw new Error("NATIVE_SKILL_DRIFT: Hermes supervisor binding changed; run skills hook install");
42886
43174
  assertHermesProtection(home, config, command, profile, supervisor);
42887
43175
  } else if (agent === "opencode") {
@@ -42979,13 +43267,13 @@ import {
42979
43267
  statSync as statSync9,
42980
43268
  writeFileSync as writeFileSync6
42981
43269
  } from "fs";
42982
- import { basename as basename10, dirname as dirname18, isAbsolute as isAbsolute18, join as join26, normalize as normalize3, relative as relative6, resolve as resolve17, sep as sep8 } from "path";
43270
+ import { basename as basename10, dirname as dirname18, isAbsolute as isAbsolute18, join as join26, normalize as normalize4, relative as relative6, resolve as resolve17, sep as sep8 } from "path";
42983
43271
 
42984
43272
  // src/lib/registry-data/index.ts
42985
43273
  var SKILLS = [];
42986
43274
 
42987
43275
  // src/lib/skill-hash.ts
42988
- import { createHash as createHash18 } from "crypto";
43276
+ import { createHash as createHash19 } from "crypto";
42989
43277
  import { existsSync as existsSync7, readdirSync as readdirSync9, readFileSync as readFileSync15, statSync as statSync7 } from "fs";
42990
43278
  import { join as join23, sep as sep6 } from "path";
42991
43279
  var CONTENT_HASH_ALGORITHM = "sha256";
@@ -43109,13 +43397,13 @@ function* bundleHashParts(files) {
43109
43397
  yield new TextEncoder().encode("\x00");
43110
43398
  }
43111
43399
  function hashBundleFiles(files) {
43112
- const hash2 = createHash18(CONTENT_HASH_ALGORITHM);
43400
+ const hash2 = createHash19(CONTENT_HASH_ALGORITHM);
43113
43401
  for (const part of bundleHashParts(files))
43114
43402
  hash2.update(part);
43115
43403
  return hash2.digest("hex");
43116
43404
  }
43117
43405
  async function hashBundleFilesCooperatively(files, check) {
43118
- const hash2 = createHash18(CONTENT_HASH_ALGORITHM);
43406
+ const hash2 = createHash19(CONTENT_HASH_ALGORITHM);
43119
43407
  let bytesSinceYield = 0;
43120
43408
  for (const part of bundleHashParts(files)) {
43121
43409
  for (let offset = 0;offset < part.byteLength; offset += 64 * 1024) {
@@ -43373,7 +43661,7 @@ var MAX_RUNTIME_TIMEOUT_SECONDS = 900;
43373
43661
  function add2(target, code, message) {
43374
43662
  target.push({ code, message });
43375
43663
  }
43376
- function isRecord(value) {
43664
+ function isRecord2(value) {
43377
43665
  return typeof value === "object" && value !== null && !Array.isArray(value);
43378
43666
  }
43379
43667
  function isNonEmptyString(value) {
@@ -43401,7 +43689,7 @@ function validatePortableManifestContract(manifest, options = {}) {
43401
43689
  }
43402
43690
  validateRuntimeContract(manifest, issues, options.strict === true);
43403
43691
  const provenance = manifest.provenance;
43404
- if (provenance && !isRecord(provenance)) {
43692
+ if (provenance && !isRecord2(provenance)) {
43405
43693
  add2(issues, "contract.provenance_invalid", "provenance must be an object");
43406
43694
  } else {
43407
43695
  const sourceCommit = provenance?.source_commit;
@@ -43434,7 +43722,7 @@ function validateRuntimeContract(manifest, issues, strict) {
43434
43722
  }
43435
43723
  return;
43436
43724
  }
43437
- if (!isRecord(runtime)) {
43725
+ if (!isRecord2(runtime)) {
43438
43726
  add2(issues, "contract.runtime_invalid", "runtime must be an object");
43439
43727
  return;
43440
43728
  }
@@ -43721,7 +44009,7 @@ function readExistingSkillJson(skillPath) {
43721
44009
  return {};
43722
44010
  try {
43723
44011
  const parsed = JSON.parse(readFileSync16(path, "utf-8"));
43724
- return isRecord2(parsed) ? parsed : {};
44012
+ return isRecord3(parsed) ? parsed : {};
43725
44013
  } catch {
43726
44014
  return {};
43727
44015
  }
@@ -43777,7 +44065,7 @@ function ensurePackageJson(skillPath, manifest) {
43777
44065
  }
43778
44066
  const existing = readJsonObject(pkgPath);
43779
44067
  const bin = {};
43780
- if (isRecord2(existing.bin)) {
44068
+ if (isRecord3(existing.bin)) {
43781
44069
  for (const [name, value] of Object.entries(existing.bin)) {
43782
44070
  if (typeof value === "string" && value.trim())
43783
44071
  bin[normalizePortableSkillName(name)] = value.replace(/^\.\//, "");
@@ -43788,7 +44076,7 @@ function ensurePackageJson(skillPath, manifest) {
43788
44076
  bin[manifest.name] = binEntry.replace(/^\.\//, "");
43789
44077
  }
43790
44078
  bin[commandName] = entry;
43791
- const scripts = isRecord2(existing.scripts) ? { ...existing.scripts } : {};
44079
+ const scripts = isRecord3(existing.scripts) ? { ...existing.scripts } : {};
43792
44080
  if (!stringValue(scripts.dev))
43793
44081
  scripts.dev = `bun run ${entry}`;
43794
44082
  writeFileSync5(pkgPath, `${JSON.stringify({
@@ -44009,7 +44297,7 @@ function parseManifestCommands(value) {
44009
44297
  if (!Array.isArray(raw))
44010
44298
  return;
44011
44299
  const commands = raw.map((item) => {
44012
- if (!isRecord2(item))
44300
+ if (!isRecord3(item))
44013
44301
  return null;
44014
44302
  const name = stringValue(item.name);
44015
44303
  if (!name)
@@ -44026,7 +44314,7 @@ function parseManifestCommands(value) {
44026
44314
  }
44027
44315
  function parseManifestRuntime(value) {
44028
44316
  const raw = value?.runtime;
44029
- if (!isRecord2(raw))
44317
+ if (!isRecord3(raw))
44030
44318
  return;
44031
44319
  const runtimeName = stringValue(raw.runtime);
44032
44320
  if (!runtimeName)
@@ -44052,7 +44340,7 @@ function parseManifestRuntime(value) {
44052
44340
  }
44053
44341
  function parseManifestProvenance(value) {
44054
44342
  const raw = value?.provenance;
44055
- if (!isRecord2(raw))
44343
+ if (!isRecord3(raw))
44056
44344
  return;
44057
44345
  const parsed = {};
44058
44346
  if (stringValue(raw.source_commit))
@@ -44068,7 +44356,7 @@ function parseManifestInputs(value) {
44068
44356
  if (!Array.isArray(raw))
44069
44357
  return;
44070
44358
  const inputs = raw.map((item) => {
44071
- if (!isRecord2(item))
44359
+ if (!isRecord3(item))
44072
44360
  return null;
44073
44361
  const name = stringValue(item.name);
44074
44362
  const type = stringValue(item.type);
@@ -44086,7 +44374,7 @@ function parseManifestInputs(value) {
44086
44374
  function inferPackageCommands(pkg, fallbackName) {
44087
44375
  if (!pkg)
44088
44376
  return;
44089
- if (isRecord2(pkg.bin)) {
44377
+ if (isRecord3(pkg.bin)) {
44090
44378
  const commands = Object.entries(pkg.bin).filter((entry) => typeof entry[1] === "string" && entry[1].trim().length > 0).map(([name, entry]) => ({
44091
44379
  name: normalizePortableSkillName(name),
44092
44380
  entry: entry.replace(/^\.\//, ""),
@@ -44095,7 +44383,7 @@ function inferPackageCommands(pkg, fallbackName) {
44095
44383
  if (commands.length)
44096
44384
  return commands;
44097
44385
  }
44098
- const scripts = isRecord2(pkg.scripts) ? pkg.scripts : undefined;
44386
+ const scripts = isRecord3(pkg.scripts) ? pkg.scripts : undefined;
44099
44387
  const dev = stringValue(scripts?.dev);
44100
44388
  const match = dev?.match(/(?:bun\s+run\s+|bun\s+)([^ ]+)/);
44101
44389
  if (match?.[1]) {
@@ -44111,20 +44399,20 @@ function inferRuntimeFromCommands(commands) {
44111
44399
  }
44112
44400
  function readJsonObject(path) {
44113
44401
  const parsed = JSON.parse(readFileSync16(path, "utf-8"));
44114
- if (!isRecord2(parsed))
44402
+ if (!isRecord3(parsed))
44115
44403
  throw new Error(`${basename8(path)} must contain a JSON object`);
44116
44404
  return parsed;
44117
44405
  }
44118
44406
  function hasPackageDependencies(pkgPath) {
44119
44407
  try {
44120
44408
  const pkg = readJsonObject(pkgPath);
44121
- const deps = isRecord2(pkg.dependencies) ? Object.keys(pkg.dependencies) : [];
44409
+ const deps = isRecord3(pkg.dependencies) ? Object.keys(pkg.dependencies) : [];
44122
44410
  return deps.length > 0;
44123
44411
  } catch {
44124
44412
  return false;
44125
44413
  }
44126
44414
  }
44127
- function isRecord2(value) {
44415
+ function isRecord3(value) {
44128
44416
  return typeof value === "object" && value !== null && !Array.isArray(value);
44129
44417
  }
44130
44418
  function stringField(value, key) {
@@ -44339,7 +44627,7 @@ function scaffoldPortableSkill(name, options = {}) {
44339
44627
  return { name: skillName, path: skillPath, manifest, created: true };
44340
44628
  }
44341
44629
  function portPortableSkillDirectory(sourceDir, options = {}) {
44342
- const absoluteSource = normalize3(sourceDir);
44630
+ const absoluteSource = normalize4(sourceDir);
44343
44631
  if (!existsSync9(absoluteSource) || !statSync9(absoluteSource).isDirectory()) {
44344
44632
  throw new Error(`Import directory not found: ${sourceDir}`);
44345
44633
  }
@@ -44406,7 +44694,7 @@ function assertDisjointImportPaths(source, destination) {
44406
44694
  }
44407
44695
  }
44408
44696
  function portPortableSkill(sourcePath, options = {}) {
44409
- const absoluteSource = normalize3(sourcePath);
44697
+ const absoluteSource = normalize4(sourcePath);
44410
44698
  if (!existsSync9(absoluteSource) || !statSync9(absoluteSource).isDirectory()) {
44411
44699
  throw new Error(`Skill source directory not found: ${sourcePath}`);
44412
44700
  }
@@ -44682,7 +44970,7 @@ function safeIsDirectory(path) {
44682
44970
  function isSafeRelativePath2(value) {
44683
44971
  if (!value.trim() || isAbsolute18(value))
44684
44972
  return false;
44685
- const normalized = normalize3(value).replace(/\\/g, "/");
44973
+ const normalized = normalize4(value).replace(/\\/g, "/");
44686
44974
  return normalized !== ".." && !normalized.startsWith("../") && !normalized.includes("/../");
44687
44975
  }
44688
44976
  function add3(target, code, message) {
@@ -46333,7 +46621,7 @@ async function executeSelectedLocal(selected, options = {}) {
46333
46621
  selection: selection2,
46334
46622
  target: "local",
46335
46623
  runtime: runtimeName,
46336
- inputDigest: `sha256:${createHash19("sha256").update(input).digest("hex")}`,
46624
+ inputDigest: `sha256:${createHash20("sha256").update(input).digest("hex")}`,
46337
46625
  runDirectory,
46338
46626
  ...executionGrant ? { executionGrant } : {},
46339
46627
  ...bindings ? { secretBinding: { schema: bindings.schema, selection: bindings.selection, consumer: bindings.consumer, secretsAuthority: bindings.secretsAuthority, bindings: bindings.bindings } } : {},
@@ -46391,7 +46679,7 @@ async function subprocess(command, cwd, env, input, timeoutMs) {
46391
46679
  // src/lib/remote-run-contract.ts
46392
46680
  var REMOTE_SKILL_RUN_CONTRACT_VERSION = 1;
46393
46681
  function normalizeRemoteSkillRunContract(payload, fallbackSkill) {
46394
- const record3 = isRecord3(payload) ? payload : {};
46682
+ const record3 = isRecord4(payload) ? payload : {};
46395
46683
  return {
46396
46684
  contractVersion: REMOTE_SKILL_RUN_CONTRACT_VERSION,
46397
46685
  ...pickString(record3, "id"),
@@ -46413,7 +46701,7 @@ function normalizeRemoteSkillRunContract(payload, fallbackSkill) {
46413
46701
  ...hasOwn(record3, "details") ? { details: record3.details } : {}
46414
46702
  };
46415
46703
  }
46416
- function isRecord3(value) {
46704
+ function isRecord4(value) {
46417
46705
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
46418
46706
  }
46419
46707
  function hasOwn(record3, key) {
@@ -55623,7 +55911,7 @@ var import_node_http_handler2 = __toESM(require_dist_cjs6(), 1);
55623
55911
 
55624
55912
  // node_modules/@aws-sdk/checksums/dist-cjs/submodules/sha/index.js
55625
55913
  var { toUint8Array: toUint8Array2, concatBytes } = require_serde();
55626
- var { createHmac: createHmac2, createHash: createHash21 } = __require("crypto");
55914
+ var { createHmac: createHmac2, createHash: createHash22 } = __require("crypto");
55627
55915
  var { Sha256: Sha2562, Sha256Js, Sha256Node } = require_checksum();
55628
55916
  var BLOCK2 = 64;
55629
55917
  var DIGEST_LENGTH = 20;
@@ -55792,7 +56080,7 @@ class Sha1Js {
55792
56080
  }
55793
56081
  var hasNativeCrypto = (() => {
55794
56082
  try {
55795
- createHash21("sha1");
56083
+ createHash22("sha1");
55796
56084
  return true;
55797
56085
  } catch {
55798
56086
  return false;
@@ -55832,7 +56120,7 @@ function buildNativeClass() {
55832
56120
  this.finished = false;
55833
56121
  }
55834
56122
  createHash() {
55835
- return this.secret ? createHmac2("sha1", toBuffer(this.secret)) : createHash21("sha1");
56123
+ return this.secret ? createHmac2("sha1", toBuffer(this.secret)) : createHash22("sha1");
55836
56124
  }
55837
56125
  };
55838
56126
  }
@@ -56700,9 +56988,9 @@ import { mkdirSync as mkdirSync11, readFileSync as readFileSync23, readdirSync a
56700
56988
  import { dirname as dirname23, join as join36 } from "path";
56701
56989
 
56702
56990
  // src/server/auth.ts
56703
- import { createHash as createHash22 } from "crypto";
56991
+ import { createHash as createHash23 } from "crypto";
56704
56992
  function hashApiKey(token) {
56705
- return createHash22("sha256").update(token).digest("hex");
56993
+ return createHash23("sha256").update(token).digest("hex");
56706
56994
  }
56707
56995
  function bearerToken(request2) {
56708
56996
  const header = request2.headers.get("authorization") || "";
@@ -57024,7 +57312,7 @@ function validOperatorScopeEnrollmentInput(input) {
57024
57312
  }
57025
57313
 
57026
57314
  // src/lib/revision.ts
57027
- import { createHash as createHash23 } from "crypto";
57315
+ import { createHash as createHash24 } from "crypto";
57028
57316
  var REVISION_ID_PATTERN = /^[0-9a-f]{64}$/;
57029
57317
  function revisionIdOf(content) {
57030
57318
  const canonicalContent = {
@@ -57045,8 +57333,8 @@ function revisionIdOf(content) {
57045
57333
  canonicalContent.archiveReason = content.archiveReason ?? null;
57046
57334
  canonicalContent.replacementSlug = content.replacementSlug ?? null;
57047
57335
  }
57048
- const canonical5 = JSON.stringify(canonicalContent);
57049
- return createHash23("sha256").update(canonical5).digest("hex");
57336
+ const canonical6 = JSON.stringify(canonicalContent);
57337
+ return createHash24("sha256").update(canonical6).digest("hex");
57050
57338
  }
57051
57339
  function revisionIdOfRecord(record3) {
57052
57340
  return revisionIdOf(record3);
@@ -58130,7 +58418,7 @@ function nextMonthPrefix(monthPrefix) {
58130
58418
  }
58131
58419
 
58132
58420
  // src/server/skills-api.ts
58133
- import { createHash as createHash24 } from "crypto";
58421
+ import { createHash as createHash25 } from "crypto";
58134
58422
  var SLUG_PATTERN = /^[a-z0-9][a-z0-9._-]*$/;
58135
58423
  var SHA256_HEX2 = /^[0-9a-f]{64}$/;
58136
58424
  var MAX_SLUG_LENGTH = 128;
@@ -58320,7 +58608,7 @@ async function parsePublishRequest(request2, config) {
58320
58608
  if (bundleBytes.byteLength === 0) {
58321
58609
  throw new SkillRequestError(400, "BUNDLE_EMPTY", "the uploaded bundle is empty");
58322
58610
  }
58323
- const sha2562 = createHash24("sha256").update(bundleBytes).digest("hex");
58611
+ const sha2562 = createHash25("sha256").update(bundleBytes).digest("hex");
58324
58612
  const claimed = optionalString(manifest.bundleSha256);
58325
58613
  if (claimed)
58326
58614
  assertSha2562(claimed);
@@ -58435,7 +58723,7 @@ async function readPublishedBundle(store, artifactStorage, principal, slug) {
58435
58723
  if (!bytes) {
58436
58724
  throw new SkillRequestError(503, "BUNDLE_BACKEND_UNAVAILABLE", "bundle storage backend unavailable");
58437
58725
  }
58438
- const actual = createHash24("sha256").update(bytes).digest("hex");
58726
+ const actual = createHash25("sha256").update(bytes).digest("hex");
58439
58727
  if (actual !== record3.bundleSha256) {
58440
58728
  throw new SkillRequestError(500, "BUNDLE_DIGEST_DRIFT", `stored bundle for '${slug}' hashes to ${actual} but was published as ${record3.bundleSha256}`);
58441
58729
  }
@@ -58583,7 +58871,7 @@ async function readSkillVersionBundle(store, artifactStorage, principal, slug, v
58583
58871
  const bytes = await artifactStorage.readBundle(bundle2);
58584
58872
  if (!bytes)
58585
58873
  throw new SkillRequestError(503, "BUNDLE_BACKEND_UNAVAILABLE", "bundle storage backend unavailable");
58586
- const actual = createHash24("sha256").update(bytes).digest("hex");
58874
+ const actual = createHash25("sha256").update(bytes).digest("hex");
58587
58875
  if (actual !== found.bundleSha256) {
58588
58876
  throw new SkillRequestError(500, "BUNDLE_DIGEST_DRIFT", `stored bundle for '${slug}@${version2}' hashes to ${actual} but was published as ${found.bundleSha256}`);
58589
58877
  }
@@ -59286,7 +59574,7 @@ class RuntimeExecutionStore {
59286
59574
  }
59287
59575
 
59288
59576
  // src/sdk/execution/admission.ts
59289
- import { createHash as createHash26 } from "crypto";
59577
+ import { createHash as createHash27 } from "crypto";
59290
59578
 
59291
59579
  // src/sdk/execution/image-profile.ts
59292
59580
  class ImageProfileResolutionError extends Error {
@@ -59898,11 +60186,11 @@ function ownedAdmission(admission) {
59898
60186
  };
59899
60187
  }
59900
60188
  function digestInput(input) {
59901
- return createHash26("sha256").update(canonicalJson2(input)).digest("hex");
60189
+ return createHash27("sha256").update(canonicalJson2(input)).digest("hex");
59902
60190
  }
59903
60191
 
59904
60192
  // src/sdk/execution/dispatchers/ecs.ts
59905
- import { createHash as createHash27 } from "crypto";
60193
+ import { createHash as createHash28 } from "crypto";
59906
60194
 
59907
60195
  // src/sdk/execution/state-machine.ts
59908
60196
  var LEGAL_TRANSITIONS = {
@@ -63302,13 +63590,13 @@ function observedTask(states, taskArn) {
63302
63590
  return state2.lastStatus === "STOPPED" || LIVE_TASK_STATUSES.has(state2.lastStatus) ? state2 : undefined;
63303
63591
  }
63304
63592
  function clientTokenFor(runId3, attemptId) {
63305
- return createHash27("sha256").update(`${runId3}\x00${attemptId}`).digest("hex").slice(0, CLIENT_TOKEN_BYTES * 2);
63593
+ return createHash28("sha256").update(`${runId3}\x00${attemptId}`).digest("hex").slice(0, CLIENT_TOKEN_BYTES * 2);
63306
63594
  }
63307
63595
  function startedByFor(runId3, attemptNumber) {
63308
63596
  return `skills-exec/${runId3}/a${attemptNumber}`;
63309
63597
  }
63310
63598
  function requestDigestFor(admission, attemptId) {
63311
- return createHash27("sha256").update(canonicalJson2({ admission, attemptId })).digest("hex");
63599
+ return createHash28("sha256").update(canonicalJson2({ admission, attemptId })).digest("hex");
63312
63600
  }
63313
63601
 
63314
63602
  class EcsDispatcher {
@@ -63604,10 +63892,10 @@ function validText(value) {
63604
63892
  }
63605
63893
 
63606
63894
  // src/server/runtime-policy.ts
63607
- import { createHash as createHash29, createHmac as createHmac3, timingSafeEqual as timingSafeEqual2 } from "crypto";
63895
+ import { createHash as createHash30, createHmac as createHmac3, timingSafeEqual as timingSafeEqual2 } from "crypto";
63608
63896
 
63609
63897
  // src/server/runtime-pure-contract.ts
63610
- import { createHash as createHash28 } from "crypto";
63898
+ import { createHash as createHash29 } from "crypto";
63611
63899
  var PURE_DESCRIPTOR = Object.freeze({
63612
63900
  id: "regex-test.v1",
63613
63901
  runtime: "bun",
@@ -63631,7 +63919,7 @@ var PURE_LIMITS = Object.freeze({
63631
63919
  maxArtifactsBytes: 0,
63632
63920
  maxConcurrency: 1
63633
63921
  });
63634
- var hash2 = (bytes) => createHash28("sha256").update(bytes).digest("hex");
63922
+ var hash2 = (bytes) => createHash29("sha256").update(bytes).digest("hex");
63635
63923
  var object6 = (v2) => {
63636
63924
  if (!v2 || typeof v2 !== "object" || Array.isArray(v2))
63637
63925
  throw Error("Pure contract requires an object");
@@ -63860,7 +64148,7 @@ function verifyRuntimeToken(token, key, admission, attempt, now = Date.now()) {
63860
64148
  const actual = Buffer.from(token);
63861
64149
  return actual.length === expected.length && timingSafeEqual2(actual, expected);
63862
64150
  }
63863
- var hashBytes = (bytes) => createHash29("sha256").update(bytes).digest("hex");
64151
+ var hashBytes = (bytes) => createHash30("sha256").update(bytes).digest("hex");
63864
64152
 
63865
64153
  // src/server/runtime-api.ts
63866
64154
  async function createRuntimeService(options) {
@@ -66048,7 +66336,7 @@ async function readJson(request2, limitBytes) {
66048
66336
  if (!text2.trim())
66049
66337
  return {};
66050
66338
  const parsed = JSON.parse(text2);
66051
- return isRecord4(parsed) ? parsed : {};
66339
+ return isRecord5(parsed) ? parsed : {};
66052
66340
  }
66053
66341
  function pathSegments(pathname) {
66054
66342
  return pathname.split("/").filter(Boolean).map(decodeSegment);
@@ -66069,7 +66357,7 @@ function json4(payload, init = {}) {
66069
66357
  headers: { "Cache-Control": "no-store", ...init.headers }
66070
66358
  });
66071
66359
  }
66072
- function isRecord4(value) {
66360
+ function isRecord5(value) {
66073
66361
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
66074
66362
  }
66075
66363
  function clampInt(value, fallback, max) {
@@ -70232,7 +70520,7 @@ var localRunExecutor = {
70232
70520
  // src/sdk/storage.ts
70233
70521
  var artifactStorageSeam = ArtifactStorage;
70234
70522
  // src/sdk/outputs.ts
70235
- import { createHash as createHash30 } from "crypto";
70523
+ import { createHash as createHash31 } from "crypto";
70236
70524
  class DatabaseOnlyObjectStore {
70237
70525
  usesS3 = false;
70238
70526
  async materialize(run, artifact, body4) {
@@ -70279,7 +70567,7 @@ function createGovernedArtifactWriter(options) {
70279
70567
  const stamped = {
70280
70568
  ...meta,
70281
70569
  byteSize: outputBytes,
70282
- sha256: createHash30("sha256").update(persistedBytes).digest("hex"),
70570
+ sha256: createHash31("sha256").update(persistedBytes).digest("hex"),
70283
70571
  visibility: options.visibility ?? config.defaultVisibility,
70284
70572
  ...config.artifactTtlSeconds !== undefined ? { expiresAt: expiresAtFor(createdAt, config.artifactTtlSeconds) } : {}
70285
70573
  };
@@ -73750,15 +74038,15 @@ var $ZodDate = /* @__PURE__ */ $constructor("$ZodDate", (inst, def) => {
73750
74038
  } catch (_err) {}
73751
74039
  }
73752
74040
  const input = payload.value;
73753
- const isDate = input instanceof Date;
73754
- const isValidDate = isDate && !Number.isNaN(input.getTime());
74041
+ const isDate2 = input instanceof Date;
74042
+ const isValidDate = isDate2 && !Number.isNaN(input.getTime());
73755
74043
  if (isValidDate)
73756
74044
  return payload;
73757
74045
  payload.issues.push({
73758
74046
  expected: "date",
73759
74047
  code: "invalid_type",
73760
74048
  input,
73761
- ...isDate ? { received: "Invalid Date" } : {},
74049
+ ...isDate2 ? { received: "Invalid Date" } : {},
73762
74050
  inst
73763
74051
  });
73764
74052
  return payload;
@@ -89046,7 +89334,7 @@ function date4(params) {
89046
89334
  return _coercedDate(ZodDate2, params);
89047
89335
  }
89048
89336
  // src/lib/canonical-json.ts
89049
- import { createHash as createHash31 } from "crypto";
89337
+ import { createHash as createHash32 } from "crypto";
89050
89338
  function canonicalJson3(value, maximumBytes = 2 * 1024 * 1024) {
89051
89339
  return canonicalJsonAtDepth(value, maximumBytes, 64);
89052
89340
  }
@@ -89090,7 +89378,7 @@ function canonicalJsonAtDepth(value, maximumBytes, maximumDepth) {
89090
89378
  return visit3(value, 0);
89091
89379
  }
89092
89380
  function canonicalJsonSha256(value, maximumBytes) {
89093
- return createHash31("sha256").update(canonicalJson3(value, maximumBytes)).digest("hex");
89381
+ return createHash32("sha256").update(canonicalJson3(value, maximumBytes)).digest("hex");
89094
89382
  }
89095
89383
 
89096
89384
  // src/lib/remote-recurring-contract.ts
@@ -89956,7 +90244,7 @@ function creditCheckoutFailure(value, status, key) {
89956
90244
 
89957
90245
  // src/lib/remote-profile.ts
89958
90246
  function customerNamePatch(input2, field2) {
89959
- if (!isRecord5(input2) || Object.keys(input2).length !== 1 || !Object.hasOwn(input2, field2))
90247
+ if (!isRecord6(input2) || Object.keys(input2).length !== 1 || !Object.hasOwn(input2, field2))
89960
90248
  throw new Error("Provide only the requested name field.");
89961
90249
  const value = input2[field2];
89962
90250
  if (typeof value !== "string" || /[\p{Cc}\p{Cs}\u2028\u2029]/u.test(value) || !value.trim() || [...value.trim()].length > 100) {
@@ -89964,22 +90252,22 @@ function customerNamePatch(input2, field2) {
89964
90252
  }
89965
90253
  return { [field2]: value.trim() };
89966
90254
  }
89967
- function isRecord5(value) {
90255
+ function isRecord6(value) {
89968
90256
  return !!value && typeof value === "object" && !Array.isArray(value);
89969
90257
  }
89970
90258
  function string4(value) {
89971
90259
  return typeof value === "string" && value.length > 0;
89972
90260
  }
89973
90261
  function parseUpdatedProfile(value) {
89974
- const user = isRecord5(value) && value.user;
89975
- if (!isRecord5(user) || !string4(user.id) || !string4(user.email) || !(user.displayName === null || typeof user.displayName === "string") || typeof user.role !== "string" || !["owner", "admin", "member", "viewer"].includes(user.role)) {
90262
+ const user = isRecord6(value) && value.user;
90263
+ if (!isRecord6(user) || !string4(user.id) || !string4(user.email) || !(user.displayName === null || typeof user.displayName === "string") || typeof user.role !== "string" || !["owner", "admin", "member", "viewer"].includes(user.role)) {
89976
90264
  throw new Error("The server returned an invalid account profile.");
89977
90265
  }
89978
90266
  return { user: { id: user.id, email: user.email, displayName: user.displayName, role: user.role } };
89979
90267
  }
89980
90268
  function parseUpdatedWorkspace(value) {
89981
- const organization2 = isRecord5(value) && value.organization;
89982
- if (!isRecord5(organization2) || !string4(organization2.id) || !string4(organization2.slug) || !string4(organization2.name)) {
90269
+ const organization2 = isRecord6(value) && value.organization;
90270
+ if (!isRecord6(organization2) || !string4(organization2.id) || !string4(organization2.slug) || !string4(organization2.name)) {
89983
90271
  throw new Error("The server returned an invalid workspace.");
89984
90272
  }
89985
90273
  return { organization: { id: organization2.id, slug: organization2.slug, name: organization2.name } };
@@ -91204,7 +91492,7 @@ async function requestInvitationEmail(origin, action, input2) {
91204
91492
  }
91205
91493
 
91206
91494
  // src/lib/remote-private-publications.ts
91207
- import { createHash as createHash32 } from "crypto";
91495
+ import { createHash as createHash33 } from "crypto";
91208
91496
  var PRIVATE_PUBLICATION_MAX_BYTES = 16 * 1024 * 1024;
91209
91497
  var failures2 = {
91210
91498
  INVALID_REQUEST: [400, "The publication request is invalid."],
@@ -91251,7 +91539,7 @@ var hash4 = (v2) => typeof v2 === "string" && /^[a-f0-9]{64}$/.test(v2);
91251
91539
  var record9 = (v2) => !!v2 && typeof v2 === "object" && !Array.isArray(v2);
91252
91540
  var exact = (v2, keys3) => record9(v2) && Object.keys(v2).sort().join(",") === keys3.sort().join(",");
91253
91541
  var date5 = (v2) => typeof v2 === "string" && /^\d{4}-\d\d-\d\dT[0-9:.]+(?:Z|[+-](?:[01]\d|2[0-3]):[0-5]\d)$/.test(v2) && Number.isFinite(Date.parse(v2));
91254
- var publicationSha256 = (bytes) => createHash32("sha256").update(bytes).digest("hex");
91542
+ var publicationSha256 = (bytes) => createHash33("sha256").update(bytes).digest("hex");
91255
91543
  function checkedPublicationDeclaration(value) {
91256
91544
  if (!exact(value, ["idempotencyKey", "version", "expectedCurrentVersionId", "manifestText", "archiveSha256", "archiveByteSize"]) || !publicationUuid(value.idempotencyKey) || !(value.expectedCurrentVersionId === null || publicationUuid(value.expectedCurrentVersionId)) || typeof value.version !== "string" || !value.version || value.version.length > 128 || /[\p{Cc}\p{Cs}]/u.test(value.version) || typeof value.manifestText !== "string" || Buffer.byteLength(value.manifestText) > 16384 || !hash4(value.archiveSha256) || !Number.isSafeInteger(value.archiveByteSize) || Number(value.archiveByteSize) < 1 || Number(value.archiveByteSize) > PRIVATE_PUBLICATION_MAX_BYTES)
91257
91545
  return bad();
@@ -91550,7 +91838,7 @@ async function requestAuthApi(instance, path2, options) {
91550
91838
  const text3 = await res.text();
91551
91839
  const body4 = text3 ? parseJsonBody(text3) : {};
91552
91840
  if (!res.ok) {
91553
- const record10 = isRecord6(body4) ? body4 : {};
91841
+ const record10 = isRecord7(body4) ? body4 : {};
91554
91842
  const detail = typeof record10.detail === "string" ? record10.detail : undefined;
91555
91843
  const error61 = typeof record10.error === "string" ? record10.error : undefined;
91556
91844
  const code = typeof record10.code === "string" ? record10.code : undefined;
@@ -91578,7 +91866,7 @@ function condenseErrorBody(text3) {
91578
91866
  return collapsed;
91579
91867
  return `${collapsed.slice(0, MAX_ERROR_DETAIL_LENGTH - 1).trimEnd()}\u2026`;
91580
91868
  }
91581
- function isRecord6(value) {
91869
+ function isRecord7(value) {
91582
91870
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
91583
91871
  }
91584
91872
 
@@ -92086,16 +92374,16 @@ function resultSnapshot(input2, requestId) {
92086
92374
  const value = snapshot2(input2, SKILL_OPERATION_LIMITS.resultBytes).value;
92087
92375
  if (!record10(value) || value.contractVersion !== 1 || value.requestId !== requestId)
92088
92376
  throw Error();
92089
- const fields = ["contractVersion", "requestId", "status"];
92377
+ const fields2 = ["contractVersion", "requestId", "status"];
92090
92378
  if (value.status === "succeeded")
92091
- fields.push("output");
92379
+ fields2.push("output");
92092
92380
  else if (value.status === "refused") {
92093
- fields.push("code");
92381
+ fields2.push("code");
92094
92382
  if (!refusalCodes.has(value.code))
92095
92383
  throw Error();
92096
92384
  } else if (!["not-executed", "pending", "unknown"].includes(value.status))
92097
92385
  throw Error();
92098
- if (!exact2(value, fields))
92386
+ if (!exact2(value, fields2))
92099
92387
  throw Error();
92100
92388
  return value;
92101
92389
  } catch {