@hasna/skills 0.10.39 → 0.10.42

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/bin/mcp.js CHANGED
@@ -20019,7 +20019,7 @@ var package_default;
20019
20019
  var init_package = __esm(() => {
20020
20020
  package_default = {
20021
20021
  name: "@hasna/skills",
20022
- version: "0.10.39",
20022
+ version: "0.10.42",
20023
20023
  description: "Skills library for AI coding agents",
20024
20024
  type: "module",
20025
20025
  bin: {
@@ -38343,8 +38343,8 @@ function assertAgentPolicyCollections(policy) {
38343
38343
  text(source.path);
38344
38344
  requireBound(source.sha256 === null || typeof source.sha256 === "string" && /^[a-f0-9]{64}$/.test(source.sha256));
38345
38345
  if (source.hashMode !== undefined)
38346
- requireBound(["bytes", "path-bytes", "claude-plugin-registry", "claude-marketplace-registry", "claude-settings-v1", "claude-settings-v2", "claude-settings-v3", "claude-marketplace-registry-v2", "codex-settings-v1", "codex-settings-v2", "codex-settings-v3"].includes(source.hashMode) && source.format === undefined && source.fields === undefined && (source.hashMode === "bytes" || source.sha256 !== null));
38347
- if (source.hashMode === "codex-settings-v1" || source.hashMode === "codex-settings-v2" || source.hashMode === "codex-settings-v3")
38346
+ requireBound(["bytes", "path-bytes", "claude-plugin-registry", "claude-marketplace-registry", "claude-settings-v1", "claude-settings-v2", "claude-settings-v3", "claude-marketplace-registry-v2", "codex-settings-v1", "codex-settings-v2", "codex-settings-v3", "codex-settings-v4"].includes(source.hashMode) && source.format === undefined && source.fields === undefined && (source.hashMode === "bytes" || source.sha256 !== null));
38347
+ if (source.hashMode === "codex-settings-v1" || source.hashMode === "codex-settings-v2" || (source.hashMode === "codex-settings-v3" || source.hashMode === "codex-settings-v4"))
38348
38348
  requireBound(agent === "codex" && value.agent === "codex" && value.method === "reviewed" && !/[\x00-\x1f\x7f]/.test(source.path) && isAbsolute3(source.path) && resolve2(source.path) === source.path && basename3(source.path) === "config.toml");
38349
38349
  if (source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || source.hashMode === "claude-settings-v3")
38350
38350
  requireBound(agent === "claude" && value.agent === "claude" && value.method === "reviewed" && !/[\x00-\x1f\x7f]/.test(source.path) && isAbsolute3(source.path) && resolve2(source.path) === source.path && basename3(source.path) === "settings.json");
@@ -48163,6 +48163,7 @@ var init_codex_mcp_discovery_projection = () => {};
48163
48163
 
48164
48164
  // src/lib/codex-settings-witness.ts
48165
48165
  import { createHash as createHash10 } from "crypto";
48166
+ import { isDeepStrictEqual as isDeepStrictEqual3 } from "util";
48166
48167
  function need4(value) {
48167
48168
  if (!value)
48168
48169
  throw new Error("Invalid Codex settings witness");
@@ -48268,7 +48269,7 @@ function disablesOneSkill(entry) {
48268
48269
  return selector.length === 1 && typeof entry[selector[0]] === "string" && entry[selector[0]].length > 0;
48269
48270
  }
48270
48271
  function inference(target, version2) {
48271
- const keys = version2 === 3 ? [...INFERENCE, "service_tier", "plan_mode_reasoning_effort", "personality"] : INFERENCE;
48272
+ const keys = version2 >= 3 ? [...INFERENCE, "service_tier", "plan_mode_reasoning_effort", "personality"] : INFERENCE;
48272
48273
  for (const key of keys)
48273
48274
  if (Object.hasOwn(target, key)) {
48274
48275
  const value = target[key];
@@ -48276,7 +48277,7 @@ function inference(target, version2) {
48276
48277
  need4(typeof value === "string" && MODEL.test(value));
48277
48278
  else if (key === "personality")
48278
48279
  need4(typeof value === "string" && ["none", "friendly", "pragmatic"].includes(value));
48279
- else if (version2 === 3 && key !== "model_verbosity") {
48280
+ else if (version2 >= 3 && key !== "model_verbosity") {
48280
48281
  need4(typeof value === "string" && value.length <= 128 && !/[\x00-\x1f\x7f]/.test(value));
48281
48282
  if (key !== "service_tier")
48282
48283
  need4(value.length > 0);
@@ -48285,6 +48286,115 @@ function inference(target, version2) {
48285
48286
  delete target[key];
48286
48287
  }
48287
48288
  }
48289
+ function projectModelAvailabilityNux(config2, text2) {
48290
+ const tui = config2.tui, counts = isRecord3(tui) ? tui.model_availability_nux : undefined;
48291
+ if (isRecord3(tui) && !Object.keys(tui).length) {
48292
+ delete config2.tui;
48293
+ return { config: config2, numericSource: text2 };
48294
+ }
48295
+ if (!isRecord3(counts) || Object.keys(counts).length > 256 || !Object.values(counts).every((value) => typeof value === "number" && Number.isInteger(value) && value >= 0 && value <= 4294967295))
48296
+ return { config: config2, numericSource: text2 };
48297
+ const expected = structuredClone(config2);
48298
+ delete expected.tui.model_availability_nux;
48299
+ const stripEmptyTui = (value) => {
48300
+ if (isRecord3(value.tui) && !Object.keys(value.tui).length)
48301
+ delete value.tui;
48302
+ };
48303
+ stripEmptyTui(expected);
48304
+ const headers = [];
48305
+ const spans = [];
48306
+ const integer2 = /^(?:\+?(?:0|[1-9](?:_?\d)*)|0x[0-9a-fA-F](?:_?[0-9a-fA-F])*|0o[0-7](?:_?[0-7])*|0b[01](?:_?[01])*)$/;
48307
+ const counterIntegers = (span) => {
48308
+ let values = 0;
48309
+ for (let at = 0;at < span.length; ) {
48310
+ const char = span[at];
48311
+ if (char === "#") {
48312
+ while (at < span.length && span[at] !== `
48313
+ `)
48314
+ at++;
48315
+ continue;
48316
+ }
48317
+ if (char === '"' || char === "'") {
48318
+ const quote = char;
48319
+ at++;
48320
+ while (at < span.length) {
48321
+ if (quote === '"' && span[at] === "\\") {
48322
+ at += 2;
48323
+ continue;
48324
+ }
48325
+ if (span[at++] === quote)
48326
+ break;
48327
+ }
48328
+ continue;
48329
+ }
48330
+ if (char !== "=") {
48331
+ at++;
48332
+ continue;
48333
+ }
48334
+ at++;
48335
+ while (at < span.length && /\s/.test(span[at]))
48336
+ at++;
48337
+ if (span[at] === "{") {
48338
+ at++;
48339
+ continue;
48340
+ }
48341
+ const start = at;
48342
+ while (at < span.length && !/[\s,\]{}#]/.test(span[at]))
48343
+ at++;
48344
+ if (!integer2.test(span.slice(start, at)))
48345
+ return false;
48346
+ values++;
48347
+ }
48348
+ return values === Object.keys(counts).length;
48349
+ };
48350
+ let attempts = 0;
48351
+ const realPrefix = (end) => {
48352
+ if (++attempts > 256)
48353
+ return false;
48354
+ try {
48355
+ Bun.TOML.parse(text2.slice(0, end));
48356
+ return true;
48357
+ } catch {
48358
+ return false;
48359
+ }
48360
+ };
48361
+ for (const match of text2.matchAll(/^[ \t]*\[[^\r\n]+\][ \t]*(?:#[^\r\n]*)?(?:\r?\n|$)/gm)) {
48362
+ const start = match.index, end = start + match[0].length;
48363
+ if (realPrefix(end))
48364
+ headers.push({ start, end });
48365
+ }
48366
+ for (let at = 0;at < headers.length; at++) {
48367
+ const header = headers[at];
48368
+ let parsed;
48369
+ try {
48370
+ parsed = Bun.TOML.parse(text2.slice(header.start, header.end));
48371
+ } catch {
48372
+ continue;
48373
+ }
48374
+ if (isRecord3(parsed.tui) && isRecord3(parsed.tui.model_availability_nux) && !Object.keys(parsed.tui.model_availability_nux).length && Object.keys(parsed).length === 1 && Object.keys(parsed.tui).length === 1)
48375
+ spans.push({ start: header.start, end: headers[at + 1]?.start ?? text2.length });
48376
+ }
48377
+ for (const match of text2.matchAll(/^[ \t]*(?:(?:tui|"tui"|'tui')[ \t]*\.[ \t]*)?(?:model_availability_nux|"model_availability_nux"|'model_availability_nux')[ \t]*=[ \t]*\{[^\r\n]*(?:\r?\n|$)/gm)) {
48378
+ const start = match.index, end = start + match[0].length;
48379
+ if (realPrefix(end))
48380
+ spans.push({ start, end });
48381
+ }
48382
+ for (const { start, end } of spans) {
48383
+ if (!counterIntegers(text2.slice(start, end)))
48384
+ continue;
48385
+ const remaining = text2.slice(0, start) + text2.slice(end);
48386
+ let parsed;
48387
+ try {
48388
+ parsed = Bun.TOML.parse(remaining);
48389
+ } catch {
48390
+ continue;
48391
+ }
48392
+ stripEmptyTui(parsed);
48393
+ if (isDeepStrictEqual3(parsed, expected))
48394
+ return { config: expected, numericSource: remaining };
48395
+ }
48396
+ return { config: config2, numericSource: text2 };
48397
+ }
48288
48398
  function settingsDigest2(text2, version2 = 2) {
48289
48399
  let config2;
48290
48400
  try {
@@ -48293,7 +48403,8 @@ function settingsDigest2(text2, version2 = 2) {
48293
48403
  throw new Error("Invalid Codex settings witness");
48294
48404
  }
48295
48405
  need4(isRecord3(config2));
48296
- const projected = version2 === 3 ? projectRegularCodexMcp(config2, text2) : { config: config2, numericSource: text2 };
48406
+ const mcp = version2 >= 3 ? projectRegularCodexMcp(config2, text2) : { config: config2, numericSource: text2 };
48407
+ const projected = version2 === 4 ? projectModelAvailabilityNux(mcp.config, mcp.numericSource) : mcp;
48297
48408
  normalize2(projected.config, version2);
48298
48409
  return sha2(`hasna.skills.codex-settings.v${version2}\x00${JSON.stringify([canonical4(projected.config), numericTokens2(projected.numericSource)])}`);
48299
48410
  }
@@ -48314,6 +48425,14 @@ function hashCodexSettingsReplacementV3(text2, budget = { remaining: 256 * 1024
48314
48425
  function captureCodexSettingsV3(path, budget = { remaining: 256 * 1024 * 1024 }) {
48315
48426
  return { path, hashMode: "codex-settings-v3", sha256: settingsDigest2(readNativeSettingsWitnessFile(path, budget, "config.toml"), 3) };
48316
48427
  }
48428
+ function hashCodexSettingsReplacementV4(text2, budget = { remaining: 256 * 1024 * 1024 }) {
48429
+ need4(Buffer.byteLength(text2) <= 1024 * 1024 && budget.remaining >= Buffer.byteLength(text2));
48430
+ budget.remaining -= Buffer.byteLength(text2);
48431
+ return settingsDigest2(text2, 4);
48432
+ }
48433
+ function captureCodexSettingsV4(path, budget = { remaining: 256 * 1024 * 1024 }) {
48434
+ return { path, hashMode: "codex-settings-v4", sha256: settingsDigest2(readNativeSettingsWitnessFile(path, budget, "config.toml"), 4) };
48435
+ }
48317
48436
  var sha2 = (text2) => createHash10("sha256").update(text2).digest("hex"), EFFORT2, VERBOSITY2, MODEL, CODEX_DISCOVERY_PROJECTION_FIELDS, INFERENCE;
48318
48437
  var init_codex_settings_witness = __esm(() => {
48319
48438
  init_codex_settings_witness_v1();
@@ -50114,7 +50233,7 @@ var init_codex_hook_discovery_recovery = __esm(() => {
50114
50233
  import { createHash as createHash16 } from "crypto";
50115
50234
  import { lstatSync as lstatSync18, readFileSync as readFileSync15, readdirSync as readdirSync7, realpathSync as realpathSync5 } from "fs";
50116
50235
  import { basename as basename8, dirname as dirname15, isAbsolute as isAbsolute13, join as join25, resolve as resolve15, sep as sep5 } from "path";
50117
- import { isDeepStrictEqual as isDeepStrictEqual3 } from "util";
50236
+ import { isDeepStrictEqual as isDeepStrictEqual4 } from "util";
50118
50237
  function parseConfig(text2, path, toml = false) {
50119
50238
  try {
50120
50239
  const value = toml ? Bun.TOML.parse(text2) : JSON.parse(text2);
@@ -50153,19 +50272,19 @@ function projectNativeDiscoveryFields(text2, format, fields2, path) {
50153
50272
  return digest(JSON.stringify(Object.fromEntries(fields2.map((field2) => [field2, object7[field2] ?? null]))));
50154
50273
  }
50155
50274
  function isSupersededCodexProjection(agent, configPath, source) {
50156
- return agent === "codex" && source.path === configPath && source.format === "toml" && isDeepStrictEqual3(source.fields, [...CODEX_DISCOVERY_PROJECTION_FIELDS]);
50275
+ return agent === "codex" && source.path === configPath && source.format === "toml" && isDeepStrictEqual4(source.fields, [...CODEX_DISCOVERY_PROJECTION_FIELDS]);
50157
50276
  }
50158
50277
  function supersedesCodexProjection(sources, configPath) {
50159
- return sources.some((source) => source.path === configPath && (source.hashMode === "codex-settings-v2" || source.hashMode === "codex-settings-v3"));
50278
+ return sources.some((source) => source.path === configPath && (source.hashMode === "codex-settings-v2" || (source.hashMode === "codex-settings-v3" || source.hashMode === "codex-settings-v4")));
50160
50279
  }
50161
50280
  function projected(source, changes, budget = discoveryByteBudget()) {
50162
- if (source.hashMode === "codex-settings-v1" || source.hashMode === "codex-settings-v2" || source.hashMode === "codex-settings-v3") {
50281
+ if (source.hashMode === "codex-settings-v1" || source.hashMode === "codex-settings-v2" || (source.hashMode === "codex-settings-v3" || source.hashMode === "codex-settings-v4")) {
50163
50282
  if (source.format !== undefined || source.fields !== undefined || source.managedPlugins !== undefined || typeof source.sha256 !== "string" || !/^[a-f0-9]{64}$/.test(source.sha256))
50164
50283
  throw new Error("Codex settings witnesses require exact typed metadata");
50165
- const current = (source.hashMode === "codex-settings-v3" ? captureCodexSettingsV3 : source.hashMode === "codex-settings-v2" ? captureCodexSettingsV2 : captureCodexSettings)(source.path, budget).sha256;
50284
+ const current = (source.hashMode === "codex-settings-v4" ? captureCodexSettingsV4 : source.hashMode === "codex-settings-v3" ? captureCodexSettingsV3 : source.hashMode === "codex-settings-v2" ? captureCodexSettingsV2 : captureCodexSettings)(source.path, budget).sha256;
50166
50285
  if (current !== source.sha256)
50167
50286
  throw new Error(`Native discovery input changed; run skills hook install with a fresh discovery review: ${source.path}`);
50168
- return changes?.has(source.path) ? (source.hashMode === "codex-settings-v3" ? hashCodexSettingsReplacementV3 : source.hashMode === "codex-settings-v2" ? hashCodexSettingsReplacementV2 : hashCodexSettingsReplacement)(changes.get(source.path), budget) : current;
50287
+ return changes?.has(source.path) ? (source.hashMode === "codex-settings-v4" ? hashCodexSettingsReplacementV4 : source.hashMode === "codex-settings-v3" ? hashCodexSettingsReplacementV3 : source.hashMode === "codex-settings-v2" ? hashCodexSettingsReplacementV2 : hashCodexSettingsReplacement)(changes.get(source.path), budget) : current;
50169
50288
  }
50170
50289
  if (source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || source.hashMode === "claude-settings-v3") {
50171
50290
  if (source.format !== undefined || source.fields !== undefined || source.managedPlugins !== undefined || typeof source.sha256 !== "string" || !/^[a-f0-9]{64}$/.test(source.sha256))
@@ -50321,7 +50440,7 @@ function verifyAgentDiscovery(binding, codexRecovery) {
50321
50440
  if (omitted.some((root) => !retiredRoots.includes(root)))
50322
50441
  throw new Error("Missing reviewed directory membership inventory; provide a fresh discovery review");
50323
50442
  const current = captureDiscoveryDirectoryProjection(ordinary.map((item) => item.path), retiredRoots).map(({ entries, ...item }) => item);
50324
- if (!isDeepStrictEqual3(current, projection))
50443
+ if (!isDeepStrictEqual4(current, projection))
50325
50444
  throw new Error("Native discovery directory membership changed outside retired Codex roots");
50326
50445
  }
50327
50446
  } else
@@ -50380,7 +50499,7 @@ function codexInstallationRoots(binding) {
50380
50499
  });
50381
50500
  }
50382
50501
  function assertMarketplaceBinding(binding, source) {
50383
- if ((source.hashMode === "codex-settings-v1" || source.hashMode === "codex-settings-v2" || source.hashMode === "codex-settings-v3") && (binding.agent !== "codex" || binding.method !== "reviewed" || basename8(source.path) !== "config.toml"))
50502
+ if ((source.hashMode === "codex-settings-v1" || source.hashMode === "codex-settings-v2" || (source.hashMode === "codex-settings-v3" || source.hashMode === "codex-settings-v4")) && (binding.agent !== "codex" || binding.method !== "reviewed" || basename8(source.path) !== "config.toml"))
50384
50503
  throw new Error("Codex settings witnesses require explicit reviewed Codex configuration");
50385
50504
  if ((source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || source.hashMode === "claude-settings-v3") && (binding.agent !== "claude" || binding.method !== "reviewed" || basename8(source.path) !== "settings.json"))
50386
50505
  throw new Error("Claude settings witnesses require explicit reviewed Claude configuration");
@@ -50501,10 +50620,10 @@ function resolveAgentDiscovery(options) {
50501
50620
  verifyAgentDiscovery(retained);
50502
50621
  if (!retained.sources.some((source) => source.path === canonical6(configPath) && source.format === undefined && source.fields === undefined))
50503
50622
  unresolved("retained review is missing the full agent configuration source");
50504
- if (retained.sources.some((source) => (source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || (source.hashMode === "claude-settings-v3" || (source.hashMode === "codex-settings-v1" || source.hashMode === "codex-settings-v2" || source.hashMode === "codex-settings-v3"))) && source.path !== canonical6(configPath)))
50623
+ if (retained.sources.some((source) => (source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || (source.hashMode === "claude-settings-v3" || (source.hashMode === "codex-settings-v1" || source.hashMode === "codex-settings-v2" || (source.hashMode === "codex-settings-v3" || source.hashMode === "codex-settings-v4")))) && source.path !== canonical6(configPath)))
50505
50624
  unresolved("retained settings witness names another configuration source");
50506
50625
  const covered = supersedesCodexProjection(retained.sources, canonical6(configPath)) ? sources.filter((source) => !isSupersededCodexProjection(agent, canonical6(configPath), source)) : sources;
50507
- if (covered.some((source) => !retained.sources.some((saved) => isDeepStrictEqual3(saved, source))) || [...roots].some((root) => !retained.roots.includes(root)) || agent === "gemini" && JSON.stringify(retained.builtinNames) !== JSON.stringify(builtinNames))
50626
+ if (covered.some((source) => !retained.sources.some((saved) => isDeepStrictEqual4(saved, source))) || [...roots].some((root) => !retained.roots.includes(root)) || agent === "gemini" && JSON.stringify(retained.builtinNames) !== JSON.stringify(builtinNames))
50508
50627
  unresolved("retained review is missing current runtime discovery coverage");
50509
50628
  return retained;
50510
50629
  }
@@ -50518,7 +50637,7 @@ function resolveAgentDiscovery(options) {
50518
50637
  if (review.sources.some((source) => source.format !== undefined || source.fields !== undefined))
50519
50638
  throw new Error("Explicit discovery reviews require full source-file hashes");
50520
50639
  verifyAgentDiscovery(supplied);
50521
- if (review.sources.some((source) => (source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || (source.hashMode === "claude-settings-v3" || (source.hashMode === "codex-settings-v1" || source.hashMode === "codex-settings-v2" || source.hashMode === "codex-settings-v3"))) && source.path !== canonical6(configPath)))
50640
+ if (review.sources.some((source) => (source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || (source.hashMode === "claude-settings-v3" || (source.hashMode === "codex-settings-v1" || source.hashMode === "codex-settings-v2" || (source.hashMode === "codex-settings-v3" || source.hashMode === "codex-settings-v4")))) && source.path !== canonical6(configPath)))
50522
50641
  throw new Error("Semantic settings witnesses must name the configured Claude configuration source");
50523
50642
  if (!review.sources.some((source) => source.path === canonical6(configPath)))
50524
50643
  throw new Error("Discovery review must include the agent configuration source");
@@ -58865,7 +58984,7 @@ var init_execution_grants = __esm(() => {
58865
58984
  });
58866
58985
 
58867
58986
  // src/lib/execution-grant-client.ts
58868
- import { isDeepStrictEqual as isDeepStrictEqual4 } from "util";
58987
+ import { isDeepStrictEqual as isDeepStrictEqual5 } from "util";
58869
58988
  function id(value) {
58870
58989
  if (!grantIdentifier(value))
58871
58990
  throw new Error("Invalid execution grant profile or revision identifier.");
@@ -58908,7 +59027,7 @@ async function resolveExecutionGrant(input2) {
58908
59027
  if (!grantRecord(value) || Object.keys(value).length !== 3 || !grantIdentifier(value.policyRevision) || !grantIdentifier(value.grantId) || !grantRecord(value.bindings)) {
58909
59028
  throw new SkillSelectionError("INVALID_EXECUTION_GRANT", "The Skills API returned an invalid execution grant.");
58910
59029
  }
58911
- if (!isDeepStrictEqual4(value.bindings.selection, snapshot2.selection) || !isDeepStrictEqual4(value.bindings.consumer, snapshot2.consumer)) {
59030
+ if (!isDeepStrictEqual5(value.bindings.selection, snapshot2.selection) || !isDeepStrictEqual5(value.bindings.consumer, snapshot2.consumer)) {
58912
59031
  throw new SkillSelectionError("EXECUTION_GRANT_SCOPE_MISMATCH", "The Skills API returned a grant for a different selection or consumer.");
58913
59032
  }
58914
59033
  return value;
package/bin/migrate.js CHANGED
@@ -7,7 +7,7 @@ import { join as join5 } from "path";
7
7
  // package.json
8
8
  var package_default = {
9
9
  name: "@hasna/skills",
10
- version: "0.10.39",
10
+ version: "0.10.42",
11
11
  description: "Skills library for AI coding agents",
12
12
  type: "module",
13
13
  bin: {
package/bin/server.js CHANGED
@@ -24122,7 +24122,7 @@ var init_dist_es9 = __esm(() => {
24122
24122
  // package.json
24123
24123
  var package_default = {
24124
24124
  name: "@hasna/skills",
24125
- version: "0.10.39",
24125
+ version: "0.10.42",
24126
24126
  description: "Skills library for AI coding agents",
24127
24127
  type: "module",
24128
24128
  bin: {
package/bin/worker.js CHANGED
@@ -24125,7 +24125,7 @@ import { randomUUID as randomUUID6 } from "crypto";
24125
24125
  // package.json
24126
24126
  var package_default = {
24127
24127
  name: "@hasna/skills",
24128
- version: "0.10.39",
24128
+ version: "0.10.42",
24129
24129
  description: "Skills library for AI coding agents",
24130
24130
  type: "module",
24131
24131
  bin: {
@@ -0,0 +1,17 @@
1
+ type Row = Record<string, unknown>;
2
+ export interface ReviewedRuntimeLockContext {
3
+ version: string;
4
+ archiveIntegrity: string;
5
+ packageManifest: Row;
6
+ registryOrigin: string;
7
+ minReleaseAge: number;
8
+ minReleaseAgeExclude: string[];
9
+ fetcher?: typeof fetch;
10
+ now?: number;
11
+ }
12
+ /** Validate the immutable install input without resolving any version ranges.
13
+ * npm ci subsequently verifies archive bytes and package/root range agreement;
14
+ * npm sbom forceActual validates the installed required closure, including optional peers.
15
+ */
16
+ export declare function validateReviewedRuntimeLock(bytes: Uint8Array, sha256: string, context: ReviewedRuntimeLockContext): Promise<void>;
17
+ export {};
@@ -28,6 +28,8 @@ export declare function updateCopyfileRuntime(version: string, options?: {
28
28
  fetcher?: typeof fetch;
29
29
  minReleaseAge?: number;
30
30
  minReleaseAgeExclude?: string[];
31
+ reviewedLock?: string;
32
+ reviewedLockSha256?: string;
31
33
  onLauncherSwitched?: (path: string) => void;
32
34
  }): Promise<JsonObject>;
33
35
  export declare function rollbackCopyfileRuntime(receiptId: string, options?: {
package/dist/index.d.ts CHANGED
@@ -71,5 +71,5 @@ export { captureManagedPluginRegistry, type ManagedPluginRegistrationWitness } f
71
71
  export type { RemoteCreditCheckoutOptions, RemoteCreditCheckout, RemoteCreditCheckoutErrorCode } from "./lib/remote-credit-checkout.js";
72
72
  export { assertPortableAuthoringPath, type PortableAuthoringPathOptions } from "./lib/authoring-path.js";
73
73
  export { CLAUDE_COORDINATED_HOOK_EVENTS, type ClaudeCoordinatedHookEvent } from "./lib/claude-settings-witness.js";
74
- export { captureCodexSettings, captureCodexSettingsV2, captureCodexSettingsV3, upgradeCodexSettingsWitness, upgradeCodexSettingsWitnessV3 } from "./lib/codex-settings-witness.js";
74
+ export { captureCodexSettings, captureCodexSettingsV2, captureCodexSettingsV3, captureCodexSettingsV4, upgradeCodexSettingsWitness, upgradeCodexSettingsWitnessV3, upgradeCodexSettingsWitnessV4 } from "./lib/codex-settings-witness.js";
75
75
  export { projectCodexNativeSkillCatalog, projectCodexInstalledPlugins, projectCodexInstalledPluginEntries, captureCodexNativeSkillCatalog, isCodexNativeSkillDisabled, type CodexNativeSkillCatalog, type CodexNativeSkill, type CodexInstalledPlugin } from "./lib/codex-native-skill-catalog.js";