@hasna/skills 0.10.26 → 0.10.28

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.26",
10917
+ version: "0.10.28",
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,25 @@ 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", "personality"] : 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 (key === "personality")
14060
+ need4(typeof value === "string" && ["none", "friendly", "pragmatic"].includes(value));
14061
+ else if (version === 3 && key !== "model_verbosity") {
14062
+ need4(typeof value === "string" && value.length <= 128 && !/[\x00-\x1f\x7f]/.test(value));
14063
+ if (key !== "service_tier")
14064
+ need4(value.length > 0);
14065
+ } else
13981
14066
  need4(typeof value === "string" && (key === "model_reasoning_effort" ? EFFORT2.has(value) : VERBOSITY2.has(value)));
13982
14067
  delete target[key];
13983
14068
  }
13984
14069
  }
13985
- function settingsDigest2(text2) {
14070
+ function settingsDigest2(text2, version = 2) {
13986
14071
  let config;
13987
14072
  try {
13988
14073
  config = Bun.TOML.parse(text2);
@@ -13990,8 +14075,9 @@ function settingsDigest2(text2) {
13990
14075
  throw new Error("Invalid Codex settings witness");
13991
14076
  }
13992
14077
  need4(isRecord3(config));
13993
- normalize3(config);
13994
- return sha2(`hasna.skills.codex-settings.v2\x00${JSON.stringify([canonical4(config), numericTokens2(text2)])}`);
14078
+ const projected = version === 3 ? projectRegularCodexMcp(config, text2) : { config, numericSource: text2 };
14079
+ normalize3(projected.config, version);
14080
+ return sha2(`hasna.skills.codex-settings.v${version}\x00${JSON.stringify([canonical4(projected.config), numericTokens2(projected.numericSource)])}`);
13995
14081
  }
13996
14082
  function hashCodexSettingsReplacementV2(text2, budget = { remaining: 256 * 1024 * 1024 }) {
13997
14083
  need4(Buffer.byteLength(text2) <= 1024 * 1024 && budget.remaining >= Buffer.byteLength(text2));
@@ -14015,10 +14101,29 @@ function upgradeCodexSettingsWitness(previous, reviewedSettingsPath) {
14015
14101
  throw new Error("Codex non-preference settings changed; explicit discovery review required");
14016
14102
  return { path: previous.path, hashMode: "codex-settings-v2", sha256: sha2562 };
14017
14103
  }
14104
+ function hashCodexSettingsReplacementV3(text2, budget = { remaining: 256 * 1024 * 1024 }) {
14105
+ need4(Buffer.byteLength(text2) <= 1024 * 1024 && budget.remaining >= Buffer.byteLength(text2));
14106
+ budget.remaining -= Buffer.byteLength(text2);
14107
+ return settingsDigest2(text2, 3);
14108
+ }
14109
+ function captureCodexSettingsV3(path, budget = { remaining: 256 * 1024 * 1024 }) {
14110
+ return { path, hashMode: "codex-settings-v3", sha256: settingsDigest2(readNativeSettingsWitnessFile(path, budget, "config.toml"), 3) };
14111
+ }
14112
+ function upgradeCodexSettingsWitnessV3(previous, reviewedSettingsPath) {
14113
+ 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));
14114
+ const budget = { remaining: 2 * 1024 * 1024 };
14115
+ const before = readNativeSettingsWitnessFile(reviewedSettingsPath, budget, "config.toml"), current = readNativeSettingsWitnessFile(previous.path, budget, "config.toml");
14116
+ const original = previous.hashMode === "codex-settings-v2" ? settingsDigest2(before) : previous.hashMode === "codex-settings-v1" ? hashCodexSettingsReplacement(before) : sha2(before);
14117
+ need4(original === previous.sha256);
14118
+ const sha2562 = settingsDigest2(current, 3);
14119
+ if (settingsDigest2(before, 3) !== sha2562)
14120
+ throw new Error("Codex settings outside the reviewed V3 contract changed; explicit discovery review required");
14121
+ return { path: previous.path, hashMode: "codex-settings-v3", sha256: sha2562 };
14122
+ }
14018
14123
 
14019
14124
  // src/lib/agent-integration.ts
14020
14125
  import { createHash as createHash12, randomUUID as randomUUID2 } from "crypto";
14021
- import { isDeepStrictEqual as isDeepStrictEqual3 } from "util";
14126
+ import { isDeepStrictEqual as isDeepStrictEqual4 } from "util";
14022
14127
  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
14128
  import { dirname as dirname11, join as join17, resolve as resolve10, relative as relative5, isAbsolute as isAbsolute11, sep as sep5 } from "path";
14024
14129
  import { homedir as homedir2 } from "os";
@@ -14147,7 +14252,7 @@ function isOwnedCliBridge(path, expectedPaths) {
14147
14252
  }
14148
14253
 
14149
14254
  // src/lib/agent-codex.ts
14150
- import { isDeepStrictEqual as isDeepStrictEqual2 } from "util";
14255
+ import { isDeepStrictEqual as isDeepStrictEqual3 } from "util";
14151
14256
  var CODEX_SKILL_CONFIG_SECTIONS = /^\[\[skills\.config\]\][^\n]*(?:\n(?!\s*\[)[^\n]*)*/gm;
14152
14257
  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
14258
  function splitTopLevel(value, delimiter) {
@@ -14278,7 +14383,7 @@ function normalizeCodexInlinePathConfig(text2) {
14278
14383
  const expectedWithoutConfig = structuredClone(before);
14279
14384
  delete expectedWithoutConfig.skills.config;
14280
14385
  try {
14281
- if (isDeepStrictEqual2(Bun.TOML.parse(text2.replace(CODEX_SKILL_CONFIG_SECTIONS, "")), expectedWithoutConfig))
14386
+ if (isDeepStrictEqual3(Bun.TOML.parse(text2.replace(CODEX_SKILL_CONFIG_SECTIONS, "")), expectedWithoutConfig))
14282
14387
  return text2;
14283
14388
  } catch {}
14284
14389
  const matches = [];
@@ -14331,7 +14436,7 @@ function normalizeCodexInlinePathConfig(text2) {
14331
14436
  try {
14332
14437
  const after = Bun.TOML.parse(candidate);
14333
14438
  const expected = structuredClone(before);
14334
- if (isDeepStrictEqual2(after, expected))
14439
+ if (isDeepStrictEqual3(after, expected))
14335
14440
  matches.push(candidate);
14336
14441
  } catch {}
14337
14442
  }
@@ -14347,11 +14452,11 @@ function assertCodexPathConfigEditable(text2) {
14347
14452
  delete expected.skills.config;
14348
14453
  try {
14349
14454
  const withoutSections = Bun.TOML.parse(text2.replace(CODEX_SKILL_CONFIG_SECTIONS, ""));
14350
- if (isDeepStrictEqual2(withoutSections, expected))
14455
+ if (isDeepStrictEqual3(withoutSections, expected))
14351
14456
  return;
14352
14457
  const normalized = normalizeCodexInlinePathConfig(text2);
14353
14458
  const withoutNormalizedSections = Bun.TOML.parse(normalized.replace(CODEX_SKILL_CONFIG_SECTIONS, ""));
14354
- if (isDeepStrictEqual2(withoutNormalizedSections, expected))
14459
+ if (isDeepStrictEqual3(withoutNormalizedSections, expected))
14355
14460
  return;
14356
14461
  } catch {}
14357
14462
  throw codexPathConfigRefusal();
@@ -14389,7 +14494,7 @@ function disableCodexBundledSkills(text2) {
14389
14494
  const candidates = new Set;
14390
14495
  const consider = (candidate) => {
14391
14496
  try {
14392
- if (isDeepStrictEqual2(Bun.TOML.parse(candidate), expected))
14497
+ if (isDeepStrictEqual3(Bun.TOML.parse(candidate), expected))
14393
14498
  candidates.add(candidate);
14394
14499
  } catch {}
14395
14500
  };
@@ -15200,6 +15305,8 @@ function atomicWrite2(path, content) {
15200
15305
  }
15201
15306
  }
15202
15307
  function planAgentSettingsWitnessUpgrade(options) {
15308
+ if (options.targetCodexVersion !== undefined && (options.agent !== "codex" || ![2, 3].includes(options.targetCodexVersion)))
15309
+ throw new Error("Invalid Codex witness target version");
15203
15310
  const home = resolve10(options.home ?? homedir2()), dataDir2 = options.dataDir ?? getDataDirReadOnly();
15204
15311
  const snapshot = readManagedSkillPolicySnapshot(dataDir2);
15205
15312
  if (!snapshot || sha3(snapshot.text) !== options.expectedPolicySha256)
@@ -15221,21 +15328,21 @@ function planAgentSettingsWitnessUpgrade(options) {
15221
15328
  throw new Error("Settings witness upgrade requires a preserved settings preimage");
15222
15329
  const replaced = [previous];
15223
15330
  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");
15331
+ if (previous.hashMode !== undefined && previous.hashMode !== "bytes" && previous.hashMode !== "codex-settings-v1" && !(options.targetCodexVersion === 3 && previous.hashMode === "codex-settings-v2"))
15332
+ throw new Error("Codex settings witness upgrade requires an eligible preserved configuration witness");
15226
15333
  const preimage = readCodexSettingsPreimage(options.reviewedPreimage);
15227
15334
  for (const source of binding.sources) {
15228
15335
  if (source === previous || source.path !== configPath)
15229
15336
  continue;
15230
15337
  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")
15338
+ if (source.hashMode !== undefined || source.format !== "toml" || !Array.isArray(fields) || !isDeepStrictEqual4(fields, [...CODEX_DISCOVERY_PROJECTION_FIELDS]) || typeof source.sha256 !== "string")
15232
15339
  throw new Error("Codex settings witness upgrade found an unrecognized configuration witness");
15233
15340
  if (projectNativeDiscoveryFields(preimage, "toml", fields, configPath) !== source.sha256)
15234
15341
  throw new Error("Reviewed preimage does not explain the Codex discovery projection witness");
15235
15342
  replaced.push(source);
15236
15343
  }
15237
15344
  }
15238
- const next = options.agent === "claude" ? upgradeClaudeSettingsWitness(previous, options.reviewedPreimage) : upgradeCodexSettingsWitness(previous, options.reviewedPreimage);
15345
+ const next = options.agent === "claude" ? upgradeClaudeSettingsWitness(previous, options.reviewedPreimage) : options.targetCodexVersion === 3 ? upgradeCodexSettingsWitnessV3(previous, options.reviewedPreimage) : upgradeCodexSettingsWitness(previous, options.reviewedPreimage);
15239
15346
  const rebound = [];
15240
15347
  for (const source of binding.sources) {
15241
15348
  if (!replaced.includes(source)) {
@@ -15272,7 +15379,7 @@ function applyAgentIntegration(plan) {
15272
15379
  const upgrade = plan.settingsWitnessUpgrade;
15273
15380
  if (!plan.managedAgentChecks || !plan.observedPolicy?.before)
15274
15381
  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 });
15382
+ 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
15383
  if (JSON.stringify(verified.changes) !== JSON.stringify(plan.changes) || JSON.stringify(verified.settingsWitnessUpgrade) !== JSON.stringify(upgrade))
15277
15384
  throw new Error("Settings witness upgrade plan changed");
15278
15385
  provenDiscovery = verified.discoveryBefore[0];
@@ -18248,19 +18355,19 @@ function projectNativeDiscoveryFields(text2, format, fields2, path) {
18248
18355
  return digest(JSON.stringify(Object.fromEntries(fields2.map((field2) => [field2, object5[field2] ?? null]))));
18249
18356
  }
18250
18357
  function isSupersededCodexProjection(agent, configPath, source) {
18251
- return agent === "codex" && source.path === configPath && source.format === "toml" && isDeepStrictEqual4(source.fields, [...CODEX_DISCOVERY_PROJECTION_FIELDS]);
18358
+ return agent === "codex" && source.path === configPath && source.format === "toml" && isDeepStrictEqual5(source.fields, [...CODEX_DISCOVERY_PROJECTION_FIELDS]);
18252
18359
  }
18253
18360
  function supersedesCodexProjection(sources, configPath) {
18254
- return sources.some((source) => source.path === configPath && source.hashMode === "codex-settings-v2");
18361
+ return sources.some((source) => source.path === configPath && (source.hashMode === "codex-settings-v2" || source.hashMode === "codex-settings-v3"));
18255
18362
  }
18256
18363
  function projected(source, changes, budget = discoveryByteBudget()) {
18257
- if (source.hashMode === "codex-settings-v1" || source.hashMode === "codex-settings-v2") {
18364
+ if (source.hashMode === "codex-settings-v1" || source.hashMode === "codex-settings-v2" || source.hashMode === "codex-settings-v3") {
18258
18365
  if (source.format !== undefined || source.fields !== undefined || source.managedPlugins !== undefined || typeof source.sha256 !== "string" || !/^[a-f0-9]{64}$/.test(source.sha256))
18259
18366
  throw new Error("Codex settings witnesses require exact typed metadata");
18260
- const current = (source.hashMode === "codex-settings-v2" ? captureCodexSettingsV2 : captureCodexSettings)(source.path, budget).sha256;
18367
+ const current = (source.hashMode === "codex-settings-v3" ? captureCodexSettingsV3 : source.hashMode === "codex-settings-v2" ? captureCodexSettingsV2 : captureCodexSettings)(source.path, budget).sha256;
18261
18368
  if (current !== source.sha256)
18262
18369
  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;
18370
+ 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
18371
  }
18265
18372
  if (source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || source.hashMode === "claude-settings-v3") {
18266
18373
  if (source.format !== undefined || source.fields !== undefined || source.managedPlugins !== undefined || typeof source.sha256 !== "string" || !/^[a-f0-9]{64}$/.test(source.sha256))
@@ -18360,7 +18467,7 @@ function codexInstallationRoots(binding) {
18360
18467
  });
18361
18468
  }
18362
18469
  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"))
18470
+ 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
18471
  throw new Error("Codex settings witnesses require explicit reviewed Codex configuration");
18365
18472
  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
18473
  throw new Error("Claude settings witnesses require explicit reviewed Claude configuration");
@@ -18510,10 +18617,10 @@ function resolveAgentDiscovery(options) {
18510
18617
  verifyAgentDiscovery(retained);
18511
18618
  if (!retained.sources.some((source) => source.path === canonical6(configPath) && source.format === undefined && source.fields === undefined))
18512
18619
  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)))
18620
+ 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
18621
  unresolved("retained settings witness names another configuration source");
18515
18622
  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))
18623
+ 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
18624
  unresolved("retained review is missing current runtime discovery coverage");
18518
18625
  return retained;
18519
18626
  }
@@ -18527,7 +18634,7 @@ function resolveAgentDiscovery(options) {
18527
18634
  if (review.sources.some((source) => source.format !== undefined || source.fields !== undefined))
18528
18635
  throw new Error("Explicit discovery reviews require full source-file hashes");
18529
18636
  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)))
18637
+ 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
18638
  throw new Error("Semantic settings witnesses must name the configured Claude configuration source");
18532
18639
  if (!review.sources.some((source) => source.path === canonical6(configPath)))
18533
18640
  throw new Error("Discovery review must include the agent configuration source");
@@ -19505,7 +19612,7 @@ function createSkillRun(params, targetDir = process.cwd()) {
19505
19612
  mkdirSync10(logsDir, { recursive: true });
19506
19613
  mkdirSync10(exportDir, { recursive: true });
19507
19614
  mkdirSync10(join31(root2, "tmp"), { recursive: true });
19508
- const record2 = {
19615
+ const record3 = {
19509
19616
  id,
19510
19617
  skill: skillName,
19511
19618
  status: params.status ?? "running",
@@ -19523,10 +19630,10 @@ function createSkillRun(params, targetDir = process.cwd()) {
19523
19630
  logsDir: toProjectRelative(targetDir, logsDir)
19524
19631
  }
19525
19632
  };
19526
- const context = { targetDir, runDir, exportDir, logsDir, record: record2 };
19633
+ const context = { targetDir, runDir, exportDir, logsDir, record: record3 };
19527
19634
  writeRunRecord(context);
19528
19635
  writeArtifactsManifest(context, []);
19529
- appendRunEvent(context, "created", { status: record2.status });
19636
+ appendRunEvent(context, "created", { status: record3.status });
19530
19637
  return context;
19531
19638
  }
19532
19639
  function completeSkillRun(context, patch) {
@@ -19576,9 +19683,9 @@ function listSkillRuns(targetDir = process.cwd(), limit = 50) {
19576
19683
  if (!statSync11(dayDir).isDirectory())
19577
19684
  continue;
19578
19685
  for (const runId of readdirSync13(dayDir).sort().reverse()) {
19579
- const record2 = readRunRecord(join31(dayDir, runId));
19580
- if (record2)
19581
- records.push(record2);
19686
+ const record3 = readRunRecord(join31(dayDir, runId));
19687
+ if (record3)
19688
+ records.push(record3);
19582
19689
  if (records.length >= limit)
19583
19690
  return records;
19584
19691
  }
@@ -19590,9 +19697,9 @@ function findSkillRun(runId, targetDir = process.cwd()) {
19590
19697
  if (!existsSync15(runsRoot))
19591
19698
  return null;
19592
19699
  for (const day of readdirSync13(runsRoot)) {
19593
- const record2 = readRunRecord(join31(runsRoot, day, runId));
19594
- if (record2)
19595
- return record2;
19700
+ const record3 = readRunRecord(join31(runsRoot, day, runId));
19701
+ if (record3)
19702
+ return record3;
19596
19703
  }
19597
19704
  return null;
19598
19705
  }
@@ -19733,7 +19840,7 @@ __export(exports_external, {
19733
19840
  regexes: () => exports_regexes,
19734
19841
  regex: () => _regex,
19735
19842
  refine: () => refine,
19736
- record: () => record2,
19843
+ record: () => record3,
19737
19844
  readonly: () => readonly,
19738
19845
  property: () => _property,
19739
19846
  properties: () => _properties,
@@ -35507,8 +35614,8 @@ function rewriteKeyNames(ctx) {
35507
35614
  bySchema.set(entry.schema, entry);
35508
35615
  }
35509
35616
  const rewrites = new Map;
35510
- for (const record2 of pendingRecords.get(ctx) ?? []) {
35511
- const seen = ctx.seen.get(record2);
35617
+ for (const record3 of pendingRecords.get(ctx) ?? []) {
35618
+ const seen = ctx.seen.get(record3);
35512
35619
  const names = (seen?.def ?? seen?.schema)?.propertyNames;
35513
35620
  if (!names || names === true || rewrites.has(names))
35514
35621
  continue;
@@ -35835,7 +35942,7 @@ __export(exports_schemas2, {
35835
35942
  strictObject: () => strictObject,
35836
35943
  set: () => set,
35837
35944
  refine: () => refine,
35838
- record: () => record2,
35945
+ record: () => record3,
35839
35946
  readonly: () => readonly,
35840
35947
  promise: () => promise,
35841
35948
  preprocess: () => preprocess,
@@ -37005,7 +37112,7 @@ var ZodRecord = /* @__PURE__ */ $constructor("ZodRecord", (inst, def) => {
37005
37112
  inst.keyType = def.keyType;
37006
37113
  inst.valueType = def.valueType;
37007
37114
  });
37008
- function record2(keyType, valueType, params) {
37115
+ function record3(keyType, valueType, params) {
37009
37116
  if (!valueType || !valueType._zod) {
37010
37117
  return new ZodRecord({
37011
37118
  type: "record",
@@ -37471,7 +37578,7 @@ var stringbool = (...args) => _stringbool({
37471
37578
  }, ...args);
37472
37579
  function json(params) {
37473
37580
  const jsonSchema = lazy(() => {
37474
- return union([string2(params), number2(), boolean2(), _null3(), array2(jsonSchema), record2(string2(), jsonSchema)]);
37581
+ return union([string2(params), number2(), boolean2(), _null3(), array2(jsonSchema), record3(string2(), jsonSchema)]);
37475
37582
  });
37476
37583
  return jsonSchema;
37477
37584
  }
@@ -39459,12 +39566,12 @@ class RemoteWorkspaceInvitationReadError extends Error {
39459
39566
  }
39460
39567
  }
39461
39568
  function invitationFailure(value, status) {
39462
- if (!record3(value) || typeof value.code !== "string" || !Object.hasOwn(invitationFailures, value.code))
39569
+ if (!record4(value) || typeof value.code !== "string" || !Object.hasOwn(invitationFailures, value.code))
39463
39570
  return null;
39464
39571
  const code = value.code;
39465
39572
  return invitationFailures[code][0] === status ? code : null;
39466
39573
  }
39467
- var record3 = (v) => !!v && typeof v === "object" && !Array.isArray(v);
39574
+ var record4 = (v) => !!v && typeof v === "object" && !Array.isArray(v);
39468
39575
  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
39576
  var role = (v) => typeof v === "string" && ["owner", "admin", "member", "viewer"].includes(v);
39470
39577
  var email3 = (v) => typeof v === "string" && v.length <= 254 && !/[\p{Cc}\p{Cs}\u2028\u2029\s]/u.test(v) && /^[^@]+@[^@]+\.[^@]+$/.test(v);
@@ -39473,7 +39580,7 @@ var inputFailure = () => {
39473
39580
  throw new WorkspaceInvitationInputError;
39474
39581
  };
39475
39582
  function invitationInput(action, input2) {
39476
- if (!record3(input2))
39583
+ if (!record4(input2))
39477
39584
  return inputFailure();
39478
39585
  const keys = {
39479
39586
  list: ["after"],
@@ -39524,7 +39631,7 @@ function invalid2() {
39524
39631
  throw new RemoteWorkspaceInvitationReadError;
39525
39632
  }
39526
39633
  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)
39634
+ 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
39635
  return invalid2();
39529
39636
  return {
39530
39637
  id: v.id,
@@ -39539,7 +39646,7 @@ function projection(v, organizationId) {
39539
39646
  };
39540
39647
  }
39541
39648
  function parseInvitationResult(action, value, input2, organizationId) {
39542
- if (!record3(value))
39649
+ if (!record4(value))
39543
39650
  return invalid2();
39544
39651
  const request = input2;
39545
39652
  if (action === "accept") {
@@ -39572,7 +39679,7 @@ function parseInvitationResult(action, value, input2, organizationId) {
39572
39679
  }
39573
39680
 
39574
39681
  // src/lib/remote-workspace-selection.ts
39575
- var record4 = (v) => !!v && typeof v === "object" && !Array.isArray(v);
39682
+ var record5 = (v) => !!v && typeof v === "object" && !Array.isArray(v);
39576
39683
  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
39684
  var text2 = (v, max = 1024) => typeof v === "string" && !!v.trim() && v.length <= max && !/[\p{Cc}\p{Cs}\u2028\u2029]/u.test(v);
39578
39685
  var role2 = (v) => typeof v === "string" && ["owner", "admin", "member", "viewer"].includes(v);
@@ -39597,7 +39704,7 @@ function workspaceExpectedUserId(value) {
39597
39704
  return value;
39598
39705
  }
39599
39706
  function workspaceContext(value) {
39600
- if (!record4(value) || Object.keys(value).sort().join(",") !== "membershipId,userId" || !uuid8(value.userId) || !uuid8(value.membershipId))
39707
+ if (!record5(value) || Object.keys(value).sort().join(",") !== "membershipId,userId" || !uuid8(value.userId) || !uuid8(value.membershipId))
39601
39708
  throw new WorkspaceContextInputError;
39602
39709
  return { userId: value.userId, membershipId: value.membershipId };
39603
39710
  }
@@ -39605,15 +39712,15 @@ function invalid3() {
39605
39712
  throw new Error(invalidWorkspaceResult);
39606
39713
  }
39607
39714
  function organization(v) {
39608
- if (!record4(v) || !uuid8(v.id) || !text2(v.slug) || !text2(v.name))
39715
+ if (!record5(v) || !uuid8(v.id) || !text2(v.slug) || !text2(v.name))
39609
39716
  return invalid3();
39610
39717
  return { id: v.id, slug: v.slug, name: v.name };
39611
39718
  }
39612
39719
  function parseAccountWorkspaces(value) {
39613
- if (!record4(value) || !Array.isArray(value.workspaces) || !value.workspaces.length || value.workspaces.length > 1000)
39720
+ if (!record5(value) || !Array.isArray(value.workspaces) || !value.workspaces.length || value.workspaces.length > 1000)
39614
39721
  return invalid3();
39615
39722
  const workspaces = value.workspaces.map((v) => {
39616
- if (!record4(v) || !uuid8(v.membershipId) || !role2(v.role) || typeof v.current !== "boolean")
39723
+ if (!record5(v) || !uuid8(v.membershipId) || !role2(v.role) || typeof v.current !== "boolean")
39617
39724
  return invalid3();
39618
39725
  return { membershipId: v.membershipId, organization: organization(v.organization), role: v.role, current: v.current };
39619
39726
  });
@@ -39622,10 +39729,10 @@ function parseAccountWorkspaces(value) {
39622
39729
  return { workspaces };
39623
39730
  }
39624
39731
  function parseWorkspaceIdentity(value, expectedUserId) {
39625
- if (!record4(value))
39732
+ if (!record5(value))
39626
39733
  return invalid3();
39627
39734
  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))
39735
+ if (!record5(user) || !uuid8(user.id) || !uuid8(user.membershipId) || !text2(user.email, 320) || !(user.displayName === null || text2(user.displayName)) || !role2(user.role))
39629
39736
  return invalid3();
39630
39737
  if (user.id !== expectedUserId)
39631
39738
  throw new WorkspaceIdentityMismatchError;
@@ -39643,8 +39750,8 @@ function parseWorkspaceSession(value, expected) {
39643
39750
  return { token: sessionToken(value.token), ...identity4 };
39644
39751
  }
39645
39752
  function parseWorkspaceLogin(value, expectedUserId) {
39646
- const user = record4(value) && value.user;
39647
- if (!record4(value) || !record4(user) || !uuid8(user.id))
39753
+ const user = record5(value) && value.user;
39754
+ if (!record5(value) || !record5(user) || !uuid8(user.id))
39648
39755
  return invalid3();
39649
39756
  if (expectedUserId !== undefined && user.id !== expectedUserId)
39650
39757
  throw new WorkspaceIdentityMismatchError;
@@ -39659,18 +39766,18 @@ var workspaceSelectionFailures = {
39659
39766
  WORKSPACE_BUSY: [503, "Workspace is busy. Refresh before retrying."]
39660
39767
  };
39661
39768
  function workspaceSelectionFailure(value, status) {
39662
- if (!record4(value) || typeof value.code !== "string" || !Object.hasOwn(workspaceSelectionFailures, value.code))
39769
+ if (!record5(value) || typeof value.code !== "string" || !Object.hasOwn(workspaceSelectionFailures, value.code))
39663
39770
  return null;
39664
39771
  const code = value.code;
39665
39772
  return workspaceSelectionFailures[code][0] === status ? code : null;
39666
39773
  }
39667
39774
 
39668
39775
  // src/lib/remote-workspace.ts
39669
- var record5 = (value) => !!value && typeof value === "object" && !Array.isArray(value);
39776
+ var record6 = (value) => !!value && typeof value === "object" && !Array.isArray(value);
39670
39777
  var cursor = (value) => typeof value === "string" && /^[A-Za-z0-9_-]{1,512}$/.test(value);
39671
39778
  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
39779
  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))
39780
+ 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
39781
  throw new Error("Use a roster limit from 1 to 100 and an unchanged continuation cursor.");
39675
39782
  const query = new URLSearchParams;
39676
39783
  if (options.limit !== undefined)
@@ -39686,7 +39793,7 @@ function timestamp2(value) {
39686
39793
  return Number.isFinite(time3) && new Date(time3).toISOString().slice(0, 23) === value.slice(0, 23);
39687
39794
  }
39688
39795
  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))
39796
+ 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
39797
  return fail();
39691
39798
  return {
39692
39799
  membershipId: row.membershipId,
@@ -39706,7 +39813,7 @@ class WorkspaceMemberInputError extends Error {
39706
39813
  }
39707
39814
  }
39708
39815
  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"))
39816
+ if (typeof membershipId !== "string" || !uuid10(membershipId) || membershipId !== membershipId.toLowerCase() || !record6(input2) || Object.keys(input2).sort().join(",") !== (roleChange ? "expectedRole,role" : "expectedRole"))
39710
39817
  throw new WorkspaceMemberInputError;
39711
39818
  const expectedRole = input2.expectedRole, role3 = roleChange ? input2.role : undefined;
39712
39819
  if (!isRole(expectedRole) || roleChange && !isRole(role3))
@@ -39726,7 +39833,7 @@ function parseWorkspaceMemberRoleResult(value, membershipId, role3) {
39726
39833
  const fail = () => {
39727
39834
  throw new Error(invalidMemberResult);
39728
39835
  };
39729
- if (!record5(value) || !uuid10(value.organizationId) || typeof value.changed !== "boolean")
39836
+ if (!record6(value) || !uuid10(value.organizationId) || typeof value.changed !== "boolean")
39730
39837
  return fail();
39731
39838
  const member = parseMember(value.member, fail);
39732
39839
  if (member.membershipId !== membershipId || member.role !== role3)
@@ -39734,7 +39841,7 @@ function parseWorkspaceMemberRoleResult(value, membershipId, role3) {
39734
39841
  return { organizationId: value.organizationId, member, changed: value.changed };
39735
39842
  }
39736
39843
  function parseWorkspaceMemberRemovalResult(value, membershipId) {
39737
- if (!record5(value) || !uuid10(value.organizationId) || value.membershipId !== membershipId || value.removed !== true || typeof value.alreadyRemoved !== "boolean")
39844
+ if (!record6(value) || !uuid10(value.organizationId) || value.membershipId !== membershipId || value.removed !== true || typeof value.alreadyRemoved !== "boolean")
39738
39845
  throw new Error(invalidMemberResult);
39739
39846
  return { organizationId: value.organizationId, membershipId, removed: true, alreadyRemoved: value.alreadyRemoved };
39740
39847
  }
@@ -39751,7 +39858,7 @@ var workspaceMemberFailures = {
39751
39858
  MEMBERSHIP_BUSY: [503, "Membership is busy. Refresh the roster before another action."]
39752
39859
  };
39753
39860
  function workspaceMemberFailure(value, status) {
39754
- if (!record5(value) || typeof value.code !== "string" || !Object.hasOwn(workspaceMemberFailures, value.code))
39861
+ if (!record6(value) || typeof value.code !== "string" || !Object.hasOwn(workspaceMemberFailures, value.code))
39755
39862
  return null;
39756
39863
  const code = value.code;
39757
39864
  return workspaceMemberFailures[code][0] === status ? code : null;
@@ -39760,7 +39867,7 @@ function parseWorkspaceMembersPage(value) {
39760
39867
  const fail = () => {
39761
39868
  throw new Error("The server returned an invalid workspace roster.");
39762
39869
  };
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)
39870
+ 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
39871
  return fail();
39765
39872
  const members2 = value.members.map((row) => parseMember(row, fail));
39766
39873
  if (new Set(members2.map((row) => row.membershipId)).size !== members2.length)
@@ -39836,44 +39943,44 @@ function getApiUrl(action, env = process.env, options = {}) {
39836
39943
  // src/lib/remote-run-contract.ts
39837
39944
  var REMOTE_SKILL_RUN_CONTRACT_VERSION = 1;
39838
39945
  function normalizeRemoteSkillRunContract(payload, fallbackSkill) {
39839
- const record6 = isRecord4(payload) ? payload : {};
39946
+ const record7 = isRecord4(payload) ? payload : {};
39840
39947
  return {
39841
39948
  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 } : {}
39949
+ ...pickString(record7, "id"),
39950
+ skill: pickStringValue(record7, "skill") ?? fallbackSkill,
39951
+ ...pickString(record7, "requestedSlug"),
39952
+ ...pickString(record7, "status"),
39953
+ ...pickNumber(record7, "exitCode"),
39954
+ ...pickString(record7, "correlationId"),
39955
+ ...pickString(record7, "createdAt"),
39956
+ ...pickString(record7, "startedAt"),
39957
+ ...pickString(record7, "completedAt"),
39958
+ ...pickNumber(record7, "durationMs"),
39959
+ ...pickString(record7, "outputType"),
39960
+ ...hasOwn(record7, "outputPreview") ? { outputPreview: record7.outputPreview } : {},
39961
+ ...pickString(record7, "errorCode"),
39962
+ ...pickString(record7, "errorMessage"),
39963
+ ...pickString(record7, "error"),
39964
+ ...pickString(record7, "code"),
39965
+ ...hasOwn(record7, "details") ? { details: record7.details } : {}
39859
39966
  };
39860
39967
  }
39861
39968
  function isRecord4(value) {
39862
39969
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
39863
39970
  }
39864
- function hasOwn(record6, key) {
39865
- return Object.prototype.hasOwnProperty.call(record6, key);
39971
+ function hasOwn(record7, key) {
39972
+ return Object.prototype.hasOwnProperty.call(record7, key);
39866
39973
  }
39867
- function pickString(record6, key) {
39868
- const value = pickStringValue(record6, key);
39974
+ function pickString(record7, key) {
39975
+ const value = pickStringValue(record7, key);
39869
39976
  return value === undefined ? {} : { [key]: value };
39870
39977
  }
39871
- function pickStringValue(record6, key) {
39872
- const value = record6[key];
39978
+ function pickStringValue(record7, key) {
39979
+ const value = record7[key];
39873
39980
  return typeof value === "string" ? value : undefined;
39874
39981
  }
39875
- function pickNumber(record6, key) {
39876
- const value = record6[key];
39982
+ function pickNumber(record7, key) {
39983
+ const value = record7[key];
39877
39984
  return typeof value === "number" && Number.isFinite(value) ? { [key]: value } : {};
39878
39985
  }
39879
39986
 
@@ -40093,11 +40200,11 @@ var permissionNames = [
40093
40200
  "executionGrantsWrite",
40094
40201
  "executionGrantsResolve"
40095
40202
  ];
40096
- var record6 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
40203
+ var record7 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
40097
40204
  function parseSkillsAccess(value) {
40098
40205
  if (value === undefined)
40099
40206
  return {};
40100
- if (!record6(value))
40207
+ if (!record7(value))
40101
40208
  throw new Error("Invalid Skills permission contract");
40102
40209
  const result = {};
40103
40210
  if (value.scopes !== undefined) {
@@ -40106,7 +40213,7 @@ function parseSkillsAccess(value) {
40106
40213
  result.scopes = [...value.scopes];
40107
40214
  }
40108
40215
  if (value.permissions !== undefined) {
40109
- if (!record6(value.permissions))
40216
+ if (!record7(value.permissions))
40110
40217
  throw new Error("Invalid Skills permission contract");
40111
40218
  result.permissions = {};
40112
40219
  for (const name of permissionNames) {
@@ -41003,13 +41110,13 @@ class RemoteSkillsClient {
41003
41110
  return normalizeUpdatedSincePage(await response.json());
41004
41111
  }
41005
41112
  }
41006
- function requireOptionalString(record7, field2) {
41007
- if (record7[field2] === undefined)
41113
+ function requireOptionalString(record8, field2) {
41114
+ if (record8[field2] === undefined)
41008
41115
  return;
41009
- if (typeof record7[field2] !== "string") {
41116
+ if (typeof record8[field2] !== "string") {
41010
41117
  throw new Error(`Remote payload did not match the expected contract (${field2} must be a string when present)`);
41011
41118
  }
41012
- return record7[field2];
41119
+ return record8[field2];
41013
41120
  }
41014
41121
  var INVALID_SKILL_VERSION_RESPONSE = "Remote skill version payload did not match the expected contract.";
41015
41122
  function isVersionRecord(value) {
@@ -41032,19 +41139,19 @@ function normalizePin(entry) {
41032
41139
  if (!entry || typeof entry !== "object") {
41033
41140
  throw new Error("Remote pin payload did not match the expected contract (expected an object)");
41034
41141
  }
41035
- const record7 = entry;
41036
- const slug2 = typeof record7.slug === "string" && record7.slug.trim() ? record7.slug.trim() : undefined;
41142
+ const record8 = entry;
41143
+ const slug2 = typeof record8.slug === "string" && record8.slug.trim() ? record8.slug.trim() : undefined;
41037
41144
  if (!slug2) {
41038
41145
  throw new Error("Remote pin payload did not match the expected contract (missing slug)");
41039
41146
  }
41040
41147
  let metadata;
41041
- if (record7.metadata !== undefined) {
41042
- if (!record7.metadata || typeof record7.metadata !== "object" || Array.isArray(record7.metadata)) {
41148
+ if (record8.metadata !== undefined) {
41149
+ if (!record8.metadata || typeof record8.metadata !== "object" || Array.isArray(record8.metadata)) {
41043
41150
  throw new Error("Remote pin payload did not match the expected contract (metadata must be a JSON object when present)");
41044
41151
  }
41045
- metadata = record7.metadata;
41152
+ metadata = record8.metadata;
41046
41153
  }
41047
- const pinnedAt = requireOptionalString(record7, "pinnedAt");
41154
+ const pinnedAt = requireOptionalString(record8, "pinnedAt");
41048
41155
  return {
41049
41156
  slug: slug2,
41050
41157
  ...pinnedAt !== undefined ? { pinnedAt } : {},
@@ -41061,16 +41168,16 @@ function normalizeSkillSummary(entry) {
41061
41168
  if (!entry || typeof entry !== "object") {
41062
41169
  throw new Error("Remote skill payload did not match the expected contract (expected an object)");
41063
41170
  }
41064
- const record7 = entry;
41065
- const slug2 = typeof record7.slug === "string" && record7.slug.trim() ? record7.slug.trim() : undefined;
41171
+ const record8 = entry;
41172
+ const slug2 = typeof record8.slug === "string" && record8.slug.trim() ? record8.slug.trim() : undefined;
41066
41173
  if (!slug2) {
41067
41174
  throw new Error("Remote skill payload did not match the expected contract (missing slug)");
41068
41175
  }
41069
41176
  return {
41070
41177
  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") } : {}
41178
+ ...requireOptionalString(record8, "name") !== undefined ? { name: requireOptionalString(record8, "name") } : {},
41179
+ ...requireOptionalString(record8, "version") !== undefined ? { version: requireOptionalString(record8, "version") } : {},
41180
+ ...requireOptionalString(record8, "updatedAt") !== undefined ? { updatedAt: requireOptionalString(record8, "updatedAt") } : {}
41074
41181
  };
41075
41182
  }
41076
41183
  function normalizeSkillSummaryList(payload) {
@@ -41127,12 +41234,12 @@ function normalizeUpdatedSincePage(payload) {
41127
41234
  if (!payload || typeof payload !== "object") {
41128
41235
  throw new Error("Updated-since payload did not match the expected contract (expected an object)");
41129
41236
  }
41130
- const record7 = payload;
41131
- if (!Array.isArray(record7.skills)) {
41237
+ const record8 = payload;
41238
+ if (!Array.isArray(record8.skills)) {
41132
41239
  throw new Error("Updated-since payload did not match the expected contract (missing skills array)");
41133
41240
  }
41134
- const skills = record7.skills.map(normalizeSkillSummary);
41135
- const nextCursor = record7.nextCursor === undefined || record7.nextCursor === null ? null : record7.nextCursor;
41241
+ const skills = record8.skills.map(normalizeSkillSummary);
41242
+ const nextCursor = record8.nextCursor === undefined || record8.nextCursor === null ? null : record8.nextCursor;
41136
41243
  if (nextCursor !== null && typeof nextCursor !== "string") {
41137
41244
  throw new Error("Updated-since payload did not match the expected contract (nextCursor must be a string or absent)");
41138
41245
  }
@@ -41371,8 +41478,8 @@ function revisionIdOf(content) {
41371
41478
  const canonical6 = JSON.stringify(canonicalContent);
41372
41479
  return createHash21("sha256").update(canonical6).digest("hex");
41373
41480
  }
41374
- function revisionIdOfRecord(record7) {
41375
- return revisionIdOf(record7);
41481
+ function revisionIdOfRecord(record8) {
41482
+ return revisionIdOf(record8);
41376
41483
  }
41377
41484
  // src/lib/pull.ts
41378
41485
  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 +41855,16 @@ function installBundleAtomically(name, entries, options = {}, marker = {}) {
41748
41855
  }
41749
41856
  return { path: target, created };
41750
41857
  }
41751
- function writePullMarker(dir, record7) {
41858
+ function writePullMarker(dir, record8) {
41752
41859
  const marker = {
41753
41860
  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 } : {},
41861
+ skill: record8.skill,
41862
+ source: record8.source ?? "pull",
41863
+ ...record8.version ? { version: record8.version } : {},
41864
+ ...record8.contentHash ? { contentHash: record8.contentHash } : {},
41865
+ ...record8.sourceCommit ? { sourceCommit: record8.sourceCommit } : {},
41866
+ ...record8.signature ? { signature: record8.signature } : {},
41867
+ ...record8.revisionId ? { revisionId: record8.revisionId } : {},
41761
41868
  syncedAt: new Date().toISOString()
41762
41869
  };
41763
41870
  writeFileSync11(join33(dir, PULL_MARKER_FILE), `${JSON.stringify(marker, null, 2)}
@@ -41772,19 +41879,19 @@ async function safeMeta(client2, slug2) {
41772
41879
  }
41773
41880
  if (!raw || typeof raw !== "object")
41774
41881
  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;
41882
+ const record8 = raw;
41883
+ const kind = record8.kind === "instruction" || record8.kind === "executable" ? record8.kind : undefined;
41884
+ const tags = Array.isArray(record8.tags) ? record8.tags.filter((tag) => typeof tag === "string" && tag.trim().length > 0) : undefined;
41778
41885
  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) } : {},
41886
+ ...str(record8.displayName) ? { displayName: str(record8.displayName) } : {},
41887
+ ...str(record8.description) ? { description: str(record8.description) } : {},
41888
+ ...str(record8.category) ? { category: str(record8.category) } : {},
41782
41889
  ...tags && tags.length ? { tags } : {},
41783
- ...str(record7.version) ? { version: str(record7.version) } : {},
41890
+ ...str(record8.version) ? { version: str(record8.version) } : {},
41784
41891
  ...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) } : {}
41892
+ ...REVISION_ID_PATTERN.test(str(record8.revisionId) ?? "") ? { revisionId: str(record8.revisionId) } : {},
41893
+ ...typeof record8.skillMd === "string" && record8.skillMd.length > 0 ? { skillMd: record8.skillMd } : {},
41894
+ ...str(record8.publishedSource) ? { publishedSource: str(record8.publishedSource) } : {}
41788
41895
  };
41789
41896
  }
41790
41897
  function pickCorpusOptions(options) {
@@ -41793,8 +41900,8 @@ function pickCorpusOptions(options) {
41793
41900
  function extractSlug(entry) {
41794
41901
  if (!entry || typeof entry !== "object")
41795
41902
  return;
41796
- const record7 = entry;
41797
- return str(record7.slug) ?? str(record7.name);
41903
+ const record8 = entry;
41904
+ return str(record8.slug) ?? str(record8.name);
41798
41905
  }
41799
41906
  function dedupe(values) {
41800
41907
  return [...new Set(values)];
@@ -41851,7 +41958,7 @@ class RemoteInvitationEmailUnconfirmedError extends Error {
41851
41958
  this.name = "RemoteInvitationEmailUnconfirmedError";
41852
41959
  }
41853
41960
  }
41854
- var record7 = (v) => !!v && typeof v === "object" && !Array.isArray(v);
41961
+ var record8 = (v) => !!v && typeof v === "object" && !Array.isArray(v);
41855
41962
  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
41963
  function invitationEmailIds(invitationId, challengeId) {
41857
41964
  if (!uuid11(invitationId) || !uuid11(challengeId))
@@ -41860,7 +41967,7 @@ function invitationEmailIds(invitationId, challengeId) {
41860
41967
  }
41861
41968
  function invitationEmailInput(action, input2) {
41862
41969
  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)))
41970
+ if (!record8(input2) || Object.keys(input2).length !== keys.length || keys.some((key) => !Object.hasOwn(input2, key)))
41864
41971
  throw new InvitationEmailInputError;
41865
41972
  const value = { ...input2 };
41866
41973
  const ids = invitationEmailIds(value.invitationId, value.challengeId);
@@ -41889,12 +41996,12 @@ async function requestInvitationEmail(origin, action, input2) {
41889
41996
  signal: AbortSignal.timeout(15000)
41890
41997
  });
41891
41998
  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)) {
41999
+ if (!response.ok && record8(parsed) && typeof parsed.code === "string" && Object.hasOwn(refusals, parsed.code)) {
41893
42000
  const code = parsed.code;
41894
42001
  if (response.status === refusals[code][0])
41895
42002
  throw new RemoteInvitationEmailError(code);
41896
42003
  }
41897
- if (!record7(parsed))
42004
+ if (!record8(parsed))
41898
42005
  throw new RemoteInvitationEmailUnconfirmedError(action);
41899
42006
  if (action === "challenge" && response.status === 202 && parsed.challengeId === value.challengeId && parsed.expiresIn === 600 && typeof parsed.message === "string" && parsed.message.length <= 256) {
41900
42007
  return { challengeId: value.challengeId, message: "If this invitation is eligible, a verification code will arrive. Delivery is not confirmed.", expiresIn: 600 };
@@ -41954,8 +42061,8 @@ var invalid4 = () => {
41954
42061
  };
41955
42062
  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
42063
  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(",");
42064
+ var record9 = (v) => !!v && typeof v === "object" && !Array.isArray(v);
42065
+ var exact = (v, keys) => record9(v) && Object.keys(v).sort().join(",") === keys.sort().join(",");
41959
42066
  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
42067
  var publicationSha256 = (bytes) => createHash22("sha256").update(bytes).digest("hex");
41961
42068
  function checkedPublicationDeclaration(value) {
@@ -41963,7 +42070,7 @@ function checkedPublicationDeclaration(value) {
41963
42070
  return bad();
41964
42071
  try {
41965
42072
  const manifest = JSON.parse(value.manifestText);
41966
- if (!record8(manifest) || manifest.version !== value.version || validatePortableManifestContract(manifest, { strict: true }).length || !hash3(manifest.provenance?.content_hash))
42073
+ if (!record9(manifest) || manifest.version !== value.version || validatePortableManifestContract(manifest, { strict: true }).length || !hash3(manifest.provenance?.content_hash))
41967
42074
  return bad();
41968
42075
  } catch {
41969
42076
  return bad();
@@ -42021,7 +42128,7 @@ async function boundedJson(url2, init, token, mutation, budget2 = 15000, signal)
42021
42128
  return invalid4();
42022
42129
  }
42023
42130
  if (!response.ok) {
42024
- const code = record8(body) && typeof body.code === "string" && Object.hasOwn(failures2, body.code) ? body.code : null;
42131
+ const code = record9(body) && typeof body.code === "string" && Object.hasOwn(failures2, body.code) ? body.code : null;
42025
42132
  if (code && failures2[code][0] === response.status)
42026
42133
  throw new PrivatePublicationError(code, failures2[code][1], mutation && code === "PUBLICATION_UNCERTAIN", response.status);
42027
42134
  throw new PrivatePublicationError("PUBLICATION_REQUEST_FAILED", "The publication request was refused. Inspect its status before retrying.", mutation && response.status >= 500, response.status);
@@ -42076,8 +42183,8 @@ class RemotePrivatePublicationsClient {
42076
42183
  if (options.timeoutMs !== undefined && (!Number.isSafeInteger(options.timeoutMs) || options.timeoutMs < 1 || options.timeoutMs > 15000))
42077
42184
  return bad();
42078
42185
  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")
42186
+ const p = record9(response) && response.privatePublishing;
42187
+ 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
42188
  throw new PrivatePublicationError("PUBLICATION_CONTRACT_UNAVAILABLE", "This server does not support the hosted private publication contract.");
42082
42189
  return Object.freeze({ ...p });
42083
42190
  }
@@ -42093,7 +42200,7 @@ class RemotePrivatePublicationsClient {
42093
42200
  async#view(path, method, skillId, intentId, declaration, options = {}) {
42094
42201
  const value = await boundedJson(path, { method, ...method === "GET" ? {} : { body: JSON.stringify(declaration ?? {}) } }, this.#token, method !== "GET", options.timeoutMs, options.signal);
42095
42202
  try {
42096
- if (!record8(value) || !Object.keys(value).every((k) => k === "upload" || k === "changed") || value.changed !== undefined && typeof value.changed !== "boolean")
42203
+ if (!record9(value) || !Object.keys(value).every((k) => k === "upload" || k === "changed") || value.changed !== undefined && typeof value.changed !== "boolean")
42097
42204
  return invalid4();
42098
42205
  return checkedPublicationView(value.upload, skillId, intentId, declaration);
42099
42206
  } catch (error61) {
@@ -42256,10 +42363,10 @@ async function requestAuthApi(instance, path, options) {
42256
42363
  const text3 = await res.text();
42257
42364
  const body = text3 ? parseJsonBody(text3) : {};
42258
42365
  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;
42366
+ const record10 = isRecord6(body) ? body : {};
42367
+ const detail = typeof record10.detail === "string" ? record10.detail : undefined;
42368
+ const error61 = typeof record10.error === "string" ? record10.error : undefined;
42369
+ const code = typeof record10.code === "string" ? record10.code : undefined;
42263
42370
  throw new HostedApiError(detail || error61 || `${res.status} ${res.statusText}`, {
42264
42371
  status: res.status,
42265
42372
  code,
@@ -44068,7 +44175,7 @@ class SkillsPostgresSyncStore {
44068
44175
  }
44069
44176
  async upsertRecords(records) {
44070
44177
  let count = 0;
44071
- for (const record9 of records) {
44178
+ for (const record10 of records) {
44072
44179
  await this.client.query([
44073
44180
  "INSERT INTO skills_sync_records",
44074
44181
  "(scope, kind, id, updated_at, deleted_at, source, payload)",
@@ -44079,13 +44186,13 @@ class SkillsPostgresSyncStore {
44079
44186
  "source = EXCLUDED.source,",
44080
44187
  "payload = EXCLUDED.payload"
44081
44188
  ].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)
44189
+ record10.scope,
44190
+ record10.kind,
44191
+ record10.id,
44192
+ record10.updatedAt,
44193
+ record10.deletedAt ?? null,
44194
+ record10.source ?? null,
44195
+ JSON.stringify(record10.payload)
44089
44196
  ]);
44090
44197
  count += 1;
44091
44198
  }
@@ -45489,6 +45596,7 @@ export {
45489
45596
  validateCron,
45490
45597
  validateBlogArticleRunOptions,
45491
45598
  uploadSkillsSnapshotFilesToS3,
45599
+ upgradeCodexSettingsWitnessV3,
45492
45600
  upgradeCodexSettingsWitness,
45493
45601
  upgradeClaudeSettingsWitness,
45494
45602
  updateSkillRun,
@@ -45674,6 +45782,7 @@ export {
45674
45782
  captureDiscoveryPathSources,
45675
45783
  captureDiscoveryDirectories,
45676
45784
  captureDiscoveryByteSources,
45785
+ captureCodexSettingsV3,
45677
45786
  captureCodexSettingsV2,
45678
45787
  captureCodexSettings,
45679
45788
  captureCodexNativeSkillCatalog,