@hasna/skills 0.10.25 → 0.10.27

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -9101,8 +9101,8 @@ function assertAgentPolicyCollections(policy) {
9101
9101
  text(source.path);
9102
9102
  requireBound(source.sha256 === null || typeof source.sha256 === "string" && /^[a-f0-9]{64}$/.test(source.sha256));
9103
9103
  if (source.hashMode !== undefined)
9104
- 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));
9105
- if (source.hashMode === "codex-settings-v1" || source.hashMode === "codex-settings-v2")
9104
+ 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));
9105
+ if (source.hashMode === "codex-settings-v1" || source.hashMode === "codex-settings-v2" || source.hashMode === "codex-settings-v3")
9106
9106
  requireBound(agent === "codex" && value.agent === "codex" && value.method === "reviewed" && !/[\x00-\x1f\x7f]/.test(source.path) && isAbsolute2(source.path) && resolve2(source.path) === source.path && basename2(source.path) === "config.toml");
9107
9107
  if (source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || source.hashMode === "claude-settings-v3")
9108
9108
  requireBound(agent === "claude" && value.agent === "claude" && value.method === "reviewed" && !/[\x00-\x1f\x7f]/.test(source.path) && isAbsolute2(source.path) && resolve2(source.path) === source.path && basename2(source.path) === "settings.json");
@@ -9141,7 +9141,7 @@ function assertAgentPolicyCollections(policy) {
9141
9141
  import { createHash as createHash18 } from "crypto";
9142
9142
  import { lstatSync as lstatSync21, readFileSync as readFileSync17, readdirSync as readdirSync10, realpathSync as realpathSync7 } from "fs";
9143
9143
  import { basename as basename9, dirname as dirname17, isAbsolute as isAbsolute16, join as join27, resolve as resolve15, sep as sep6 } from "path";
9144
- import { isDeepStrictEqual as isDeepStrictEqual4 } from "util";
9144
+ import { isDeepStrictEqual as isDeepStrictEqual5 } from "util";
9145
9145
 
9146
9146
  // node_modules/yaml/dist/index.js
9147
9147
  var composer = require_composer();
@@ -10914,7 +10914,7 @@ function replaceSkillSession(expected, replacement, plan, options = {}, beforeCo
10914
10914
  // package.json
10915
10915
  var package_default = {
10916
10916
  name: "@hasna/skills",
10917
- version: "0.10.25",
10917
+ version: "0.10.27",
10918
10918
  description: "Skills library for AI coding agents",
10919
10919
  type: "module",
10920
10920
  bin: {
@@ -12749,6 +12749,72 @@ import {
12749
12749
  import { homedir as homedir3 } from "os";
12750
12750
  import { basename as basename6, dirname as dirname12, join as join18 } from "path";
12751
12751
 
12752
+ // src/lib/codex-local-mcp-controls.ts
12753
+ function isCodexLocalStdioMcpServer(name, server) {
12754
+ const identifier2 = (value) => typeof value === "string" && /^[A-Za-z0-9_-]{1,64}$/.test(value);
12755
+ const refuse = () => {
12756
+ throw new Error("Unsupported Codex local stdio MCP controls");
12757
+ };
12758
+ const object4 = (v) => Boolean(v && typeof v === "object" && !Array.isArray(v) && !(v instanceof Date));
12759
+ const textField = (v, empty = false) => typeof v === "string" && (empty || Boolean(v.trim())) && Buffer.byteLength(v) <= 16384 && !/[\x00-\x1f\x7f]/.test(v);
12760
+ const envName = (v) => typeof v === "string" && /^[A-Za-z_][A-Za-z0-9_]{0,255}$/.test(v);
12761
+ const optional = (v, valid) => v === undefined || v === null || valid(v);
12762
+ const stringList = (v) => Array.isArray(v) && v.length <= 256 && v.every((item) => textField(item));
12763
+ const approval = (v) => ["auto", "prompt", "writes", "approve"].includes(v);
12764
+ const duration = (v) => typeof v === "number" && Number.isFinite(v) && v >= 0;
12765
+ const positiveInteger = (v) => Number.isSafeInteger(v) && v > 0;
12766
+ const fields = [
12767
+ "command",
12768
+ "args",
12769
+ "cwd",
12770
+ "env",
12771
+ "env_vars",
12772
+ "enabled",
12773
+ "required",
12774
+ "environment_id",
12775
+ "startup_readiness",
12776
+ "supports_parallel_tool_calls",
12777
+ "tool_input_schema_max_bytes",
12778
+ "startup_timeout_sec",
12779
+ "startup_timeout_ms",
12780
+ "tool_timeout_sec",
12781
+ "default_tools_approval_mode",
12782
+ "enabled_tools",
12783
+ "disabled_tools",
12784
+ "omit_tools_from",
12785
+ "tools",
12786
+ "name"
12787
+ ];
12788
+ try {
12789
+ if (!identifier2(name) || !object4(server) || !Object.keys(server).every((key) => fields.includes(key)) || !textField(server.command) || !optional(server.args, (v) => Array.isArray(v) && v.length <= 256 && v.every((arg) => textField(arg, true))) || !optional(server.cwd, textField) || !optional(server.env, (v) => object4(v) && Object.keys(v).length <= 256 && Object.entries(v).every(([key, value]) => envName(key) && textField(value, true))) || !["enabled", "required", "supports_parallel_tool_calls"].every((key) => optional(server[key], (v) => typeof v === "boolean")) || !optional(server.environment_id, (v) => v === "local") || !optional(server.startup_readiness, (v) => ["connection", "catalog"].includes(v)) || !optional(server.tool_input_schema_max_bytes, positiveInteger) || !["startup_timeout_sec", "tool_timeout_sec"].every((key) => optional(server[key], duration)) || !optional(server.startup_timeout_ms, (v) => Number.isSafeInteger(v) && v >= 0) || !optional(server.default_tools_approval_mode, approval) || !["enabled_tools", "disabled_tools"].every((key) => optional(server[key], stringList)) || !optional(server.omit_tools_from, (v) => Array.isArray(v) && v.length <= 256 && v.every((item) => ["code_mode", "deferred", "direct"].includes(item))) || !optional(server.name, textField))
12790
+ refuse();
12791
+ if (server.env_vars !== undefined && server.env_vars !== null) {
12792
+ if (!Array.isArray(server.env_vars) || server.env_vars.length > 256)
12793
+ refuse();
12794
+ const names = server.env_vars.map((entry) => {
12795
+ if (envName(entry))
12796
+ return entry;
12797
+ if (!object4(entry) || !Object.keys(entry).every((key) => ["name", "source"].includes(key)) || !envName(entry.name) || !optional(entry.source, (v) => v === "local"))
12798
+ refuse();
12799
+ return entry.name;
12800
+ });
12801
+ if (new Set(names).size !== names.length)
12802
+ refuse();
12803
+ }
12804
+ if (server.tools !== undefined && server.tools !== null) {
12805
+ if (!object4(server.tools) || Object.keys(server.tools).length > 256)
12806
+ refuse();
12807
+ for (const [tool, config] of Object.entries(server.tools)) {
12808
+ if (!textField(tool) || !object4(config) || !Object.keys(config).every((key) => ["approval_mode", "output_token_limit"].includes(key)) || !optional(config.approval_mode, approval) || !optional(config.output_token_limit, positiveInteger))
12809
+ refuse();
12810
+ }
12811
+ }
12812
+ return true;
12813
+ } catch {
12814
+ return false;
12815
+ }
12816
+ }
12817
+
12752
12818
  // src/lib/claude-settings-witness.ts
12753
12819
  import { createHash as createHash8 } from "crypto";
12754
12820
  import { closeSync as closeSync6, constants as constants5, fstatSync as fstatSync6, lstatSync as lstatSync11, openSync as openSync6, readSync as readSync4 } from "fs";
@@ -13430,65 +13496,14 @@ function mcpControls(path, read2) {
13430
13496
  refuse2();
13431
13497
  }
13432
13498
  const object5 = (v) => Boolean(v && typeof v === "object" && !Array.isArray(v));
13433
- const textField = (v, empty = false) => typeof v === "string" && (empty || Boolean(v.trim())) && Buffer.byteLength(v) <= 16384 && !/[\x00-\x1f\x7f]/.test(v);
13434
- const envName = (v) => typeof v === "string" && /^[A-Za-z_][A-Za-z0-9_]{0,255}$/.test(v);
13435
- const optional = (v, valid) => v === undefined || v === null || valid(v);
13436
- const stringList = (v) => Array.isArray(v) && v.length <= 256 && v.every((item) => textField(item));
13437
- const approval = (v) => ["auto", "prompt", "writes", "approve"].includes(v);
13438
- const duration = (v) => typeof v === "number" && Number.isFinite(v) && v >= 0;
13439
- const positiveInteger = (v) => Number.isSafeInteger(v) && v > 0;
13440
- const fields = [
13441
- "command",
13442
- "args",
13443
- "cwd",
13444
- "env",
13445
- "env_vars",
13446
- "enabled",
13447
- "required",
13448
- "environment_id",
13449
- "startup_readiness",
13450
- "supports_parallel_tool_calls",
13451
- "tool_input_schema_max_bytes",
13452
- "startup_timeout_sec",
13453
- "startup_timeout_ms",
13454
- "tool_timeout_sec",
13455
- "default_tools_approval_mode",
13456
- "enabled_tools",
13457
- "disabled_tools",
13458
- "omit_tools_from",
13459
- "tools",
13460
- "name"
13461
- ];
13462
13499
  if (!object5(value) || Object.keys(value).length !== 1 || !object5(value.mcpServers))
13463
13500
  refuse2();
13464
13501
  const servers = Object.entries(value.mcpServers);
13465
13502
  if (!servers.length || servers.length > 256)
13466
13503
  refuse2();
13467
- for (const [name, server] of servers) {
13468
- if (!identifier2(name) || !object5(server) || !Object.keys(server).every((key) => fields.includes(key)) || !textField(server.command) || !optional(server.args, (v) => Array.isArray(v) && v.length <= 256 && v.every((arg) => textField(arg, true))) || !optional(server.cwd, textField) || !optional(server.env, (v) => object5(v) && Object.keys(v).length <= 256 && Object.entries(v).every(([key, value2]) => envName(key) && textField(value2, true))) || !["enabled", "required", "supports_parallel_tool_calls"].every((key) => optional(server[key], (v) => typeof v === "boolean")) || !optional(server.environment_id, (v) => v === "local") || !optional(server.startup_readiness, (v) => ["connection", "catalog"].includes(v)) || !optional(server.tool_input_schema_max_bytes, positiveInteger) || !["startup_timeout_sec", "tool_timeout_sec"].every((key) => optional(server[key], duration)) || !optional(server.startup_timeout_ms, (v) => Number.isSafeInteger(v) && v >= 0) || !optional(server.default_tools_approval_mode, approval) || !["enabled_tools", "disabled_tools"].every((key) => optional(server[key], stringList)) || !optional(server.omit_tools_from, (v) => Array.isArray(v) && v.length <= 256 && v.every((item) => ["code_mode", "deferred", "direct"].includes(item))) || !optional(server.name, textField))
13504
+ for (const [name, server] of servers)
13505
+ if (!isCodexLocalStdioMcpServer(name, server))
13469
13506
  refuse2();
13470
- if (server.env_vars !== undefined && server.env_vars !== null) {
13471
- if (!Array.isArray(server.env_vars) || server.env_vars.length > 256)
13472
- refuse2();
13473
- const names = server.env_vars.map((entry) => {
13474
- if (envName(entry))
13475
- return entry;
13476
- if (!object5(entry) || !Object.keys(entry).every((key) => ["name", "source"].includes(key)) || !envName(entry.name) || !optional(entry.source, (v) => v === "local"))
13477
- refuse2();
13478
- return entry.name;
13479
- });
13480
- if (new Set(names).size !== names.length)
13481
- refuse2();
13482
- }
13483
- if (server.tools !== undefined && server.tools !== null) {
13484
- if (!object5(server.tools) || Object.keys(server.tools).length > 256)
13485
- refuse2();
13486
- for (const [tool, config] of Object.entries(server.tools)) {
13487
- if (!textField(tool) || !object5(config) || !Object.keys(config).every((key) => ["approval_mode", "output_token_limit"].includes(key)) || !optional(config.approval_mode, approval) || !optional(config.output_token_limit, positiveInteger))
13488
- refuse2();
13489
- }
13490
- }
13491
- }
13492
13507
  return sha2562;
13493
13508
  }
13494
13509
  function rootControls(root, read2) {
@@ -13858,6 +13873,69 @@ function captureCodexSettings(path, budget = { remaining: 256 * 1024 * 1024 }) {
13858
13873
  const text2 = readNativeSettingsWitnessFile(path, budget, "config.toml");
13859
13874
  return { path, hashMode: "codex-settings-v1", sha256: hashCodexSettingsReplacement(text2) };
13860
13875
  }
13876
+ // src/lib/codex-mcp-discovery-projection.ts
13877
+ import { isDeepStrictEqual as isDeepStrictEqual2 } from "util";
13878
+ function record2(value) {
13879
+ return !!value && typeof value === "object" && !Array.isArray(value) && !(value instanceof Date);
13880
+ }
13881
+ function localStdio(name, row) {
13882
+ return name !== "codex_apps" && name !== "_codex_apps" && isCodexLocalStdioMcpServer(name, row);
13883
+ }
13884
+ function stripEmptyParent(config) {
13885
+ if (record2(config.mcp_servers) && !Object.keys(config.mcp_servers).length)
13886
+ delete config.mcp_servers;
13887
+ return config;
13888
+ }
13889
+ function projectRegularCodexMcp(config, source) {
13890
+ const unchanged2 = { config, numericSource: source };
13891
+ if (!record2(config.mcp_servers))
13892
+ return unchanged2;
13893
+ const candidates = Object.entries(config.mcp_servers).filter(([name, row]) => localStdio(name, row)).map(([name]) => name);
13894
+ if (!candidates.length)
13895
+ return unchanged2;
13896
+ const headers = [];
13897
+ let attempts = 0;
13898
+ for (const match of source.matchAll(/^[ \t]*\[{1,2}[^\r\n]*\]{1,2}[ \t]*(?:#[^\r\n]*)?(?:\r?\n|$)/gm)) {
13899
+ if (++attempts > 256)
13900
+ return unchanged2;
13901
+ try {
13902
+ Bun.TOML.parse(source.slice(0, match.index));
13903
+ } catch {
13904
+ continue;
13905
+ }
13906
+ let header;
13907
+ try {
13908
+ header = Bun.TOML.parse(match[0]);
13909
+ } catch {
13910
+ return unchanged2;
13911
+ }
13912
+ const path = [];
13913
+ while (record2(header) && Object.keys(header).length === 1) {
13914
+ const key = Object.keys(header)[0];
13915
+ path.push(key);
13916
+ header = header[key];
13917
+ }
13918
+ headers.push({ start: match.index, path });
13919
+ }
13920
+ const names = candidates.filter((name) => headers.filter((header) => header.path.length === 2 && header.path[0] === "mcp_servers" && header.path[1] === name).length === 1);
13921
+ if (!names.length)
13922
+ return unchanged2;
13923
+ const selected = headers.map((header, index) => ({ ...header, end: headers[index + 1]?.start ?? source.length })).filter((header) => header.path[0] === "mcp_servers" && names.includes(header.path[1]));
13924
+ let numericSource = source;
13925
+ for (const range of selected.reverse())
13926
+ numericSource = numericSource.slice(0, range.start) + numericSource.slice(range.end);
13927
+ const expected = structuredClone(config);
13928
+ for (const name of names)
13929
+ delete expected.mcp_servers[name];
13930
+ stripEmptyParent(expected);
13931
+ try {
13932
+ if (!isDeepStrictEqual2(stripEmptyParent(Bun.TOML.parse(numericSource)), expected))
13933
+ return unchanged2;
13934
+ } catch {
13935
+ return unchanged2;
13936
+ }
13937
+ return { config: expected, numericSource };
13938
+ }
13861
13939
 
13862
13940
  // src/lib/codex-settings-witness.ts
13863
13941
  import { createHash as createHash10 } from "crypto";
@@ -13937,7 +14015,7 @@ function canonical4(value, depth = 0, budget = { remaining: 65536 }) {
13937
14015
  need4(isRecord3(value));
13938
14016
  return ["object", Object.entries(value).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0).map(([key, child]) => [key, canonical4(child, depth + 1, budget)])];
13939
14017
  }
13940
- function normalize3(config) {
14018
+ function normalize3(config, version = 2) {
13941
14019
  if (isRecord3(config.hooks)) {
13942
14020
  delete config.hooks.state;
13943
14021
  if (!Object.keys(config.hooks).length)
@@ -13955,11 +14033,11 @@ function normalize3(config) {
13955
14033
  if (!Object.keys(skills).length)
13956
14034
  delete config.skills;
13957
14035
  }
13958
- inference(config);
14036
+ inference(config, version);
13959
14037
  if (isRecord3(config.profiles)) {
13960
14038
  for (const profile of Object.values(config.profiles))
13961
14039
  if (isRecord3(profile))
13962
- inference(profile);
14040
+ inference(profile, version);
13963
14041
  }
13964
14042
  }
13965
14043
  function disablesOneSkill(entry) {
@@ -13971,18 +14049,23 @@ function disablesOneSkill(entry) {
13971
14049
  const selector = ["path", "name"].filter((key) => Object.hasOwn(entry, key));
13972
14050
  return selector.length === 1 && typeof entry[selector[0]] === "string" && entry[selector[0]].length > 0;
13973
14051
  }
13974
- function inference(target) {
13975
- for (const key of INFERENCE)
14052
+ function inference(target, version) {
14053
+ const keys = version === 3 ? [...INFERENCE, "service_tier", "plan_mode_reasoning_effort"] : INFERENCE;
14054
+ for (const key of keys)
13976
14055
  if (Object.hasOwn(target, key)) {
13977
14056
  const value = target[key];
13978
14057
  if (key === "model")
13979
14058
  need4(typeof value === "string" && MODEL.test(value));
13980
- else
14059
+ else if (version === 3 && key !== "model_verbosity") {
14060
+ need4(typeof value === "string" && value.length <= 128 && !/[\x00-\x1f\x7f]/.test(value));
14061
+ if (key !== "service_tier")
14062
+ need4(value.length > 0);
14063
+ } else
13981
14064
  need4(typeof value === "string" && (key === "model_reasoning_effort" ? EFFORT2.has(value) : VERBOSITY2.has(value)));
13982
14065
  delete target[key];
13983
14066
  }
13984
14067
  }
13985
- function settingsDigest2(text2) {
14068
+ function settingsDigest2(text2, version = 2) {
13986
14069
  let config;
13987
14070
  try {
13988
14071
  config = Bun.TOML.parse(text2);
@@ -13990,8 +14073,9 @@ function settingsDigest2(text2) {
13990
14073
  throw new Error("Invalid Codex settings witness");
13991
14074
  }
13992
14075
  need4(isRecord3(config));
13993
- normalize3(config);
13994
- return sha2(`hasna.skills.codex-settings.v2\x00${JSON.stringify([canonical4(config), numericTokens2(text2)])}`);
14076
+ const projected = version === 3 ? projectRegularCodexMcp(config, text2) : { config, numericSource: text2 };
14077
+ normalize3(projected.config, version);
14078
+ return sha2(`hasna.skills.codex-settings.v${version}\x00${JSON.stringify([canonical4(projected.config), numericTokens2(projected.numericSource)])}`);
13995
14079
  }
13996
14080
  function hashCodexSettingsReplacementV2(text2, budget = { remaining: 256 * 1024 * 1024 }) {
13997
14081
  need4(Buffer.byteLength(text2) <= 1024 * 1024 && budget.remaining >= Buffer.byteLength(text2));
@@ -14015,10 +14099,29 @@ function upgradeCodexSettingsWitness(previous, reviewedSettingsPath) {
14015
14099
  throw new Error("Codex non-preference settings changed; explicit discovery review required");
14016
14100
  return { path: previous.path, hashMode: "codex-settings-v2", sha256: sha2562 };
14017
14101
  }
14102
+ function hashCodexSettingsReplacementV3(text2, budget = { remaining: 256 * 1024 * 1024 }) {
14103
+ need4(Buffer.byteLength(text2) <= 1024 * 1024 && budget.remaining >= Buffer.byteLength(text2));
14104
+ budget.remaining -= Buffer.byteLength(text2);
14105
+ return settingsDigest2(text2, 3);
14106
+ }
14107
+ function captureCodexSettingsV3(path, budget = { remaining: 256 * 1024 * 1024 }) {
14108
+ return { path, hashMode: "codex-settings-v3", sha256: settingsDigest2(readNativeSettingsWitnessFile(path, budget, "config.toml"), 3) };
14109
+ }
14110
+ function upgradeCodexSettingsWitnessV3(previous, reviewedSettingsPath) {
14111
+ need4(previous && Object.keys(previous).every((key) => ["path", "hashMode", "sha256"].includes(key)) && (previous.hashMode === undefined || ["bytes", "codex-settings-v1", "codex-settings-v2"].includes(previous.hashMode)) && /^[a-f0-9]{64}$/.test(previous.sha256));
14112
+ const budget = { remaining: 2 * 1024 * 1024 };
14113
+ const before = readNativeSettingsWitnessFile(reviewedSettingsPath, budget, "config.toml"), current = readNativeSettingsWitnessFile(previous.path, budget, "config.toml");
14114
+ const original = previous.hashMode === "codex-settings-v2" ? settingsDigest2(before) : previous.hashMode === "codex-settings-v1" ? hashCodexSettingsReplacement(before) : sha2(before);
14115
+ need4(original === previous.sha256);
14116
+ const sha2562 = settingsDigest2(current, 3);
14117
+ if (settingsDigest2(before, 3) !== sha2562)
14118
+ throw new Error("Codex settings outside the reviewed V3 contract changed; explicit discovery review required");
14119
+ return { path: previous.path, hashMode: "codex-settings-v3", sha256: sha2562 };
14120
+ }
14018
14121
 
14019
14122
  // src/lib/agent-integration.ts
14020
14123
  import { createHash as createHash12, randomUUID as randomUUID2 } from "crypto";
14021
- import { isDeepStrictEqual as isDeepStrictEqual3 } from "util";
14124
+ import { isDeepStrictEqual as isDeepStrictEqual4 } from "util";
14022
14125
  import { existsSync as existsSync8, lstatSync as lstatSync15, statSync as statSync8, mkdirSync as mkdirSync5, readFileSync as readFileSync12, readdirSync as readdirSync8, opendirSync as opendirSync3, readlinkSync as readlinkSync4, realpathSync as realpathSync6, renameSync as renameSync2, rmdirSync as rmdirSync2, writeFileSync as writeFileSync4, unlinkSync as unlinkSync3, chmodSync, openSync as openSync8, closeSync as closeSync8, fsyncSync as fsyncSync2, fstatSync as fstatSync8, readSync as readSync6, constants as constants7, linkSync } from "fs";
14023
14126
  import { dirname as dirname11, join as join17, resolve as resolve10, relative as relative5, isAbsolute as isAbsolute11, sep as sep5 } from "path";
14024
14127
  import { homedir as homedir2 } from "os";
@@ -14147,7 +14250,7 @@ function isOwnedCliBridge(path, expectedPaths) {
14147
14250
  }
14148
14251
 
14149
14252
  // src/lib/agent-codex.ts
14150
- import { isDeepStrictEqual as isDeepStrictEqual2 } from "util";
14253
+ import { isDeepStrictEqual as isDeepStrictEqual3 } from "util";
14151
14254
  var CODEX_SKILL_CONFIG_SECTIONS = /^\[\[skills\.config\]\][^\n]*(?:\n(?!\s*\[)[^\n]*)*/gm;
14152
14255
  var codexPathConfigRefusal = () => new Error("Codex skill path controls require ordinary [[skills.config]] TOML tables or a native single-line inline array; preserve and review unsupported inline, dotted, or malformed definitions before running skills hook install");
14153
14256
  function splitTopLevel(value, delimiter) {
@@ -14278,7 +14381,7 @@ function normalizeCodexInlinePathConfig(text2) {
14278
14381
  const expectedWithoutConfig = structuredClone(before);
14279
14382
  delete expectedWithoutConfig.skills.config;
14280
14383
  try {
14281
- if (isDeepStrictEqual2(Bun.TOML.parse(text2.replace(CODEX_SKILL_CONFIG_SECTIONS, "")), expectedWithoutConfig))
14384
+ if (isDeepStrictEqual3(Bun.TOML.parse(text2.replace(CODEX_SKILL_CONFIG_SECTIONS, "")), expectedWithoutConfig))
14282
14385
  return text2;
14283
14386
  } catch {}
14284
14387
  const matches = [];
@@ -14331,7 +14434,7 @@ function normalizeCodexInlinePathConfig(text2) {
14331
14434
  try {
14332
14435
  const after = Bun.TOML.parse(candidate);
14333
14436
  const expected = structuredClone(before);
14334
- if (isDeepStrictEqual2(after, expected))
14437
+ if (isDeepStrictEqual3(after, expected))
14335
14438
  matches.push(candidate);
14336
14439
  } catch {}
14337
14440
  }
@@ -14347,11 +14450,11 @@ function assertCodexPathConfigEditable(text2) {
14347
14450
  delete expected.skills.config;
14348
14451
  try {
14349
14452
  const withoutSections = Bun.TOML.parse(text2.replace(CODEX_SKILL_CONFIG_SECTIONS, ""));
14350
- if (isDeepStrictEqual2(withoutSections, expected))
14453
+ if (isDeepStrictEqual3(withoutSections, expected))
14351
14454
  return;
14352
14455
  const normalized = normalizeCodexInlinePathConfig(text2);
14353
14456
  const withoutNormalizedSections = Bun.TOML.parse(normalized.replace(CODEX_SKILL_CONFIG_SECTIONS, ""));
14354
- if (isDeepStrictEqual2(withoutNormalizedSections, expected))
14457
+ if (isDeepStrictEqual3(withoutNormalizedSections, expected))
14355
14458
  return;
14356
14459
  } catch {}
14357
14460
  throw codexPathConfigRefusal();
@@ -14389,7 +14492,7 @@ function disableCodexBundledSkills(text2) {
14389
14492
  const candidates = new Set;
14390
14493
  const consider = (candidate) => {
14391
14494
  try {
14392
- if (isDeepStrictEqual2(Bun.TOML.parse(candidate), expected))
14495
+ if (isDeepStrictEqual3(Bun.TOML.parse(candidate), expected))
14393
14496
  candidates.add(candidate);
14394
14497
  } catch {}
14395
14498
  };
@@ -14719,7 +14822,7 @@ function inventoryNativeSkills(home = homedir2(), options = {}) {
14719
14822
  admit(path);
14720
14823
  const scan = { complete: true, hasSkills: false, entries: 1 };
14721
14824
  assertSafePath(path);
14722
- if (configuredRoot && agent === "codex" && installationInputs.includes(path))
14825
+ if (configuredRoot && agent === "codex" && installationInputs.some((root) => path === root || path.startsWith(`${root}${sep5}`)))
14723
14826
  return scan;
14724
14827
  if (!existsSync8(path))
14725
14828
  return scan;
@@ -15200,6 +15303,8 @@ function atomicWrite2(path, content) {
15200
15303
  }
15201
15304
  }
15202
15305
  function planAgentSettingsWitnessUpgrade(options) {
15306
+ if (options.targetCodexVersion !== undefined && (options.agent !== "codex" || ![2, 3].includes(options.targetCodexVersion)))
15307
+ throw new Error("Invalid Codex witness target version");
15203
15308
  const home = resolve10(options.home ?? homedir2()), dataDir2 = options.dataDir ?? getDataDirReadOnly();
15204
15309
  const snapshot = readManagedSkillPolicySnapshot(dataDir2);
15205
15310
  if (!snapshot || sha3(snapshot.text) !== options.expectedPolicySha256)
@@ -15221,21 +15326,21 @@ function planAgentSettingsWitnessUpgrade(options) {
15221
15326
  throw new Error("Settings witness upgrade requires a preserved settings preimage");
15222
15327
  const replaced = [previous];
15223
15328
  if (options.agent === "codex") {
15224
- if (previous.hashMode !== undefined && previous.hashMode !== "bytes" && previous.hashMode !== "codex-settings-v1")
15225
- throw new Error("Codex settings witness upgrade requires a preserved raw or codex-settings-v1 configuration witness");
15329
+ if (previous.hashMode !== undefined && previous.hashMode !== "bytes" && previous.hashMode !== "codex-settings-v1" && !(options.targetCodexVersion === 3 && previous.hashMode === "codex-settings-v2"))
15330
+ throw new Error("Codex settings witness upgrade requires an eligible preserved configuration witness");
15226
15331
  const preimage = readCodexSettingsPreimage(options.reviewedPreimage);
15227
15332
  for (const source of binding.sources) {
15228
15333
  if (source === previous || source.path !== configPath)
15229
15334
  continue;
15230
15335
  const fields = source.fields;
15231
- if (source.hashMode !== undefined || source.format !== "toml" || !Array.isArray(fields) || !isDeepStrictEqual3(fields, [...CODEX_DISCOVERY_PROJECTION_FIELDS]) || typeof source.sha256 !== "string")
15336
+ if (source.hashMode !== undefined || source.format !== "toml" || !Array.isArray(fields) || !isDeepStrictEqual4(fields, [...CODEX_DISCOVERY_PROJECTION_FIELDS]) || typeof source.sha256 !== "string")
15232
15337
  throw new Error("Codex settings witness upgrade found an unrecognized configuration witness");
15233
15338
  if (projectNativeDiscoveryFields(preimage, "toml", fields, configPath) !== source.sha256)
15234
15339
  throw new Error("Reviewed preimage does not explain the Codex discovery projection witness");
15235
15340
  replaced.push(source);
15236
15341
  }
15237
15342
  }
15238
- const next = options.agent === "claude" ? upgradeClaudeSettingsWitness(previous, options.reviewedPreimage) : upgradeCodexSettingsWitness(previous, options.reviewedPreimage);
15343
+ const next = options.agent === "claude" ? upgradeClaudeSettingsWitness(previous, options.reviewedPreimage) : options.targetCodexVersion === 3 ? upgradeCodexSettingsWitnessV3(previous, options.reviewedPreimage) : upgradeCodexSettingsWitness(previous, options.reviewedPreimage);
15239
15344
  const rebound = [];
15240
15345
  for (const source of binding.sources) {
15241
15346
  if (!replaced.includes(source)) {
@@ -15272,7 +15377,7 @@ function applyAgentIntegration(plan) {
15272
15377
  const upgrade = plan.settingsWitnessUpgrade;
15273
15378
  if (!plan.managedAgentChecks || !plan.observedPolicy?.before)
15274
15379
  throw new Error("Invalid settings witness upgrade plan");
15275
- const verified = planAgentSettingsWitnessUpgrade({ agent: upgrade.agent, reviewedPreimage: upgrade.reviewedPreimage, home: plan.managedAgentChecks.home, dataDir: plan.dataDir, expectedPolicySha256: sha3(plan.observedPolicy.before), expectedSettingsSha256: upgrade.currentSettingsSha256 });
15380
+ const verified = planAgentSettingsWitnessUpgrade({ agent: upgrade.agent, ...upgrade.agent === "codex" ? { targetCodexVersion: upgrade.toHashMode === "codex-settings-v3" ? 3 : 2 } : {}, reviewedPreimage: upgrade.reviewedPreimage, home: plan.managedAgentChecks.home, dataDir: plan.dataDir, expectedPolicySha256: sha3(plan.observedPolicy.before), expectedSettingsSha256: upgrade.currentSettingsSha256 });
15276
15381
  if (JSON.stringify(verified.changes) !== JSON.stringify(plan.changes) || JSON.stringify(verified.settingsWitnessUpgrade) !== JSON.stringify(upgrade))
15277
15382
  throw new Error("Settings witness upgrade plan changed");
15278
15383
  provenDiscovery = verified.discoveryBefore[0];
@@ -18248,19 +18353,19 @@ function projectNativeDiscoveryFields(text2, format, fields2, path) {
18248
18353
  return digest(JSON.stringify(Object.fromEntries(fields2.map((field2) => [field2, object5[field2] ?? null]))));
18249
18354
  }
18250
18355
  function isSupersededCodexProjection(agent, configPath, source) {
18251
- return agent === "codex" && source.path === configPath && source.format === "toml" && isDeepStrictEqual4(source.fields, [...CODEX_DISCOVERY_PROJECTION_FIELDS]);
18356
+ return agent === "codex" && source.path === configPath && source.format === "toml" && isDeepStrictEqual5(source.fields, [...CODEX_DISCOVERY_PROJECTION_FIELDS]);
18252
18357
  }
18253
18358
  function supersedesCodexProjection(sources, configPath) {
18254
- return sources.some((source) => source.path === configPath && source.hashMode === "codex-settings-v2");
18359
+ return sources.some((source) => source.path === configPath && (source.hashMode === "codex-settings-v2" || source.hashMode === "codex-settings-v3"));
18255
18360
  }
18256
18361
  function projected(source, changes, budget = discoveryByteBudget()) {
18257
- if (source.hashMode === "codex-settings-v1" || source.hashMode === "codex-settings-v2") {
18362
+ if (source.hashMode === "codex-settings-v1" || source.hashMode === "codex-settings-v2" || source.hashMode === "codex-settings-v3") {
18258
18363
  if (source.format !== undefined || source.fields !== undefined || source.managedPlugins !== undefined || typeof source.sha256 !== "string" || !/^[a-f0-9]{64}$/.test(source.sha256))
18259
18364
  throw new Error("Codex settings witnesses require exact typed metadata");
18260
- const current = (source.hashMode === "codex-settings-v2" ? captureCodexSettingsV2 : captureCodexSettings)(source.path, budget).sha256;
18365
+ const current = (source.hashMode === "codex-settings-v3" ? captureCodexSettingsV3 : source.hashMode === "codex-settings-v2" ? captureCodexSettingsV2 : captureCodexSettings)(source.path, budget).sha256;
18261
18366
  if (current !== source.sha256)
18262
18367
  throw new Error(`Native discovery input changed; run skills hook install with a fresh discovery review: ${source.path}`);
18263
- return changes?.has(source.path) ? (source.hashMode === "codex-settings-v2" ? hashCodexSettingsReplacementV2 : hashCodexSettingsReplacement)(changes.get(source.path), budget) : current;
18368
+ return changes?.has(source.path) ? (source.hashMode === "codex-settings-v3" ? hashCodexSettingsReplacementV3 : source.hashMode === "codex-settings-v2" ? hashCodexSettingsReplacementV2 : hashCodexSettingsReplacement)(changes.get(source.path), budget) : current;
18264
18369
  }
18265
18370
  if (source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || source.hashMode === "claude-settings-v3") {
18266
18371
  if (source.format !== undefined || source.fields !== undefined || source.managedPlugins !== undefined || typeof source.sha256 !== "string" || !/^[a-f0-9]{64}$/.test(source.sha256))
@@ -18360,7 +18465,7 @@ function codexInstallationRoots(binding) {
18360
18465
  });
18361
18466
  }
18362
18467
  function assertMarketplaceBinding(binding, source) {
18363
- if ((source.hashMode === "codex-settings-v1" || source.hashMode === "codex-settings-v2") && (binding.agent !== "codex" || binding.method !== "reviewed" || basename9(source.path) !== "config.toml"))
18468
+ if ((source.hashMode === "codex-settings-v1" || source.hashMode === "codex-settings-v2" || source.hashMode === "codex-settings-v3") && (binding.agent !== "codex" || binding.method !== "reviewed" || basename9(source.path) !== "config.toml"))
18364
18469
  throw new Error("Codex settings witnesses require explicit reviewed Codex configuration");
18365
18470
  if ((source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || source.hashMode === "claude-settings-v3") && (binding.agent !== "claude" || binding.method !== "reviewed" || basename9(source.path) !== "settings.json"))
18366
18471
  throw new Error("Claude settings witnesses require explicit reviewed Claude configuration");
@@ -18510,10 +18615,10 @@ function resolveAgentDiscovery(options) {
18510
18615
  verifyAgentDiscovery(retained);
18511
18616
  if (!retained.sources.some((source) => source.path === canonical6(configPath) && source.format === undefined && source.fields === undefined))
18512
18617
  unresolved("retained review is missing the full agent configuration source");
18513
- 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)))
18618
+ 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)))
18514
18619
  unresolved("retained settings witness names another configuration source");
18515
18620
  const covered = supersedesCodexProjection(retained.sources, canonical6(configPath)) ? sources.filter((source) => !isSupersededCodexProjection(agent, canonical6(configPath), source)) : sources;
18516
- if (covered.some((source) => !retained.sources.some((saved) => isDeepStrictEqual4(saved, source))) || [...roots].some((root2) => !retained.roots.includes(root2)) || agent === "gemini" && JSON.stringify(retained.builtinNames) !== JSON.stringify(builtinNames))
18621
+ if (covered.some((source) => !retained.sources.some((saved) => isDeepStrictEqual5(saved, source))) || [...roots].some((root2) => !retained.roots.includes(root2)) || agent === "gemini" && JSON.stringify(retained.builtinNames) !== JSON.stringify(builtinNames))
18517
18622
  unresolved("retained review is missing current runtime discovery coverage");
18518
18623
  return retained;
18519
18624
  }
@@ -18527,7 +18632,7 @@ function resolveAgentDiscovery(options) {
18527
18632
  if (review.sources.some((source) => source.format !== undefined || source.fields !== undefined))
18528
18633
  throw new Error("Explicit discovery reviews require full source-file hashes");
18529
18634
  verifyAgentDiscovery(supplied);
18530
- 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)))
18635
+ 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)))
18531
18636
  throw new Error("Semantic settings witnesses must name the configured Claude configuration source");
18532
18637
  if (!review.sources.some((source) => source.path === canonical6(configPath)))
18533
18638
  throw new Error("Discovery review must include the agent configuration source");
@@ -19505,7 +19610,7 @@ function createSkillRun(params, targetDir = process.cwd()) {
19505
19610
  mkdirSync10(logsDir, { recursive: true });
19506
19611
  mkdirSync10(exportDir, { recursive: true });
19507
19612
  mkdirSync10(join31(root2, "tmp"), { recursive: true });
19508
- const record2 = {
19613
+ const record3 = {
19509
19614
  id,
19510
19615
  skill: skillName,
19511
19616
  status: params.status ?? "running",
@@ -19523,10 +19628,10 @@ function createSkillRun(params, targetDir = process.cwd()) {
19523
19628
  logsDir: toProjectRelative(targetDir, logsDir)
19524
19629
  }
19525
19630
  };
19526
- const context = { targetDir, runDir, exportDir, logsDir, record: record2 };
19631
+ const context = { targetDir, runDir, exportDir, logsDir, record: record3 };
19527
19632
  writeRunRecord(context);
19528
19633
  writeArtifactsManifest(context, []);
19529
- appendRunEvent(context, "created", { status: record2.status });
19634
+ appendRunEvent(context, "created", { status: record3.status });
19530
19635
  return context;
19531
19636
  }
19532
19637
  function completeSkillRun(context, patch) {
@@ -19576,9 +19681,9 @@ function listSkillRuns(targetDir = process.cwd(), limit = 50) {
19576
19681
  if (!statSync11(dayDir).isDirectory())
19577
19682
  continue;
19578
19683
  for (const runId of readdirSync13(dayDir).sort().reverse()) {
19579
- const record2 = readRunRecord(join31(dayDir, runId));
19580
- if (record2)
19581
- records.push(record2);
19684
+ const record3 = readRunRecord(join31(dayDir, runId));
19685
+ if (record3)
19686
+ records.push(record3);
19582
19687
  if (records.length >= limit)
19583
19688
  return records;
19584
19689
  }
@@ -19590,9 +19695,9 @@ function findSkillRun(runId, targetDir = process.cwd()) {
19590
19695
  if (!existsSync15(runsRoot))
19591
19696
  return null;
19592
19697
  for (const day of readdirSync13(runsRoot)) {
19593
- const record2 = readRunRecord(join31(runsRoot, day, runId));
19594
- if (record2)
19595
- return record2;
19698
+ const record3 = readRunRecord(join31(runsRoot, day, runId));
19699
+ if (record3)
19700
+ return record3;
19596
19701
  }
19597
19702
  return null;
19598
19703
  }
@@ -19733,7 +19838,7 @@ __export(exports_external, {
19733
19838
  regexes: () => exports_regexes,
19734
19839
  regex: () => _regex,
19735
19840
  refine: () => refine,
19736
- record: () => record2,
19841
+ record: () => record3,
19737
19842
  readonly: () => readonly,
19738
19843
  property: () => _property,
19739
19844
  properties: () => _properties,
@@ -35507,8 +35612,8 @@ function rewriteKeyNames(ctx) {
35507
35612
  bySchema.set(entry.schema, entry);
35508
35613
  }
35509
35614
  const rewrites = new Map;
35510
- for (const record2 of pendingRecords.get(ctx) ?? []) {
35511
- const seen = ctx.seen.get(record2);
35615
+ for (const record3 of pendingRecords.get(ctx) ?? []) {
35616
+ const seen = ctx.seen.get(record3);
35512
35617
  const names = (seen?.def ?? seen?.schema)?.propertyNames;
35513
35618
  if (!names || names === true || rewrites.has(names))
35514
35619
  continue;
@@ -35835,7 +35940,7 @@ __export(exports_schemas2, {
35835
35940
  strictObject: () => strictObject,
35836
35941
  set: () => set,
35837
35942
  refine: () => refine,
35838
- record: () => record2,
35943
+ record: () => record3,
35839
35944
  readonly: () => readonly,
35840
35945
  promise: () => promise,
35841
35946
  preprocess: () => preprocess,
@@ -37005,7 +37110,7 @@ var ZodRecord = /* @__PURE__ */ $constructor("ZodRecord", (inst, def) => {
37005
37110
  inst.keyType = def.keyType;
37006
37111
  inst.valueType = def.valueType;
37007
37112
  });
37008
- function record2(keyType, valueType, params) {
37113
+ function record3(keyType, valueType, params) {
37009
37114
  if (!valueType || !valueType._zod) {
37010
37115
  return new ZodRecord({
37011
37116
  type: "record",
@@ -37471,7 +37576,7 @@ var stringbool = (...args) => _stringbool({
37471
37576
  }, ...args);
37472
37577
  function json(params) {
37473
37578
  const jsonSchema = lazy(() => {
37474
- return union([string2(params), number2(), boolean2(), _null3(), array2(jsonSchema), record2(string2(), jsonSchema)]);
37579
+ return union([string2(params), number2(), boolean2(), _null3(), array2(jsonSchema), record3(string2(), jsonSchema)]);
37475
37580
  });
37476
37581
  return jsonSchema;
37477
37582
  }
@@ -39459,12 +39564,12 @@ class RemoteWorkspaceInvitationReadError extends Error {
39459
39564
  }
39460
39565
  }
39461
39566
  function invitationFailure(value, status) {
39462
- if (!record3(value) || typeof value.code !== "string" || !Object.hasOwn(invitationFailures, value.code))
39567
+ if (!record4(value) || typeof value.code !== "string" || !Object.hasOwn(invitationFailures, value.code))
39463
39568
  return null;
39464
39569
  const code = value.code;
39465
39570
  return invitationFailures[code][0] === status ? code : null;
39466
39571
  }
39467
- var record3 = (v) => !!v && typeof v === "object" && !Array.isArray(v);
39572
+ var record4 = (v) => !!v && typeof v === "object" && !Array.isArray(v);
39468
39573
  var uuid5 = (v) => typeof v === "string" && /^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/.test(v);
39469
39574
  var role = (v) => typeof v === "string" && ["owner", "admin", "member", "viewer"].includes(v);
39470
39575
  var email3 = (v) => typeof v === "string" && v.length <= 254 && !/[\p{Cc}\p{Cs}\u2028\u2029\s]/u.test(v) && /^[^@]+@[^@]+\.[^@]+$/.test(v);
@@ -39473,7 +39578,7 @@ var inputFailure = () => {
39473
39578
  throw new WorkspaceInvitationInputError;
39474
39579
  };
39475
39580
  function invitationInput(action, input2) {
39476
- if (!record3(input2))
39581
+ if (!record4(input2))
39477
39582
  return inputFailure();
39478
39583
  const keys = {
39479
39584
  list: ["after"],
@@ -39524,7 +39629,7 @@ function invalid2() {
39524
39629
  throw new RemoteWorkspaceInvitationReadError;
39525
39630
  }
39526
39631
  function projection(v, organizationId) {
39527
- if (!record3(v) || !uuid5(v.id) || v.organizationId !== organizationId || !email3(v.email) || v.email !== v.email.trim().toLowerCase() || !role(v.role) || !Number.isInteger(v.generation) || Number(v.generation) < 1 || Number(v.generation) > 10 || typeof v.status !== "string" || !["pending", "expired", "accepted", "revoked"].includes(v.status) || !timestamp(v.expiresAt) || !timestamp(v.createdAt) || !record3(v.delivery) || typeof v.delivery.state !== "string" || !["queued", "sending", "uncertain", "provider_accepted", "failed", "cancelled"].includes(v.delivery.state) || !Number.isInteger(v.delivery.attempts) || Number(v.delivery.attempts) < 0 || Number(v.delivery.attempts) > 5)
39632
+ if (!record4(v) || !uuid5(v.id) || v.organizationId !== organizationId || !email3(v.email) || v.email !== v.email.trim().toLowerCase() || !role(v.role) || !Number.isInteger(v.generation) || Number(v.generation) < 1 || Number(v.generation) > 10 || typeof v.status !== "string" || !["pending", "expired", "accepted", "revoked"].includes(v.status) || !timestamp(v.expiresAt) || !timestamp(v.createdAt) || !record4(v.delivery) || typeof v.delivery.state !== "string" || !["queued", "sending", "uncertain", "provider_accepted", "failed", "cancelled"].includes(v.delivery.state) || !Number.isInteger(v.delivery.attempts) || Number(v.delivery.attempts) < 0 || Number(v.delivery.attempts) > 5)
39528
39633
  return invalid2();
39529
39634
  return {
39530
39635
  id: v.id,
@@ -39539,7 +39644,7 @@ function projection(v, organizationId) {
39539
39644
  };
39540
39645
  }
39541
39646
  function parseInvitationResult(action, value, input2, organizationId) {
39542
- if (!record3(value))
39647
+ if (!record4(value))
39543
39648
  return invalid2();
39544
39649
  const request = input2;
39545
39650
  if (action === "accept") {
@@ -39572,7 +39677,7 @@ function parseInvitationResult(action, value, input2, organizationId) {
39572
39677
  }
39573
39678
 
39574
39679
  // src/lib/remote-workspace-selection.ts
39575
- var record4 = (v) => !!v && typeof v === "object" && !Array.isArray(v);
39680
+ var record5 = (v) => !!v && typeof v === "object" && !Array.isArray(v);
39576
39681
  var uuid8 = (v) => typeof v === "string" && /^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/.test(v);
39577
39682
  var text2 = (v, max = 1024) => typeof v === "string" && !!v.trim() && v.length <= max && !/[\p{Cc}\p{Cs}\u2028\u2029]/u.test(v);
39578
39683
  var role2 = (v) => typeof v === "string" && ["owner", "admin", "member", "viewer"].includes(v);
@@ -39597,7 +39702,7 @@ function workspaceExpectedUserId(value) {
39597
39702
  return value;
39598
39703
  }
39599
39704
  function workspaceContext(value) {
39600
- if (!record4(value) || Object.keys(value).sort().join(",") !== "membershipId,userId" || !uuid8(value.userId) || !uuid8(value.membershipId))
39705
+ if (!record5(value) || Object.keys(value).sort().join(",") !== "membershipId,userId" || !uuid8(value.userId) || !uuid8(value.membershipId))
39601
39706
  throw new WorkspaceContextInputError;
39602
39707
  return { userId: value.userId, membershipId: value.membershipId };
39603
39708
  }
@@ -39605,15 +39710,15 @@ function invalid3() {
39605
39710
  throw new Error(invalidWorkspaceResult);
39606
39711
  }
39607
39712
  function organization(v) {
39608
- if (!record4(v) || !uuid8(v.id) || !text2(v.slug) || !text2(v.name))
39713
+ if (!record5(v) || !uuid8(v.id) || !text2(v.slug) || !text2(v.name))
39609
39714
  return invalid3();
39610
39715
  return { id: v.id, slug: v.slug, name: v.name };
39611
39716
  }
39612
39717
  function parseAccountWorkspaces(value) {
39613
- if (!record4(value) || !Array.isArray(value.workspaces) || !value.workspaces.length || value.workspaces.length > 1000)
39718
+ if (!record5(value) || !Array.isArray(value.workspaces) || !value.workspaces.length || value.workspaces.length > 1000)
39614
39719
  return invalid3();
39615
39720
  const workspaces = value.workspaces.map((v) => {
39616
- if (!record4(v) || !uuid8(v.membershipId) || !role2(v.role) || typeof v.current !== "boolean")
39721
+ if (!record5(v) || !uuid8(v.membershipId) || !role2(v.role) || typeof v.current !== "boolean")
39617
39722
  return invalid3();
39618
39723
  return { membershipId: v.membershipId, organization: organization(v.organization), role: v.role, current: v.current };
39619
39724
  });
@@ -39622,10 +39727,10 @@ function parseAccountWorkspaces(value) {
39622
39727
  return { workspaces };
39623
39728
  }
39624
39729
  function parseWorkspaceIdentity(value, expectedUserId) {
39625
- if (!record4(value))
39730
+ if (!record5(value))
39626
39731
  return invalid3();
39627
39732
  const user = value.user;
39628
- if (!record4(user) || !uuid8(user.id) || !uuid8(user.membershipId) || !text2(user.email, 320) || !(user.displayName === null || text2(user.displayName)) || !role2(user.role))
39733
+ if (!record5(user) || !uuid8(user.id) || !uuid8(user.membershipId) || !text2(user.email, 320) || !(user.displayName === null || text2(user.displayName)) || !role2(user.role))
39629
39734
  return invalid3();
39630
39735
  if (user.id !== expectedUserId)
39631
39736
  throw new WorkspaceIdentityMismatchError;
@@ -39643,8 +39748,8 @@ function parseWorkspaceSession(value, expected) {
39643
39748
  return { token: sessionToken(value.token), ...identity4 };
39644
39749
  }
39645
39750
  function parseWorkspaceLogin(value, expectedUserId) {
39646
- const user = record4(value) && value.user;
39647
- if (!record4(value) || !record4(user) || !uuid8(user.id))
39751
+ const user = record5(value) && value.user;
39752
+ if (!record5(value) || !record5(user) || !uuid8(user.id))
39648
39753
  return invalid3();
39649
39754
  if (expectedUserId !== undefined && user.id !== expectedUserId)
39650
39755
  throw new WorkspaceIdentityMismatchError;
@@ -39659,18 +39764,18 @@ var workspaceSelectionFailures = {
39659
39764
  WORKSPACE_BUSY: [503, "Workspace is busy. Refresh before retrying."]
39660
39765
  };
39661
39766
  function workspaceSelectionFailure(value, status) {
39662
- if (!record4(value) || typeof value.code !== "string" || !Object.hasOwn(workspaceSelectionFailures, value.code))
39767
+ if (!record5(value) || typeof value.code !== "string" || !Object.hasOwn(workspaceSelectionFailures, value.code))
39663
39768
  return null;
39664
39769
  const code = value.code;
39665
39770
  return workspaceSelectionFailures[code][0] === status ? code : null;
39666
39771
  }
39667
39772
 
39668
39773
  // src/lib/remote-workspace.ts
39669
- var record5 = (value) => !!value && typeof value === "object" && !Array.isArray(value);
39774
+ var record6 = (value) => !!value && typeof value === "object" && !Array.isArray(value);
39670
39775
  var cursor = (value) => typeof value === "string" && /^[A-Za-z0-9_-]{1,512}$/.test(value);
39671
39776
  var uuid10 = (value) => typeof value === "string" && /^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/i.test(value);
39672
39777
  function workspaceMembersQuery(options = {}) {
39673
- if (!record5(options) || Object.keys(options).some((key) => key !== "limit" && key !== "cursor") || options.limit !== undefined && (!Number.isInteger(options.limit) || options.limit < 1 || options.limit > 100) || options.cursor !== undefined && !cursor(options.cursor))
39778
+ if (!record6(options) || Object.keys(options).some((key) => key !== "limit" && key !== "cursor") || options.limit !== undefined && (!Number.isInteger(options.limit) || options.limit < 1 || options.limit > 100) || options.cursor !== undefined && !cursor(options.cursor))
39674
39779
  throw new Error("Use a roster limit from 1 to 100 and an unchanged continuation cursor.");
39675
39780
  const query = new URLSearchParams;
39676
39781
  if (options.limit !== undefined)
@@ -39686,7 +39791,7 @@ function timestamp2(value) {
39686
39791
  return Number.isFinite(time3) && new Date(time3).toISOString().slice(0, 23) === value.slice(0, 23);
39687
39792
  }
39688
39793
  function parseMember(row, fail) {
39689
- if (!record5(row) || !uuid10(row.membershipId) || !uuid10(row.userId) || typeof row.email !== "string" || !row.email || !(row.displayName === null || typeof row.displayName === "string") || !isRole(row.role) || !timestamp2(row.createdAt))
39794
+ if (!record6(row) || !uuid10(row.membershipId) || !uuid10(row.userId) || typeof row.email !== "string" || !row.email || !(row.displayName === null || typeof row.displayName === "string") || !isRole(row.role) || !timestamp2(row.createdAt))
39690
39795
  return fail();
39691
39796
  return {
39692
39797
  membershipId: row.membershipId,
@@ -39706,7 +39811,7 @@ class WorkspaceMemberInputError extends Error {
39706
39811
  }
39707
39812
  }
39708
39813
  function mutationInput(membershipId, input2, roleChange) {
39709
- if (typeof membershipId !== "string" || !uuid10(membershipId) || membershipId !== membershipId.toLowerCase() || !record5(input2) || Object.keys(input2).sort().join(",") !== (roleChange ? "expectedRole,role" : "expectedRole"))
39814
+ if (typeof membershipId !== "string" || !uuid10(membershipId) || membershipId !== membershipId.toLowerCase() || !record6(input2) || Object.keys(input2).sort().join(",") !== (roleChange ? "expectedRole,role" : "expectedRole"))
39710
39815
  throw new WorkspaceMemberInputError;
39711
39816
  const expectedRole = input2.expectedRole, role3 = roleChange ? input2.role : undefined;
39712
39817
  if (!isRole(expectedRole) || roleChange && !isRole(role3))
@@ -39726,7 +39831,7 @@ function parseWorkspaceMemberRoleResult(value, membershipId, role3) {
39726
39831
  const fail = () => {
39727
39832
  throw new Error(invalidMemberResult);
39728
39833
  };
39729
- if (!record5(value) || !uuid10(value.organizationId) || typeof value.changed !== "boolean")
39834
+ if (!record6(value) || !uuid10(value.organizationId) || typeof value.changed !== "boolean")
39730
39835
  return fail();
39731
39836
  const member = parseMember(value.member, fail);
39732
39837
  if (member.membershipId !== membershipId || member.role !== role3)
@@ -39734,7 +39839,7 @@ function parseWorkspaceMemberRoleResult(value, membershipId, role3) {
39734
39839
  return { organizationId: value.organizationId, member, changed: value.changed };
39735
39840
  }
39736
39841
  function parseWorkspaceMemberRemovalResult(value, membershipId) {
39737
- if (!record5(value) || !uuid10(value.organizationId) || value.membershipId !== membershipId || value.removed !== true || typeof value.alreadyRemoved !== "boolean")
39842
+ if (!record6(value) || !uuid10(value.organizationId) || value.membershipId !== membershipId || value.removed !== true || typeof value.alreadyRemoved !== "boolean")
39738
39843
  throw new Error(invalidMemberResult);
39739
39844
  return { organizationId: value.organizationId, membershipId, removed: true, alreadyRemoved: value.alreadyRemoved };
39740
39845
  }
@@ -39751,7 +39856,7 @@ var workspaceMemberFailures = {
39751
39856
  MEMBERSHIP_BUSY: [503, "Membership is busy. Refresh the roster before another action."]
39752
39857
  };
39753
39858
  function workspaceMemberFailure(value, status) {
39754
- if (!record5(value) || typeof value.code !== "string" || !Object.hasOwn(workspaceMemberFailures, value.code))
39859
+ if (!record6(value) || typeof value.code !== "string" || !Object.hasOwn(workspaceMemberFailures, value.code))
39755
39860
  return null;
39756
39861
  const code = value.code;
39757
39862
  return workspaceMemberFailures[code][0] === status ? code : null;
@@ -39760,7 +39865,7 @@ function parseWorkspaceMembersPage(value) {
39760
39865
  const fail = () => {
39761
39866
  throw new Error("The server returned an invalid workspace roster.");
39762
39867
  };
39763
- if (!record5(value) || !uuid10(value.organizationId) || !Array.isArray(value.members) || value.members.length > 100 || !(value.nextCursor === null || cursor(value.nextCursor)) || !value.members.length && value.nextCursor !== null)
39868
+ if (!record6(value) || !uuid10(value.organizationId) || !Array.isArray(value.members) || value.members.length > 100 || !(value.nextCursor === null || cursor(value.nextCursor)) || !value.members.length && value.nextCursor !== null)
39764
39869
  return fail();
39765
39870
  const members2 = value.members.map((row) => parseMember(row, fail));
39766
39871
  if (new Set(members2.map((row) => row.membershipId)).size !== members2.length)
@@ -39836,44 +39941,44 @@ function getApiUrl(action, env = process.env, options = {}) {
39836
39941
  // src/lib/remote-run-contract.ts
39837
39942
  var REMOTE_SKILL_RUN_CONTRACT_VERSION = 1;
39838
39943
  function normalizeRemoteSkillRunContract(payload, fallbackSkill) {
39839
- const record6 = isRecord4(payload) ? payload : {};
39944
+ const record7 = isRecord4(payload) ? payload : {};
39840
39945
  return {
39841
39946
  contractVersion: REMOTE_SKILL_RUN_CONTRACT_VERSION,
39842
- ...pickString(record6, "id"),
39843
- skill: pickStringValue(record6, "skill") ?? fallbackSkill,
39844
- ...pickString(record6, "requestedSlug"),
39845
- ...pickString(record6, "status"),
39846
- ...pickNumber(record6, "exitCode"),
39847
- ...pickString(record6, "correlationId"),
39848
- ...pickString(record6, "createdAt"),
39849
- ...pickString(record6, "startedAt"),
39850
- ...pickString(record6, "completedAt"),
39851
- ...pickNumber(record6, "durationMs"),
39852
- ...pickString(record6, "outputType"),
39853
- ...hasOwn(record6, "outputPreview") ? { outputPreview: record6.outputPreview } : {},
39854
- ...pickString(record6, "errorCode"),
39855
- ...pickString(record6, "errorMessage"),
39856
- ...pickString(record6, "error"),
39857
- ...pickString(record6, "code"),
39858
- ...hasOwn(record6, "details") ? { details: record6.details } : {}
39947
+ ...pickString(record7, "id"),
39948
+ skill: pickStringValue(record7, "skill") ?? fallbackSkill,
39949
+ ...pickString(record7, "requestedSlug"),
39950
+ ...pickString(record7, "status"),
39951
+ ...pickNumber(record7, "exitCode"),
39952
+ ...pickString(record7, "correlationId"),
39953
+ ...pickString(record7, "createdAt"),
39954
+ ...pickString(record7, "startedAt"),
39955
+ ...pickString(record7, "completedAt"),
39956
+ ...pickNumber(record7, "durationMs"),
39957
+ ...pickString(record7, "outputType"),
39958
+ ...hasOwn(record7, "outputPreview") ? { outputPreview: record7.outputPreview } : {},
39959
+ ...pickString(record7, "errorCode"),
39960
+ ...pickString(record7, "errorMessage"),
39961
+ ...pickString(record7, "error"),
39962
+ ...pickString(record7, "code"),
39963
+ ...hasOwn(record7, "details") ? { details: record7.details } : {}
39859
39964
  };
39860
39965
  }
39861
39966
  function isRecord4(value) {
39862
39967
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
39863
39968
  }
39864
- function hasOwn(record6, key) {
39865
- return Object.prototype.hasOwnProperty.call(record6, key);
39969
+ function hasOwn(record7, key) {
39970
+ return Object.prototype.hasOwnProperty.call(record7, key);
39866
39971
  }
39867
- function pickString(record6, key) {
39868
- const value = pickStringValue(record6, key);
39972
+ function pickString(record7, key) {
39973
+ const value = pickStringValue(record7, key);
39869
39974
  return value === undefined ? {} : { [key]: value };
39870
39975
  }
39871
- function pickStringValue(record6, key) {
39872
- const value = record6[key];
39976
+ function pickStringValue(record7, key) {
39977
+ const value = record7[key];
39873
39978
  return typeof value === "string" ? value : undefined;
39874
39979
  }
39875
- function pickNumber(record6, key) {
39876
- const value = record6[key];
39980
+ function pickNumber(record7, key) {
39981
+ const value = record7[key];
39877
39982
  return typeof value === "number" && Number.isFinite(value) ? { [key]: value } : {};
39878
39983
  }
39879
39984
 
@@ -40093,11 +40198,11 @@ var permissionNames = [
40093
40198
  "executionGrantsWrite",
40094
40199
  "executionGrantsResolve"
40095
40200
  ];
40096
- var record6 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
40201
+ var record7 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
40097
40202
  function parseSkillsAccess(value) {
40098
40203
  if (value === undefined)
40099
40204
  return {};
40100
- if (!record6(value))
40205
+ if (!record7(value))
40101
40206
  throw new Error("Invalid Skills permission contract");
40102
40207
  const result = {};
40103
40208
  if (value.scopes !== undefined) {
@@ -40106,7 +40211,7 @@ function parseSkillsAccess(value) {
40106
40211
  result.scopes = [...value.scopes];
40107
40212
  }
40108
40213
  if (value.permissions !== undefined) {
40109
- if (!record6(value.permissions))
40214
+ if (!record7(value.permissions))
40110
40215
  throw new Error("Invalid Skills permission contract");
40111
40216
  result.permissions = {};
40112
40217
  for (const name of permissionNames) {
@@ -41003,13 +41108,13 @@ class RemoteSkillsClient {
41003
41108
  return normalizeUpdatedSincePage(await response.json());
41004
41109
  }
41005
41110
  }
41006
- function requireOptionalString(record7, field2) {
41007
- if (record7[field2] === undefined)
41111
+ function requireOptionalString(record8, field2) {
41112
+ if (record8[field2] === undefined)
41008
41113
  return;
41009
- if (typeof record7[field2] !== "string") {
41114
+ if (typeof record8[field2] !== "string") {
41010
41115
  throw new Error(`Remote payload did not match the expected contract (${field2} must be a string when present)`);
41011
41116
  }
41012
- return record7[field2];
41117
+ return record8[field2];
41013
41118
  }
41014
41119
  var INVALID_SKILL_VERSION_RESPONSE = "Remote skill version payload did not match the expected contract.";
41015
41120
  function isVersionRecord(value) {
@@ -41032,19 +41137,19 @@ function normalizePin(entry) {
41032
41137
  if (!entry || typeof entry !== "object") {
41033
41138
  throw new Error("Remote pin payload did not match the expected contract (expected an object)");
41034
41139
  }
41035
- const record7 = entry;
41036
- const slug2 = typeof record7.slug === "string" && record7.slug.trim() ? record7.slug.trim() : undefined;
41140
+ const record8 = entry;
41141
+ const slug2 = typeof record8.slug === "string" && record8.slug.trim() ? record8.slug.trim() : undefined;
41037
41142
  if (!slug2) {
41038
41143
  throw new Error("Remote pin payload did not match the expected contract (missing slug)");
41039
41144
  }
41040
41145
  let metadata;
41041
- if (record7.metadata !== undefined) {
41042
- if (!record7.metadata || typeof record7.metadata !== "object" || Array.isArray(record7.metadata)) {
41146
+ if (record8.metadata !== undefined) {
41147
+ if (!record8.metadata || typeof record8.metadata !== "object" || Array.isArray(record8.metadata)) {
41043
41148
  throw new Error("Remote pin payload did not match the expected contract (metadata must be a JSON object when present)");
41044
41149
  }
41045
- metadata = record7.metadata;
41150
+ metadata = record8.metadata;
41046
41151
  }
41047
- const pinnedAt = requireOptionalString(record7, "pinnedAt");
41152
+ const pinnedAt = requireOptionalString(record8, "pinnedAt");
41048
41153
  return {
41049
41154
  slug: slug2,
41050
41155
  ...pinnedAt !== undefined ? { pinnedAt } : {},
@@ -41061,16 +41166,16 @@ function normalizeSkillSummary(entry) {
41061
41166
  if (!entry || typeof entry !== "object") {
41062
41167
  throw new Error("Remote skill payload did not match the expected contract (expected an object)");
41063
41168
  }
41064
- const record7 = entry;
41065
- const slug2 = typeof record7.slug === "string" && record7.slug.trim() ? record7.slug.trim() : undefined;
41169
+ const record8 = entry;
41170
+ const slug2 = typeof record8.slug === "string" && record8.slug.trim() ? record8.slug.trim() : undefined;
41066
41171
  if (!slug2) {
41067
41172
  throw new Error("Remote skill payload did not match the expected contract (missing slug)");
41068
41173
  }
41069
41174
  return {
41070
41175
  slug: slug2,
41071
- ...requireOptionalString(record7, "name") !== undefined ? { name: requireOptionalString(record7, "name") } : {},
41072
- ...requireOptionalString(record7, "version") !== undefined ? { version: requireOptionalString(record7, "version") } : {},
41073
- ...requireOptionalString(record7, "updatedAt") !== undefined ? { updatedAt: requireOptionalString(record7, "updatedAt") } : {}
41176
+ ...requireOptionalString(record8, "name") !== undefined ? { name: requireOptionalString(record8, "name") } : {},
41177
+ ...requireOptionalString(record8, "version") !== undefined ? { version: requireOptionalString(record8, "version") } : {},
41178
+ ...requireOptionalString(record8, "updatedAt") !== undefined ? { updatedAt: requireOptionalString(record8, "updatedAt") } : {}
41074
41179
  };
41075
41180
  }
41076
41181
  function normalizeSkillSummaryList(payload) {
@@ -41127,12 +41232,12 @@ function normalizeUpdatedSincePage(payload) {
41127
41232
  if (!payload || typeof payload !== "object") {
41128
41233
  throw new Error("Updated-since payload did not match the expected contract (expected an object)");
41129
41234
  }
41130
- const record7 = payload;
41131
- if (!Array.isArray(record7.skills)) {
41235
+ const record8 = payload;
41236
+ if (!Array.isArray(record8.skills)) {
41132
41237
  throw new Error("Updated-since payload did not match the expected contract (missing skills array)");
41133
41238
  }
41134
- const skills = record7.skills.map(normalizeSkillSummary);
41135
- const nextCursor = record7.nextCursor === undefined || record7.nextCursor === null ? null : record7.nextCursor;
41239
+ const skills = record8.skills.map(normalizeSkillSummary);
41240
+ const nextCursor = record8.nextCursor === undefined || record8.nextCursor === null ? null : record8.nextCursor;
41136
41241
  if (nextCursor !== null && typeof nextCursor !== "string") {
41137
41242
  throw new Error("Updated-since payload did not match the expected contract (nextCursor must be a string or absent)");
41138
41243
  }
@@ -41371,8 +41476,8 @@ function revisionIdOf(content) {
41371
41476
  const canonical6 = JSON.stringify(canonicalContent);
41372
41477
  return createHash21("sha256").update(canonical6).digest("hex");
41373
41478
  }
41374
- function revisionIdOfRecord(record7) {
41375
- return revisionIdOf(record7);
41479
+ function revisionIdOfRecord(record8) {
41480
+ return revisionIdOf(record8);
41376
41481
  }
41377
41482
  // src/lib/pull.ts
41378
41483
  import { existsSync as existsSync17, mkdirSync as mkdirSync12, mkdtempSync as mkdtempSync3, readFileSync as readFileSync21, renameSync as renameSync6, rmSync as rmSync5, writeFileSync as writeFileSync11 } from "fs";
@@ -41748,16 +41853,16 @@ function installBundleAtomically(name, entries, options = {}, marker = {}) {
41748
41853
  }
41749
41854
  return { path: target, created };
41750
41855
  }
41751
- function writePullMarker(dir, record7) {
41856
+ function writePullMarker(dir, record8) {
41752
41857
  const marker = {
41753
41858
  managedBy: "@hasna/skills",
41754
- skill: record7.skill,
41755
- source: record7.source ?? "pull",
41756
- ...record7.version ? { version: record7.version } : {},
41757
- ...record7.contentHash ? { contentHash: record7.contentHash } : {},
41758
- ...record7.sourceCommit ? { sourceCommit: record7.sourceCommit } : {},
41759
- ...record7.signature ? { signature: record7.signature } : {},
41760
- ...record7.revisionId ? { revisionId: record7.revisionId } : {},
41859
+ skill: record8.skill,
41860
+ source: record8.source ?? "pull",
41861
+ ...record8.version ? { version: record8.version } : {},
41862
+ ...record8.contentHash ? { contentHash: record8.contentHash } : {},
41863
+ ...record8.sourceCommit ? { sourceCommit: record8.sourceCommit } : {},
41864
+ ...record8.signature ? { signature: record8.signature } : {},
41865
+ ...record8.revisionId ? { revisionId: record8.revisionId } : {},
41761
41866
  syncedAt: new Date().toISOString()
41762
41867
  };
41763
41868
  writeFileSync11(join33(dir, PULL_MARKER_FILE), `${JSON.stringify(marker, null, 2)}
@@ -41772,19 +41877,19 @@ async function safeMeta(client2, slug2) {
41772
41877
  }
41773
41878
  if (!raw || typeof raw !== "object")
41774
41879
  return null;
41775
- const record7 = raw;
41776
- const kind = record7.kind === "instruction" || record7.kind === "executable" ? record7.kind : undefined;
41777
- const tags = Array.isArray(record7.tags) ? record7.tags.filter((tag) => typeof tag === "string" && tag.trim().length > 0) : undefined;
41880
+ const record8 = raw;
41881
+ const kind = record8.kind === "instruction" || record8.kind === "executable" ? record8.kind : undefined;
41882
+ const tags = Array.isArray(record8.tags) ? record8.tags.filter((tag) => typeof tag === "string" && tag.trim().length > 0) : undefined;
41778
41883
  return {
41779
- ...str(record7.displayName) ? { displayName: str(record7.displayName) } : {},
41780
- ...str(record7.description) ? { description: str(record7.description) } : {},
41781
- ...str(record7.category) ? { category: str(record7.category) } : {},
41884
+ ...str(record8.displayName) ? { displayName: str(record8.displayName) } : {},
41885
+ ...str(record8.description) ? { description: str(record8.description) } : {},
41886
+ ...str(record8.category) ? { category: str(record8.category) } : {},
41782
41887
  ...tags && tags.length ? { tags } : {},
41783
- ...str(record7.version) ? { version: str(record7.version) } : {},
41888
+ ...str(record8.version) ? { version: str(record8.version) } : {},
41784
41889
  ...kind ? { kind } : {},
41785
- ...REVISION_ID_PATTERN.test(str(record7.revisionId) ?? "") ? { revisionId: str(record7.revisionId) } : {},
41786
- ...typeof record7.skillMd === "string" && record7.skillMd.length > 0 ? { skillMd: record7.skillMd } : {},
41787
- ...str(record7.publishedSource) ? { publishedSource: str(record7.publishedSource) } : {}
41890
+ ...REVISION_ID_PATTERN.test(str(record8.revisionId) ?? "") ? { revisionId: str(record8.revisionId) } : {},
41891
+ ...typeof record8.skillMd === "string" && record8.skillMd.length > 0 ? { skillMd: record8.skillMd } : {},
41892
+ ...str(record8.publishedSource) ? { publishedSource: str(record8.publishedSource) } : {}
41788
41893
  };
41789
41894
  }
41790
41895
  function pickCorpusOptions(options) {
@@ -41793,8 +41898,8 @@ function pickCorpusOptions(options) {
41793
41898
  function extractSlug(entry) {
41794
41899
  if (!entry || typeof entry !== "object")
41795
41900
  return;
41796
- const record7 = entry;
41797
- return str(record7.slug) ?? str(record7.name);
41901
+ const record8 = entry;
41902
+ return str(record8.slug) ?? str(record8.name);
41798
41903
  }
41799
41904
  function dedupe(values) {
41800
41905
  return [...new Set(values)];
@@ -41851,7 +41956,7 @@ class RemoteInvitationEmailUnconfirmedError extends Error {
41851
41956
  this.name = "RemoteInvitationEmailUnconfirmedError";
41852
41957
  }
41853
41958
  }
41854
- var record7 = (v) => !!v && typeof v === "object" && !Array.isArray(v);
41959
+ var record8 = (v) => !!v && typeof v === "object" && !Array.isArray(v);
41855
41960
  var uuid11 = (v) => typeof v === "string" && /^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/.test(v);
41856
41961
  function invitationEmailIds(invitationId, challengeId) {
41857
41962
  if (!uuid11(invitationId) || !uuid11(challengeId))
@@ -41860,7 +41965,7 @@ function invitationEmailIds(invitationId, challengeId) {
41860
41965
  }
41861
41966
  function invitationEmailInput(action, input2) {
41862
41967
  const keys = ["invitationId", "token", "challengeId", "confirm", ...action === "accept" ? ["code"] : []];
41863
- if (!record7(input2) || Object.keys(input2).length !== keys.length || keys.some((key) => !Object.hasOwn(input2, key)))
41968
+ if (!record8(input2) || Object.keys(input2).length !== keys.length || keys.some((key) => !Object.hasOwn(input2, key)))
41864
41969
  throw new InvitationEmailInputError;
41865
41970
  const value = { ...input2 };
41866
41971
  const ids = invitationEmailIds(value.invitationId, value.challengeId);
@@ -41889,12 +41994,12 @@ async function requestInvitationEmail(origin, action, input2) {
41889
41994
  signal: AbortSignal.timeout(15000)
41890
41995
  });
41891
41996
  const parsed = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(await readBoundedResponse(response, 4096)));
41892
- if (!response.ok && record7(parsed) && typeof parsed.code === "string" && Object.hasOwn(refusals, parsed.code)) {
41997
+ if (!response.ok && record8(parsed) && typeof parsed.code === "string" && Object.hasOwn(refusals, parsed.code)) {
41893
41998
  const code = parsed.code;
41894
41999
  if (response.status === refusals[code][0])
41895
42000
  throw new RemoteInvitationEmailError(code);
41896
42001
  }
41897
- if (!record7(parsed))
42002
+ if (!record8(parsed))
41898
42003
  throw new RemoteInvitationEmailUnconfirmedError(action);
41899
42004
  if (action === "challenge" && response.status === 202 && parsed.challengeId === value.challengeId && parsed.expiresIn === 600 && typeof parsed.message === "string" && parsed.message.length <= 256) {
41900
42005
  return { challengeId: value.challengeId, message: "If this invitation is eligible, a verification code will arrive. Delivery is not confirmed.", expiresIn: 600 };
@@ -41954,8 +42059,8 @@ var invalid4 = () => {
41954
42059
  };
41955
42060
  var publicationUuid = (v) => typeof v === "string" && /^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/.test(v);
41956
42061
  var hash3 = (v) => typeof v === "string" && /^[a-f0-9]{64}$/.test(v);
41957
- var record8 = (v) => !!v && typeof v === "object" && !Array.isArray(v);
41958
- var exact = (v, keys) => record8(v) && Object.keys(v).sort().join(",") === keys.sort().join(",");
42062
+ var record9 = (v) => !!v && typeof v === "object" && !Array.isArray(v);
42063
+ var exact = (v, keys) => record9(v) && Object.keys(v).sort().join(",") === keys.sort().join(",");
41959
42064
  var date5 = (v) => typeof v === "string" && /^\d{4}-\d\d-\d\dT[0-9:.]+(?:Z|[+-](?:[01]\d|2[0-3]):[0-5]\d)$/.test(v) && Number.isFinite(Date.parse(v));
41960
42065
  var publicationSha256 = (bytes) => createHash22("sha256").update(bytes).digest("hex");
41961
42066
  function checkedPublicationDeclaration(value) {
@@ -41963,7 +42068,7 @@ function checkedPublicationDeclaration(value) {
41963
42068
  return bad();
41964
42069
  try {
41965
42070
  const manifest = JSON.parse(value.manifestText);
41966
- if (!record8(manifest) || manifest.version !== value.version || validatePortableManifestContract(manifest, { strict: true }).length || !hash3(manifest.provenance?.content_hash))
42071
+ if (!record9(manifest) || manifest.version !== value.version || validatePortableManifestContract(manifest, { strict: true }).length || !hash3(manifest.provenance?.content_hash))
41967
42072
  return bad();
41968
42073
  } catch {
41969
42074
  return bad();
@@ -42021,7 +42126,7 @@ async function boundedJson(url2, init, token, mutation, budget2 = 15000, signal)
42021
42126
  return invalid4();
42022
42127
  }
42023
42128
  if (!response.ok) {
42024
- const code = record8(body) && typeof body.code === "string" && Object.hasOwn(failures2, body.code) ? body.code : null;
42129
+ const code = record9(body) && typeof body.code === "string" && Object.hasOwn(failures2, body.code) ? body.code : null;
42025
42130
  if (code && failures2[code][0] === response.status)
42026
42131
  throw new PrivatePublicationError(code, failures2[code][1], mutation && code === "PUBLICATION_UNCERTAIN", response.status);
42027
42132
  throw new PrivatePublicationError("PUBLICATION_REQUEST_FAILED", "The publication request was refused. Inspect its status before retrying.", mutation && response.status >= 500, response.status);
@@ -42076,8 +42181,8 @@ class RemotePrivatePublicationsClient {
42076
42181
  if (options.timeoutMs !== undefined && (!Number.isSafeInteger(options.timeoutMs) || options.timeoutMs < 1 || options.timeoutMs > 15000))
42077
42182
  return bad();
42078
42183
  const response = await boundedJson(skillsApiRequestUrl(this.apiOrigin, "/api/v1/capabilities"), {}, this.#token, false, options.timeoutMs, options.signal);
42079
- const p = record8(response) && response.privatePublishing;
42080
- if (!record8(response) || response.contractVersion !== 1 || response.apiVersion !== 1 || !exact(p, ["contractVersion", "enabled", "authentication", "maxArchiveBytes", "uploadMaxTtlSeconds", "executionEnabled"]) || p.contractVersion !== 1 || typeof p.enabled !== "boolean" || p.authentication !== "interactive-session" || p.maxArchiveBytes !== PRIVATE_PUBLICATION_MAX_BYTES || p.uploadMaxTtlSeconds !== 300 || typeof p.executionEnabled !== "boolean")
42184
+ const p = record9(response) && response.privatePublishing;
42185
+ if (!record9(response) || response.contractVersion !== 1 || response.apiVersion !== 1 || !exact(p, ["contractVersion", "enabled", "authentication", "maxArchiveBytes", "uploadMaxTtlSeconds", "executionEnabled"]) || p.contractVersion !== 1 || typeof p.enabled !== "boolean" || p.authentication !== "interactive-session" || p.maxArchiveBytes !== PRIVATE_PUBLICATION_MAX_BYTES || p.uploadMaxTtlSeconds !== 300 || typeof p.executionEnabled !== "boolean")
42081
42186
  throw new PrivatePublicationError("PUBLICATION_CONTRACT_UNAVAILABLE", "This server does not support the hosted private publication contract.");
42082
42187
  return Object.freeze({ ...p });
42083
42188
  }
@@ -42093,7 +42198,7 @@ class RemotePrivatePublicationsClient {
42093
42198
  async#view(path, method, skillId, intentId, declaration, options = {}) {
42094
42199
  const value = await boundedJson(path, { method, ...method === "GET" ? {} : { body: JSON.stringify(declaration ?? {}) } }, this.#token, method !== "GET", options.timeoutMs, options.signal);
42095
42200
  try {
42096
- if (!record8(value) || !Object.keys(value).every((k) => k === "upload" || k === "changed") || value.changed !== undefined && typeof value.changed !== "boolean")
42201
+ if (!record9(value) || !Object.keys(value).every((k) => k === "upload" || k === "changed") || value.changed !== undefined && typeof value.changed !== "boolean")
42097
42202
  return invalid4();
42098
42203
  return checkedPublicationView(value.upload, skillId, intentId, declaration);
42099
42204
  } catch (error61) {
@@ -42256,10 +42361,10 @@ async function requestAuthApi(instance, path, options) {
42256
42361
  const text3 = await res.text();
42257
42362
  const body = text3 ? parseJsonBody(text3) : {};
42258
42363
  if (!res.ok) {
42259
- const record9 = isRecord6(body) ? body : {};
42260
- const detail = typeof record9.detail === "string" ? record9.detail : undefined;
42261
- const error61 = typeof record9.error === "string" ? record9.error : undefined;
42262
- const code = typeof record9.code === "string" ? record9.code : undefined;
42364
+ const record10 = isRecord6(body) ? body : {};
42365
+ const detail = typeof record10.detail === "string" ? record10.detail : undefined;
42366
+ const error61 = typeof record10.error === "string" ? record10.error : undefined;
42367
+ const code = typeof record10.code === "string" ? record10.code : undefined;
42263
42368
  throw new HostedApiError(detail || error61 || `${res.status} ${res.statusText}`, {
42264
42369
  status: res.status,
42265
42370
  code,
@@ -44068,7 +44173,7 @@ class SkillsPostgresSyncStore {
44068
44173
  }
44069
44174
  async upsertRecords(records) {
44070
44175
  let count = 0;
44071
- for (const record9 of records) {
44176
+ for (const record10 of records) {
44072
44177
  await this.client.query([
44073
44178
  "INSERT INTO skills_sync_records",
44074
44179
  "(scope, kind, id, updated_at, deleted_at, source, payload)",
@@ -44079,13 +44184,13 @@ class SkillsPostgresSyncStore {
44079
44184
  "source = EXCLUDED.source,",
44080
44185
  "payload = EXCLUDED.payload"
44081
44186
  ].join(" "), [
44082
- record9.scope,
44083
- record9.kind,
44084
- record9.id,
44085
- record9.updatedAt,
44086
- record9.deletedAt ?? null,
44087
- record9.source ?? null,
44088
- JSON.stringify(record9.payload)
44187
+ record10.scope,
44188
+ record10.kind,
44189
+ record10.id,
44190
+ record10.updatedAt,
44191
+ record10.deletedAt ?? null,
44192
+ record10.source ?? null,
44193
+ JSON.stringify(record10.payload)
44089
44194
  ]);
44090
44195
  count += 1;
44091
44196
  }
@@ -45489,6 +45594,7 @@ export {
45489
45594
  validateCron,
45490
45595
  validateBlogArticleRunOptions,
45491
45596
  uploadSkillsSnapshotFilesToS3,
45597
+ upgradeCodexSettingsWitnessV3,
45492
45598
  upgradeCodexSettingsWitness,
45493
45599
  upgradeClaudeSettingsWitness,
45494
45600
  updateSkillRun,
@@ -45674,6 +45780,7 @@ export {
45674
45780
  captureDiscoveryPathSources,
45675
45781
  captureDiscoveryDirectories,
45676
45782
  captureDiscoveryByteSources,
45783
+ captureCodexSettingsV3,
45677
45784
  captureCodexSettingsV2,
45678
45785
  captureCodexSettings,
45679
45786
  captureCodexNativeSkillCatalog,