@hasna/skills 0.10.45 → 0.10.46

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/bin/index.js CHANGED
@@ -36868,7 +36868,7 @@ var package_default;
36868
36868
  var init_package = __esm(() => {
36869
36869
  package_default = {
36870
36870
  name: "@hasna/skills",
36871
- version: "0.10.45",
36871
+ version: "0.10.46",
36872
36872
  description: "Skills library for AI coding agents",
36873
36873
  type: "module",
36874
36874
  bin: {
@@ -39885,8 +39885,348 @@ var init_agent_adapters = __esm(() => {
39885
39885
  };
39886
39886
  });
39887
39887
 
39888
+ // src/lib/claude-settings-witness.ts
39889
+ import { createHash as createHash2 } from "crypto";
39890
+ import { closeSync, constants as constants2, fstatSync, lstatSync as lstatSync3, openSync, readSync } from "fs";
39891
+ import { basename as basename2, dirname as dirname3, isAbsolute as isAbsolute2, resolve as resolve3 } from "path";
39892
+ function need(value, reason) {
39893
+ if (!value)
39894
+ throw new Error(`Claude settings witness ${reason}`);
39895
+ }
39896
+ function absolutePath(value) {
39897
+ need(typeof value === "string" && value.length > 0 && value.length <= CLAUDE_SETTINGS_WITNESS_LIMITS.pathCharacters && !/[\x00-\x1f\x7f]/.test(value) && isAbsolute2(value) && resolve3(value) === value, "requires a normalized absolute path");
39898
+ }
39899
+ function parents(path) {
39900
+ const result2 = [];
39901
+ for (let at2 = dirname3(path);; at2 = dirname3(at2)) {
39902
+ const stat = lstatSync3(at2, { bigint: true });
39903
+ need(stat.isDirectory() && !stat.isSymbolicLink(), "path traverses a symlink or non-directory");
39904
+ result2.push([at2, stat]);
39905
+ if (at2 === dirname3(at2))
39906
+ return result2;
39907
+ }
39908
+ }
39909
+ function readNativeSettingsWitnessFile(path, budget, filename = "settings.json") {
39910
+ absolutePath(path);
39911
+ need(basename2(path) === filename, `requires ${filename}`);
39912
+ need(Number.isSafeInteger(budget.remaining) && budget.remaining >= 0, "has an invalid byte budget");
39913
+ const ancestors = parents(path), initial2 = lstatSync3(path, { bigint: true });
39914
+ need(initial2.isFile() && !initial2.isSymbolicLink() && initial2.size <= BigInt(CLAUDE_SETTINGS_WITNESS_LIMITS.bytes), "is not a bounded regular file");
39915
+ need(initial2.size <= BigInt(budget.remaining), "exceeds its aggregate byte limit");
39916
+ const fd = openSync(path, constants2.O_RDONLY | constants2.O_NOFOLLOW | constants2.O_NONBLOCK);
39917
+ try {
39918
+ const opened = fstatSync(fd, { bigint: true });
39919
+ need(opened.isFile() && sameFile(initial2, opened), "changed during open");
39920
+ const bytes = Buffer.alloc(Number(opened.size) + 1);
39921
+ let length = 0;
39922
+ while (length < bytes.length) {
39923
+ const count = readSync(fd, bytes, length, bytes.length - length, null);
39924
+ if (!count)
39925
+ break;
39926
+ length += count;
39927
+ }
39928
+ const after2 = fstatSync(fd, { bigint: true }), current = lstatSync3(path, { bigint: true });
39929
+ need(current.isFile() && sameFile(opened, after2) && sameFile(after2, current) && BigInt(length) === opened.size, "changed during read");
39930
+ for (const [ancestor, before2] of ancestors) {
39931
+ const now3 = lstatSync3(ancestor, { bigint: true });
39932
+ need(now3.isDirectory() && before2.dev === now3.dev && before2.ino === now3.ino && before2.mode === now3.mode, "parent changed during read");
39933
+ }
39934
+ budget.remaining -= length;
39935
+ try {
39936
+ return new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(bytes.subarray(0, length));
39937
+ } catch {
39938
+ throw new Error("Claude settings witness is not strict UTF-8");
39939
+ }
39940
+ } finally {
39941
+ closeSync(fd);
39942
+ }
39943
+ }
39944
+ function parse(text) {
39945
+ let at2 = 0, nodes = 0;
39946
+ const numberPattern = /-?(?:0|[1-9][0-9]*)(?:\.[0-9]+)?(?:[eE][+-]?[0-9]+)?/y;
39947
+ const space = () => {
39948
+ while (at2 < text.length && /[\x20\t\r\n]/.test(text[at2]))
39949
+ at2++;
39950
+ };
39951
+ function string() {
39952
+ need(text[at2] === '"', "contains invalid JSON");
39953
+ const start = at2++;
39954
+ while (at2 < text.length) {
39955
+ const character = text[at2++];
39956
+ if (character === '"') {
39957
+ let value2;
39958
+ try {
39959
+ value2 = JSON.parse(text.slice(start, at2));
39960
+ } catch {
39961
+ throw new Error("Claude settings witness contains invalid JSON string");
39962
+ }
39963
+ need(value2.length <= CLAUDE_SETTINGS_WITNESS_LIMITS.stringCharacters, "exceeds its string limit");
39964
+ return value2;
39965
+ }
39966
+ if (character === "\\")
39967
+ at2++;
39968
+ }
39969
+ throw new Error("Claude settings witness contains an unterminated JSON string");
39970
+ }
39971
+ function value(depth) {
39972
+ need(depth <= CLAUDE_SETTINGS_WITNESS_LIMITS.depth && ++nodes <= CLAUDE_SETTINGS_WITNESS_LIMITS.nodes, "exceeds its nesting or node limit");
39973
+ space();
39974
+ const character = text[at2];
39975
+ if (character === '"')
39976
+ return { kind: "string", value: string() };
39977
+ if (character === "{" || character === "[") {
39978
+ at2++;
39979
+ space();
39980
+ const object = character === "{", end = object ? "}" : "]", entries = [], items = [], keys2 = new Set;
39981
+ if (text[at2] !== end)
39982
+ while (true) {
39983
+ if (object) {
39984
+ space();
39985
+ const key = string();
39986
+ need(!keys2.has(key), "contains a duplicate JSON key");
39987
+ keys2.add(key);
39988
+ space();
39989
+ need(text[at2++] === ":", "contains invalid JSON");
39990
+ entries.push([key, value(depth + 1)]);
39991
+ } else
39992
+ items.push(value(depth + 1));
39993
+ space();
39994
+ if (text[at2] === end)
39995
+ break;
39996
+ need(text[at2++] === ",", "contains invalid JSON");
39997
+ }
39998
+ at2++;
39999
+ return object ? { kind: "object", entries } : { kind: "array", items };
40000
+ }
40001
+ for (const literal of ["true", "false", "null"])
40002
+ if (text.startsWith(literal, at2)) {
40003
+ at2 += literal.length;
40004
+ return { kind: "literal", value: literal };
40005
+ }
40006
+ numberPattern.lastIndex = at2;
40007
+ const number = numberPattern.exec(text);
40008
+ need(number, "contains invalid JSON");
40009
+ at2 += number[0].length;
40010
+ return { kind: "number", value: number[0] };
40011
+ }
40012
+ const root = value(0);
40013
+ space();
40014
+ need(at2 === text.length && root.kind === "object", "requires a JSON object without trailing content");
40015
+ need(root.entries.length <= CLAUDE_SETTINGS_WITNESS_LIMITS.rows, "exceeds its settings field limit");
40016
+ return root;
40017
+ }
40018
+ function canonical(value) {
40019
+ if (value.kind === "object")
40020
+ return { kind: "object", entries: value.entries.map(([key, child]) => [key, canonical(child)]).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0) };
40021
+ if (value.kind === "array")
40022
+ return { kind: "array", items: value.items.map(canonical) };
40023
+ return value;
40024
+ }
40025
+ function inferencePreference(key, child, version) {
40026
+ if (key === "skipDangerousModePermissionPrompt") {
40027
+ need(child.kind === "literal" && (child.value === "true" || child.value === "false"), "contains an invalid dialog acknowledgment");
40028
+ return false;
40029
+ }
40030
+ if (key === "effortLevel") {
40031
+ need(child.kind === "string" && PERSISTED_EFFORT_LEVELS.has(child.value), "contains an invalid persisted effort level");
40032
+ return true;
40033
+ }
40034
+ if (key !== "modelSettings")
40035
+ return false;
40036
+ need(child.kind === "object", "requires an object of model preferences");
40037
+ child.entries = child.entries.filter(([model, preferences]) => {
40038
+ if (version === 2 && !BUILTIN_MODEL_SELECTIONS.has(model) || preferences.kind !== "object" || preferences.entries.length !== 1 || preferences.entries[0][0] !== "effortLevel")
40039
+ return true;
40040
+ const effort = preferences.entries[0][1];
40041
+ need(effort.kind === "string" && PERSISTED_EFFORT_LEVELS.has(effort.value), "contains an invalid persisted model effort level");
40042
+ return false;
40043
+ });
40044
+ return child.entries.length === 0;
40045
+ }
40046
+ function settingsDigest(text, version = 1) {
40047
+ const value = parse(text);
40048
+ value.entries = value.entries.filter(([key, child]) => {
40049
+ if (version !== 1 && inferencePreference(key, child, version))
40050
+ return false;
40051
+ if (key === "model") {
40052
+ need(child.kind === "string", "contains an invalid model selection");
40053
+ return !BUILTIN_MODEL_SELECTIONS.has(child.value);
40054
+ }
40055
+ if (BOOLEAN_PREFERENCES.has(key)) {
40056
+ need(child.kind === "literal" && (child.value === "true" || child.value === "false"), "contains an invalid display preference");
40057
+ return false;
40058
+ }
40059
+ if (Object.hasOwn(ENUM_PREFERENCES, key)) {
40060
+ need(child.kind === "string" && ENUM_PREFERENCES[key].includes(child.value), "contains an invalid display preference");
40061
+ return false;
40062
+ }
40063
+ return true;
40064
+ });
40065
+ return createHash2("sha256").update(`hasna.skills.claude-settings.v${version}\x00`).update(JSON.stringify(canonical(value))).digest("hex");
40066
+ }
40067
+ function hashClaudeSettingsReplacement(text, budget) {
40068
+ need(typeof text === "string", "requires settings text");
40069
+ const bytes = Buffer.byteLength(text);
40070
+ need(bytes <= CLAUDE_SETTINGS_WITNESS_LIMITS.bytes && Number.isSafeInteger(budget.remaining) && budget.remaining >= bytes, "exceeds its byte limit");
40071
+ budget.remaining -= bytes;
40072
+ return settingsDigest(text);
40073
+ }
40074
+ function captureClaudeSettings(path, budget = { remaining: 256 * 1024 * 1024 }) {
40075
+ return { path, hashMode: "claude-settings-v1", sha256: settingsDigest(readNativeSettingsWitnessFile(path, budget)) };
40076
+ }
40077
+ function captureClaudeSettingsV2(path, budget = { remaining: 256 * 1024 * 1024 }) {
40078
+ return { path, hashMode: "claude-settings-v2", sha256: settingsDigest(readNativeSettingsWitnessFile(path, budget), 2) };
40079
+ }
40080
+ function hashClaudeSettingsReplacementV2(text, budget) {
40081
+ need(typeof text === "string", "requires settings text");
40082
+ const bytes = Buffer.byteLength(text);
40083
+ need(bytes <= CLAUDE_SETTINGS_WITNESS_LIMITS.bytes && Number.isSafeInteger(budget.remaining) && budget.remaining >= bytes, "exceeds its byte limit");
40084
+ budget.remaining -= bytes;
40085
+ return settingsDigest(text, 2);
40086
+ }
40087
+ function captureClaudeSettingsV3(path, budget = { remaining: 256 * 1024 * 1024 }) {
40088
+ return { path, hashMode: "claude-settings-v3", sha256: settingsDigest(readNativeSettingsWitnessFile(path, budget), 3) };
40089
+ }
40090
+ function hashClaudeSettingsReplacementV3(text, budget) {
40091
+ need(typeof text === "string", "requires settings text");
40092
+ const bytes = Buffer.byteLength(text);
40093
+ need(bytes <= CLAUDE_SETTINGS_WITNESS_LIMITS.bytes && Number.isSafeInteger(budget.remaining) && budget.remaining >= bytes, "exceeds its byte limit");
40094
+ budget.remaining -= bytes;
40095
+ return settingsDigest(text, 3);
40096
+ }
40097
+ function upgradeClaudeSettingsWitness(previous, reviewedSettingsPath) {
40098
+ need(previous && Object.keys(previous).every((key) => ["path", "hashMode", "sha256"].includes(key)) && (previous.hashMode === undefined || previous.hashMode === "bytes" || previous.hashMode === "claude-settings-v1" || previous.hashMode === "claude-settings-v2") && typeof previous.sha256 === "string" && /^[a-f0-9]{64}$/.test(previous.sha256), "requires an exact legacy settings witness");
40099
+ const budget = { remaining: 2 * CLAUDE_SETTINGS_WITNESS_LIMITS.bytes };
40100
+ const before2 = readNativeSettingsWitnessFile(reviewedSettingsPath, budget), current = readNativeSettingsWitnessFile(previous.path, budget);
40101
+ const beforeDigest = previous.hashMode === undefined || previous.hashMode === "bytes" ? createHash2("sha256").update(before2).digest("hex") : settingsDigest(before2, previous.hashMode === "claude-settings-v1" ? 1 : 2);
40102
+ need(beforeDigest === previous.sha256, "reviewed preimage does not match the legacy witness");
40103
+ const sha256 = settingsDigest(current, 3);
40104
+ need(settingsDigest(before2, 3) === sha256, "non-preference settings changed; explicit discovery review required");
40105
+ return { path: previous.path, hashMode: "claude-settings-v3", sha256 };
40106
+ }
40107
+ function hashNativeJsonControls(text, excludedMetadata) {
40108
+ need(Buffer.byteLength(text) <= CLAUDE_SETTINGS_WITNESS_LIMITS.bytes, "exceeds its byte limit");
40109
+ const value = parse(text);
40110
+ value.entries = value.entries.filter(([key, child]) => {
40111
+ if (key !== excludedMetadata)
40112
+ return true;
40113
+ need(child.kind === "string" && child.value.length <= 128, "has invalid version metadata");
40114
+ return false;
40115
+ });
40116
+ return createHash2("sha256").update("hasna.skills.native-json-controls.v1\x00").update(JSON.stringify(canonical(value))).digest("hex");
40117
+ }
40118
+ function hashSumiNativeJsonControls(text) {
40119
+ need(Buffer.byteLength(text) <= CLAUDE_SETTINGS_WITNESS_LIMITS.bytes, "exceeds its byte limit");
40120
+ const value = parse(text);
40121
+ value.entries = value.entries.filter(([key, child]) => {
40122
+ if (key === "$schema" || key === "username") {
40123
+ need(child.kind === "string", "has invalid Sumi display metadata");
40124
+ return false;
40125
+ }
40126
+ if (key !== "experimental")
40127
+ return true;
40128
+ need(child.kind === "object", "requires Sumi experimental controls to be an object");
40129
+ child.entries = child.entries.filter(([name, option]) => {
40130
+ if (name !== "statusline" && name !== "compact_tools")
40131
+ return true;
40132
+ need(option.kind === "literal" && (option.value === "true" || option.value === "false"), "has invalid Sumi display preference");
40133
+ return false;
40134
+ });
40135
+ return child.entries.length > 0;
40136
+ });
40137
+ return createHash2("sha256").update("hasna.skills.sumi-settings.v1\x00").update(JSON.stringify(value)).digest("hex");
40138
+ }
40139
+ var CLAUDE_SETTINGS_WITNESS_LIMITS, sameFile = (a, b) => a.dev === b.dev && a.ino === b.ino && a.mode === b.mode && a.uid === b.uid && a.gid === b.gid && a.nlink === b.nlink && a.size === b.size && a.mtimeNs === b.mtimeNs && a.ctimeNs === b.ctimeNs, BOOLEAN_PREFERENCES, ENUM_PREFERENCES, BUILTIN_MODEL_SELECTIONS, PERSISTED_EFFORT_LEVELS;
40140
+ var init_claude_settings_witness = __esm(() => {
40141
+ CLAUDE_SETTINGS_WITNESS_LIMITS = Object.freeze({ bytes: 1024 * 1024, rows: 1024, depth: 32, nodes: 65536, stringCharacters: 16384, pathCharacters: 4096 });
40142
+ BOOLEAN_PREFERENCES = new Set([
40143
+ "autoScrollEnabled",
40144
+ "axScreenReader",
40145
+ "emojiCompletionEnabled",
40146
+ "prefersReducedMotion",
40147
+ "showTurnDuration",
40148
+ "spinnerTipsEnabled",
40149
+ "syntaxHighlightingDisabled",
40150
+ "terminalProgressBarEnabled",
40151
+ "terminalTitleFromRename",
40152
+ "verbose",
40153
+ "wheelScrollAccelerationEnabled"
40154
+ ]);
40155
+ ENUM_PREFERENCES = Object.freeze({
40156
+ editorMode: ["normal", "vim"],
40157
+ tui: ["default", "fullscreen"],
40158
+ viewMode: ["default", "verbose", "focus"]
40159
+ });
40160
+ BUILTIN_MODEL_SELECTIONS = new Set([
40161
+ "default",
40162
+ "best",
40163
+ "fable",
40164
+ "fable[1m]",
40165
+ "sonnet",
40166
+ "sonnet[1m]",
40167
+ "opus",
40168
+ "opus[1m]",
40169
+ "haiku",
40170
+ "opusplan",
40171
+ "claude-fable-5-1",
40172
+ "claude-fable-5",
40173
+ "claude-fable-5[1m]",
40174
+ "claude-opus-5",
40175
+ "claude-sonnet-5",
40176
+ "claude-haiku-4-5-20251001",
40177
+ "claude-opus-4-6",
40178
+ "claude-sonnet-4-5",
40179
+ "claude-sonnet-4-5-20250929",
40180
+ "claude-opus-4-8",
40181
+ "claude-opus-4-8[1m]",
40182
+ "claude-opus-4-7",
40183
+ "claude-sonnet-4-6",
40184
+ "claude-opus-4-5-20251101",
40185
+ "claude-opus-4-5",
40186
+ "claude-haiku-4-5",
40187
+ "claude-fable-5-1[1m]",
40188
+ "claude-opus-5[1m]",
40189
+ "claude-opus-4-7[1m]",
40190
+ "claude-opus-4-6[1m]",
40191
+ "claude-sonnet-4-6[1m]"
40192
+ ]);
40193
+ PERSISTED_EFFORT_LEVELS = new Set(["low", "medium", "high", "xhigh"]);
40194
+ });
40195
+
40196
+ // src/lib/sumi-settings-witness.ts
40197
+ import { createHash as createHash3 } from "crypto";
40198
+ function readSumiSettingsPreimage(path) {
40199
+ return readNativeSettingsWitnessFile(path, budget(), "sumi.json");
40200
+ }
40201
+ function hashSumiSettingsReplacement(text, limits) {
40202
+ const bytes = Buffer.byteLength(text);
40203
+ if (bytes > CLAUDE_SETTINGS_WITNESS_LIMITS.bytes || !Number.isSafeInteger(limits.remaining) || limits.remaining < bytes)
40204
+ throw new Error("Sumi settings witness exceeds its byte limit");
40205
+ limits.remaining -= bytes;
40206
+ return hashSumiNativeJsonControls(text);
40207
+ }
40208
+ function captureSumiSettings(path, limits = budget()) {
40209
+ return { path, hashMode: "sumi-settings-v1", sha256: hashSumiNativeJsonControls(readNativeSettingsWitnessFile(path, limits, "sumi.json")) };
40210
+ }
40211
+ function upgradeSumiSettingsWitness(previous, reviewedSettingsPath) {
40212
+ if (!previous || Object.keys(previous).some((key) => !["path", "hashMode", "sha256"].includes(key)) || ![undefined, "bytes"].includes(previous.hashMode) || !/^[a-f0-9]{64}$/.test(previous.sha256))
40213
+ throw new Error("Sumi settings upgrade requires one exact preserved byte witness");
40214
+ const before2 = readSumiSettingsPreimage(reviewedSettingsPath);
40215
+ if (createHash3("sha256").update(before2).digest("hex") !== previous.sha256)
40216
+ throw new Error("Reviewed Sumi preimage does not match its byte witness");
40217
+ const next = captureSumiSettings(previous.path);
40218
+ if (hashSumiNativeJsonControls(before2) !== next.sha256)
40219
+ throw new Error("Sumi non-display settings changed; explicit discovery review required");
40220
+ return next;
40221
+ }
40222
+ var SUMI_DISCOVERY_PROJECTION_FIELDS, budget = () => ({ remaining: 256 * 1024 * 1024 });
40223
+ var init_sumi_settings_witness = __esm(() => {
40224
+ init_claude_settings_witness();
40225
+ SUMI_DISCOVERY_PROJECTION_FIELDS = ["skills", "plugin", "plugins", "permissions"];
40226
+ });
40227
+
39888
40228
  // src/lib/agent-policy-limits.ts
39889
- import { basename as basename2, isAbsolute as isAbsolute2, resolve as resolve3 } from "path";
40229
+ import { basename as basename3, isAbsolute as isAbsolute3, resolve as resolve4 } from "path";
39890
40230
  function object(value) {
39891
40231
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
39892
40232
  }
@@ -39939,7 +40279,7 @@ function assertAgentPolicyCollections(policy) {
39939
40279
  text(control.pluginId, 1024);
39940
40280
  text(control.namespace, 64);
39941
40281
  text(control.pluginParent);
39942
- requireBound(isAbsolute2(control.pluginParent) && resolve3(control.pluginParent) === control.pluginParent && /^[a-f0-9]{64}$/.test(control.manifestSha256));
40282
+ requireBound(isAbsolute3(control.pluginParent) && resolve4(control.pluginParent) === control.pluginParent && /^[a-f0-9]{64}$/.test(control.manifestSha256));
39943
40283
  if (control.remotePluginId !== undefined)
39944
40284
  requireBound(typeof control.remotePluginId === "string" && /^[A-Za-z0-9_~-]{1,1024}$/.test(control.remotePluginId));
39945
40285
  if (control.skillsOnly !== undefined)
@@ -39957,7 +40297,7 @@ function assertAgentPolicyCollections(policy) {
39957
40297
  text(control.pluginId, 1024);
39958
40298
  text(control.namespace, 64);
39959
40299
  text(control.pluginParent);
39960
- requireBound(!ids.has(control.pluginId) && isAbsolute2(control.pluginParent) && resolve3(control.pluginParent) === control.pluginParent && ["local", "git", "npm"].includes(control.sourceType) && typeof control.sourceSha256 === "string" && /^[a-f0-9]{64}$/.test(control.sourceSha256));
40300
+ requireBound(!ids.has(control.pluginId) && isAbsolute3(control.pluginParent) && resolve4(control.pluginParent) === control.pluginParent && ["local", "git", "npm"].includes(control.sourceType) && typeof control.sourceSha256 === "string" && /^[a-f0-9]{64}$/.test(control.sourceSha256));
39961
40301
  ids.add(control.pluginId);
39962
40302
  }
39963
40303
  }
@@ -39982,15 +40322,15 @@ function assertAgentPolicyCollections(policy) {
39982
40322
  requireBound(object(value));
39983
40323
  text(value.agent, 128);
39984
40324
  if (value.codexRetiredMaterializations !== undefined) {
39985
- const proof = record(value.codexRetiredMaterializations, 3), roots = array(proof.roots, AGENT_POLICY_LIMITS.discoveryRoots), parents = proof.parents === undefined ? [] : array(proof.parents, AGENT_POLICY_LIMITS.discoveryRoots);
39986
- requireBound(agent === "codex" && value.agent === "codex" && value.method === "reviewed" && Object.keys(proof).every((key) => ["roots", "parents", "directories"].includes(key)) && roots.length + parents.length > 0 && new Set(roots).size === roots.length && new Set(parents).size === parents.length);
40325
+ const proof = record(value.codexRetiredMaterializations, 3), roots = array(proof.roots, AGENT_POLICY_LIMITS.discoveryRoots), parents2 = proof.parents === undefined ? [] : array(proof.parents, AGENT_POLICY_LIMITS.discoveryRoots);
40326
+ requireBound(agent === "codex" && value.agent === "codex" && value.method === "reviewed" && Object.keys(proof).every((key) => ["roots", "parents", "directories"].includes(key)) && roots.length + parents2.length > 0 && new Set(roots).size === roots.length && new Set(parents2).size === parents2.length);
39987
40327
  for (const root of roots) {
39988
40328
  text(root);
39989
- requireBound(isAbsolute2(root) && resolve3(root) === root);
40329
+ requireBound(isAbsolute3(root) && resolve4(root) === root);
39990
40330
  }
39991
- for (const parent of parents) {
40331
+ for (const parent of parents2) {
39992
40332
  text(parent);
39993
- requireBound(isAbsolute2(parent) && resolve3(parent) === parent);
40333
+ requireBound(isAbsolute3(parent) && resolve4(parent) === parent);
39994
40334
  }
39995
40335
  for (const directory of array(proof.directories, AGENT_POLICY_LIMITS.discoveryDirectories)) {
39996
40336
  requireBound(object(directory));
@@ -40010,7 +40350,7 @@ function assertAgentPolicyCollections(policy) {
40010
40350
  text(input.namespace, 64);
40011
40351
  text(input.pluginParent);
40012
40352
  text(input.sourceRoot);
40013
- requireBound(!ids.has(input.pluginId) && [input.pluginParent, input.sourceRoot].every((path) => isAbsolute2(path) && resolve3(path) === path) && typeof input.sourceSha256 === "string" && /^[a-f0-9]{64}$/.test(input.sourceSha256));
40353
+ requireBound(!ids.has(input.pluginId) && [input.pluginParent, input.sourceRoot].every((path) => isAbsolute3(path) && resolve4(path) === path) && typeof input.sourceSha256 === "string" && /^[a-f0-9]{64}$/.test(input.sourceSha256));
40014
40354
  ids.add(input.pluginId);
40015
40355
  }
40016
40356
  if (proof.directories !== undefined)
@@ -40027,13 +40367,15 @@ function assertAgentPolicyCollections(policy) {
40027
40367
  text(source.path);
40028
40368
  requireBound(source.sha256 === null || typeof source.sha256 === "string" && /^[a-f0-9]{64}$/.test(source.sha256));
40029
40369
  if (source.hashMode !== undefined)
40030
- requireBound(["bytes", "path-bytes", "claude-plugin-registry", "claude-marketplace-registry", "claude-settings-v1", "claude-settings-v2", "claude-settings-v3", "claude-marketplace-registry-v2", "codex-settings-v1", "codex-settings-v2", "codex-settings-v3", "codex-settings-v4"].includes(source.hashMode) && source.format === undefined && source.fields === undefined && (source.hashMode === "bytes" || source.sha256 !== null));
40370
+ requireBound(["bytes", "path-bytes", "claude-plugin-registry", "claude-marketplace-registry", "claude-settings-v1", "claude-settings-v2", "claude-settings-v3", "claude-marketplace-registry-v2", "codex-settings-v1", "codex-settings-v2", "codex-settings-v3", "codex-settings-v4", "sumi-settings-v1"].includes(source.hashMode) && source.format === undefined && source.fields === undefined && (source.hashMode === "bytes" || source.sha256 !== null));
40371
+ if (source.hashMode === "sumi-settings-v1")
40372
+ requireBound(agent === "sumi" && value.agent === "sumi" && value.method === "reviewed" && !/[\x00-\x1f\x7f]/.test(source.path) && isAbsolute3(source.path) && resolve4(source.path) === source.path && basename3(source.path) === "sumi.json");
40031
40373
  if (source.hashMode === "codex-settings-v1" || source.hashMode === "codex-settings-v2" || (source.hashMode === "codex-settings-v3" || source.hashMode === "codex-settings-v4"))
40032
- requireBound(agent === "codex" && value.agent === "codex" && value.method === "reviewed" && !/[\x00-\x1f\x7f]/.test(source.path) && isAbsolute2(source.path) && resolve3(source.path) === source.path && basename2(source.path) === "config.toml");
40374
+ requireBound(agent === "codex" && value.agent === "codex" && value.method === "reviewed" && !/[\x00-\x1f\x7f]/.test(source.path) && isAbsolute3(source.path) && resolve4(source.path) === source.path && basename3(source.path) === "config.toml");
40033
40375
  if (source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || source.hashMode === "claude-settings-v3")
40034
- requireBound(agent === "claude" && value.agent === "claude" && value.method === "reviewed" && !/[\x00-\x1f\x7f]/.test(source.path) && isAbsolute2(source.path) && resolve3(source.path) === source.path && basename2(source.path) === "settings.json");
40376
+ requireBound(agent === "claude" && value.agent === "claude" && value.method === "reviewed" && !/[\x00-\x1f\x7f]/.test(source.path) && isAbsolute3(source.path) && resolve4(source.path) === source.path && basename3(source.path) === "settings.json");
40035
40377
  if (source.hashMode === "claude-marketplace-registry" || source.hashMode === "claude-marketplace-registry-v2")
40036
- requireBound(agent === "claude" && value.agent === "claude" && value.method === "reviewed" && !/[\x00-\x1f\x7f]/.test(source.path) && isAbsolute2(source.path) && resolve3(source.path) === source.path && basename2(source.path) === "known_marketplaces.json");
40378
+ requireBound(agent === "claude" && value.agent === "claude" && value.method === "reviewed" && !/[\x00-\x1f\x7f]/.test(source.path) && isAbsolute3(source.path) && resolve4(source.path) === source.path && basename3(source.path) === "known_marketplaces.json");
40037
40379
  if (source.hashMode === "claude-plugin-registry") {
40038
40380
  requireBound(agent === "claude");
40039
40381
  const managed = array(source.managedPlugins, 64);
@@ -46961,7 +47303,7 @@ var require_public_api = __commonJS((exports) => {
46961
47303
  }
46962
47304
  return doc;
46963
47305
  }
46964
- function parse(src, reviver, options) {
47306
+ function parse2(src, reviver, options) {
46965
47307
  let _reviver = undefined;
46966
47308
  if (typeof reviver === "function") {
46967
47309
  _reviver = reviver;
@@ -47002,7 +47344,7 @@ var require_public_api = __commonJS((exports) => {
47002
47344
  return value.toString(options);
47003
47345
  return new Document.Document(value, _replacer, options).toString(options);
47004
47346
  }
47005
- exports.parse = parse;
47347
+ exports.parse = parse2;
47006
47348
  exports.parseAllDocuments = parseAllDocuments;
47007
47349
  exports.parseDocument = parseDocument;
47008
47350
  exports.stringify = stringify;
@@ -47058,8 +47400,8 @@ var init_dist = __esm(() => {
47058
47400
  });
47059
47401
 
47060
47402
  // src/lib/agent-hermes.ts
47061
- import { dirname as dirname3, isAbsolute as isAbsolute3, join as join11, resolve as resolve4 } from "path";
47062
- import { lstatSync as lstatSync3, readFileSync as readFileSync7, opendirSync } from "fs";
47403
+ import { dirname as dirname4, isAbsolute as isAbsolute4, join as join11, resolve as resolve5 } from "path";
47404
+ import { lstatSync as lstatSync4, readFileSync as readFileSync7, opendirSync } from "fs";
47063
47405
  function object2(value) {
47064
47406
  return Boolean(value && typeof value === "object" && (Object.getPrototypeOf(value) === Object.prototype || Object.getPrototypeOf(value) === null));
47065
47407
  }
@@ -47094,7 +47436,7 @@ function quoted(value) {
47094
47436
  return `'${value.replace(/'/g, `'\\''`)}'`;
47095
47437
  }
47096
47438
  function hermesHookDefinitions(supervisor) {
47097
- if (!isAbsolute3(supervisor.runtime) || !isAbsolute3(supervisor.path))
47439
+ if (!isAbsolute4(supervisor.runtime) || !isAbsolute4(supervisor.path))
47098
47440
  throw new Error("Expected absolute Hermes supervisor paths");
47099
47441
  const entry = (event) => ({ command: `${quoted(supervisor.runtime)} ${quoted(supervisor.path)} --event ${event}`, timeout: 15, ...event === "pre_tool_call" ? { fail_closed: true } : {} });
47100
47442
  return { pre_llm_call: entry("pre_llm_call"), pre_tool_call: entry("pre_tool_call") };
@@ -47130,19 +47472,19 @@ function assertHermesEnvironment(home) {
47130
47472
  throw new Error(`NATIVE_SKILL_DRIFT: Hermes ${variable} requires a dedicated discovery adapter; unset it before using this adapter`);
47131
47473
  }
47132
47474
  const selected = process.env.HERMES_HOME?.trim();
47133
- if (selected && (!isAbsolute3(selected) || resolve4(selected) !== join11(resolve4(home), ".hermes")))
47475
+ if (selected && (!isAbsolute4(selected) || resolve5(selected) !== join11(resolve5(home), ".hermes")))
47134
47476
  throw new Error("NATIVE_SKILL_DRIFT: custom Hermes homes/profiles require their own reviewed bridge");
47135
47477
  if (process.env.HERMES_ENABLE_PROJECT_PLUGINS?.trim() && !["0", "false", "no", "off"].includes(process.env.HERMES_ENABLE_PROJECT_PLUGINS.trim().toLowerCase()))
47136
47478
  throw new Error("NATIVE_SKILL_DRIFT: Hermes project plugins require a dedicated discovery review");
47137
47479
  }
47138
47480
  function read(path) {
47139
- for (let current = path;; current = dirname3(current)) {
47140
- if (lstatSync3(current, { throwIfNoEntry: false })?.isSymbolicLink())
47481
+ for (let current = path;; current = dirname4(current)) {
47482
+ if (lstatSync4(current, { throwIfNoEntry: false })?.isSymbolicLink())
47141
47483
  throw new Error("NATIVE_SKILL_DRIFT: symlink Hermes protection input");
47142
- if (dirname3(current) === current)
47484
+ if (dirname4(current) === current)
47143
47485
  break;
47144
47486
  }
47145
- const stat = lstatSync3(path, { throwIfNoEntry: false });
47487
+ const stat = lstatSync4(path, { throwIfNoEntry: false });
47146
47488
  if (!stat)
47147
47489
  return null;
47148
47490
  if (!stat.isFile() || stat.size > 1024 * 1024)
@@ -47153,7 +47495,7 @@ function assertHermesProtection(home, config, command, profile, supervisor) {
47153
47495
  assertHermesEnvironment(home);
47154
47496
  if (read(join11(home, ".hermes", HERMES_OPT_OUT)) === null)
47155
47497
  throw new Error("NATIVE_SKILL_DRIFT: Hermes bundled skill reseeding is not disabled; run skills hook install");
47156
- if (!supervisor || !isAbsolute3(supervisor.path) || supervisor.runtime !== process.execPath || read(supervisor.path) !== renderHermesSupervisor(command, profile))
47498
+ if (!supervisor || !isAbsolute4(supervisor.path) || supervisor.runtime !== process.execPath || read(supervisor.path) !== renderHermesSupervisor(command, profile))
47157
47499
  throw new Error("NATIVE_SKILL_DRIFT: Hermes owned supervisor changed; run skills hook install");
47158
47500
  const raw = read(join11(home, ".hermes/shell-hooks-allowlist.json"));
47159
47501
  let trust;
@@ -47179,16 +47521,16 @@ function assertHermesProtection(home, config, command, profile, supervisor) {
47179
47521
  }
47180
47522
  function assertNoHermesLegacyShadow(root) {
47181
47523
  let entries = 0;
47182
- for (let cursor = resolve4(root);; cursor = dirname3(cursor)) {
47183
- if (lstatSync3(cursor, { throwIfNoEntry: false })?.isSymbolicLink())
47524
+ for (let cursor = resolve5(root);; cursor = dirname4(cursor)) {
47525
+ if (lstatSync4(cursor, { throwIfNoEntry: false })?.isSymbolicLink())
47184
47526
  throw new Error("NATIVE_SKILL_DRIFT: symlink Hermes legacy discovery root");
47185
- if (dirname3(cursor) === cursor)
47527
+ if (dirname4(cursor) === cursor)
47186
47528
  break;
47187
47529
  }
47188
47530
  function scan(path, depth) {
47189
47531
  if (++entries > 1e4 || depth > 64)
47190
47532
  throw new Error("NATIVE_SKILL_DRIFT: Hermes legacy discovery limit exceeded; review the root before continuing");
47191
- const stat = lstatSync3(path, { throwIfNoEntry: false });
47533
+ const stat = lstatSync4(path, { throwIfNoEntry: false });
47192
47534
  if (!stat)
47193
47535
  return;
47194
47536
  if (stat.isSymbolicLink())
@@ -47198,9 +47540,9 @@ function assertNoHermesLegacyShadow(root) {
47198
47540
  throw new Error("NATIVE_SKILL_DRIFT: unsupported Hermes legacy discovery input");
47199
47541
  return;
47200
47542
  }
47201
- if (lstatSync3(join11(path, "skills-cli.md"), { throwIfNoEntry: false }))
47543
+ if (lstatSync4(join11(path, "skills-cli.md"), { throwIfNoEntry: false }))
47202
47544
  throw new Error("NATIVE_SKILL_DRIFT: legacy Hermes skills-cli.md can shadow the owned bridge; preserve and retire it before continuing");
47203
- const hasDescriptor = Boolean(lstatSync3(join11(path, "SKILL.md"), { throwIfNoEntry: false }));
47545
+ const hasDescriptor = Boolean(lstatSync4(join11(path, "SKILL.md"), { throwIfNoEntry: false }));
47204
47546
  const directory = opendirSync(path);
47205
47547
  try {
47206
47548
  for (let child = directory.readSync();child; child = directory.readSync()) {
@@ -47281,189 +47623,189 @@ var init_agent_hermes = __esm(() => {
47281
47623
  });
47282
47624
 
47283
47625
  // src/lib/agent-discovery-directories.ts
47284
- import { createHash as createHash2 } from "crypto";
47285
- import { lstatSync as lstatSync4, opendirSync as opendirSync2 } from "fs";
47286
- import { dirname as dirname4, isAbsolute as isAbsolute4, join as join12, resolve as resolve5 } from "path";
47287
- function need(value, message) {
47626
+ import { createHash as createHash4 } from "crypto";
47627
+ import { lstatSync as lstatSync5, opendirSync as opendirSync2 } from "fs";
47628
+ import { dirname as dirname5, isAbsolute as isAbsolute5, join as join12, resolve as resolve6 } from "path";
47629
+ function need2(value, message) {
47288
47630
  if (!value)
47289
47631
  throw new Error(message);
47290
47632
  }
47291
47633
  function safe(path) {
47292
- need(typeof path === "string" && path.length <= AGENT_POLICY_LIMITS.pathCharacters && isAbsolute4(path) && resolve5(path) === path && !path.includes("\x00"), "Expected a canonical absolute discovery directory path");
47293
- for (let cursor = path;; cursor = dirname4(cursor)) {
47294
- need(!lstatSync4(cursor, { throwIfNoEntry: false })?.isSymbolicLink(), "Refusing symlink native discovery directory");
47295
- if (dirname4(cursor) === cursor)
47634
+ need2(typeof path === "string" && path.length <= AGENT_POLICY_LIMITS.pathCharacters && isAbsolute5(path) && resolve6(path) === path && !path.includes("\x00"), "Expected a canonical absolute discovery directory path");
47635
+ for (let cursor = path;; cursor = dirname5(cursor)) {
47636
+ need2(!lstatSync5(cursor, { throwIfNoEntry: false })?.isSymbolicLink(), "Refusing symlink native discovery directory");
47637
+ if (dirname5(cursor) === cursor)
47296
47638
  break;
47297
47639
  }
47298
47640
  }
47299
47641
  function same(before2, after2) {
47300
47642
  return Boolean(after2 && after2.isDirectory() && before2.dev === after2.dev && before2.ino === after2.ino && before2.mtimeMs === after2.mtimeMs && before2.ctimeMs === after2.ctimeMs);
47301
47643
  }
47302
- function capture(path, budget, excludedRoots, omittedRoots = [], rows) {
47644
+ function capture(path, budget2, excludedRoots, omittedRoots = [], rows) {
47303
47645
  safe(path);
47304
47646
  if (omittedRoots.some((root2) => path === root2 || path.startsWith(root2 + "/")))
47305
47647
  return { path, sha256: null };
47306
- const root = lstatSync4(path, { throwIfNoEntry: false });
47648
+ const root = lstatSync5(path, { throwIfNoEntry: false });
47307
47649
  if (!root)
47308
47650
  return { path, sha256: null };
47309
- need(root.isDirectory(), "Unsupported native discovery directory input");
47310
- const hash = createHash2("sha256");
47651
+ need2(root.isDirectory(), "Unsupported native discovery directory input");
47652
+ const hash = createHash4("sha256");
47311
47653
  function walk(current, relative2, before2, depth) {
47312
- need(depth <= 64, "Native discovery directory depth limit exceeded");
47654
+ need2(depth <= 64, "Native discovery directory depth limit exceeded");
47313
47655
  const names = [], directory = opendirSync2(current);
47314
47656
  try {
47315
47657
  for (let entry = directory.readSync();entry; entry = directory.readSync()) {
47316
- need(++budget.entries <= AGENT_POLICY_LIMITS.discoveryDirectoryEntries, "Native discovery directory entry limit exceeded");
47658
+ need2(++budget2.entries <= AGENT_POLICY_LIMITS.discoveryDirectoryEntries, "Native discovery directory entry limit exceeded");
47317
47659
  names.push(entry.name);
47318
47660
  }
47319
47661
  } finally {
47320
47662
  directory.closeSync();
47321
47663
  }
47322
- need(new Set(names).size === names.length, "Ambiguous native discovery directory names");
47664
+ need2(new Set(names).size === names.length, "Ambiguous native discovery directory names");
47323
47665
  for (const name of names.sort()) {
47324
47666
  const child = join12(current, name), childRelative = relative2 ? `${relative2}/${name}` : name;
47325
47667
  if (omittedRoots.includes(child))
47326
47668
  continue;
47327
- need(child.length <= AGENT_POLICY_LIMITS.pathCharacters, "Native discovery directory path limit exceeded");
47328
- const stat = lstatSync4(child);
47329
- need(stat.isFile() || stat.isDirectory(), "Refusing symlink or special native discovery directory member");
47669
+ need2(child.length <= AGENT_POLICY_LIMITS.pathCharacters, "Native discovery directory path limit exceeded");
47670
+ const stat = lstatSync5(child);
47671
+ need2(stat.isFile() || stat.isDirectory(), "Refusing symlink or special native discovery directory member");
47330
47672
  const row = JSON.stringify([childRelative, stat.isDirectory() ? "directory" : "file"]) + `
47331
47673
  `;
47332
- budget.bytes += Buffer.byteLength(row);
47333
- need(budget.bytes <= AGENT_POLICY_LIMITS.discoveryDirectoryBytes, "Native discovery directory metadata limit exceeded");
47674
+ budget2.bytes += Buffer.byteLength(row);
47675
+ need2(budget2.bytes <= AGENT_POLICY_LIMITS.discoveryDirectoryBytes, "Native discovery directory metadata limit exceeded");
47334
47676
  hash.update(row);
47335
47677
  rows?.push(row);
47336
47678
  if (stat.isDirectory() && !excludedRoots.includes(child))
47337
47679
  walk(child, childRelative, stat, depth + 1);
47338
47680
  }
47339
- need(same(before2, lstatSync4(current, { throwIfNoEntry: false })), "Native discovery directory changed while reading");
47681
+ need2(same(before2, lstatSync5(current, { throwIfNoEntry: false })), "Native discovery directory changed while reading");
47340
47682
  }
47341
47683
  walk(path, "", root, 0);
47342
47684
  safe(path);
47343
47685
  return { path, sha256: hash.digest("hex") };
47344
47686
  }
47345
47687
  function captureDiscoveryDirectoryProjection(paths, omittedRoots) {
47346
- need(Array.isArray(paths) && paths.length <= AGENT_POLICY_LIMITS.discoveryDirectories && new Set(paths).size === paths.length, "Invalid projected discovery directory collection");
47347
- need(omittedRoots.length <= AGENT_POLICY_LIMITS.discoveryRoots && new Set(omittedRoots).size === omittedRoots.length, "Invalid inactive discovery roots");
47688
+ need2(Array.isArray(paths) && paths.length <= AGENT_POLICY_LIMITS.discoveryDirectories && new Set(paths).size === paths.length, "Invalid projected discovery directory collection");
47689
+ need2(omittedRoots.length <= AGENT_POLICY_LIMITS.discoveryRoots && new Set(omittedRoots).size === omittedRoots.length, "Invalid inactive discovery roots");
47348
47690
  for (const root of omittedRoots)
47349
47691
  safe(root);
47350
- const budget = { entries: 0, bytes: 0 };
47692
+ const budget2 = { entries: 0, bytes: 0 };
47351
47693
  return paths.map((path) => {
47352
47694
  const entries = [];
47353
- return { ...capture(path, budget, [], omittedRoots, entries), entries };
47695
+ return { ...capture(path, budget2, [], omittedRoots, entries), entries };
47354
47696
  });
47355
47697
  }
47356
47698
  function verifyDiscoveryDirectoryProjection(directories, omittedRoots) {
47357
- need(directories.length <= AGENT_POLICY_LIMITS.discoveryDirectories, "Invalid projected discovery directory collection");
47699
+ need2(directories.length <= AGENT_POLICY_LIMITS.discoveryDirectories, "Invalid projected discovery directory collection");
47358
47700
  let count = 0, bytes = 0;
47359
47701
  const expected = directories.map((directory) => {
47360
47702
  safe(directory.path);
47361
- need(Array.isArray(directory.entries), "Missing reviewed directory membership inventory");
47362
- const hash = createHash2("sha256");
47703
+ need2(Array.isArray(directory.entries), "Missing reviewed directory membership inventory");
47704
+ const hash = createHash4("sha256");
47363
47705
  const kept = [];
47364
47706
  for (const row of directory.entries) {
47365
- need(typeof row === "string" && ++count <= AGENT_POLICY_LIMITS.discoveryDirectoryEntries, "Invalid reviewed directory membership rows");
47707
+ need2(typeof row === "string" && ++count <= AGENT_POLICY_LIMITS.discoveryDirectoryEntries, "Invalid reviewed directory membership rows");
47366
47708
  bytes += Buffer.byteLength(row);
47367
- need(bytes <= AGENT_POLICY_LIMITS.discoveryDirectoryBytes, "Reviewed directory membership byte limit exceeded");
47709
+ need2(bytes <= AGENT_POLICY_LIMITS.discoveryDirectoryBytes, "Reviewed directory membership byte limit exceeded");
47368
47710
  const value = JSON.parse(row);
47369
- need(Array.isArray(value) && value.length === 2 && typeof value[0] === "string" && value[0] && !isAbsolute4(value[0]) && !value[0].split("/").some((part) => !part || part === "." || part === "..") && ["file", "directory"].includes(value[1]) && row === JSON.stringify(value) + `
47711
+ need2(Array.isArray(value) && value.length === 2 && typeof value[0] === "string" && value[0] && !isAbsolute5(value[0]) && !value[0].split("/").some((part) => !part || part === "." || part === "..") && ["file", "directory"].includes(value[1]) && row === JSON.stringify(value) + `
47370
47712
  `, "Invalid reviewed directory member");
47371
47713
  hash.update(row);
47372
47714
  const path = join12(directory.path, value[0]);
47373
47715
  if (!omittedRoots.some((root) => path === root || path.startsWith(root + "/")))
47374
47716
  kept.push(row);
47375
47717
  }
47376
- need(directory.sha256 === null ? directory.entries.length === 0 : hash.digest("hex") === directory.sha256, "Reviewed directory inventory does not match its fingerprint");
47718
+ need2(directory.sha256 === null ? directory.entries.length === 0 : hash.digest("hex") === directory.sha256, "Reviewed directory inventory does not match its fingerprint");
47377
47719
  const absent = omittedRoots.some((root) => directory.path === root || directory.path.startsWith(root + "/"));
47378
- return { path: directory.path, sha256: absent || directory.sha256 === null ? null : createHash2("sha256").update(kept.join("")).digest("hex") };
47720
+ return { path: directory.path, sha256: absent || directory.sha256 === null ? null : createHash4("sha256").update(kept.join("")).digest("hex") };
47379
47721
  });
47380
47722
  const current = captureDiscoveryDirectoryProjection(directories.map((item) => item.path), omittedRoots);
47381
- need(current.every((item, index) => item.sha256 === expected[index].sha256), "Native discovery directory membership changed outside retired Codex roots");
47723
+ need2(current.every((item, index) => item.sha256 === expected[index].sha256), "Native discovery directory membership changed outside retired Codex roots");
47382
47724
  }
47383
47725
  function captureDiscoveryDirectories(paths, excludedRoots = []) {
47384
- need(Array.isArray(paths) && paths.length <= AGENT_POLICY_LIMITS.discoveryDirectories && new Set(paths).size === paths.length, "Invalid native discovery directory collection");
47385
- const budget = { entries: 0, bytes: 0 };
47726
+ need2(Array.isArray(paths) && paths.length <= AGENT_POLICY_LIMITS.discoveryDirectories && new Set(paths).size === paths.length, "Invalid native discovery directory collection");
47727
+ const budget2 = { entries: 0, bytes: 0 };
47386
47728
  for (const root of excludedRoots)
47387
47729
  safe(root);
47388
- return paths.map((path) => capture(path, budget, excludedRoots));
47730
+ return paths.map((path) => capture(path, budget2, excludedRoots));
47389
47731
  }
47390
47732
  function verifyDiscoveryDirectories(directories, excludedRoots = []) {
47391
- need(Array.isArray(directories) && directories.length <= AGENT_POLICY_LIMITS.discoveryDirectories, "Invalid native discovery directory collection");
47733
+ need2(Array.isArray(directories) && directories.length <= AGENT_POLICY_LIMITS.discoveryDirectories, "Invalid native discovery directory collection");
47392
47734
  for (const directory of directories)
47393
- need(directory && typeof directory === "object" && (directory.sha256 === null || typeof directory.sha256 === "string" && /^[a-f0-9]{64}$/.test(directory.sha256)), "Invalid native discovery directory digest");
47735
+ need2(directory && typeof directory === "object" && (directory.sha256 === null || typeof directory.sha256 === "string" && /^[a-f0-9]{64}$/.test(directory.sha256)), "Invalid native discovery directory digest");
47394
47736
  const current = captureDiscoveryDirectories(directories.map((directory) => directory.path), excludedRoots);
47395
47737
  for (let i = 0;i < directories.length; i++)
47396
- need(current[i].sha256 === directories[i].sha256, `Native discovery directory membership changed; run skills hook install with a fresh discovery review: ${directories[i].path}`);
47738
+ need2(current[i].sha256 === directories[i].sha256, `Native discovery directory membership changed; run skills hook install with a fresh discovery review: ${directories[i].path}`);
47397
47739
  }
47398
47740
  var init_agent_discovery_directories = __esm(() => {
47399
47741
  init_agent_policy_limits();
47400
47742
  });
47401
47743
 
47402
47744
  // src/lib/agent-discovery-bytes.ts
47403
- import { createHash as createHash3 } from "crypto";
47404
- import { closeSync, constants as constants2, fstatSync, lstatSync as lstatSync5, openSync, readSync } from "fs";
47405
- import { dirname as dirname5, isAbsolute as isAbsolute5, resolve as resolve6 } from "path";
47745
+ import { createHash as createHash5 } from "crypto";
47746
+ import { closeSync as closeSync2, constants as constants3, fstatSync as fstatSync2, lstatSync as lstatSync6, openSync as openSync2, readSync as readSync2 } from "fs";
47747
+ import { dirname as dirname6, isAbsolute as isAbsolute6, resolve as resolve7 } from "path";
47406
47748
  function discoveryByteBudget() {
47407
47749
  return { remaining: AGENT_POLICY_LIMITS.discoveryRawTotalBytes };
47408
47750
  }
47409
47751
  function safe2(path) {
47410
- if (typeof path !== "string" || !isAbsolute5(path) || path !== resolve6(path) || path.length > AGENT_POLICY_LIMITS.pathCharacters || path.includes("\x00"))
47752
+ if (typeof path !== "string" || !isAbsolute6(path) || path !== resolve7(path) || path.length > AGENT_POLICY_LIMITS.pathCharacters || path.includes("\x00"))
47411
47753
  throw new Error("Expected a canonical absolute raw discovery path");
47412
- for (let cursor = path;; cursor = dirname5(cursor)) {
47413
- if (lstatSync5(cursor, { throwIfNoEntry: false })?.isSymbolicLink())
47754
+ for (let cursor = path;; cursor = dirname6(cursor)) {
47755
+ if (lstatSync6(cursor, { throwIfNoEntry: false })?.isSymbolicLink())
47414
47756
  throw new Error("Refusing symlink raw discovery input");
47415
- if (dirname5(cursor) === cursor)
47757
+ if (dirname6(cursor) === cursor)
47416
47758
  break;
47417
47759
  }
47418
47760
  }
47419
47761
  function same2(left, right) {
47420
47762
  return left.dev === right.dev && left.ino === right.ino && left.size === right.size && left.mtimeMs === right.mtimeMs && left.ctimeMs === right.ctimeMs;
47421
47763
  }
47422
- function consume(budget, bytes) {
47423
- if (bytes > budget.remaining)
47764
+ function consume(budget2, bytes) {
47765
+ if (bytes > budget2.remaining)
47424
47766
  throw new Error("Raw discovery aggregate byte limit exceeded");
47425
- budget.remaining -= bytes;
47767
+ budget2.remaining -= bytes;
47426
47768
  }
47427
- function hashRawDiscoveryFile(path, budget, changes) {
47769
+ function hashRawDiscoveryFile(path, budget2, changes) {
47428
47770
  safe2(path);
47429
47771
  if (changes?.has(path)) {
47430
47772
  const text2 = changes.get(path), bytes = Buffer.byteLength(text2);
47431
47773
  if (bytes > AGENT_POLICY_LIMITS.discoveryRawSourceBytes)
47432
47774
  throw new Error("Raw discovery file byte limit exceeded");
47433
- consume(budget, bytes);
47434
- return createHash3("sha256").update(text2).digest("hex");
47775
+ consume(budget2, bytes);
47776
+ return createHash5("sha256").update(text2).digest("hex");
47435
47777
  }
47436
- const initial2 = lstatSync5(path, { throwIfNoEntry: false });
47778
+ const initial2 = lstatSync6(path, { throwIfNoEntry: false });
47437
47779
  if (!initial2)
47438
47780
  return null;
47439
47781
  if (!initial2.isFile() || initial2.size > AGENT_POLICY_LIMITS.discoveryRawSourceBytes)
47440
47782
  throw new Error("Unsupported or oversized raw discovery input");
47441
- if (initial2.size > budget.remaining)
47783
+ if (initial2.size > budget2.remaining)
47442
47784
  throw new Error("Raw discovery aggregate byte limit exceeded");
47443
- const fd = openSync(path, constants2.O_RDONLY | constants2.O_NOFOLLOW | constants2.O_NONBLOCK);
47785
+ const fd = openSync2(path, constants3.O_RDONLY | constants3.O_NOFOLLOW | constants3.O_NONBLOCK);
47444
47786
  try {
47445
- const opened = fstatSync(fd);
47787
+ const opened = fstatSync2(fd);
47446
47788
  if (!opened.isFile() || !same2(initial2, opened))
47447
47789
  throw new Error("Raw discovery input changed during open");
47448
- const hash = createHash3("sha256"), buffer = Buffer.alloc(64 * 1024);
47790
+ const hash = createHash5("sha256"), buffer = Buffer.alloc(64 * 1024);
47449
47791
  let bytes = 0;
47450
47792
  while (true) {
47451
- const count = readSync(fd, buffer, 0, Math.min(buffer.length, AGENT_POLICY_LIMITS.discoveryRawSourceBytes - bytes + 1), null);
47793
+ const count = readSync2(fd, buffer, 0, Math.min(buffer.length, AGENT_POLICY_LIMITS.discoveryRawSourceBytes - bytes + 1), null);
47452
47794
  if (!count)
47453
47795
  break;
47454
47796
  bytes += count;
47455
47797
  if (bytes > AGENT_POLICY_LIMITS.discoveryRawSourceBytes)
47456
47798
  throw new Error("Raw discovery file byte limit exceeded");
47457
- consume(budget, count);
47799
+ consume(budget2, count);
47458
47800
  hash.update(buffer.subarray(0, count));
47459
47801
  }
47460
- const final = fstatSync(fd), current = lstatSync5(path, { throwIfNoEntry: false });
47802
+ const final = fstatSync2(fd), current = lstatSync6(path, { throwIfNoEntry: false });
47461
47803
  safe2(path);
47462
47804
  if (!current?.isFile() || !same2(opened, final) || !same2(final, current) || bytes !== final.size)
47463
47805
  throw new Error("Raw discovery input changed during read");
47464
47806
  return hash.digest("hex");
47465
47807
  } finally {
47466
- closeSync(fd);
47808
+ closeSync2(fd);
47467
47809
  }
47468
47810
  }
47469
47811
  var init_agent_discovery_bytes = __esm(() => {
@@ -47471,9 +47813,9 @@ var init_agent_discovery_bytes = __esm(() => {
47471
47813
  });
47472
47814
 
47473
47815
  // src/lib/agent-discovery-path-bytes.ts
47474
- import { createHash as createHash4 } from "crypto";
47475
- import { lstatSync as lstatSync6, readlinkSync } from "fs";
47476
- import { dirname as dirname6, isAbsolute as isAbsolute6, join as join13, parse, resolve as resolve7, sep as sep2 } from "path";
47816
+ import { createHash as createHash6 } from "crypto";
47817
+ import { lstatSync as lstatSync7, readlinkSync } from "fs";
47818
+ import { dirname as dirname7, isAbsolute as isAbsolute7, join as join13, parse as parse2, resolve as resolve8, sep as sep2 } from "path";
47477
47819
  function identity3(stat, mutable = false) {
47478
47820
  return {
47479
47821
  dev: String(stat.dev),
@@ -47484,14 +47826,14 @@ function identity3(stat, mutable = false) {
47484
47826
  ...mutable ? { size: String(stat.size), mtimeNs: String(stat.mtimeNs), ctimeNs: String(stat.ctimeNs) } : {}
47485
47827
  };
47486
47828
  }
47487
- function canonical(path) {
47488
- if (typeof path !== "string" || !isAbsolute6(path) || path !== resolve7(path) || path.length > AGENT_POLICY_LIMITS.pathCharacters || path.includes("\x00") || Buffer.from(path).toString("utf8") !== path)
47829
+ function canonical2(path) {
47830
+ if (typeof path !== "string" || !isAbsolute7(path) || path !== resolve8(path) || path.length > AGENT_POLICY_LIMITS.pathCharacters || path.includes("\x00") || Buffer.from(path).toString("utf8") !== path)
47489
47831
  throw new Error("Expected a canonical absolute discovery path");
47490
47832
  }
47491
47833
  function trace(path) {
47492
- canonical(path);
47834
+ canonical2(path);
47493
47835
  const rows = [], paths = [];
47494
- let metadataBytes = 0, steps = 0, links = 0, cursor = parse(path).root, pending = path.slice(cursor.length).split(sep2);
47836
+ let metadataBytes = 0, steps = 0, links = 0, cursor = parse2(path).root, pending = path.slice(cursor.length).split(sep2);
47495
47837
  function record2(path2, row) {
47496
47838
  const value = { path: path2, ...row };
47497
47839
  metadataBytes += Buffer.byteLength(JSON.stringify(value));
@@ -47501,7 +47843,7 @@ function trace(path) {
47501
47843
  paths.push(path2);
47502
47844
  }
47503
47845
  function root() {
47504
- const stat = lstatSync6(cursor, { bigint: true });
47846
+ const stat = lstatSync7(cursor, { bigint: true });
47505
47847
  if (!stat.isDirectory())
47506
47848
  throw new Error("Unsupported discovery path root");
47507
47849
  record2(cursor, { type: "directory", ...identity3(stat) });
@@ -47514,13 +47856,13 @@ function trace(path) {
47514
47856
  if (!component || component === ".")
47515
47857
  continue;
47516
47858
  if (component === "..") {
47517
- cursor = dirname6(cursor);
47859
+ cursor = dirname7(cursor);
47518
47860
  continue;
47519
47861
  }
47520
47862
  const candidate = join13(cursor, component);
47521
47863
  if (candidate.length > AGENT_POLICY_LIMITS.pathCharacters)
47522
47864
  throw new Error("Discovery resolved path length limit exceeded");
47523
- const stat = lstatSync6(candidate, { bigint: true, throwIfNoEntry: false });
47865
+ const stat = lstatSync7(candidate, { bigint: true, throwIfNoEntry: false });
47524
47866
  if (!stat) {
47525
47867
  record2(candidate, { type: "missing", remaining: pending });
47526
47868
  return { rows, paths, file: null, missing: candidate, metadataBytes };
@@ -47528,17 +47870,17 @@ function trace(path) {
47528
47870
  if (stat.isSymbolicLink()) {
47529
47871
  if (++links > AGENT_POLICY_LIMITS.discoveryPathLinks || stat.size > BigInt(AGENT_POLICY_LIMITS.pathCharacters))
47530
47872
  throw new Error("Discovery path link limit exceeded");
47531
- const rawTarget = readlinkSync(candidate, { encoding: "buffer" }), target = rawTarget.toString("utf8"), after2 = lstatSync6(candidate, { bigint: true });
47873
+ const rawTarget = readlinkSync(candidate, { encoding: "buffer" }), target = rawTarget.toString("utf8"), after2 = lstatSync7(candidate, { bigint: true });
47532
47874
  if (!rawTarget.equals(Buffer.from(target, "utf8")))
47533
47875
  throw new Error("Unsupported non-UTF8 discovery link target");
47534
47876
  if (!target || target.includes("\x00") || Buffer.byteLength(target) > AGENT_POLICY_LIMITS.pathCharacters || !after2.isSymbolicLink() || JSON.stringify(identity3(stat, true)) !== JSON.stringify(identity3(after2, true)))
47535
47877
  throw new Error("Discovery link changed during read");
47536
47878
  record2(candidate, { type: "link", target, ...identity3(stat, true) });
47537
- if (isAbsolute6(target)) {
47538
- cursor = parse(target).root;
47879
+ if (isAbsolute7(target)) {
47880
+ cursor = parse2(target).root;
47539
47881
  root();
47540
47882
  }
47541
- const remainder = isAbsolute6(target) ? target.slice(parse(target).root.length) : target;
47883
+ const remainder = isAbsolute7(target) ? target.slice(parse2(target).root.length) : target;
47542
47884
  pending = [...remainder.split(sep2), ...pending];
47543
47885
  if (pending.length + steps > AGENT_POLICY_LIMITS.discoveryPathSteps)
47544
47886
  throw new Error("Discovery path step limit exceeded");
@@ -47558,7 +47900,7 @@ function trace(path) {
47558
47900
  }
47559
47901
  throw new Error("Unsupported directory discovery path input");
47560
47902
  }
47561
- function hashDiscoveryPathFile(path, budget, changes) {
47903
+ function hashDiscoveryPathFile(path, budget2, changes) {
47562
47904
  const before2 = trace(path);
47563
47905
  let createsMissingPath = false;
47564
47906
  if (before2.missing !== null && changes) {
@@ -47571,17 +47913,17 @@ function hashDiscoveryPathFile(path, budget, changes) {
47571
47913
  }
47572
47914
  if (createsMissingPath || changes?.has(path) || before2.paths.some((path2) => changes?.has(path2)))
47573
47915
  throw new Error("Discovery path witness intersects a planned write; use bytes mode for owned configuration");
47574
- const remaining = budget.pathMetadataRemaining ?? AGENT_POLICY_LIMITS.discoveryPathTotalMetadataBytes;
47916
+ const remaining = budget2.pathMetadataRemaining ?? AGENT_POLICY_LIMITS.discoveryPathTotalMetadataBytes;
47575
47917
  if (before2.metadataBytes > remaining)
47576
47918
  throw new Error("Discovery path aggregate metadata limit exceeded");
47577
- budget.pathMetadataRemaining = remaining - before2.metadataBytes;
47578
- const content = before2.file === null ? null : hashRawDiscoveryFile(before2.file, budget);
47919
+ budget2.pathMetadataRemaining = remaining - before2.metadataBytes;
47920
+ const content = before2.file === null ? null : hashRawDiscoveryFile(before2.file, budget2);
47579
47921
  if (before2.file !== null && content === null)
47580
47922
  throw new Error("Discovery path input changed during read");
47581
47923
  const after2 = trace(path);
47582
47924
  if (JSON.stringify(before2.rows) !== JSON.stringify(after2.rows) || before2.file !== after2.file)
47583
47925
  throw new Error("Discovery path input changed during read");
47584
- return createHash4("sha256").update(JSON.stringify({ version: 1, path, rows: before2.rows, content })).digest("hex");
47926
+ return createHash6("sha256").update(JSON.stringify({ version: 1, path, rows: before2.rows, content })).digest("hex");
47585
47927
  }
47586
47928
  var init_agent_discovery_path_bytes = __esm(() => {
47587
47929
  init_agent_policy_limits();
@@ -47589,7 +47931,7 @@ var init_agent_discovery_path_bytes = __esm(() => {
47589
47931
  });
47590
47932
 
47591
47933
  // src/lib/skill-bundle.ts
47592
- import { createHash as createHash5 } from "crypto";
47934
+ import { createHash as createHash7 } from "crypto";
47593
47935
  import { readFileSync as readFileSync8, readdirSync as readdirSync4, statSync as statSync5 } from "fs";
47594
47936
  import { join as join14, relative as relative2 } from "path";
47595
47937
  import { createGunzip } from "zlib";
@@ -47621,7 +47963,7 @@ function ownBytes(view) {
47621
47963
  return out;
47622
47964
  }
47623
47965
  function sha256Hex(bytes) {
47624
- return createHash5("sha256").update(bytes).digest("hex");
47966
+ return createHash7("sha256").update(bytes).digest("hex");
47625
47967
  }
47626
47968
  function collectSkillBundleEntries(dir) {
47627
47969
  const entries = [];
@@ -47850,7 +48192,7 @@ async function inspectSkillBundle(bundle, options = {}) {
47850
48192
  parser2.push(chunk2);
47851
48193
  bytesSinceYield += chunk2.byteLength;
47852
48194
  if (bytesSinceYield >= 256 * 1024) {
47853
- await new Promise((resolve8) => setTimeout(resolve8, 0));
48195
+ await new Promise((resolve9) => setTimeout(resolve9, 0));
47854
48196
  bytesSinceYield = 0;
47855
48197
  check();
47856
48198
  }
@@ -48210,21 +48552,21 @@ var init_profile_limits = __esm(() => {
48210
48552
  });
48211
48553
 
48212
48554
  // src/lib/selection-cache.ts
48213
- import { createHash as createHash6, randomUUID as randomUUID3 } from "crypto";
48555
+ import { createHash as createHash8, randomUUID as randomUUID3 } from "crypto";
48214
48556
  import { spawnSync } from "child_process";
48215
- import { closeSync as closeSync2, constants as constants3, fstatSync as fstatSync2, fsyncSync, linkSync, lstatSync as lstatSync7, mkdirSync as mkdirSync3, openSync as openSync2, readFileSync as readFileSync9, readlinkSync as readlinkSync2, readSync as readSync2, renameSync, unlinkSync, writeFileSync as writeFileSync3 } from "fs";
48557
+ import { closeSync as closeSync3, constants as constants4, fstatSync as fstatSync3, fsyncSync, linkSync, lstatSync as lstatSync8, mkdirSync as mkdirSync3, openSync as openSync3, readFileSync as readFileSync9, readlinkSync as readlinkSync2, readSync as readSync3, renameSync, unlinkSync, writeFileSync as writeFileSync3 } from "fs";
48216
48558
  import { hostname } from "os";
48217
- import { dirname as dirname7, join as join15, parse as parse2, resolve as resolve8 } from "path";
48559
+ import { dirname as dirname8, join as join15, parse as parse3, resolve as resolve9 } from "path";
48218
48560
  import { isDeepStrictEqual as isDeepStrictEqual2 } from "util";
48219
48561
  function selectionCacheRoot(options = {}) {
48220
- return resolve8(options.cacheDir ?? join15(getDataDirReadOnly(), "selection-cache"));
48562
+ return resolve9(options.cacheDir ?? join15(getDataDirReadOnly(), "selection-cache"));
48221
48563
  }
48222
48564
  function selectionKey(selection) {
48223
48565
  validateSelection(selection);
48224
48566
  return hash([selection.authority, selection.workspaceId, selection.slug, selection.version, selection.bundleDigest]);
48225
48567
  }
48226
48568
  function hash(value) {
48227
- return createHash6("sha256").update(JSON.stringify(value)).digest("hex");
48569
+ return createHash8("sha256").update(JSON.stringify(value)).digest("hex");
48228
48570
  }
48229
48571
  function validateSelection(selection) {
48230
48572
  if (!selection || !/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(selection.slug) || !isValidSkillVersion(selection.version) || !/^sha256:[a-f0-9]{64}$/.test(selection.bundleDigest) || typeof selection.workspaceId !== "string" || !selection.workspaceId.trim() || typeof selection.profileRevision !== "string" || !selection.profileRevision.trim()) {
@@ -48264,14 +48606,14 @@ function selectionBundlePath(selection, options = {}) {
48264
48606
  return join15(selectionCacheRoot(options), "objects", hash(selection.authority), hash(selection.workspaceId), `${selection.bundleDigest.slice(7)}.tar.gz`);
48265
48607
  }
48266
48608
  function assertRegularPath(path, createParents = false) {
48267
- const absolute = resolve8(path);
48268
- const root = parse2(absolute).root;
48609
+ const absolute = resolve9(path);
48610
+ const root = parse3(absolute).root;
48269
48611
  let cursor = root;
48270
48612
  const segments = absolute.slice(root.length).split("/");
48271
48613
  for (let index = 0;index < segments.length; index++) {
48272
48614
  cursor = join15(cursor, segments[index]);
48273
48615
  try {
48274
- const stat = lstatSync7(cursor);
48616
+ const stat = lstatSync8(cursor);
48275
48617
  if (stat.isSymbolicLink() || index < segments.length - 1 && !stat.isDirectory()) {
48276
48618
  throw new SkillSelectionError("UNSAFE_CACHE_PATH", "Skills cache paths must not traverse symlinks or non-directories.");
48277
48619
  }
@@ -48287,20 +48629,20 @@ function readRegularFile(path, limit) {
48287
48629
  assertRegularPath(path);
48288
48630
  let fd;
48289
48631
  try {
48290
- fd = openSync2(path, constants3.O_RDONLY | constants3.O_NOFOLLOW | constants3.O_NONBLOCK);
48632
+ fd = openSync3(path, constants4.O_RDONLY | constants4.O_NOFOLLOW | constants4.O_NONBLOCK);
48291
48633
  } catch (error) {
48292
48634
  if (error.code === "ENOENT")
48293
48635
  return null;
48294
48636
  throw error;
48295
48637
  }
48296
48638
  try {
48297
- const stat = fstatSync2(fd);
48639
+ const stat = fstatSync3(fd);
48298
48640
  if (!stat.isFile() || stat.size > limit)
48299
48641
  throw new SkillSelectionError("INVALID_CACHE_FILE", "The Skills cache contains an invalid or oversized file.");
48300
48642
  const bytes = Buffer.alloc(stat.size + 1);
48301
48643
  let size2 = 0;
48302
48644
  while (size2 < bytes.length) {
48303
- const read2 = readSync2(fd, bytes, size2, bytes.length - size2, null);
48645
+ const read2 = readSync3(fd, bytes, size2, bytes.length - size2, null);
48304
48646
  if (!read2)
48305
48647
  break;
48306
48648
  size2 += read2;
@@ -48309,7 +48651,7 @@ function readRegularFile(path, limit) {
48309
48651
  throw new SkillSelectionError("INVALID_CACHE_FILE", "The Skills cache file grew during its bounded read.");
48310
48652
  return bytes.subarray(0, size2);
48311
48653
  } finally {
48312
- closeSync2(fd);
48654
+ closeSync3(fd);
48313
48655
  }
48314
48656
  }
48315
48657
  function writeSelectionJson(path, value) {
@@ -48321,19 +48663,19 @@ function writeSelectionJson(path, value) {
48321
48663
  }
48322
48664
  function atomicWrite(path, bytes, mode, durable = false) {
48323
48665
  assertRegularPath(path, true);
48324
- const temporary = join15(dirname7(path), `.selection-${randomUUID3()}.tmp`);
48666
+ const temporary = join15(dirname8(path), `.selection-${randomUUID3()}.tmp`);
48325
48667
  try {
48326
- const fd = openSync2(temporary, constants3.O_WRONLY | constants3.O_CREAT | constants3.O_EXCL | constants3.O_NOFOLLOW, mode);
48668
+ const fd = openSync3(temporary, constants4.O_WRONLY | constants4.O_CREAT | constants4.O_EXCL | constants4.O_NOFOLLOW, mode);
48327
48669
  try {
48328
48670
  writeFileSync3(fd, bytes);
48329
48671
  if (durable)
48330
48672
  fsyncSync(fd);
48331
48673
  } finally {
48332
- closeSync2(fd);
48674
+ closeSync3(fd);
48333
48675
  }
48334
48676
  renameSync(temporary, path);
48335
48677
  if (durable)
48336
- syncDirectory(dirname7(path));
48678
+ syncDirectory(dirname8(path));
48337
48679
  } finally {
48338
48680
  try {
48339
48681
  unlinkSync(temporary);
@@ -48443,7 +48785,7 @@ function assertFreshCachedProfile(receipt, options = {}) {
48443
48785
  }
48444
48786
  }
48445
48787
  function projectSelectionLockPath(projectDir) {
48446
- return join15(resolve8(projectDir), ".skills", SELECTION_LOCK_FILE);
48788
+ return join15(resolve9(projectDir), ".skills", SELECTION_LOCK_FILE);
48447
48789
  }
48448
48790
  function readProjectSelection(projectDir) {
48449
48791
  const receipt = readSelectionJson(projectSelectionLockPath(projectDir));
@@ -48557,14 +48899,14 @@ function localLockIdentity() {
48557
48899
  }
48558
48900
  function readSessionLock(sessionId, options) {
48559
48901
  const path = `${sessionReceiptPath(sessionId, options)}.write-lock`;
48560
- const before2 = lstatSync7(path, { throwIfNoEntry: false });
48902
+ const before2 = lstatSync8(path, { throwIfNoEntry: false });
48561
48903
  if (!before2)
48562
48904
  return null;
48563
48905
  if (!before2.isFile() || ![1, 2].includes(before2.nlink) || (before2.mode & 63) !== 0 || process.getuid && before2.uid !== process.getuid()) {
48564
48906
  throw new SkillSelectionError("SESSION_WRITE_LOCKED", "The session lock is not a private regular file; recovery requires review.");
48565
48907
  }
48566
48908
  const bytes = readRegularFile(path, SESSION_LOCK_MAX_BYTES);
48567
- const after2 = lstatSync7(path, { throwIfNoEntry: false });
48909
+ const after2 = lstatSync8(path, { throwIfNoEntry: false });
48568
48910
  if (!bytes || !after2?.isFile() || before2.dev !== after2.dev || before2.ino !== after2.ino || before2.mtimeMs !== after2.mtimeMs || before2.mode !== after2.mode || before2.uid !== after2.uid || before2.gid !== after2.gid || before2.nlink !== after2.nlink) {
48569
48911
  throw new SkillSelectionError("SESSION_WRITE_LOCKED", "The session lock changed during inspection; recovery requires review.");
48570
48912
  }
@@ -48581,7 +48923,7 @@ function readSessionLock(sessionId, options) {
48581
48923
  if (after2.nlink === 2) {
48582
48924
  stagingPath = `${path}.${marker.operationId}.prepared`;
48583
48925
  assertRegularPath(stagingPath);
48584
- const staged = lstatSync7(stagingPath, { throwIfNoEntry: false });
48926
+ const staged = lstatSync8(stagingPath, { throwIfNoEntry: false });
48585
48927
  if (marker.publication !== "hard-link-v1" || !staged?.isFile() || staged.dev !== after2.dev || staged.ino !== after2.ino || staged.nlink !== 2 || staged.mode !== after2.mode || staged.uid !== after2.uid || staged.gid !== after2.gid) {
48586
48928
  throw new SkillSelectionError("SESSION_WRITE_LOCKED", "The session lock has an unbound publication link; recovery requires review.");
48587
48929
  }
@@ -48592,33 +48934,33 @@ function publishSessionLock(path, marker) {
48592
48934
  const stagingPath = `${path}.${marker.operationId}.prepared`;
48593
48935
  const bytes = Buffer.from(`${JSON.stringify({ ...marker, publication: "hard-link-v1" })}
48594
48936
  `);
48595
- const fd = openSync2(stagingPath, constants3.O_WRONLY | constants3.O_CREAT | constants3.O_EXCL | constants3.O_NOFOLLOW, 384);
48596
- const stat = fstatSync2(fd);
48937
+ const fd = openSync3(stagingPath, constants4.O_WRONLY | constants4.O_CREAT | constants4.O_EXCL | constants4.O_NOFOLLOW, 384);
48938
+ const stat = fstatSync3(fd);
48597
48939
  let published = false, handedOff = false;
48598
48940
  try {
48599
48941
  writeFileSync3(fd, bytes);
48600
48942
  fsyncSync(fd);
48601
48943
  linkSync(stagingPath, path);
48602
48944
  published = true;
48603
- syncDirectory(dirname7(path));
48604
- const staged = lstatSync7(stagingPath);
48945
+ syncDirectory(dirname8(path));
48946
+ const staged = lstatSync8(stagingPath);
48605
48947
  if (!staged.isFile() || staged.dev !== stat.dev || staged.ino !== stat.ino) {
48606
48948
  throw new SkillSelectionError("SESSION_WRITE_LOCK_CHANGED", "The initialized lock staging inode changed before publication completed.");
48607
48949
  }
48608
48950
  unlinkSync(stagingPath);
48609
- syncDirectory(dirname7(path));
48951
+ syncDirectory(dirname8(path));
48610
48952
  handedOff = true;
48611
48953
  return { path, stagingPath, fd, dev: stat.dev, ino: stat.ino };
48612
48954
  } finally {
48613
48955
  if (!handedOff) {
48614
48956
  try {
48615
48957
  for (const target of [...published ? [path] : [], stagingPath]) {
48616
- const current = lstatSync7(target, { throwIfNoEntry: false });
48958
+ const current = lstatSync8(target, { throwIfNoEntry: false });
48617
48959
  if (current?.isFile() && current.dev === stat.dev && current.ino === stat.ino)
48618
48960
  unlinkSync(target);
48619
48961
  }
48620
48962
  } finally {
48621
- closeSync2(fd);
48963
+ closeSync3(fd);
48622
48964
  }
48623
48965
  }
48624
48966
  }
@@ -48667,25 +49009,25 @@ function archiveSessionLock(lock, receipt, explicitLocalHost) {
48667
49009
  const guardPath = `${lock.path}.recovery-guard`;
48668
49010
  let guardFd;
48669
49011
  try {
48670
- guardFd = openSync2(guardPath, constants3.O_WRONLY | constants3.O_CREAT | constants3.O_EXCL | constants3.O_NOFOLLOW, 384);
49012
+ guardFd = openSync3(guardPath, constants4.O_WRONLY | constants4.O_CREAT | constants4.O_EXCL | constants4.O_NOFOLLOW, 384);
48671
49013
  } catch (error) {
48672
49014
  if (error.code === "EEXIST")
48673
49015
  return null;
48674
49016
  throw error;
48675
49017
  }
48676
- const guardStat = fstatSync2(guardFd);
49018
+ const guardStat = fstatSync3(guardFd);
48677
49019
  try {
48678
49020
  writeFileSync3(guardFd, `${JSON.stringify({ schemaVersion: 1, pid: process.pid, operationId: randomUUID3() })}
48679
49021
  `);
48680
49022
  fsyncSync(guardFd);
48681
- const cacheOptions = { cacheDir: dirname7(dirname7(lock.path)) };
49023
+ const cacheOptions = { cacheDir: dirname8(dirname8(lock.path)) };
48682
49024
  const current = readSessionLock(lock.marker.sessionId, cacheOptions);
48683
49025
  if (!current || current.dev !== lock.dev || current.ino !== lock.ino || current.sha256 !== lock.sha256 || current.mtimeMs !== lock.mtimeMs || !writerIsGone(current, explicitLocalHost))
48684
49026
  return null;
48685
49027
  const currentReceipt = readSkillSessionSnapshotIfExists(lock.marker.sessionId, cacheOptions);
48686
49028
  if (currentReceipt?.sha256 !== receipt?.sha256 || currentReceipt?.generation !== receipt?.generation)
48687
49029
  return null;
48688
- const directory = join15(dirname7(dirname7(lock.path)), "session-lock-recoveries", randomUUID3());
49030
+ const directory = join15(dirname8(dirname8(lock.path)), "session-lock-recoveries", randomUUID3());
48689
49031
  const archivePath = join15(directory, "original.write-lock");
48690
49032
  const recordPath = join15(directory, "recovery.json");
48691
49033
  assertRegularPath(archivePath, true);
@@ -48702,7 +49044,7 @@ function archiveSessionLock(lock, receipt, explicitLocalHost) {
48702
49044
  })}
48703
49045
  `));
48704
49046
  syncDirectory(directory);
48705
- syncDirectory(dirname7(directory));
49047
+ syncDirectory(dirname8(directory));
48706
49048
  const finalLock = readSessionLock(lock.marker.sessionId, cacheOptions);
48707
49049
  if (!finalLock || finalLock.dev !== lock.dev || finalLock.ino !== lock.ino || finalLock.sha256 !== lock.sha256 || readSkillSessionSnapshotIfExists(lock.marker.sessionId, cacheOptions)?.sha256 !== receipt?.sha256)
48708
49050
  return null;
@@ -48717,11 +49059,11 @@ function archiveSessionLock(lock, receipt, explicitLocalHost) {
48717
49059
  archivedPaths.push(publicationPath);
48718
49060
  }
48719
49061
  syncDirectory(directory);
48720
- syncDirectory(dirname7(lock.path));
49062
+ syncDirectory(dirname8(lock.path));
48721
49063
  for (const path of archivedPaths) {
48722
- const before2 = lstatSync7(path, { throwIfNoEntry: false });
49064
+ const before2 = lstatSync8(path, { throwIfNoEntry: false });
48723
49065
  const bytes = readRegularFile(path, SESSION_LOCK_MAX_BYTES);
48724
- const after2 = lstatSync7(path, { throwIfNoEntry: false });
49066
+ const after2 = lstatSync8(path, { throwIfNoEntry: false });
48725
49067
  if (!before2?.isFile() || before2.dev !== lock.dev || before2.ino !== lock.ino || before2.nlink !== archivedPaths.length || before2.mtimeMs !== lock.mtimeMs || (before2.mode & 63) !== 0 || process.getuid && before2.uid !== process.getuid() || !bytes || sha256Hex(bytes) !== lock.sha256 || !after2?.isFile() || before2.dev !== after2.dev || before2.ino !== after2.ino || before2.mtimeMs !== after2.mtimeMs || before2.mode !== after2.mode || before2.uid !== after2.uid || before2.gid !== after2.gid || before2.nlink !== after2.nlink) {
48726
49068
  throw new Error("Archived lock ownership or bytes changed");
48727
49069
  }
@@ -48733,8 +49075,8 @@ function archiveSessionLock(lock, receipt, explicitLocalHost) {
48733
49075
  }
48734
49076
  return archivePath;
48735
49077
  } finally {
48736
- closeSync2(guardFd);
48737
- const current = lstatSync7(guardPath, { throwIfNoEntry: false });
49078
+ closeSync3(guardFd);
49079
+ const current = lstatSync8(guardPath, { throwIfNoEntry: false });
48738
49080
  if (current?.isFile() && current.dev === guardStat.dev && current.ino === guardStat.ino)
48739
49081
  unlinkSync(guardPath);
48740
49082
  }
@@ -48756,7 +49098,7 @@ function withSessionWriteLocks(sessionIds, options, action) {
48756
49098
  const owned = [];
48757
49099
  const assertOwned = () => {
48758
49100
  for (const lock of owned) {
48759
- const current = lstatSync7(lock.path, { throwIfNoEntry: false });
49101
+ const current = lstatSync8(lock.path, { throwIfNoEntry: false });
48760
49102
  if (!current?.isFile() || current.dev !== lock.dev || current.ino !== lock.ino) {
48761
49103
  throw new SkillSelectionError("SESSION_WRITE_LOCK_CHANGED", "A session write lock changed during the operation; no replacement is permitted.");
48762
49104
  }
@@ -48800,12 +49142,12 @@ function withSessionWriteLocks(sessionIds, options, action) {
48800
49142
  for (const lock of owned.reverse()) {
48801
49143
  try {
48802
49144
  for (const path of [lock.path, lock.stagingPath]) {
48803
- const current = lstatSync7(path, { throwIfNoEntry: false });
49145
+ const current = lstatSync8(path, { throwIfNoEntry: false });
48804
49146
  if (current?.isFile() && current.dev === lock.dev && current.ino === lock.ino)
48805
49147
  unlinkSync(path);
48806
49148
  }
48807
49149
  } finally {
48808
- closeSync2(lock.fd);
49150
+ closeSync3(lock.fd);
48809
49151
  }
48810
49152
  }
48811
49153
  }
@@ -48856,21 +49198,21 @@ function writeSkillSession(receipt, expected, options = {}) {
48856
49198
  }
48857
49199
  function syncDirectory(path) {
48858
49200
  assertRegularPath(path);
48859
- const fd = openSync2(path, constants3.O_RDONLY | constants3.O_DIRECTORY | constants3.O_NOFOLLOW);
49201
+ const fd = openSync3(path, constants4.O_RDONLY | constants4.O_DIRECTORY | constants4.O_NOFOLLOW);
48860
49202
  try {
48861
49203
  fsyncSync(fd);
48862
49204
  } finally {
48863
- closeSync2(fd);
49205
+ closeSync3(fd);
48864
49206
  }
48865
49207
  }
48866
49208
  function archiveBytes(path, bytes) {
48867
49209
  assertRegularPath(path, true);
48868
- const fd = openSync2(path, constants3.O_WRONLY | constants3.O_CREAT | constants3.O_EXCL | constants3.O_NOFOLLOW, 384);
49210
+ const fd = openSync3(path, constants4.O_WRONLY | constants4.O_CREAT | constants4.O_EXCL | constants4.O_NOFOLLOW, 384);
48869
49211
  try {
48870
49212
  writeFileSync3(fd, bytes);
48871
49213
  fsyncSync(fd);
48872
49214
  } finally {
48873
- closeSync2(fd);
49215
+ closeSync3(fd);
48874
49216
  }
48875
49217
  }
48876
49218
  function replaceSkillSession(expected, replacement, plan, options = {}, beforeCommit = () => {}) {
@@ -48897,7 +49239,7 @@ function replaceSkillSession(expected, replacement, plan, options = {}, beforeCo
48897
49239
  archiveBytes(receiptPath, Buffer.from(`${JSON.stringify(receipt)}
48898
49240
  `));
48899
49241
  syncDirectory(directory);
48900
- syncDirectory(dirname7(directory));
49242
+ syncDirectory(dirname8(directory));
48901
49243
  syncDirectory(selectionCacheRoot(options));
48902
49244
  if (sha256Hex(readRegularFile(archivePath, MAX_PROFILE_DOCUMENT_BYTES)) !== before2.sha256 || !sameSnapshot(readSkillSessionSnapshot(replacement.sessionId, options), expected)) {
48903
49245
  throw new SkillSelectionError("SESSION_RECEIPT_CHANGED", "The session or its preservation archive changed before replacement; retained evidence must be reviewed.");
@@ -48937,12 +49279,12 @@ import { spawnSync as spawnSync2 } from "child_process";
48937
49279
  import { closeSync as closeSync22, fstatSync as fstatSync22, openSync as openSync22, readFileSync as readFileSync22 } from "fs";
48938
49280
  import { O_NOFOLLOW as O_NOFOLLOW2, O_NONBLOCK as O_NONBLOCK2, O_RDONLY as O_RDONLY2 } from "constants";
48939
49281
  import { hostname as osHostname } from "os";
48940
- import { isAbsolute as isAbsolute7, join as join22 } from "path";
49282
+ import { isAbsolute as isAbsolute8, join as join22 } from "path";
48941
49283
  import { createRequire } from "module";
48942
49284
  import { fileURLToPath as fileURLToPath2 } from "url";
48943
- import { closeSync as closeSync3, fstatSync as fstatSync3, lstatSync as lstatSync8, openSync as openSync3, readFileSync as readFileSync10, realpathSync as realpathSync2, statSync as statSync6 } from "fs";
49285
+ import { closeSync as closeSync4, fstatSync as fstatSync4, lstatSync as lstatSync9, openSync as openSync4, readFileSync as readFileSync10, realpathSync as realpathSync2, statSync as statSync6 } from "fs";
48944
49286
  import { O_NOFOLLOW, O_NONBLOCK, O_RDONLY } from "constants";
48945
- import { basename as basename3, dirname as dirname8, join as join16, relative as relative3, sep as sep3 } from "path";
49287
+ import { basename as basename4, dirname as dirname9, join as join16, relative as relative3, sep as sep3 } from "path";
48946
49288
  import { fileURLToPath, pathToFileURL } from "url";
48947
49289
  function envToken(name) {
48948
49290
  return name.toUpperCase().replace(/-/g, "_");
@@ -49017,15 +49359,15 @@ function o(e2, r2, t2) {
49017
49359
  }
49018
49360
  function entryPoint(directory) {
49019
49361
  const root = realpathSync2(directory);
49020
- const fd = openSync3(join16(root, "package.json"), O_RDONLY | O_NOFOLLOW | O_NONBLOCK);
49362
+ const fd = openSync4(join16(root, "package.json"), O_RDONLY | O_NOFOLLOW | O_NONBLOCK);
49021
49363
  let pkg;
49022
49364
  try {
49023
- const stat = fstatSync3(fd);
49365
+ const stat = fstatSync4(fd);
49024
49366
  if (!stat.isFile() || stat.size > MAX_PACKAGE_BYTES)
49025
49367
  throw new Error("Invalid Secrets package metadata");
49026
49368
  pkg = JSON.parse(readFileSync10(fd, "utf8"));
49027
49369
  } finally {
49028
- closeSync3(fd);
49370
+ closeSync4(fd);
49029
49371
  }
49030
49372
  if (!pkg || typeof pkg !== "object" || !("name" in pkg) || pkg.name !== PACKAGE) {
49031
49373
  throw new Error("Invalid Secrets package identity");
@@ -49045,13 +49387,13 @@ function entryPoint(directory) {
49045
49387
  return pathToFileURL(file).href;
49046
49388
  }
49047
49389
  function resolveInstalledSecrets(parentUrl) {
49048
- let directory = dirname8(fileURLToPath(parentUrl));
49390
+ let directory = dirname9(fileURLToPath(parentUrl));
49049
49391
  for (;; ) {
49050
- if (basename3(directory) !== "node_modules") {
49392
+ if (basename4(directory) !== "node_modules") {
49051
49393
  const candidate = join16(directory, "node_modules", PACKAGE);
49052
49394
  let absent = false;
49053
49395
  try {
49054
- lstatSync8(candidate);
49396
+ lstatSync9(candidate);
49055
49397
  } catch (error) {
49056
49398
  if (error.code !== "ENOENT")
49057
49399
  throw error;
@@ -49060,7 +49402,7 @@ function resolveInstalledSecrets(parentUrl) {
49060
49402
  if (!absent)
49061
49403
  return entryPoint(candidate);
49062
49404
  }
49063
- const parent = dirname8(directory);
49405
+ const parent = dirname9(directory);
49064
49406
  if (parent === directory)
49065
49407
  throw new Error("Secrets SDK is not installed for this consumer");
49066
49408
  directory = parent;
@@ -49072,7 +49414,7 @@ function homeDir(env3) {
49072
49414
  }
49073
49415
  function absoluteOverride(env3, key) {
49074
49416
  const value = env3[key]?.trim();
49075
- return value && isAbsolute7(value) ? value : null;
49417
+ return value && isAbsolute8(value) ? value : null;
49076
49418
  }
49077
49419
  function hasnaHomeDir(env3) {
49078
49420
  const override = absoluteOverride(env3, HASNA_HOME_ENV_KEY);
@@ -49768,7 +50110,7 @@ function selectedCliSkillsCredentialProfile() {
49768
50110
  var cliCredentialProfile;
49769
50111
 
49770
50112
  // src/lib/instance-credentials.ts
49771
- import { closeSync as closeSync4, constants as constants4, fstatSync as fstatSync4, lstatSync as lstatSync9, openSync as openSync4, readSync as readSync3 } from "fs";
50113
+ import { closeSync as closeSync5, constants as constants5, fstatSync as fstatSync5, lstatSync as lstatSync10, openSync as openSync5, readSync as readSync4 } from "fs";
49772
50114
  function selectedSkillsProfile(env3, explicit) {
49773
50115
  const selected = explicit ?? selectedCliSkillsCredentialProfile() ?? env3.HASNA_PROFILE;
49774
50116
  if (selected === undefined)
@@ -49783,7 +50125,7 @@ function skillsProfileCredentialFiles(env3, explicit) {
49783
50125
  }
49784
50126
  function fileIdentity(file) {
49785
50127
  try {
49786
- return lstatSync9(file);
50128
+ return lstatSync10(file);
49787
50129
  } catch (error) {
49788
50130
  if (["ENOENT", "ENOTDIR"].includes(error.code ?? ""))
49789
50131
  return null;
@@ -49804,14 +50146,14 @@ function captureSkillsCredentialFiles(files) {
49804
50146
  function readMetadataText(file) {
49805
50147
  let fd;
49806
50148
  try {
49807
- fd = openSync4(file, constants4.O_RDONLY | constants4.O_NOFOLLOW | constants4.O_NONBLOCK);
50149
+ fd = openSync5(file, constants5.O_RDONLY | constants5.O_NOFOLLOW | constants5.O_NONBLOCK);
49808
50150
  } catch (error) {
49809
50151
  if (["ENOENT", "ENOTDIR"].includes(error.code ?? ""))
49810
50152
  return null;
49811
50153
  throw new Error("Cannot safely read Skills instance configuration");
49812
50154
  }
49813
50155
  try {
49814
- const before2 = fstatSync4(fd);
50156
+ const before2 = fstatSync5(fd);
49815
50157
  const uid = process.getuid?.() ?? process.geteuid?.();
49816
50158
  if (!before2.isFile() || ![256, 384].includes(before2.mode & 4095) || uid !== undefined && before2.uid !== uid || before2.size > 64 * 1024) {
49817
50159
  throw new Error("Unsafe Skills instance configuration; expected a bounded owner-only regular file");
@@ -49819,17 +50161,17 @@ function readMetadataText(file) {
49819
50161
  const bytes = Buffer.alloc(64 * 1024 + 1);
49820
50162
  let length = 0;
49821
50163
  while (length < bytes.length) {
49822
- const count = readSync3(fd, bytes, length, bytes.length - length, null);
50164
+ const count = readSync4(fd, bytes, length, bytes.length - length, null);
49823
50165
  if (!count)
49824
50166
  break;
49825
50167
  length += count;
49826
50168
  }
49827
- if (length > 64 * 1024 || !unchanged(before2, fstatSync4(fd)) || !unchanged(before2, fileIdentity(file))) {
50169
+ if (length > 64 * 1024 || !unchanged(before2, fstatSync5(fd)) || !unchanged(before2, fileIdentity(file))) {
49828
50170
  throw new Error("Skills instance configuration changed while reading");
49829
50171
  }
49830
50172
  return bytes.subarray(0, length).toString("utf8");
49831
50173
  } finally {
49832
- closeSync4(fd);
50174
+ closeSync5(fd);
49833
50175
  }
49834
50176
  }
49835
50177
  function readSkillsInstanceMetadata(file) {
@@ -50336,7 +50678,7 @@ __export(exports_remote_files, {
50336
50678
  decodeRemoteFiles: () => decodeRemoteFiles,
50337
50679
  MAX_REMOTE_FILE_BYTES: () => MAX_REMOTE_FILE_BYTES
50338
50680
  });
50339
- import { createHash as createHash7 } from "crypto";
50681
+ import { createHash as createHash9 } from "crypto";
50340
50682
  function describeRemoteFiles(files) {
50341
50683
  if (files.length > 10)
50342
50684
  throw new Error("At most 10 input files are supported");
@@ -50353,7 +50695,7 @@ function describeRemoteFiles(files) {
50353
50695
  });
50354
50696
  }
50355
50697
  function sha256(bytes) {
50356
- return createHash7("sha256").update(bytes).digest("hex");
50698
+ return createHash9("sha256").update(bytes).digest("hex");
50357
50699
  }
50358
50700
  async function readBoundedResponse(response, maximum) {
50359
50701
  if (!Number.isSafeInteger(maximum) || maximum < 0 || maximum > MAX_REMOTE_FILE_BYTES)
@@ -50608,11 +50950,11 @@ function capturePreparationProcess(child, platform2 = process.platform, signalGr
50608
50950
  }
50609
50951
 
50610
50952
  // src/lib/dependency-preparation.ts
50611
- import { constants as constants5, closeSync as closeSync5, fstatSync as fstatSync5, lstatSync as lstatSync10, mkdirSync as mkdirSync4, openSync as openSync5, readFileSync as readFileSync11, readdirSync as readdirSync5, rmdirSync, unlinkSync as unlinkSync2, ftruncateSync, writeSync } from "fs";
50953
+ import { constants as constants6, closeSync as closeSync6, fstatSync as fstatSync6, lstatSync as lstatSync11, mkdirSync as mkdirSync4, openSync as openSync6, readFileSync as readFileSync11, readdirSync as readdirSync5, rmdirSync, unlinkSync as unlinkSync2, ftruncateSync, writeSync } from "fs";
50612
50954
  import { join as join17 } from "path";
50613
50955
  function hasDependencyPreparationMarker(skillPath) {
50614
50956
  try {
50615
- lstatSync10(join17(skillPath, DEPENDENCY_PREPARATION_MARKER));
50957
+ lstatSync11(join17(skillPath, DEPENDENCY_PREPARATION_MARKER));
50616
50958
  return true;
50617
50959
  } catch (error) {
50618
50960
  return error.code !== "ENOENT";
@@ -50631,21 +50973,21 @@ function claimPreparation(skillPath) {
50631
50973
  }
50632
50974
  let fd;
50633
50975
  try {
50634
- if (!lstatSync10(marker).isDirectory() || lstatSync10(marker).isSymbolicLink())
50976
+ if (!lstatSync11(marker).isDirectory() || lstatSync11(marker).isSymbolicLink())
50635
50977
  return;
50636
50978
  if (!created) {
50637
50979
  if (readdirSync5(marker).some((name) => name !== "state.json"))
50638
50980
  return;
50639
- if (!lstatSync10(state).isFile() || lstatSync10(state).isSymbolicLink() || lstatSync10(state).size > 1024)
50981
+ if (!lstatSync11(state).isFile() || lstatSync11(state).isSymbolicLink() || lstatSync11(state).size > 1024)
50640
50982
  return;
50641
50983
  const previous = JSON.parse(readFileSync11(state, "utf8"));
50642
50984
  if (previous.version !== 1 || previous.status !== "failed" || Object.keys(previous).length !== 2)
50643
50985
  return;
50644
50986
  }
50645
50987
  mkdirSync4(active, { mode: 448 });
50646
- fd = openSync5(state, constants5.O_RDWR | constants5.O_NOFOLLOW | (created ? constants5.O_CREAT | constants5.O_EXCL : 0), 384);
50647
- if (!fstatSync5(fd).isFile()) {
50648
- closeSync5(fd);
50988
+ fd = openSync6(state, constants6.O_RDWR | constants6.O_NOFOLLOW | (created ? constants6.O_CREAT | constants6.O_EXCL : 0), 384);
50989
+ if (!fstatSync6(fd).isFile()) {
50990
+ closeSync6(fd);
50649
50991
  return;
50650
50992
  }
50651
50993
  const descriptor = fd;
@@ -50657,7 +50999,7 @@ function claimPreparation(skillPath) {
50657
50999
  record2("pending");
50658
51000
  return { abandon() {
50659
51001
  try {
50660
- closeSync5(descriptor);
51002
+ closeSync6(descriptor);
50661
51003
  } catch {}
50662
51004
  }, finish(success) {
50663
51005
  try {
@@ -50665,7 +51007,7 @@ function claimPreparation(skillPath) {
50665
51007
  unlinkSync2(state);
50666
51008
  else
50667
51009
  record2("failed");
50668
- closeSync5(descriptor);
51010
+ closeSync6(descriptor);
50669
51011
  fd = undefined;
50670
51012
  rmdirSync(active);
50671
51013
  if (success)
@@ -50673,7 +51015,7 @@ function claimPreparation(skillPath) {
50673
51015
  return true;
50674
51016
  } catch {
50675
51017
  try {
50676
- closeSync5(descriptor);
51018
+ closeSync6(descriptor);
50677
51019
  } catch {}
50678
51020
  return false;
50679
51021
  }
@@ -50681,7 +51023,7 @@ function claimPreparation(skillPath) {
50681
51023
  } catch {
50682
51024
  if (fd !== undefined)
50683
51025
  try {
50684
- closeSync5(fd);
51026
+ closeSync6(fd);
50685
51027
  } catch {}
50686
51028
  return;
50687
51029
  }
@@ -50774,32 +51116,32 @@ var init_dependency_preparation = () => {};
50774
51116
  // src/lib/codex-corpus-write.ts
50775
51117
  import { KernelLock } from "@hasna/contracts/kernel-lock";
50776
51118
  import { execFileSync } from "child_process";
50777
- import { createHash as createHash8 } from "crypto";
50778
- import { accessSync, constants as constants6, lstatSync as lstatSync11, readFileSync as readFileSync12, realpathSync as realpathSync3, statSync as statSync7 } from "fs";
50779
- import { basename as basename4, delimiter, dirname as dirname9, isAbsolute as isAbsolute8, join as join18, relative as relative4, resolve as resolve9, sep as sep4 } from "path";
51119
+ import { createHash as createHash10 } from "crypto";
51120
+ import { accessSync, constants as constants7, lstatSync as lstatSync12, readFileSync as readFileSync12, realpathSync as realpathSync3, statSync as statSync7 } from "fs";
51121
+ import { basename as basename5, delimiter, dirname as dirname10, isAbsolute as isAbsolute9, join as join18, relative as relative4, resolve as resolve10, sep as sep4 } from "path";
50780
51122
  function physicalTarget(path) {
50781
51123
  const suffix = [];
50782
- for (let cursor = path;; cursor = dirname9(cursor)) {
51124
+ for (let cursor = path;; cursor = dirname10(cursor)) {
50783
51125
  try {
50784
51126
  return join18(realpathSync3(cursor), ...suffix);
50785
51127
  } catch (error) {
50786
- if (error.code !== "ENOENT" || cursor === dirname9(cursor))
51128
+ if (error.code !== "ENOENT" || cursor === dirname10(cursor))
50787
51129
  throw error;
50788
51130
  try {
50789
- if (lstatSync11(cursor).isSymbolicLink())
51131
+ if (lstatSync12(cursor).isSymbolicLink())
50790
51132
  fail2();
50791
51133
  } catch (statError) {
50792
51134
  if (statError.code !== "ENOENT")
50793
51135
  throw statError;
50794
51136
  }
50795
- suffix.unshift(basename4(cursor));
51137
+ suffix.unshift(basename5(cursor));
50796
51138
  }
50797
51139
  }
50798
51140
  }
50799
51141
  function codexCorpusRootForPath(path) {
50800
- const target = resolve9(path), physical = physicalTarget(target);
51142
+ const target = resolve10(path), physical = physicalTarget(target);
50801
51143
  const selected = process.env.CODEX_HOME;
50802
- const selectedRoots = selected && isAbsolute8(selected) ? [resolve9(selected), physicalTarget(resolve9(selected))] : [];
51144
+ const selectedRoots = selected && isAbsolute9(selected) ? [resolve10(selected), physicalTarget(resolve10(selected))] : [];
50803
51145
  const classify = (candidate) => {
50804
51146
  const checked = (root2) => {
50805
51147
  if (candidate === root2 || candidate === join18(root2, `${KEY}.flock-v1`))
@@ -50808,10 +51150,10 @@ function codexCorpusRootForPath(path) {
50808
51150
  };
50809
51151
  for (const root2 of selectedRoots) {
50810
51152
  const distance = relative4(root2, candidate);
50811
- if (distance === "" || !distance.startsWith(`..${sep4}`) && distance !== ".." && !isAbsolute8(distance))
51153
+ if (distance === "" || !distance.startsWith(`..${sep4}`) && distance !== ".." && !isAbsolute9(distance))
50812
51154
  return checked(root2);
50813
51155
  }
50814
- for (let cursor = candidate;cursor !== dirname9(cursor); cursor = dirname9(cursor)) {
51156
+ for (let cursor = candidate;cursor !== dirname10(cursor); cursor = dirname10(cursor)) {
50815
51157
  if (cursor.endsWith(`${sep4}.codex`))
50816
51158
  return checked(cursor);
50817
51159
  }
@@ -50823,7 +51165,7 @@ function codexCorpusRootForPath(path) {
50823
51165
  return root;
50824
51166
  }
50825
51167
  function identity4(path) {
50826
- const stat = lstatSync11(path, { bigint: true });
51168
+ const stat = lstatSync12(path, { bigint: true });
50827
51169
  return { device: String(stat.dev), inode: String(stat.ino) };
50828
51170
  }
50829
51171
  function sameIdentity(value, expected) {
@@ -50837,12 +51179,12 @@ function executable(options) {
50837
51179
  if (typeof command !== "string" || !command || command.includes("\x00") || options.codexSha256 !== undefined && !/^[a-f0-9]{64}$/.test(options.codexSha256))
50838
51180
  return fail2();
50839
51181
  let found;
50840
- if (isAbsolute8(command))
51182
+ if (isAbsolute9(command))
50841
51183
  found = command;
50842
51184
  else if (!command.includes(sep4)) {
50843
- found = (process.env.PATH ?? "").split(delimiter).filter(isAbsolute8).map((dir) => join18(dir, command)).find((candidate) => {
51185
+ found = (process.env.PATH ?? "").split(delimiter).filter(isAbsolute9).map((dir) => join18(dir, command)).find((candidate) => {
50844
51186
  try {
50845
- accessSync(candidate, constants6.X_OK);
51187
+ accessSync(candidate, constants7.X_OK);
50846
51188
  return true;
50847
51189
  } catch {
50848
51190
  return false;
@@ -50854,7 +51196,7 @@ function executable(options) {
50854
51196
  const path = realpathSync3(found), initial2 = statSync7(path, { bigint: true });
50855
51197
  if (!initial2.isFile() || (initial2.mode & 0o022n) !== 0n || (initial2.mode & 0o111n) === 0n || initial2.uid !== BigInt(process.getuid()) && initial2.uid !== 0n)
50856
51198
  return fail2();
50857
- const hash2 = () => createHash8("sha256").update(readFileSync12(path)).digest("hex");
51199
+ const hash2 = () => createHash10("sha256").update(readFileSync12(path)).digest("hex");
50858
51200
  const digest = hash2();
50859
51201
  if (options.codexSha256 && digest !== options.codexSha256)
50860
51202
  return fail2();
@@ -50878,7 +51220,7 @@ function acquireCodexCorpusWrite(roots, options) {
50878
51220
  }
50879
51221
  };
50880
51222
  try {
50881
- if (roots.some((root) => typeof root !== "string" || !isAbsolute8(root) || root.includes("\x00")))
51223
+ if (roots.some((root) => typeof root !== "string" || !isAbsolute9(root) || root.includes("\x00")))
50882
51224
  fail2();
50883
51225
  const inputs = [...new Set(roots)].map((input) => ({ input, root: realpathSync3(input) })).sort((a, b) => a.root.localeCompare(b.root));
50884
51226
  for (const { input, root } of inputs) {
@@ -51011,293 +51353,6 @@ function isCodexLocalStdioMcpServer(name, server) {
51011
51353
  }
51012
51354
  }
51013
51355
 
51014
- // src/lib/claude-settings-witness.ts
51015
- import { createHash as createHash9 } from "crypto";
51016
- import { closeSync as closeSync6, constants as constants7, fstatSync as fstatSync6, lstatSync as lstatSync12, openSync as openSync6, readSync as readSync4 } from "fs";
51017
- import { basename as basename5, dirname as dirname10, isAbsolute as isAbsolute9, resolve as resolve10 } from "path";
51018
- function need2(value, reason) {
51019
- if (!value)
51020
- throw new Error(`Claude settings witness ${reason}`);
51021
- }
51022
- function absolutePath(value) {
51023
- need2(typeof value === "string" && value.length > 0 && value.length <= CLAUDE_SETTINGS_WITNESS_LIMITS.pathCharacters && !/[\x00-\x1f\x7f]/.test(value) && isAbsolute9(value) && resolve10(value) === value, "requires a normalized absolute path");
51024
- }
51025
- function parents(path) {
51026
- const result2 = [];
51027
- for (let at2 = dirname10(path);; at2 = dirname10(at2)) {
51028
- const stat = lstatSync12(at2, { bigint: true });
51029
- need2(stat.isDirectory() && !stat.isSymbolicLink(), "path traverses a symlink or non-directory");
51030
- result2.push([at2, stat]);
51031
- if (at2 === dirname10(at2))
51032
- return result2;
51033
- }
51034
- }
51035
- function readNativeSettingsWitnessFile(path, budget, filename = "settings.json") {
51036
- absolutePath(path);
51037
- need2(basename5(path) === filename, `requires ${filename}`);
51038
- need2(Number.isSafeInteger(budget.remaining) && budget.remaining >= 0, "has an invalid byte budget");
51039
- const ancestors = parents(path), initial2 = lstatSync12(path, { bigint: true });
51040
- need2(initial2.isFile() && !initial2.isSymbolicLink() && initial2.size <= BigInt(CLAUDE_SETTINGS_WITNESS_LIMITS.bytes), "is not a bounded regular file");
51041
- need2(initial2.size <= BigInt(budget.remaining), "exceeds its aggregate byte limit");
51042
- const fd = openSync6(path, constants7.O_RDONLY | constants7.O_NOFOLLOW | constants7.O_NONBLOCK);
51043
- try {
51044
- const opened = fstatSync6(fd, { bigint: true });
51045
- need2(opened.isFile() && sameFile(initial2, opened), "changed during open");
51046
- const bytes = Buffer.alloc(Number(opened.size) + 1);
51047
- let length = 0;
51048
- while (length < bytes.length) {
51049
- const count = readSync4(fd, bytes, length, bytes.length - length, null);
51050
- if (!count)
51051
- break;
51052
- length += count;
51053
- }
51054
- const after2 = fstatSync6(fd, { bigint: true }), current = lstatSync12(path, { bigint: true });
51055
- need2(current.isFile() && sameFile(opened, after2) && sameFile(after2, current) && BigInt(length) === opened.size, "changed during read");
51056
- for (const [ancestor, before2] of ancestors) {
51057
- const now3 = lstatSync12(ancestor, { bigint: true });
51058
- need2(now3.isDirectory() && before2.dev === now3.dev && before2.ino === now3.ino && before2.mode === now3.mode, "parent changed during read");
51059
- }
51060
- budget.remaining -= length;
51061
- try {
51062
- return new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(bytes.subarray(0, length));
51063
- } catch {
51064
- throw new Error("Claude settings witness is not strict UTF-8");
51065
- }
51066
- } finally {
51067
- closeSync6(fd);
51068
- }
51069
- }
51070
- function parse3(text2) {
51071
- let at2 = 0, nodes = 0;
51072
- const numberPattern = /-?(?:0|[1-9][0-9]*)(?:\.[0-9]+)?(?:[eE][+-]?[0-9]+)?/y;
51073
- const space = () => {
51074
- while (at2 < text2.length && /[\x20\t\r\n]/.test(text2[at2]))
51075
- at2++;
51076
- };
51077
- function string() {
51078
- need2(text2[at2] === '"', "contains invalid JSON");
51079
- const start = at2++;
51080
- while (at2 < text2.length) {
51081
- const character = text2[at2++];
51082
- if (character === '"') {
51083
- let value2;
51084
- try {
51085
- value2 = JSON.parse(text2.slice(start, at2));
51086
- } catch {
51087
- throw new Error("Claude settings witness contains invalid JSON string");
51088
- }
51089
- need2(value2.length <= CLAUDE_SETTINGS_WITNESS_LIMITS.stringCharacters, "exceeds its string limit");
51090
- return value2;
51091
- }
51092
- if (character === "\\")
51093
- at2++;
51094
- }
51095
- throw new Error("Claude settings witness contains an unterminated JSON string");
51096
- }
51097
- function value(depth) {
51098
- need2(depth <= CLAUDE_SETTINGS_WITNESS_LIMITS.depth && ++nodes <= CLAUDE_SETTINGS_WITNESS_LIMITS.nodes, "exceeds its nesting or node limit");
51099
- space();
51100
- const character = text2[at2];
51101
- if (character === '"')
51102
- return { kind: "string", value: string() };
51103
- if (character === "{" || character === "[") {
51104
- at2++;
51105
- space();
51106
- const object4 = character === "{", end = object4 ? "}" : "]", entries = [], items = [], keys2 = new Set;
51107
- if (text2[at2] !== end)
51108
- while (true) {
51109
- if (object4) {
51110
- space();
51111
- const key = string();
51112
- need2(!keys2.has(key), "contains a duplicate JSON key");
51113
- keys2.add(key);
51114
- space();
51115
- need2(text2[at2++] === ":", "contains invalid JSON");
51116
- entries.push([key, value(depth + 1)]);
51117
- } else
51118
- items.push(value(depth + 1));
51119
- space();
51120
- if (text2[at2] === end)
51121
- break;
51122
- need2(text2[at2++] === ",", "contains invalid JSON");
51123
- }
51124
- at2++;
51125
- return object4 ? { kind: "object", entries } : { kind: "array", items };
51126
- }
51127
- for (const literal of ["true", "false", "null"])
51128
- if (text2.startsWith(literal, at2)) {
51129
- at2 += literal.length;
51130
- return { kind: "literal", value: literal };
51131
- }
51132
- numberPattern.lastIndex = at2;
51133
- const number = numberPattern.exec(text2);
51134
- need2(number, "contains invalid JSON");
51135
- at2 += number[0].length;
51136
- return { kind: "number", value: number[0] };
51137
- }
51138
- const root = value(0);
51139
- space();
51140
- need2(at2 === text2.length && root.kind === "object", "requires a JSON object without trailing content");
51141
- need2(root.entries.length <= CLAUDE_SETTINGS_WITNESS_LIMITS.rows, "exceeds its settings field limit");
51142
- return root;
51143
- }
51144
- function canonical2(value) {
51145
- if (value.kind === "object")
51146
- return { kind: "object", entries: value.entries.map(([key, child]) => [key, canonical2(child)]).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0) };
51147
- if (value.kind === "array")
51148
- return { kind: "array", items: value.items.map(canonical2) };
51149
- return value;
51150
- }
51151
- function inferencePreference(key, child, version) {
51152
- if (key === "skipDangerousModePermissionPrompt") {
51153
- need2(child.kind === "literal" && (child.value === "true" || child.value === "false"), "contains an invalid dialog acknowledgment");
51154
- return false;
51155
- }
51156
- if (key === "effortLevel") {
51157
- need2(child.kind === "string" && PERSISTED_EFFORT_LEVELS.has(child.value), "contains an invalid persisted effort level");
51158
- return true;
51159
- }
51160
- if (key !== "modelSettings")
51161
- return false;
51162
- need2(child.kind === "object", "requires an object of model preferences");
51163
- child.entries = child.entries.filter(([model, preferences]) => {
51164
- if (version === 2 && !BUILTIN_MODEL_SELECTIONS.has(model) || preferences.kind !== "object" || preferences.entries.length !== 1 || preferences.entries[0][0] !== "effortLevel")
51165
- return true;
51166
- const effort = preferences.entries[0][1];
51167
- need2(effort.kind === "string" && PERSISTED_EFFORT_LEVELS.has(effort.value), "contains an invalid persisted model effort level");
51168
- return false;
51169
- });
51170
- return child.entries.length === 0;
51171
- }
51172
- function settingsDigest(text2, version = 1) {
51173
- const value = parse3(text2);
51174
- value.entries = value.entries.filter(([key, child]) => {
51175
- if (version !== 1 && inferencePreference(key, child, version))
51176
- return false;
51177
- if (key === "model") {
51178
- need2(child.kind === "string", "contains an invalid model selection");
51179
- return !BUILTIN_MODEL_SELECTIONS.has(child.value);
51180
- }
51181
- if (BOOLEAN_PREFERENCES.has(key)) {
51182
- need2(child.kind === "literal" && (child.value === "true" || child.value === "false"), "contains an invalid display preference");
51183
- return false;
51184
- }
51185
- if (Object.hasOwn(ENUM_PREFERENCES, key)) {
51186
- need2(child.kind === "string" && ENUM_PREFERENCES[key].includes(child.value), "contains an invalid display preference");
51187
- return false;
51188
- }
51189
- return true;
51190
- });
51191
- return createHash9("sha256").update(`hasna.skills.claude-settings.v${version}\x00`).update(JSON.stringify(canonical2(value))).digest("hex");
51192
- }
51193
- function hashClaudeSettingsReplacement(text2, budget) {
51194
- need2(typeof text2 === "string", "requires settings text");
51195
- const bytes = Buffer.byteLength(text2);
51196
- need2(bytes <= CLAUDE_SETTINGS_WITNESS_LIMITS.bytes && Number.isSafeInteger(budget.remaining) && budget.remaining >= bytes, "exceeds its byte limit");
51197
- budget.remaining -= bytes;
51198
- return settingsDigest(text2);
51199
- }
51200
- function captureClaudeSettings(path, budget = { remaining: 256 * 1024 * 1024 }) {
51201
- return { path, hashMode: "claude-settings-v1", sha256: settingsDigest(readNativeSettingsWitnessFile(path, budget)) };
51202
- }
51203
- function captureClaudeSettingsV2(path, budget = { remaining: 256 * 1024 * 1024 }) {
51204
- return { path, hashMode: "claude-settings-v2", sha256: settingsDigest(readNativeSettingsWitnessFile(path, budget), 2) };
51205
- }
51206
- function hashClaudeSettingsReplacementV2(text2, budget) {
51207
- need2(typeof text2 === "string", "requires settings text");
51208
- const bytes = Buffer.byteLength(text2);
51209
- need2(bytes <= CLAUDE_SETTINGS_WITNESS_LIMITS.bytes && Number.isSafeInteger(budget.remaining) && budget.remaining >= bytes, "exceeds its byte limit");
51210
- budget.remaining -= bytes;
51211
- return settingsDigest(text2, 2);
51212
- }
51213
- function captureClaudeSettingsV3(path, budget = { remaining: 256 * 1024 * 1024 }) {
51214
- return { path, hashMode: "claude-settings-v3", sha256: settingsDigest(readNativeSettingsWitnessFile(path, budget), 3) };
51215
- }
51216
- function hashClaudeSettingsReplacementV3(text2, budget) {
51217
- need2(typeof text2 === "string", "requires settings text");
51218
- const bytes = Buffer.byteLength(text2);
51219
- need2(bytes <= CLAUDE_SETTINGS_WITNESS_LIMITS.bytes && Number.isSafeInteger(budget.remaining) && budget.remaining >= bytes, "exceeds its byte limit");
51220
- budget.remaining -= bytes;
51221
- return settingsDigest(text2, 3);
51222
- }
51223
- function upgradeClaudeSettingsWitness(previous, reviewedSettingsPath) {
51224
- need2(previous && Object.keys(previous).every((key) => ["path", "hashMode", "sha256"].includes(key)) && (previous.hashMode === undefined || previous.hashMode === "bytes" || previous.hashMode === "claude-settings-v1" || previous.hashMode === "claude-settings-v2") && typeof previous.sha256 === "string" && /^[a-f0-9]{64}$/.test(previous.sha256), "requires an exact legacy settings witness");
51225
- const budget = { remaining: 2 * CLAUDE_SETTINGS_WITNESS_LIMITS.bytes };
51226
- const before2 = readNativeSettingsWitnessFile(reviewedSettingsPath, budget), current = readNativeSettingsWitnessFile(previous.path, budget);
51227
- const beforeDigest = previous.hashMode === undefined || previous.hashMode === "bytes" ? createHash9("sha256").update(before2).digest("hex") : settingsDigest(before2, previous.hashMode === "claude-settings-v1" ? 1 : 2);
51228
- need2(beforeDigest === previous.sha256, "reviewed preimage does not match the legacy witness");
51229
- const sha2562 = settingsDigest(current, 3);
51230
- need2(settingsDigest(before2, 3) === sha2562, "non-preference settings changed; explicit discovery review required");
51231
- return { path: previous.path, hashMode: "claude-settings-v3", sha256: sha2562 };
51232
- }
51233
- function hashNativeJsonControls(text2, excludedMetadata) {
51234
- need2(Buffer.byteLength(text2) <= CLAUDE_SETTINGS_WITNESS_LIMITS.bytes, "exceeds its byte limit");
51235
- const value = parse3(text2);
51236
- value.entries = value.entries.filter(([key, child]) => {
51237
- if (key !== excludedMetadata)
51238
- return true;
51239
- need2(child.kind === "string" && child.value.length <= 128, "has invalid version metadata");
51240
- return false;
51241
- });
51242
- return createHash9("sha256").update("hasna.skills.native-json-controls.v1\x00").update(JSON.stringify(canonical2(value))).digest("hex");
51243
- }
51244
- var CLAUDE_SETTINGS_WITNESS_LIMITS, sameFile = (a, b) => a.dev === b.dev && a.ino === b.ino && a.mode === b.mode && a.uid === b.uid && a.gid === b.gid && a.nlink === b.nlink && a.size === b.size && a.mtimeNs === b.mtimeNs && a.ctimeNs === b.ctimeNs, BOOLEAN_PREFERENCES, ENUM_PREFERENCES, BUILTIN_MODEL_SELECTIONS, PERSISTED_EFFORT_LEVELS;
51245
- var init_claude_settings_witness = __esm(() => {
51246
- CLAUDE_SETTINGS_WITNESS_LIMITS = Object.freeze({ bytes: 1024 * 1024, rows: 1024, depth: 32, nodes: 65536, stringCharacters: 16384, pathCharacters: 4096 });
51247
- BOOLEAN_PREFERENCES = new Set([
51248
- "autoScrollEnabled",
51249
- "axScreenReader",
51250
- "emojiCompletionEnabled",
51251
- "prefersReducedMotion",
51252
- "showTurnDuration",
51253
- "spinnerTipsEnabled",
51254
- "syntaxHighlightingDisabled",
51255
- "terminalProgressBarEnabled",
51256
- "terminalTitleFromRename",
51257
- "verbose",
51258
- "wheelScrollAccelerationEnabled"
51259
- ]);
51260
- ENUM_PREFERENCES = Object.freeze({
51261
- editorMode: ["normal", "vim"],
51262
- tui: ["default", "fullscreen"],
51263
- viewMode: ["default", "verbose", "focus"]
51264
- });
51265
- BUILTIN_MODEL_SELECTIONS = new Set([
51266
- "default",
51267
- "best",
51268
- "fable",
51269
- "fable[1m]",
51270
- "sonnet",
51271
- "sonnet[1m]",
51272
- "opus",
51273
- "opus[1m]",
51274
- "haiku",
51275
- "opusplan",
51276
- "claude-fable-5-1",
51277
- "claude-fable-5",
51278
- "claude-fable-5[1m]",
51279
- "claude-opus-5",
51280
- "claude-sonnet-5",
51281
- "claude-haiku-4-5-20251001",
51282
- "claude-opus-4-6",
51283
- "claude-sonnet-4-5",
51284
- "claude-sonnet-4-5-20250929",
51285
- "claude-opus-4-8",
51286
- "claude-opus-4-8[1m]",
51287
- "claude-opus-4-7",
51288
- "claude-sonnet-4-6",
51289
- "claude-opus-4-5-20251101",
51290
- "claude-opus-4-5",
51291
- "claude-haiku-4-5",
51292
- "claude-fable-5-1[1m]",
51293
- "claude-opus-5[1m]",
51294
- "claude-opus-4-7[1m]",
51295
- "claude-opus-4-6[1m]",
51296
- "claude-sonnet-4-6[1m]"
51297
- ]);
51298
- PERSISTED_EFFORT_LEVELS = new Set(["low", "medium", "high", "xhigh"]);
51299
- });
51300
-
51301
51356
  // src/lib/codex-native-compatibility.ts
51302
51357
  function supportsCodexNativeCapability(version, capability) {
51303
51358
  return typeof version === "string" && Object.hasOwn(MEASURED_CODEX_CAPABILITIES, version) && MEASURED_CODEX_CAPABILITIES[version].includes(capability);
@@ -51629,7 +51684,7 @@ var init_codex_native_skill_catalog = __esm(() => {
51629
51684
  });
51630
51685
 
51631
51686
  // src/lib/codex-plugin-skill-controls.ts
51632
- import { createHash as createHash10 } from "crypto";
51687
+ import { createHash as createHash11 } from "crypto";
51633
51688
  import { basename as basename6, dirname as dirname11, join as join20, relative as relative5, resolve as resolve11, sep as sep5 } from "path";
51634
51689
  import { lstatSync as lstatSync13, readdirSync as readdirSync6, readlinkSync as readlinkSync3, realpathSync as realpathSync6 } from "fs";
51635
51690
  function refuse2() {
@@ -51989,7 +52044,7 @@ function reviewCodexPluginControls(catalog, documents, cache3, cwd2, read2, rule
51989
52044
  const exactPathDeny = Array.isArray(rules) && rules.some((rule) => rule?.path === document3 && rule?.enabled === false);
51990
52045
  const nativeSkill = { name: parsed.name, path: document3, pluginId: expectedPluginId, enabled: true };
51991
52046
  const denial = denials.find((item) => item.path === document3);
51992
- const explicitDeny = denial !== undefined && remotePluginId !== undefined && catalog.version === "codex-cli 0.160.0" && denial.name === parsed.name && denial.sha256 === createHash10("sha256").update(read2(document3)).digest("hex") && Array.isArray(rules) && !rules.some((rule) => (rule?.path === document3 || typeof rule?.name === "string" && rule.name.trim() === parsed.name) && rule.enabled !== false) && Array.isArray(plannedRules) && plannedRules.some((rule) => rule?.path === document3 && rule.enabled === false);
52047
+ const explicitDeny = denial !== undefined && remotePluginId !== undefined && catalog.version === "codex-cli 0.160.0" && denial.name === parsed.name && denial.sha256 === createHash11("sha256").update(read2(document3)).digest("hex") && Array.isArray(rules) && !rules.some((rule) => (rule?.path === document3 || typeof rule?.name === "string" && rule.name.trim() === parsed.name) && rule.enabled !== false) && Array.isArray(plannedRules) && plannedRules.some((rule) => rule?.path === document3 && rule.enabled === false);
51993
52048
  if (denial && !explicitDeny)
51994
52049
  refuse2();
51995
52050
  if (explicitDeny)
@@ -52082,7 +52137,7 @@ var init_codex_plugin_skill_controls = __esm(() => {
52082
52137
  });
52083
52138
 
52084
52139
  // src/lib/codex-native-skill-policy.ts
52085
- import { createHash as createHash11, randomUUID as randomUUID5 } from "crypto";
52140
+ import { createHash as createHash12, randomUUID as randomUUID5 } from "crypto";
52086
52141
  import { closeSync as closeSync7, constants as constants8, fstatSync as fstatSync7, fsyncSync as fsyncSync2, lstatSync as lstatSync14, mkdirSync as mkdirSync5, openSync as openSync7, readFileSync as readFileSync13, readSync as readSync5, readlinkSync as readlinkSync4, realpathSync as realpathSync7, renameSync as renameSync2, unlinkSync as unlinkSync3, writeFileSync as writeFileSync4 } from "fs";
52087
52142
  import { dirname as dirname12, isAbsolute as isAbsolute12, join as join21, resolve as resolve12 } from "path";
52088
52143
  import { isDeepStrictEqual as isDeepStrictEqual3 } from "util";
@@ -52094,7 +52149,7 @@ function codexNativeHookEnvelopeFromInput(input, event, inputBytes, inheritedFd)
52094
52149
  policy: input.native_skill_policy,
52095
52150
  sessionId: input.session_id,
52096
52151
  ...Object.hasOwn(input, "turn_id") ? { turnId: input.turn_id } : {},
52097
- hookInputSha256: createHash11("sha256").update(inputBytes).digest("hex"),
52152
+ hookInputSha256: createHash12("sha256").update(inputBytes).digest("hex"),
52098
52153
  ...inheritedFd !== undefined ? { inheritedFd: /^(0|[1-9]\d{0,9})$/.test(inheritedFd) ? Number(inheritedFd) : inheritedFd } : {}
52099
52154
  };
52100
52155
  }
@@ -52204,7 +52259,7 @@ function verifyCodexNativeBridgeDocument(path, expectedContent, expectedSha256)
52204
52259
  if (realpathSync7.native(path) !== path)
52205
52260
  refuse3("NATIVE_SKILL_POLICY_BRIDGE_UNVERIFIED", "the bridge document real path differs from its lexical path");
52206
52261
  const bytes = readBounded(path, MAX_BRIDGE_DOCUMENT_BYTES, "the bridge document");
52207
- const sha2562 = createHash11("sha256").update(bytes).digest("hex");
52262
+ const sha2562 = createHash12("sha256").update(bytes).digest("hex");
52208
52263
  if (!bytes.equals(Buffer.from(expectedContent, "utf8")) || sha2562 !== expectedSha256)
52209
52264
  refuse3("NATIVE_SKILL_POLICY_BRIDGE_UNVERIFIED", "the bridge document bytes differ from the managed bridge");
52210
52265
  return { path, sha256: sha2562 };
@@ -52679,7 +52734,7 @@ var init_codex_native_skill_policy = __esm(() => {
52679
52734
  });
52680
52735
 
52681
52736
  // src/lib/codex-settings-witness-v1.ts
52682
- import { createHash as createHash12 } from "crypto";
52737
+ import { createHash as createHash13 } from "crypto";
52683
52738
  function need3(value) {
52684
52739
  if (!value)
52685
52740
  throw new Error("Invalid Codex settings witness");
@@ -52723,8 +52778,8 @@ function numericTokens(text2) {
52723
52778
  }
52724
52779
  return result2;
52725
52780
  }
52726
- function canonical3(value, depth = 0, budget = { remaining: 65536 }) {
52727
- need3(depth <= 32 && --budget.remaining >= 0);
52781
+ function canonical3(value, depth = 0, budget2 = { remaining: 65536 }) {
52782
+ need3(depth <= 32 && --budget2.remaining >= 0);
52728
52783
  if (value === null)
52729
52784
  return ["null"];
52730
52785
  if (typeof value === "string")
@@ -52740,13 +52795,13 @@ function canonical3(value, depth = 0, budget = { remaining: 65536 }) {
52740
52795
  return ["date", value.toISOString()];
52741
52796
  }
52742
52797
  if (Array.isArray(value))
52743
- return ["array", value.map((child) => canonical3(child, depth + 1, budget))];
52798
+ return ["array", value.map((child) => canonical3(child, depth + 1, budget2))];
52744
52799
  need3(value && typeof value === "object");
52745
- return ["object", Object.entries(value).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0).map(([key, child]) => [key, canonical3(child, depth + 1, budget)])];
52800
+ return ["object", Object.entries(value).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0).map(([key, child]) => [key, canonical3(child, depth + 1, budget2)])];
52746
52801
  }
52747
- function hashCodexSettingsReplacement(text2, budget = { remaining: 256 * 1024 * 1024 }) {
52748
- need3(Buffer.byteLength(text2) <= 1024 * 1024 && budget.remaining >= Buffer.byteLength(text2));
52749
- budget.remaining -= Buffer.byteLength(text2);
52802
+ function hashCodexSettingsReplacement(text2, budget2 = { remaining: 256 * 1024 * 1024 }) {
52803
+ need3(Buffer.byteLength(text2) <= 1024 * 1024 && budget2.remaining >= Buffer.byteLength(text2));
52804
+ budget2.remaining -= Buffer.byteLength(text2);
52750
52805
  let config;
52751
52806
  try {
52752
52807
  config = Bun.TOML.parse(text2);
@@ -52765,11 +52820,11 @@ function hashCodexSettingsReplacement(text2, budget = { remaining: 256 * 1024 *
52765
52820
  }
52766
52821
  return sha(`hasna.skills.codex-settings.v1\x00${JSON.stringify([canonical3(config), numericTokens(text2)])}`);
52767
52822
  }
52768
- function captureCodexSettings(path, budget = { remaining: 256 * 1024 * 1024 }) {
52769
- const text2 = readNativeSettingsWitnessFile(path, budget, "config.toml");
52823
+ function captureCodexSettings(path, budget2 = { remaining: 256 * 1024 * 1024 }) {
52824
+ const text2 = readNativeSettingsWitnessFile(path, budget2, "config.toml");
52770
52825
  return { path, hashMode: "codex-settings-v1", sha256: hashCodexSettingsReplacement(text2) };
52771
52826
  }
52772
- var sha = (text2) => createHash12("sha256").update(text2).digest("hex"), EFFORT, VERBOSITY;
52827
+ var sha = (text2) => createHash13("sha256").update(text2).digest("hex"), EFFORT, VERBOSITY;
52773
52828
  var init_codex_settings_witness_v1 = __esm(() => {
52774
52829
  init_claude_settings_witness();
52775
52830
  EFFORT = new Set(["none", "minimal", "low", "medium", "high", "xhigh"]);
@@ -52842,7 +52897,7 @@ function projectRegularCodexMcp(config, source) {
52842
52897
  var init_codex_mcp_discovery_projection = () => {};
52843
52898
 
52844
52899
  // src/lib/codex-settings-witness.ts
52845
- import { createHash as createHash13 } from "crypto";
52900
+ import { createHash as createHash14 } from "crypto";
52846
52901
  import { isDeepStrictEqual as isDeepStrictEqual5 } from "util";
52847
52902
  function need4(value) {
52848
52903
  if (!value)
@@ -52893,8 +52948,8 @@ function numericTokens2(text2) {
52893
52948
  }
52894
52949
  return result2.sort();
52895
52950
  }
52896
- function canonical4(value, depth = 0, budget = { remaining: 65536 }) {
52897
- need4(depth <= 32 && --budget.remaining >= 0);
52951
+ function canonical4(value, depth = 0, budget2 = { remaining: 65536 }) {
52952
+ need4(depth <= 32 && --budget2.remaining >= 0);
52898
52953
  if (value === null)
52899
52954
  return ["null"];
52900
52955
  if (typeof value === "string")
@@ -52910,9 +52965,9 @@ function canonical4(value, depth = 0, budget = { remaining: 65536 }) {
52910
52965
  return ["date", value.toISOString()];
52911
52966
  }
52912
52967
  if (Array.isArray(value))
52913
- return ["array", value.map((child) => canonical4(child, depth + 1, budget))];
52968
+ return ["array", value.map((child) => canonical4(child, depth + 1, budget2))];
52914
52969
  need4(isRecord3(value));
52915
- return ["object", Object.entries(value).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0).map(([key, child]) => [key, canonical4(child, depth + 1, budget)])];
52970
+ return ["object", Object.entries(value).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0).map(([key, child]) => [key, canonical4(child, depth + 1, budget2)])];
52916
52971
  }
52917
52972
  function normalize3(config, version = 2) {
52918
52973
  if (isRecord3(config.hooks)) {
@@ -53088,40 +53143,40 @@ function settingsDigest2(text2, version = 2) {
53088
53143
  normalize3(projected.config, version);
53089
53144
  return sha2(`hasna.skills.codex-settings.v${version}\x00${JSON.stringify([canonical4(projected.config), numericTokens2(projected.numericSource)])}`);
53090
53145
  }
53091
- function hashCodexSettingsReplacementV2(text2, budget = { remaining: 256 * 1024 * 1024 }) {
53092
- need4(Buffer.byteLength(text2) <= 1024 * 1024 && budget.remaining >= Buffer.byteLength(text2));
53093
- budget.remaining -= Buffer.byteLength(text2);
53146
+ function hashCodexSettingsReplacementV2(text2, budget2 = { remaining: 256 * 1024 * 1024 }) {
53147
+ need4(Buffer.byteLength(text2) <= 1024 * 1024 && budget2.remaining >= Buffer.byteLength(text2));
53148
+ budget2.remaining -= Buffer.byteLength(text2);
53094
53149
  return settingsDigest2(text2);
53095
53150
  }
53096
- function captureCodexSettingsV2(path, budget = { remaining: 256 * 1024 * 1024 }) {
53097
- const text2 = readNativeSettingsWitnessFile(path, budget, "config.toml");
53151
+ function captureCodexSettingsV2(path, budget2 = { remaining: 256 * 1024 * 1024 }) {
53152
+ const text2 = readNativeSettingsWitnessFile(path, budget2, "config.toml");
53098
53153
  return { path, hashMode: "codex-settings-v2", sha256: settingsDigest2(text2) };
53099
53154
  }
53100
- function readCodexSettingsPreimage(path, budget = { remaining: 2 * 1024 * 1024 }) {
53101
- return readNativeSettingsWitnessFile(path, budget, "config.toml");
53155
+ function readCodexSettingsPreimage(path, budget2 = { remaining: 2 * 1024 * 1024 }) {
53156
+ return readNativeSettingsWitnessFile(path, budget2, "config.toml");
53102
53157
  }
53103
53158
  function upgradeCodexSettingsWitness(previous, reviewedSettingsPath) {
53104
53159
  need4(previous && Object.keys(previous).every((key) => ["path", "hashMode", "sha256"].includes(key)) && (previous.hashMode === undefined || previous.hashMode === "bytes" || previous.hashMode === "codex-settings-v1") && /^[a-f0-9]{64}$/.test(previous.sha256));
53105
- const budget = { remaining: 2 * 1024 * 1024 };
53106
- const before2 = readNativeSettingsWitnessFile(reviewedSettingsPath, budget, "config.toml"), current = readNativeSettingsWitnessFile(previous.path, budget, "config.toml");
53160
+ const budget2 = { remaining: 2 * 1024 * 1024 };
53161
+ const before2 = readNativeSettingsWitnessFile(reviewedSettingsPath, budget2, "config.toml"), current = readNativeSettingsWitnessFile(previous.path, budget2, "config.toml");
53107
53162
  need4((previous.hashMode === "codex-settings-v1" ? hashCodexSettingsReplacement(before2) : sha2(before2)) === previous.sha256);
53108
53163
  const sha2562 = settingsDigest2(current);
53109
53164
  if (settingsDigest2(before2) !== sha2562)
53110
53165
  throw new Error("Codex non-preference settings changed; explicit discovery review required");
53111
53166
  return { path: previous.path, hashMode: "codex-settings-v2", sha256: sha2562 };
53112
53167
  }
53113
- function hashCodexSettingsReplacementV3(text2, budget = { remaining: 256 * 1024 * 1024 }) {
53114
- need4(Buffer.byteLength(text2) <= 1024 * 1024 && budget.remaining >= Buffer.byteLength(text2));
53115
- budget.remaining -= Buffer.byteLength(text2);
53168
+ function hashCodexSettingsReplacementV3(text2, budget2 = { remaining: 256 * 1024 * 1024 }) {
53169
+ need4(Buffer.byteLength(text2) <= 1024 * 1024 && budget2.remaining >= Buffer.byteLength(text2));
53170
+ budget2.remaining -= Buffer.byteLength(text2);
53116
53171
  return settingsDigest2(text2, 3);
53117
53172
  }
53118
- function captureCodexSettingsV3(path, budget = { remaining: 256 * 1024 * 1024 }) {
53119
- return { path, hashMode: "codex-settings-v3", sha256: settingsDigest2(readNativeSettingsWitnessFile(path, budget, "config.toml"), 3) };
53173
+ function captureCodexSettingsV3(path, budget2 = { remaining: 256 * 1024 * 1024 }) {
53174
+ return { path, hashMode: "codex-settings-v3", sha256: settingsDigest2(readNativeSettingsWitnessFile(path, budget2, "config.toml"), 3) };
53120
53175
  }
53121
53176
  function upgradeCodexSettingsWitnessV3(previous, reviewedSettingsPath) {
53122
53177
  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));
53123
- const budget = { remaining: 2 * 1024 * 1024 };
53124
- const before2 = readNativeSettingsWitnessFile(reviewedSettingsPath, budget, "config.toml"), current = readNativeSettingsWitnessFile(previous.path, budget, "config.toml");
53178
+ const budget2 = { remaining: 2 * 1024 * 1024 };
53179
+ const before2 = readNativeSettingsWitnessFile(reviewedSettingsPath, budget2, "config.toml"), current = readNativeSettingsWitnessFile(previous.path, budget2, "config.toml");
53125
53180
  const original = previous.hashMode === "codex-settings-v2" ? settingsDigest2(before2) : previous.hashMode === "codex-settings-v1" ? hashCodexSettingsReplacement(before2) : sha2(before2);
53126
53181
  need4(original === previous.sha256);
53127
53182
  const sha2562 = settingsDigest2(current, 3);
@@ -53129,18 +53184,18 @@ function upgradeCodexSettingsWitnessV3(previous, reviewedSettingsPath) {
53129
53184
  throw new Error("Codex settings outside the reviewed V3 contract changed; explicit discovery review required");
53130
53185
  return { path: previous.path, hashMode: "codex-settings-v3", sha256: sha2562 };
53131
53186
  }
53132
- function hashCodexSettingsReplacementV4(text2, budget = { remaining: 256 * 1024 * 1024 }) {
53133
- need4(Buffer.byteLength(text2) <= 1024 * 1024 && budget.remaining >= Buffer.byteLength(text2));
53134
- budget.remaining -= Buffer.byteLength(text2);
53187
+ function hashCodexSettingsReplacementV4(text2, budget2 = { remaining: 256 * 1024 * 1024 }) {
53188
+ need4(Buffer.byteLength(text2) <= 1024 * 1024 && budget2.remaining >= Buffer.byteLength(text2));
53189
+ budget2.remaining -= Buffer.byteLength(text2);
53135
53190
  return settingsDigest2(text2, 4);
53136
53191
  }
53137
- function captureCodexSettingsV4(path, budget = { remaining: 256 * 1024 * 1024 }) {
53138
- return { path, hashMode: "codex-settings-v4", sha256: settingsDigest2(readNativeSettingsWitnessFile(path, budget, "config.toml"), 4) };
53192
+ function captureCodexSettingsV4(path, budget2 = { remaining: 256 * 1024 * 1024 }) {
53193
+ return { path, hashMode: "codex-settings-v4", sha256: settingsDigest2(readNativeSettingsWitnessFile(path, budget2, "config.toml"), 4) };
53139
53194
  }
53140
53195
  function upgradeCodexSettingsWitnessV4(previous, reviewedSettingsPath) {
53141
53196
  need4(previous && Object.keys(previous).every((key) => ["path", "hashMode", "sha256"].includes(key)) && (previous.hashMode === undefined || ["bytes", "codex-settings-v1", "codex-settings-v2", "codex-settings-v3"].includes(previous.hashMode)) && /^[a-f0-9]{64}$/.test(previous.sha256));
53142
- const budget = { remaining: 2 * 1024 * 1024 };
53143
- const before2 = readNativeSettingsWitnessFile(reviewedSettingsPath, budget, "config.toml"), current = readNativeSettingsWitnessFile(previous.path, budget, "config.toml");
53197
+ const budget2 = { remaining: 2 * 1024 * 1024 };
53198
+ const before2 = readNativeSettingsWitnessFile(reviewedSettingsPath, budget2, "config.toml"), current = readNativeSettingsWitnessFile(previous.path, budget2, "config.toml");
53144
53199
  const original = previous.hashMode === "codex-settings-v3" ? settingsDigest2(before2, 3) : previous.hashMode === "codex-settings-v2" ? settingsDigest2(before2, 2) : previous.hashMode === "codex-settings-v1" ? hashCodexSettingsReplacement(before2) : sha2(before2);
53145
53200
  need4(original === previous.sha256);
53146
53201
  const sha2562 = settingsDigest2(current, 4);
@@ -53148,7 +53203,7 @@ function upgradeCodexSettingsWitnessV4(previous, reviewedSettingsPath) {
53148
53203
  throw new Error("Codex settings outside the reviewed V4 contract changed; explicit discovery review required");
53149
53204
  return { path: previous.path, hashMode: "codex-settings-v4", sha256: sha2562 };
53150
53205
  }
53151
- var sha2 = (text2) => createHash13("sha256").update(text2).digest("hex"), EFFORT2, VERBOSITY2, MODEL, CODEX_DISCOVERY_PROJECTION_FIELDS, INFERENCE;
53206
+ var sha2 = (text2) => createHash14("sha256").update(text2).digest("hex"), EFFORT2, VERBOSITY2, MODEL, CODEX_DISCOVERY_PROJECTION_FIELDS, INFERENCE;
53152
53207
  var init_codex_settings_witness = __esm(() => {
53153
53208
  init_codex_settings_witness_v1();
53154
53209
  init_codex_settings_witness_v1();
@@ -53247,7 +53302,7 @@ var init_managed_policy = __esm(() => {
53247
53302
  });
53248
53303
 
53249
53304
  // src/lib/agent-bridge.ts
53250
- import { createHash as createHash14 } from "crypto";
53305
+ import { createHash as createHash15 } from "crypto";
53251
53306
  import { lstatSync as lstatSync16, readFileSync as readFileSync14, readdirSync as readdirSync7 } from "fs";
53252
53307
  import { join as join25 } from "path";
53253
53308
  function isOwnedCliBridge(path, expectedPaths) {
@@ -53281,7 +53336,7 @@ Use the Skills CLI as the skill authority for this station.
53281
53336
  This bridge contains no skill payloads. Do not copy skill content into agent-native skill directories or load other native skill copies. If a Skills command refuses authority, selection, integrity, or native drift, report that refusal and use its repair guidance; do not substitute bundled or stale local content. Explicit local draft authoring remains available.
53282
53337
  `, CLI_BRIDGE_DIGEST, CLI_BRIDGE_FILES;
53283
53338
  var init_agent_bridge = __esm(() => {
53284
- CLI_BRIDGE_DIGEST = createHash14("sha256").update(markdown).digest("hex");
53339
+ CLI_BRIDGE_DIGEST = createHash15("sha256").update(markdown).digest("hex");
53285
53340
  CLI_BRIDGE_FILES = Object.freeze({
53286
53341
  "SKILL.md": markdown,
53287
53342
  ".hasna-skills.json": `${JSON.stringify({ managedBy: "@hasna/skills", kind: "cli-bridge", version: CLI_BRIDGE_VERSION, protocol: "selection-v1", contentSha256: CLI_BRIDGE_DIGEST }, null, 2)}
@@ -53593,31 +53648,44 @@ function sumiConfigPath(home) {
53593
53648
  return join26(sumiConfigDirectory(home), "sumi.json");
53594
53649
  }
53595
53650
  function renderSumiPlugin(command, profile) {
53651
+ return renderSumiPluginVersion(command, profile, false);
53652
+ }
53653
+ function isManagedSumiPlugin(text2, command, profile) {
53654
+ return text2 === renderSumiPlugin(command, profile) || text2 === renderSumiPluginVersion(command, profile, true);
53655
+ }
53656
+ function renderSumiPluginVersion(command, profile, legacy) {
53657
+ const failure = (message) => legacy ? `new Error(${JSON.stringify(message)})` : "refusal()";
53596
53658
  return `// Managed by @hasna/skills. Regenerate with skills hook install --agent sumi.
53597
53659
  import { spawn } from "node:child_process";
53598
53660
  const command = ${JSON.stringify(command)};
53599
53661
  const profile = ${JSON.stringify(profile)};
53600
- function context(input) {
53662
+ ${legacy ? "" : `function refusal() {
53663
+ const error = new Error("Skills verification blocked this request. Review the Sumi Skills hook configuration, then retry.");
53664
+ error.name = "SkillsHookRefusal";
53665
+ error.skillsHookRefusal = { version: 1, code: "SKILLS_HOOK_REFUSED" };
53666
+ return error;
53667
+ }
53668
+ `}function context(input) {
53601
53669
  return new Promise((resolve, reject) => {
53602
53670
  const child = spawn(command, ["hook", "user-prompt", "--agent", "sumi", "--selection-profile", profile], { cwd: input.cwd, stdio: ["pipe", "pipe", "pipe"] });
53603
53671
  const chunks = []; let bytes = 0, failure;
53604
- const timer = setTimeout(() => { failure = new Error("Skills prompt hook timed out"); child.kill("SIGKILL"); }, 15000);
53605
- child.stdout.on("data", chunk => { bytes += chunk.length; if (bytes > 1048576) { failure = new Error("Skills prompt hook output exceeded its limit"); child.kill("SIGKILL"); } else chunks.push(chunk); });
53672
+ const timer = setTimeout(() => { failure = ${failure("Skills prompt hook timed out")}; child.kill("SIGKILL"); }, 15000);
53673
+ child.stdout.on("data", chunk => { bytes += chunk.length; if (bytes > 1048576) { failure = ${failure("Skills prompt hook output exceeded its limit")}; child.kill("SIGKILL"); } else chunks.push(chunk); });
53606
53674
  child.stderr.on("data", () => {});
53607
53675
  child.stdin.on("error", () => {});
53608
- child.on("error", error => { clearTimeout(timer); reject(error); });
53676
+ child.on("error", error => { clearTimeout(timer); reject(${legacy ? "error" : "refusal()"}); });
53609
53677
  child.on("close", code => {
53610
53678
  clearTimeout(timer);
53611
- if (failure || code !== 0) return reject(failure ?? new Error("Skills prompt hook failed"));
53679
+ if (failure || code !== 0) return reject(failure ?? ${failure("Skills prompt hook failed")});
53612
53680
  try {
53613
53681
  const result = JSON.parse(Buffer.concat(chunks).toString("utf8"));
53614
- if (!result || typeof result !== "object" || Array.isArray(result)) throw new Error("Invalid Skills hook response");
53615
- if (result.decision === "block" || result.continue === false) throw new Error("Skills prompt hook refused");
53616
- if (Object.keys(result).length && (!result.hookSpecificOutput || result.hookSpecificOutput.hookEventName !== input.hook_event_name)) throw new Error("Invalid Skills hook response");
53682
+ if (!result || typeof result !== "object" || Array.isArray(result)) throw ${failure("Invalid Skills hook response")};
53683
+ if (result.decision === "block" || result.continue === false) throw ${failure("Skills prompt hook refused")};
53684
+ if (Object.keys(result).length && (!result.hookSpecificOutput || result.hookSpecificOutput.hookEventName !== input.hook_event_name)) throw ${failure("Invalid Skills hook response")};
53617
53685
  const text = result.hookSpecificOutput?.additionalContext ?? "";
53618
- if (typeof text !== "string") throw new Error("Invalid Skills prompt context");
53686
+ if (typeof text !== "string") throw ${failure("Invalid Skills prompt context")};
53619
53687
  resolve(text);
53620
- } catch (error) { reject(error); }
53688
+ } catch (error) { reject(${legacy ? "error" : "refusal()"}); }
53621
53689
  });
53622
53690
  child.stdin.end(JSON.stringify(input));
53623
53691
  });
@@ -53625,13 +53693,14 @@ function context(input) {
53625
53693
  export default {
53626
53694
  id: "local.hasna-skills-cli",
53627
53695
  async setup(ctx) {
53628
- if (!ctx?.session?.hook || !ctx?.session?.get || !ctx?.skill?.transform || !ctx?.tool?.hook) throw new Error("Unsupported Sumi native Skills contract");
53696
+ if (!ctx?.session?.hook || !ctx?.session?.get || !ctx?.skill?.transform || !ctx?.tool?.hook) throw ${failure("Unsupported Sumi native Skills contract")};
53629
53697
  const registrations = [];
53630
53698
  const sessions = new Set();
53631
53699
  async function input(sessionID, prompt, first) {
53632
53700
  // The Promise adapter unwraps single-data endpoint responses.
53633
- const session = await ctx.session.get({ sessionID });
53634
- if (!session || session.id !== sessionID || typeof session.location?.directory !== "string" || (session.parentID !== undefined && typeof session.parentID !== "string") || session.parentID === sessionID) throw new Error("Invalid Sumi session custody");
53701
+ ${legacy ? "const session = await ctx.session.get({ sessionID });" : `let session;
53702
+ try { session = await ctx.session.get({ sessionID }); } catch { throw refusal(); }`}
53703
+ if (!session || session.id !== sessionID || typeof session.location?.directory !== "string" || (session.parentID !== undefined && typeof session.parentID !== "string") || session.parentID === sessionID) throw ${failure("Invalid Sumi session custody")};
53635
53704
  return { hook_event_name: first ? session.parentID ? "SubagentStart" : "SessionStart" : "UserPromptSubmit", cwd: session.location.directory, session_id: sessionID, parent_session_id: session.parentID ?? null, prompt, restore: true };
53636
53705
  }
53637
53706
  registrations.push(await ctx.skill.transform(editor => {
@@ -53640,11 +53709,11 @@ export default {
53640
53709
  // Native config transforms may add skills after this transform. Guard
53641
53710
  // both direct tool calls and prompt attachments at the consumption edge.
53642
53711
  registrations.push(await ctx.tool.hook("execute.before", event => {
53643
- if (event.tool === "skill" && event.input?.id !== "skills-cli") throw new Error("Native Sumi skill payload refused; use Skills CLI");
53712
+ if (event.tool === "skill" && event.input?.id !== "skills-cli") throw ${failure("Native Sumi skill payload refused; use Skills CLI")};
53644
53713
  }));
53645
53714
  registrations.push(await ctx.session.hook("prompt", async event => {
53646
- if (typeof event.prompt?.text !== "string") throw new Error("Invalid Sumi prompt");
53647
- if (event.prompt.skills !== undefined && (!Array.isArray(event.prompt.skills) || event.prompt.skills.some(skill => skill?.id !== "skills-cli"))) throw new Error("Native Sumi skill attachment refused; use Skills CLI");
53715
+ if (typeof event.prompt?.text !== "string") throw ${failure("Invalid Sumi prompt")};
53716
+ if (event.prompt.skills !== undefined && (!Array.isArray(event.prompt.skills) || event.prompt.skills.some(skill => skill?.id !== "skills-cli"))) throw ${failure("Native Sumi skill attachment refused; use Skills CLI")};
53648
53717
  await context(await input(event.sessionID, event.prompt.text, !sessions.has(event.sessionID)));
53649
53718
  sessions.add(event.sessionID);
53650
53719
  }));
@@ -53672,7 +53741,7 @@ var init_agent_sumi = __esm(() => {
53672
53741
 
53673
53742
  // src/lib/codex-hook-trust-files.ts
53674
53743
  import { closeSync as closeSync9, constants as constants10, fstatSync as fstatSync9, fsyncSync as fsyncSync3, lstatSync as lstatSync18, openSync as openSync9, readSync as readSync7, writeFileSync as writeFileSync5 } from "fs";
53675
- import { createHash as createHash15 } from "crypto";
53744
+ import { createHash as createHash16 } from "crypto";
53676
53745
  import { dirname as dirname13 } from "path";
53677
53746
  function need5(value, code) {
53678
53747
  if (!value)
@@ -53707,7 +53776,7 @@ function snapshot(file, privateFile = false, options = {}) {
53707
53776
  }
53708
53777
  need5(length === Number(before2.size) && sameStat(before2, fstatSync9(fd, { bigint: true })) && sameStat(before2, lstatSync18(file, { bigint: true })), "INPUT_CHANGED");
53709
53778
  const content = bytes.subarray(0, length), text2 = new TextDecoder("utf-8", { fatal: true }).decode(content);
53710
- return { file, privateFile, readOnlyPackage, text: text2, bytes: content, stat: before2, sha256: createHash15("sha256").update(content).digest("hex") };
53779
+ return { file, privateFile, readOnlyPackage, text: text2, bytes: content, stat: before2, sha256: createHash16("sha256").update(content).digest("hex") };
53711
53780
  } finally {
53712
53781
  closeSync9(fd);
53713
53782
  }
@@ -53730,7 +53799,7 @@ var sameStat = (a, b) => ["dev", "ino", "uid", "nlink", "mode", "size", "mtimeNs
53730
53799
  var init_codex_hook_trust_files = () => {};
53731
53800
 
53732
53801
  // src/lib/agent-integration.ts
53733
- import { createHash as createHash16, randomUUID as randomUUID6 } from "crypto";
53802
+ import { createHash as createHash17, randomUUID as randomUUID6 } from "crypto";
53734
53803
  import { isDeepStrictEqual as isDeepStrictEqual7 } from "util";
53735
53804
  import { existsSync as existsSync13, lstatSync as lstatSync19, statSync as statSync9, mkdirSync as mkdirSync6, readFileSync as readFileSync15, readdirSync as readdirSync8, opendirSync as opendirSync3, readlinkSync as readlinkSync5, realpathSync as realpathSync9, renameSync as renameSync3, rmdirSync as rmdirSync2, writeFileSync as writeFileSync6, unlinkSync as unlinkSync4, chmodSync, openSync as openSync10, closeSync as closeSync10, fsyncSync as fsyncSync4, fstatSync as fstatSync10, readSync as readSync8, constants as constants11, linkSync as linkSync2 } from "fs";
53736
53805
  import { dirname as dirname14, join as join27, resolve as resolve14, relative as relative6, isAbsolute as isAbsolute13, sep as sep6 } from "path";
@@ -53927,7 +53996,7 @@ function readNativeBytes(path, maximum = 64 * 1024 * 1024) {
53927
53996
  }
53928
53997
  }
53929
53998
  function treeHash(root) {
53930
- const hash2 = createHash16("sha256");
53999
+ const hash2 = createHash17("sha256");
53931
54000
  let bytes = 0, files = 0;
53932
54001
  function visit2(path) {
53933
54002
  const stat = lstatSync19(path);
@@ -54470,7 +54539,7 @@ function planAgentIntegration(options) {
54470
54539
  const pluginPath = join27(sumiConfigDirectory(home), "plugins", "skills-cli.js"), pluginBefore = readOptional(pluginPath);
54471
54540
  const pluginAfter = renderSumiPlugin(command, profileId2);
54472
54541
  const priorCommand = policy.bridge?.commands?.sumi, priorProfile = policy.bridge?.profiles?.sumi ?? policy.profileId;
54473
- if (pluginBefore !== null && pluginBefore !== pluginAfter && !(typeof priorCommand === "string" && typeof priorProfile === "string" && pluginBefore === renderSumiPlugin(priorCommand, priorProfile)))
54542
+ if (pluginBefore !== null && pluginBefore !== pluginAfter && !(typeof priorCommand === "string" && typeof priorProfile === "string" && isManagedSumiPlugin(pluginBefore, priorCommand, priorProfile)))
54474
54543
  throw new Error("Refusing to overwrite a modified Sumi Skills plugin; preserve and review it first");
54475
54544
  if (pluginBefore !== pluginAfter)
54476
54545
  changes.push({ path: pluginPath, before: pluginBefore, after: pluginAfter });
@@ -54743,7 +54812,7 @@ function planAgentSettingsWitnessUpgrade(options) {
54743
54812
  const binding = policy.bridge?.discovery?.[options.agent];
54744
54813
  if (!binding || binding.agent !== options.agent || binding.method !== "reviewed")
54745
54814
  throw new Error("Settings witness upgrade requires an existing reviewed native binding");
54746
- const configPath = canonicalAgentPath(join27(home, options.agent === "claude" ? ".claude/settings.json" : ".codex/config.toml"), aliases);
54815
+ const configPath = canonicalAgentPath(options.agent === "sumi" ? sumiConfigPath(home) : join27(home, options.agent === "claude" ? ".claude/settings.json" : ".codex/config.toml"), aliases);
54747
54816
  const settings = readOptional(configPath);
54748
54817
  if (settings === null || sha3(settings) !== options.expectedSettingsSha256)
54749
54818
  throw new Error("Native settings preimage changed");
@@ -54769,7 +54838,19 @@ function planAgentSettingsWitnessUpgrade(options) {
54769
54838
  replaced.push(source);
54770
54839
  }
54771
54840
  }
54772
- const next = options.agent === "claude" ? upgradeClaudeSettingsWitness(previous, options.reviewedPreimage) : options.targetCodexVersion === 4 ? upgradeCodexSettingsWitnessV4(previous, options.reviewedPreimage) : options.targetCodexVersion === 3 ? upgradeCodexSettingsWitnessV3(previous, options.reviewedPreimage) : upgradeCodexSettingsWitness(previous, options.reviewedPreimage);
54841
+ if (options.agent === "sumi") {
54842
+ const preimage = readSumiSettingsPreimage(options.reviewedPreimage);
54843
+ for (const source of binding.sources) {
54844
+ if (source === previous || source.path !== configPath)
54845
+ continue;
54846
+ if (source.hashMode !== undefined || source.format !== "json" || !isDeepStrictEqual7(source.fields, [...SUMI_DISCOVERY_PROJECTION_FIELDS]) || typeof source.sha256 !== "string")
54847
+ throw new Error("Sumi settings witness upgrade found an unrecognized configuration witness");
54848
+ if (projectNativeDiscoveryFields(preimage, "json", source.fields, configPath) !== source.sha256)
54849
+ throw new Error("Reviewed preimage does not explain the Sumi discovery projection witness");
54850
+ replaced.push(source);
54851
+ }
54852
+ }
54853
+ const next = options.agent === "sumi" ? upgradeSumiSettingsWitness(previous, options.reviewedPreimage) : options.agent === "claude" ? upgradeClaudeSettingsWitness(previous, options.reviewedPreimage) : options.targetCodexVersion === 4 ? upgradeCodexSettingsWitnessV4(previous, options.reviewedPreimage) : options.targetCodexVersion === 3 ? upgradeCodexSettingsWitnessV3(previous, options.reviewedPreimage) : upgradeCodexSettingsWitness(previous, options.reviewedPreimage);
54773
54854
  const rebound = [];
54774
54855
  for (const source of binding.sources) {
54775
54856
  if (!replaced.includes(source)) {
@@ -55130,7 +55211,7 @@ function assertManagedAgentBridgeWithDiscovery(agent, options = {}, provenDiscov
55130
55211
  throw new Error("NATIVE_SKILL_DRIFT: Hermes supervisor binding changed; run skills hook install");
55131
55212
  assertHermesProtection(home, config, command, profile, supervisor);
55132
55213
  } else if (agent === "sumi") {
55133
- if (JSON.stringify(config.permissions?.filter((rule) => rule.action === "skill")) !== JSON.stringify(SUMI_SKILL_PERMISSIONS) || readOptional(join27(sumiConfigDirectory(home), "plugins", "skills-cli.js")) !== renderSumiPlugin(command, profile))
55214
+ if (JSON.stringify(config.permissions?.filter((rule) => rule.action === "skill")) !== JSON.stringify(SUMI_SKILL_PERMISSIONS) || !isManagedSumiPlugin(readOptional(join27(sumiConfigDirectory(home), "plugins", "skills-cli.js")), command, profile))
55134
55215
  throw new Error("NATIVE_SKILL_DRIFT: Sumi bridge protection changed; run skills hook install");
55135
55216
  } else if (agent === "opencode") {
55136
55217
  if (JSON.stringify(config.permission?.skill) !== JSON.stringify({ "*": "deny", [CLI_BRIDGE_NAME]: "allow" }) || readOptional(join27(home, ".config", "opencode", "plugins", "skills-cli.js")) !== renderOpenCodePlugin(command, profile))
@@ -55276,8 +55357,9 @@ function assertNativeExportAllowed(dataDir3 = getDataDirReadOnly()) {
55276
55357
  if (requiresCliSkillLoading(dataDir3))
55277
55358
  throw new Error("NATIVE_SKILL_EXPORT_DISABLED: this station loads skills through the Skills CLI; use skills sync --selection-profile <id>");
55278
55359
  }
55279
- var sha3 = (data) => createHash16("sha256").update(data).digest("hex"), HOOK_EVENTS, ROOTS, SKILLS_LOADING_POLICY = "Skills loading policy: discover skills with `skills list` or `skills search`, and read selected instructions with `skills load <slug>`. Use `skills sync` to refresh the shared profile. The only native skill is the owned skills-cli bridge. Create and edit payload skills in the Skills authoring workspace; do not copy payload instructions into native discovery folders. Context loading does not authorize execution; use `skills run` only when the task calls for running a skill.";
55360
+ var sha3 = (data) => createHash17("sha256").update(data).digest("hex"), HOOK_EVENTS, ROOTS, SKILLS_LOADING_POLICY = "Skills loading policy: discover skills with `skills list` or `skills search`, and read selected instructions with `skills load <slug>`. Use `skills sync` to refresh the shared profile. The only native skill is the owned skills-cli bridge. Create and edit payload skills in the Skills authoring workspace; do not copy payload instructions into native discovery folders. Context loading does not authorize execution; use `skills run` only when the task calls for running a skill.";
55280
55361
  var init_agent_integration = __esm(() => {
55362
+ init_sumi_settings_witness();
55281
55363
  init_codex_corpus_write();
55282
55364
  init_codex_plugin_skill_controls();
55283
55365
  init_codex_native_skill_policy();
@@ -56890,7 +56972,7 @@ var init_selection_resolver = __esm(() => {
56890
56972
  });
56891
56973
 
56892
56974
  // src/lib/plugin-projection.ts
56893
- import { createHash as createHash17 } from "crypto";
56975
+ import { createHash as createHash18 } from "crypto";
56894
56976
  import { posix } from "path";
56895
56977
  function pluginRefusal(message) {
56896
56978
  throw new SkillSelectionError("PLUGIN_ADMISSION_REFUSED", message);
@@ -57083,7 +57165,7 @@ function buildPluginProjection(entries) {
57083
57165
  files.sort((a, b) => a.path < b.path ? -1 : a.path > b.path ? 1 : 0);
57084
57166
  return { manifest, payloads: manifest.payloads, files, witnesses: pluginFileWitnesses(files), originalTreeDigest, projectionTreeDigest: pluginTreeDigest(files), removed: removed.length ? pluginFileWitnesses(removed) : [] };
57085
57167
  }
57086
- var PLUGIN_PROJECTION_MANIFEST = "plugin-projection.json", PLUGIN_PROJECTION_LIMITS, pluginHash = (bytes) => createHash17("sha256").update(bytes).digest("hex"), MANIFEST_FIELDS;
57168
+ var PLUGIN_PROJECTION_MANIFEST = "plugin-projection.json", PLUGIN_PROJECTION_LIMITS, pluginHash = (bytes) => createHash18("sha256").update(bytes).digest("hex"), MANIFEST_FIELDS;
57087
57169
  var init_plugin_projection = __esm(() => {
57088
57170
  init_selection_cache();
57089
57171
  PLUGIN_PROJECTION_LIMITS = Object.freeze({ files: 1024, bytes: 64 * 1024 * 1024, fileBytes: 16 * 1024 * 1024, metadataBytes: 512 * 1024, registrations: 64, history: 128 });
@@ -57091,7 +57173,7 @@ var init_plugin_projection = __esm(() => {
57091
57173
  });
57092
57174
 
57093
57175
  // src/lib/plugin-projection-store.ts
57094
- import { createHash as createHash18, randomUUID as randomUUID7 } from "crypto";
57176
+ import { createHash as createHash19, randomUUID as randomUUID7 } from "crypto";
57095
57177
  import { constants as constants12, closeSync as closeSync11, fchmodSync, fstatSync as fstatSync11, fsyncSync as fsyncSync5, linkSync as linkSync3, lstatSync as lstatSync21, mkdirSync as mkdirSync10, openSync as openSync11, opendirSync as opendirSync4, readSync as readSync9, renameSync as renameSync6, rmdirSync as rmdirSync3, rmSync as rmSync4, unlinkSync as unlinkSync5, writeSync as writeSync2 } from "fs";
57096
57178
  import { dirname as dirname16, isAbsolute as isAbsolute14, join as join33, parse as parse5, resolve as resolve15 } from "path";
57097
57179
  function stat(path) {
@@ -57429,7 +57511,7 @@ function pluginExecutableDigest(path) {
57429
57511
  const opened = fstatSync11(fd, { bigint: true });
57430
57512
  same3(before2, opened);
57431
57513
  fileShape(opened, maximum, "executable");
57432
- const hash2 = createHash18("sha256"), buffer = new Uint8Array(64 * 1024);
57514
+ const hash2 = createHash19("sha256"), buffer = new Uint8Array(64 * 1024);
57433
57515
  let remaining = Number(opened.size);
57434
57516
  while (remaining > 0) {
57435
57517
  const count = readSync9(fd, buffer, 0, Math.min(buffer.byteLength, remaining), null);
@@ -58012,7 +58094,7 @@ var init_plugin_discovery = __esm(() => {
58012
58094
  });
58013
58095
 
58014
58096
  // src/lib/claude-marketplace-registry.ts
58015
- import { createHash as createHash19 } from "crypto";
58097
+ import { createHash as createHash20 } from "crypto";
58016
58098
  import { closeSync as closeSync13, constants as constants14, fstatSync as fstatSync13, lstatSync as lstatSync23, openSync as openSync13, readSync as readSync11 } from "fs";
58017
58099
  import { basename as basename9, dirname as dirname18, isAbsolute as isAbsolute17, resolve as resolve18 } from "path";
58018
58100
  function need6(value, reason) {
@@ -58032,13 +58114,13 @@ function parents2(path) {
58032
58114
  return result2;
58033
58115
  }
58034
58116
  }
58035
- function readRegistry2(path, budget) {
58117
+ function readRegistry2(path, budget2) {
58036
58118
  absolutePath3(path);
58037
58119
  need6(basename9(path) === "known_marketplaces.json", "requires known_marketplaces.json");
58038
- need6(Number.isSafeInteger(budget.remaining) && budget.remaining >= 0, "has an invalid byte budget");
58120
+ need6(Number.isSafeInteger(budget2.remaining) && budget2.remaining >= 0, "has an invalid byte budget");
58039
58121
  const ancestors2 = parents2(path), initial2 = lstatSync23(path, { bigint: true });
58040
58122
  need6(initial2.isFile() && !initial2.isSymbolicLink() && initial2.size <= BigInt(CLAUDE_MARKETPLACE_REGISTRY_LIMITS.bytes), "is not a bounded regular file");
58041
- need6(initial2.size <= BigInt(budget.remaining), "exceeds its aggregate byte limit");
58123
+ need6(initial2.size <= BigInt(budget2.remaining), "exceeds its aggregate byte limit");
58042
58124
  const fd = openSync13(path, constants14.O_RDONLY | constants14.O_NOFOLLOW | constants14.O_NONBLOCK);
58043
58125
  try {
58044
58126
  const opened = fstatSync13(fd, { bigint: true });
@@ -58057,7 +58139,7 @@ function readRegistry2(path, budget) {
58057
58139
  const now3 = lstatSync23(ancestor, { bigint: true });
58058
58140
  need6(now3.isDirectory() && before2.dev === now3.dev && before2.ino === now3.ino && before2.mode === now3.mode, "parent changed during read");
58059
58141
  }
58060
- budget.remaining -= length;
58142
+ budget2.remaining -= length;
58061
58143
  try {
58062
58144
  return new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(bytes.subarray(0, length));
58063
58145
  } catch {
@@ -58174,18 +58256,18 @@ function normalizeRow(row, version = 1) {
58174
58256
  need6(Number.isFinite(millis) && new Date(millis).toISOString() === updated, "contains an invalid recognized update timestamp");
58175
58257
  row.entries = row.entries.map(([key, value]) => [key, key === "lastUpdated" ? { kind: "validated-update-time" } : value]);
58176
58258
  }
58177
- function captureClaudeMarketplaceRegistry(path, budget = { remaining: 256 * 1024 * 1024 }) {
58178
- const value = parse6(readRegistry2(path, budget));
58259
+ function captureClaudeMarketplaceRegistry(path, budget2 = { remaining: 256 * 1024 * 1024 }) {
58260
+ const value = parse6(readRegistry2(path, budget2));
58179
58261
  for (const [, row] of value.entries)
58180
58262
  normalizeRow(row);
58181
- const sha2562 = createHash19("sha256").update("hasna.skills.claude-marketplace-registry.v1\x00").update(JSON.stringify(value)).digest("hex");
58263
+ const sha2562 = createHash20("sha256").update("hasna.skills.claude-marketplace-registry.v1\x00").update(JSON.stringify(value)).digest("hex");
58182
58264
  return { path, hashMode: "claude-marketplace-registry", sha256: sha2562 };
58183
58265
  }
58184
- function captureClaudeMarketplaceRegistryV2(path, budget = { remaining: 256 * 1024 * 1024 }) {
58185
- const value = parse6(readRegistry2(path, budget));
58266
+ function captureClaudeMarketplaceRegistryV2(path, budget2 = { remaining: 256 * 1024 * 1024 }) {
58267
+ const value = parse6(readRegistry2(path, budget2));
58186
58268
  for (const [, row] of value.entries)
58187
58269
  normalizeRow(row, 2);
58188
- const sha2562 = createHash19("sha256").update("hasna.skills.claude-marketplace-registry.v2\x00").update(JSON.stringify(value)).digest("hex");
58270
+ const sha2562 = createHash20("sha256").update("hasna.skills.claude-marketplace-registry.v2\x00").update(JSON.stringify(value)).digest("hex");
58189
58271
  return { path, hashMode: "claude-marketplace-registry-v2", sha256: sha2562 };
58190
58272
  }
58191
58273
  var CLAUDE_MARKETPLACE_REGISTRY_LIMITS, sameFile2 = (a, b) => a.dev === b.dev && a.ino === b.ino && a.mode === b.mode && a.uid === b.uid && a.gid === b.gid && a.nlink === b.nlink && a.size === b.size && a.mtimeNs === b.mtimeNs && a.ctimeNs === b.ctimeNs, field = (object6, key) => object6.entries.find(([name]) => name === key)?.[1];
@@ -58411,7 +58493,7 @@ var init_codex_hook_additions_review = __esm(() => {
58411
58493
  });
58412
58494
 
58413
58495
  // src/lib/codex-hook-discovery-recovery.ts
58414
- import { createHash as createHash20 } from "crypto";
58496
+ import { createHash as createHash21 } from "crypto";
58415
58497
  import { isDeepStrictEqual as isDeepStrictEqual10 } from "util";
58416
58498
  function createCodexHookDiscoveryRecovery(binding, before2, current, hooks, additions) {
58417
58499
  const journalHooks = hooks.map(({ key, currentHash }) => ({ key, currentHash }));
@@ -58461,7 +58543,7 @@ function verifiesCodexHookDiscoverySource(binding, source, currentDigest, witnes
58461
58543
  need5(source.sha256 === witness.beforeSha256 && currentDigest === witness.currentSha256, "RECONCILE_DISCOVERY_RECOVERY_CHANGED");
58462
58544
  return true;
58463
58545
  }
58464
- var sha4 = (text3) => createHash20("sha256").update(text3).digest("hex"), fields, structure2 = (text3) => JSON.parse(JSON.stringify(Bun.TOML.parse(text3))), proofs2;
58546
+ var sha4 = (text3) => createHash21("sha256").update(text3).digest("hex"), fields, structure2 = (text3) => JSON.parse(JSON.stringify(Bun.TOML.parse(text3))), proofs2;
58465
58547
  var init_codex_hook_discovery_recovery = __esm(() => {
58466
58548
  init_codex_hook_trust_files();
58467
58549
  init_codex_hook_trust_layout();
@@ -58472,7 +58554,7 @@ var init_codex_hook_discovery_recovery = __esm(() => {
58472
58554
  });
58473
58555
 
58474
58556
  // src/lib/agent-discovery.ts
58475
- import { createHash as createHash21 } from "crypto";
58557
+ import { createHash as createHash22 } from "crypto";
58476
58558
  import { lstatSync as lstatSync24, readFileSync as readFileSync20, readdirSync as readdirSync11, realpathSync as realpathSync10 } from "fs";
58477
58559
  import { basename as basename10, dirname as dirname19, isAbsolute as isAbsolute19, join as join36, resolve as resolve19, sep as sep7 } from "path";
58478
58560
  import { isDeepStrictEqual as isDeepStrictEqual11 } from "util";
@@ -58513,33 +58595,45 @@ function projectNativeDiscoveryFields(text3, format, fields2, path) {
58513
58595
  throw new Error("Expected native discovery configuration object");
58514
58596
  return digest(JSON.stringify(Object.fromEntries(fields2.map((field2) => [field2, object6[field2] ?? null]))));
58515
58597
  }
58516
- function isSupersededCodexProjection(agent, configPath, source) {
58598
+ function isSupersededSettingsProjection(agent, configPath, source) {
58599
+ if (agent === "sumi")
58600
+ return source.path === configPath && source.format === "json" && isDeepStrictEqual11(source.fields, [...SUMI_DISCOVERY_PROJECTION_FIELDS]);
58517
58601
  return agent === "codex" && source.path === configPath && source.format === "toml" && isDeepStrictEqual11(source.fields, [...CODEX_DISCOVERY_PROJECTION_FIELDS]);
58518
58602
  }
58519
- function supersedesCodexProjection(sources, configPath) {
58520
- return sources.some((source) => source.path === configPath && (source.hashMode === "codex-settings-v2" || (source.hashMode === "codex-settings-v3" || source.hashMode === "codex-settings-v4")));
58603
+ function supersedesSettingsProjection(agent, sources, configPath) {
58604
+ if (agent === "sumi")
58605
+ return sources.some((source) => source.path === configPath && source.hashMode === "sumi-settings-v1");
58606
+ return agent === "codex" && sources.some((source) => source.path === configPath && (source.hashMode === "codex-settings-v2" || (source.hashMode === "codex-settings-v3" || source.hashMode === "codex-settings-v4")));
58521
58607
  }
58522
- function projected(source, changes, budget = discoveryByteBudget()) {
58608
+ function projected(source, changes, budget2 = discoveryByteBudget()) {
58609
+ if (source.hashMode === "sumi-settings-v1") {
58610
+ if (source.format !== undefined || source.fields !== undefined || source.managedPlugins !== undefined || typeof source.sha256 !== "string" || !/^[a-f0-9]{64}$/.test(source.sha256))
58611
+ throw new Error("Sumi settings witnesses require exact typed metadata");
58612
+ const current = captureSumiSettings(source.path, budget2).sha256;
58613
+ if (current !== source.sha256)
58614
+ throw new Error(`Native discovery input changed; run skills hook install with a fresh discovery review: ${source.path}`);
58615
+ return changes?.has(source.path) ? hashSumiSettingsReplacement(changes.get(source.path), budget2) : current;
58616
+ }
58523
58617
  if (source.hashMode === "codex-settings-v1" || source.hashMode === "codex-settings-v2" || (source.hashMode === "codex-settings-v3" || source.hashMode === "codex-settings-v4")) {
58524
58618
  if (source.format !== undefined || source.fields !== undefined || source.managedPlugins !== undefined || typeof source.sha256 !== "string" || !/^[a-f0-9]{64}$/.test(source.sha256))
58525
58619
  throw new Error("Codex settings witnesses require exact typed metadata");
58526
- const current = (source.hashMode === "codex-settings-v4" ? captureCodexSettingsV4 : source.hashMode === "codex-settings-v3" ? captureCodexSettingsV3 : source.hashMode === "codex-settings-v2" ? captureCodexSettingsV2 : captureCodexSettings)(source.path, budget).sha256;
58620
+ const current = (source.hashMode === "codex-settings-v4" ? captureCodexSettingsV4 : source.hashMode === "codex-settings-v3" ? captureCodexSettingsV3 : source.hashMode === "codex-settings-v2" ? captureCodexSettingsV2 : captureCodexSettings)(source.path, budget2).sha256;
58527
58621
  if (current !== source.sha256)
58528
58622
  throw new Error(`Native discovery input changed; run skills hook install with a fresh discovery review: ${source.path}`);
58529
- return changes?.has(source.path) ? (source.hashMode === "codex-settings-v4" ? hashCodexSettingsReplacementV4 : source.hashMode === "codex-settings-v3" ? hashCodexSettingsReplacementV3 : source.hashMode === "codex-settings-v2" ? hashCodexSettingsReplacementV2 : hashCodexSettingsReplacement)(changes.get(source.path), budget) : current;
58623
+ return changes?.has(source.path) ? (source.hashMode === "codex-settings-v4" ? hashCodexSettingsReplacementV4 : source.hashMode === "codex-settings-v3" ? hashCodexSettingsReplacementV3 : source.hashMode === "codex-settings-v2" ? hashCodexSettingsReplacementV2 : hashCodexSettingsReplacement)(changes.get(source.path), budget2) : current;
58530
58624
  }
58531
58625
  if (source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || source.hashMode === "claude-settings-v3") {
58532
58626
  if (source.format !== undefined || source.fields !== undefined || source.managedPlugins !== undefined || typeof source.sha256 !== "string" || !/^[a-f0-9]{64}$/.test(source.sha256))
58533
58627
  throw new Error("Claude settings witnesses require exact typed metadata");
58534
- const current = (source.hashMode === "claude-settings-v3" ? captureClaudeSettingsV3 : source.hashMode === "claude-settings-v2" ? captureClaudeSettingsV2 : captureClaudeSettings)(source.path, budget).sha256;
58628
+ const current = (source.hashMode === "claude-settings-v3" ? captureClaudeSettingsV3 : source.hashMode === "claude-settings-v2" ? captureClaudeSettingsV2 : captureClaudeSettings)(source.path, budget2).sha256;
58535
58629
  if (current !== source.sha256)
58536
58630
  throw new Error(`Native discovery input changed; run skills hook install with a fresh discovery review: ${source.path}`);
58537
- return changes?.has(source.path) ? (source.hashMode === "claude-settings-v3" ? hashClaudeSettingsReplacementV3 : source.hashMode === "claude-settings-v2" ? hashClaudeSettingsReplacementV2 : hashClaudeSettingsReplacement)(changes.get(source.path), budget) : current;
58631
+ return changes?.has(source.path) ? (source.hashMode === "claude-settings-v3" ? hashClaudeSettingsReplacementV3 : source.hashMode === "claude-settings-v2" ? hashClaudeSettingsReplacementV2 : hashClaudeSettingsReplacement)(changes.get(source.path), budget2) : current;
58538
58632
  }
58539
58633
  if (source.hashMode === "claude-marketplace-registry" || source.hashMode === "claude-marketplace-registry-v2") {
58540
58634
  if (source.format !== undefined || source.fields !== undefined || source.managedPlugins !== undefined || typeof source.sha256 !== "string" || !/^[a-f0-9]{64}$/.test(source.sha256) || changes?.has(source.path))
58541
58635
  throw new Error("Claude marketplace witnesses require an exact reviewed registry without synthetic changes");
58542
- const sha2562 = (source.hashMode === "claude-marketplace-registry-v2" ? captureClaudeMarketplaceRegistryV2 : captureClaudeMarketplaceRegistry)(source.path, budget).sha256;
58636
+ const sha2562 = (source.hashMode === "claude-marketplace-registry-v2" ? captureClaudeMarketplaceRegistryV2 : captureClaudeMarketplaceRegistry)(source.path, budget2).sha256;
58543
58637
  if (sha2562 !== source.sha256)
58544
58638
  throw new Error(`Native discovery input changed; run skills hook install with a fresh discovery review: ${source.path}`);
58545
58639
  return sha2562;
@@ -58557,8 +58651,8 @@ function projected(source, changes, budget = discoveryByteBudget()) {
58557
58651
  if (source.format !== undefined || source.fields !== undefined)
58558
58652
  throw new Error("Raw discovery witnesses cannot project configuration fields");
58559
58653
  if (source.hashMode === "path-bytes")
58560
- return hashDiscoveryPathFile(source.path, budget, changes);
58561
- return hashRawDiscoveryFile(source.path, budget, changes);
58654
+ return hashDiscoveryPathFile(source.path, budget2, changes);
58655
+ return hashRawDiscoveryFile(source.path, budget2, changes);
58562
58656
  }
58563
58657
  const text3 = read2(source.path, changes);
58564
58658
  if (text3 === null)
@@ -58706,7 +58800,7 @@ function verifyAgentDiscovery(binding, codexRecovery) {
58706
58800
  verifyDiscoveryDirectories(projected2, installationRoots);
58707
58801
  }
58708
58802
  const absentRoots = [...absentCodexSkillRoots(binding), ...absentRetiredClaudeRoots(binding), ...retiredRoots.filter((root2) => !lstatSync24(root2, { throwIfNoEntry: false }))];
58709
- const budget = discoveryByteBudget();
58803
+ const budget2 = discoveryByteBudget();
58710
58804
  for (const source of binding.sources) {
58711
58805
  assertMarketplaceBinding(binding, source);
58712
58806
  if (source.hashMode === "claude-plugin-registry" && binding.agent !== "claude")
@@ -58723,7 +58817,7 @@ function verifyAgentDiscovery(binding, codexRecovery) {
58723
58817
  safe4(source.path);
58724
58818
  continue;
58725
58819
  }
58726
- const current = projected(source, undefined, budget);
58820
+ const current = projected(source, undefined, budget2);
58727
58821
  if (current !== source.sha256 && !verifiesCodexHookDiscoverySource(binding, source, current, codexRecovery))
58728
58822
  throw new Error(`Native discovery input changed; run skills hook install with a fresh discovery review: ${source.path}`);
58729
58823
  }
@@ -58757,6 +58851,8 @@ function codexInstallationRoots(binding) {
58757
58851
  });
58758
58852
  }
58759
58853
  function assertMarketplaceBinding(binding, source) {
58854
+ if (source.hashMode === "sumi-settings-v1" && (binding.agent !== "sumi" || binding.method !== "reviewed" || basename10(source.path) !== "sumi.json"))
58855
+ throw new Error("Sumi settings witnesses require explicit reviewed Sumi configuration");
58760
58856
  if ((source.hashMode === "codex-settings-v1" || source.hashMode === "codex-settings-v2" || (source.hashMode === "codex-settings-v3" || source.hashMode === "codex-settings-v4")) && (binding.agent !== "codex" || binding.method !== "reviewed" || basename10(source.path) !== "config.toml"))
58761
58857
  throw new Error("Codex settings witnesses require explicit reviewed Codex configuration");
58762
58858
  if ((source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || source.hashMode === "claude-settings-v3") && (binding.agent !== "claude" || binding.method !== "reviewed" || basename10(source.path) !== "settings.json"))
@@ -58765,13 +58861,13 @@ function assertMarketplaceBinding(binding, source) {
58765
58861
  throw new Error("Claude marketplace witnesses require explicit reviewed Claude discovery");
58766
58862
  }
58767
58863
  function rebindAgentDiscovery(binding, changes) {
58768
- const budget = discoveryByteBudget();
58864
+ const budget2 = discoveryByteBudget();
58769
58865
  const installationRoots = codexInstallationRoots(binding), absentRoots = [...absentCodexSkillRoots(binding), ...absentRetiredClaudeRoots(binding), ...retiredCodexRoots(binding).filter((root2) => !lstatSync24(root2, { throwIfNoEntry: false }))];
58770
58866
  const rebound = { ...binding, sources: binding.sources.map((source) => {
58771
58867
  assertMarketplaceBinding(binding, source);
58772
58868
  if (!changes.has(source.path) && (installationRoots.some((root2) => source.path.startsWith(root2 + sep7)) || absentRoots.some((root2) => source.path.startsWith(root2 + sep7)) && source.format === undefined && source.fields === undefined && source.managedPlugins === undefined && [undefined, "bytes"].includes(source.hashMode)))
58773
58869
  return source;
58774
- const sha2562 = projected(source, changes, budget);
58870
+ const sha2562 = projected(source, changes, budget2);
58775
58871
  if (!changes.has(source.path) && sha2562 !== source.sha256)
58776
58872
  throw new Error(`Native discovery input changed; run skills hook install with a fresh discovery review: ${source.path}`);
58777
58873
  return { ...source, sha256: sha2562 };
@@ -58849,7 +58945,7 @@ function resolveAgentDiscovery(options) {
58849
58945
  if (agent === "hermes")
58850
58946
  assertHermesEnvironment(home);
58851
58947
  const configPath = agentDiscoveryConfigPath(home, agent);
58852
- const configText = witness(configPath, agent === "hermes" ? "yaml" : agent === "codex" ? "toml" : "json", agent === "hermes" ? ["skills", "plugins", "hooks"] : agent === "claude" ? ["enabledPlugins", "extraKnownMarketplaces"] : agent === "codex" ? [...CODEX_DISCOVERY_PROJECTION_FIELDS] : agent === "gemini" ? ["skills", "extensions", "security"] : agent === "opencode" ? ["plugin", "skills"] : agent === "sumi" ? ["skills", "plugin", "plugins", "permissions"] : ["version"]);
58948
+ const configText = witness(configPath, agent === "hermes" ? "yaml" : agent === "codex" ? "toml" : "json", agent === "hermes" ? ["skills", "plugins", "hooks"] : agent === "claude" ? ["enabledPlugins", "extraKnownMarketplaces"] : agent === "codex" ? [...CODEX_DISCOVERY_PROJECTION_FIELDS] : agent === "gemini" ? ["skills", "extensions", "security"] : agent === "opencode" ? ["plugin", "skills"] : agent === "sumi" ? [...SUMI_DISCOVERY_PROJECTION_FIELDS] : ["version"]);
58853
58949
  const config = configText === null ? {} : agent === "hermes" ? parseHermesConfig(configText) : parseConfig(configText, configPath, agent === "codex");
58854
58950
  const unresolved = (detail) => {
58855
58951
  throw new Error(`Native discovery is unresolved (${agent}: ${detail}); provide a reviewed --discovery-inputs file`);
@@ -58946,9 +59042,9 @@ function resolveAgentDiscovery(options) {
58946
59042
  verifyAgentDiscovery(retained);
58947
59043
  if (!retained.sources.some((source) => source.path === canonical6(configPath) && source.format === undefined && source.fields === undefined))
58948
59044
  unresolved("retained review is missing the full agent configuration source");
58949
- if (retained.sources.some((source) => (source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || (source.hashMode === "claude-settings-v3" || (source.hashMode === "codex-settings-v1" || source.hashMode === "codex-settings-v2" || (source.hashMode === "codex-settings-v3" || source.hashMode === "codex-settings-v4")))) && source.path !== canonical6(configPath)))
59045
+ if (retained.sources.some((source) => (source.hashMode === "sumi-settings-v1" || source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || (source.hashMode === "claude-settings-v3" || (source.hashMode === "codex-settings-v1" || source.hashMode === "codex-settings-v2" || (source.hashMode === "codex-settings-v3" || source.hashMode === "codex-settings-v4")))) && source.path !== canonical6(configPath)))
58950
59046
  unresolved("retained settings witness names another configuration source");
58951
- const covered = supersedesCodexProjection(retained.sources, canonical6(configPath)) ? sources.filter((source) => !isSupersededCodexProjection(agent, canonical6(configPath), source)) : sources;
59047
+ const covered = supersedesSettingsProjection(agent, retained.sources, canonical6(configPath)) ? sources.filter((source) => !isSupersededSettingsProjection(agent, canonical6(configPath), source)) : sources;
58952
59048
  if (covered.some((source) => !retained.sources.some((saved) => isDeepStrictEqual11(saved, source))) || [...roots].some((root2) => !retained.roots.includes(root2)) || agent === "gemini" && JSON.stringify(retained.builtinNames) !== JSON.stringify(builtinNames))
58953
59049
  unresolved("retained review is missing current runtime discovery coverage");
58954
59050
  return retained;
@@ -58963,11 +59059,11 @@ function resolveAgentDiscovery(options) {
58963
59059
  if (review.sources.some((source) => source.format !== undefined || source.fields !== undefined))
58964
59060
  throw new Error("Explicit discovery reviews require full source-file hashes");
58965
59061
  verifyAgentDiscovery(supplied);
58966
- if (review.sources.some((source) => (source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || (source.hashMode === "claude-settings-v3" || (source.hashMode === "codex-settings-v1" || source.hashMode === "codex-settings-v2" || (source.hashMode === "codex-settings-v3" || source.hashMode === "codex-settings-v4")))) && source.path !== canonical6(configPath)))
58967
- throw new Error("Semantic settings witnesses must name the configured Claude configuration source");
59062
+ if (review.sources.some((source) => (source.hashMode === "sumi-settings-v1" || source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || (source.hashMode === "claude-settings-v3" || (source.hashMode === "codex-settings-v1" || source.hashMode === "codex-settings-v2" || (source.hashMode === "codex-settings-v3" || source.hashMode === "codex-settings-v4")))) && source.path !== canonical6(configPath)))
59063
+ throw new Error("Semantic settings witnesses must name the configured agent configuration source");
58968
59064
  if (!review.sources.some((source) => source.path === canonical6(configPath)))
58969
59065
  throw new Error("Discovery review must include the agent configuration source");
58970
- const reviewedSources = supersedesCodexProjection(review.sources, canonical6(configPath)) ? sources.filter((source) => !isSupersededCodexProjection(agent, canonical6(configPath), source)) : sources;
59066
+ const reviewedSources = supersedesSettingsProjection(agent, review.sources, canonical6(configPath)) ? sources.filter((source) => !isSupersededSettingsProjection(agent, canonical6(configPath), source)) : sources;
58971
59067
  return { ...supplied, roots: [...new Set([...roots, ...supplied.roots])].sort(), sources: [...reviewedSources, ...review.sources], ...agent === "gemini" ? { builtinNames } : {} };
58972
59068
  }
58973
59069
  function plugin(root2) {
@@ -59082,8 +59178,9 @@ function resolveAgentDiscovery(options) {
59082
59178
  }
59083
59179
  return { agent, roots: [...roots].sort(), sources, method: "automatic", ...agent === "gemini" ? { builtinNames } : {}, ...agent === "hermes" ? { directories: captureDiscoveryDirectories([join36(home, ".hermes/plugins"), join36(home, ".hermes/hermes-agent")].map((path) => canonical6(path))) } : {} };
59084
59180
  }
59085
- var digest = (text3) => createHash21("sha256").update(text3).digest("hex");
59181
+ var digest = (text3) => createHash22("sha256").update(text3).digest("hex");
59086
59182
  var init_agent_discovery = __esm(() => {
59183
+ init_sumi_settings_witness();
59087
59184
  init_agent_policy_limits();
59088
59185
  init_agent_hermes();
59089
59186
  init_agent_discovery_directories();
@@ -62021,7 +62118,7 @@ var init_remote_workspace_selection = __esm(() => {
62021
62118
  });
62022
62119
 
62023
62120
  // src/lib/remote-private-publications.ts
62024
- import { createHash as createHash22 } from "crypto";
62121
+ import { createHash as createHash23 } from "crypto";
62025
62122
  function checkedPublicationDeclaration(value) {
62026
62123
  if (!exact(value, ["idempotencyKey", "version", "expectedCurrentVersionId", "manifestText", "archiveSha256", "archiveByteSize"]) || !publicationUuid(value.idempotencyKey) || !(value.expectedCurrentVersionId === null || publicationUuid(value.expectedCurrentVersionId)) || typeof value.version !== "string" || !value.version || value.version.length > 128 || /[\p{Cc}\p{Cs}]/u.test(value.version) || typeof value.manifestText !== "string" || Buffer.byteLength(value.manifestText) > 16384 || !hash3(value.archiveSha256) || !Number.isSafeInteger(value.archiveByteSize) || Number(value.archiveByteSize) < 1 || Number(value.archiveByteSize) > PRIVATE_PUBLICATION_MAX_BYTES)
62027
62124
  return bad();
@@ -62041,7 +62138,7 @@ function checkedPublicationView(value, skillId, intentId, declaration) {
62041
62138
  return invalid3();
62042
62139
  return Object.freeze({ ...value });
62043
62140
  }
62044
- async function boundedJson(url, init, token, mutation, budget = 15000, signal) {
62141
+ async function boundedJson(url, init, token, mutation, budget2 = 15000, signal) {
62045
62142
  const controller = new AbortController;
62046
62143
  let reader;
62047
62144
  let response;
@@ -62096,7 +62193,7 @@ async function boundedJson(url, init, token, mutation, budget = 15000, signal) {
62096
62193
  controller.abort();
62097
62194
  reject2(timeout);
62098
62195
  };
62099
- timer = setTimeout(abort, Math.max(1, Math.min(15000, budget)));
62196
+ timer = setTimeout(abort, Math.max(1, Math.min(15000, budget2)));
62100
62197
  signal?.addEventListener("abort", abort, { once: true });
62101
62198
  })]);
62102
62199
  } catch (error) {
@@ -62282,7 +62379,7 @@ var PRIVATE_PUBLICATION_MAX_BYTES, failures, PrivatePublicationError, bad = () =
62282
62379
  throw new PrivatePublicationError("INVALID_PUBLICATION_INPUT", "Invalid publication input or recovery data.");
62283
62380
  }, invalid3 = () => {
62284
62381
  throw new PrivatePublicationError("INVALID_PUBLICATION_RESPONSE", "The server returned an invalid publication result.");
62285
- }, 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), hash3 = (v) => typeof v === "string" && /^[a-f0-9]{64}$/.test(v), record5 = (v) => !!v && typeof v === "object" && !Array.isArray(v), exact = (v, keys2) => record5(v) && Object.keys(v).sort().join(",") === keys2.sort().join(","), date = (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)), publicationSha256 = (bytes) => createHash22("sha256").update(bytes).digest("hex");
62382
+ }, 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), hash3 = (v) => typeof v === "string" && /^[a-f0-9]{64}$/.test(v), record5 = (v) => !!v && typeof v === "object" && !Array.isArray(v), exact = (v, keys2) => record5(v) && Object.keys(v).sort().join(",") === keys2.sort().join(","), date = (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)), publicationSha256 = (bytes) => createHash23("sha256").update(bytes).digest("hex");
62286
62383
  var init_remote_private_publications = __esm(() => {
62287
62384
  init_fleet_credentials();
62288
62385
  init_remote_workspace_selection();
@@ -81671,7 +81768,7 @@ var init_v4 = __esm(() => {
81671
81768
  });
81672
81769
 
81673
81770
  // src/lib/canonical-json.ts
81674
- import { createHash as createHash23 } from "crypto";
81771
+ import { createHash as createHash24 } from "crypto";
81675
81772
  function canonicalJson2(value, maximumBytes = 2 * 1024 * 1024) {
81676
81773
  return canonicalJsonAtDepth(value, maximumBytes, 64);
81677
81774
  }
@@ -81715,7 +81812,7 @@ function canonicalJsonAtDepth(value, maximumBytes, maximumDepth) {
81715
81812
  return visit3(value, 0);
81716
81813
  }
81717
81814
  function canonicalJsonSha256(value, maximumBytes) {
81718
- return createHash23("sha256").update(canonicalJson2(value, maximumBytes)).digest("hex");
81815
+ return createHash24("sha256").update(canonicalJson2(value, maximumBytes)).digest("hex");
81719
81816
  }
81720
81817
  var init_canonical_json = () => {};
81721
81818
 
@@ -81894,7 +81991,7 @@ function parseRecurringResult(action, value, input2, identity6) {
81894
81991
  }
81895
81992
  return result2;
81896
81993
  }
81897
- var RecurringInputError, RemoteRecurringUnavailableError, RemoteRecurringReadError, RemoteRecurringUnconfirmedError, failures2, RemoteRecurringError, uuid10, instant2, integer2, digest2, list, inputs, capabilityNames, budget, period, preview, consent, refusal2, occurrence, revocation, page = (item) => exports_external.object({ contractVersion: exports_external.literal(1), items: exports_external.array(item).max(100), nextCursor: exports_external.string().min(1).max(2048).nullable() }), results;
81994
+ var RecurringInputError, RemoteRecurringUnavailableError, RemoteRecurringReadError, RemoteRecurringUnconfirmedError, failures2, RemoteRecurringError, uuid10, instant2, integer2, digest2, list, inputs, capabilityNames, budget2, period, preview, consent, refusal2, occurrence, revocation, page = (item) => exports_external.object({ contractVersion: exports_external.literal(1), items: exports_external.array(item).max(100), nextCursor: exports_external.string().min(1).max(2048).nullable() }), results;
81898
81995
  var init_remote_recurring = __esm(() => {
81899
81996
  init_v4();
81900
81997
  init_canonical_json();
@@ -81980,7 +82077,7 @@ var init_remote_recurring = __esm(() => {
81980
82077
  occurrences: "recurring.occurrences",
81981
82078
  revoke: "recurring.revoke"
81982
82079
  };
81983
- budget = exports_external.object({ reservedCredits: integer2, settledCredits: integer2, admittedOccurrences: integer2 });
82080
+ budget2 = exports_external.object({ reservedCredits: integer2, settledCredits: integer2, admittedOccurrences: integer2 });
81984
82081
  period = exports_external.object({ startsAt: instant2, endsAt: instant2 });
81985
82082
  preview = exports_external.object({
81986
82083
  contractVersion: exports_external.literal(1),
@@ -82002,8 +82099,8 @@ var init_remote_recurring = __esm(() => {
82002
82099
  state: exports_external.enum(["active", "revoked", "expired"]),
82003
82100
  activatedAt: instant2,
82004
82101
  revokedAt: instant2.nullable(),
82005
- total: budget,
82006
- currentPeriod: budget.extend(period.shape).nullable(),
82102
+ total: budget2,
82103
+ currentPeriod: budget2.extend(period.shape).nullable(),
82007
82104
  nextDueAt: instant2.nullable()
82008
82105
  });
82009
82106
  refusal2 = exports_external.enum([
@@ -83629,7 +83726,7 @@ var init_remote_auth = __esm(() => {
83629
83726
  });
83630
83727
 
83631
83728
  // src/lib/sign-in.ts
83632
- import { createHash as createHash24 } from "crypto";
83729
+ import { createHash as createHash25 } from "crypto";
83633
83730
  import { chmodSync as chmodSync3, mkdirSync as mkdirSync13, readFileSync as readFileSync25, readdirSync as readdirSync14, renameSync as renameSync9, unlinkSync as unlinkSync7, writeFileSync as writeFileSync12 } from "fs";
83634
83731
  import { basename as basename14, dirname as dirname23, join as join41 } from "path";
83635
83732
  function isRecord7(value) {
@@ -83780,7 +83877,7 @@ function pendingDeviceSignInStem(env3) {
83780
83877
  }
83781
83878
  function pendingDeviceSignInPath(origin, env3 = process.env) {
83782
83879
  const { dir, stem } = pendingDeviceSignInStem(env3);
83783
- return join41(dir, `${stem}-${createHash24("sha256").update(origin).digest("hex").slice(0, 16)}.json`);
83880
+ return join41(dir, `${stem}-${createHash25("sha256").update(origin).digest("hex").slice(0, 16)}.json`);
83784
83881
  }
83785
83882
  function savePendingDeviceSignIn(origin, start, env3 = process.env, now3 = Date.now()) {
83786
83883
  const path = pendingDeviceSignInPath(origin, env3);
@@ -84484,7 +84581,7 @@ function optionPrefix(program2, args) {
84484
84581
  }
84485
84582
 
84486
84583
  // src/lib/revision.ts
84487
- import { createHash as createHash25 } from "crypto";
84584
+ import { createHash as createHash26 } from "crypto";
84488
84585
  function revisionIdOf(content) {
84489
84586
  const canonicalContent = {
84490
84587
  slug: content.slug,
@@ -84505,7 +84602,7 @@ function revisionIdOf(content) {
84505
84602
  canonicalContent.replacementSlug = content.replacementSlug ?? null;
84506
84603
  }
84507
84604
  const canonical6 = JSON.stringify(canonicalContent);
84508
- return createHash25("sha256").update(canonical6).digest("hex");
84605
+ return createHash26("sha256").update(canonical6).digest("hex");
84509
84606
  }
84510
84607
  var REVISION_ID_PATTERN;
84511
84608
  var init_revision = __esm(() => {
@@ -84954,7 +85051,7 @@ var init_pull = __esm(() => {
84954
85051
  });
84955
85052
 
84956
85053
  // src/lib/skill-context.ts
84957
- import { createHash as createHash26 } from "crypto";
85054
+ import { createHash as createHash27 } from "crypto";
84958
85055
  import { resolve as resolve22 } from "path";
84959
85056
  function words2(value) {
84960
85057
  return new Set(value.toLowerCase().match(/[a-z0-9]+/g) ?? []);
@@ -85047,7 +85144,7 @@ ${content}`;
85047
85144
  `);
85048
85145
  const receipt = {
85049
85146
  schemaVersion: 1,
85050
- id: createHash26("sha256").update(JSON.stringify({ profile: profile.profileRevision, sessionId, selections, omitted })).digest("hex"),
85147
+ id: createHash27("sha256").update(JSON.stringify({ profile: profile.profileRevision, sessionId, selections, omitted })).digest("hex"),
85051
85148
  profileId: profile.profileId,
85052
85149
  profileRevision: profile.profileRevision,
85053
85150
  authority: profile.authority,
@@ -85069,7 +85166,7 @@ var init_skill_context = __esm(() => {
85069
85166
  });
85070
85167
 
85071
85168
  // src/lib/session-reconciliation.ts
85072
- import { createHash as createHash27 } from "crypto";
85169
+ import { createHash as createHash28 } from "crypto";
85073
85170
  import { isDeepStrictEqual as isDeepStrictEqual12 } from "util";
85074
85171
  function exactTimestamp(value) {
85075
85172
  const parsed = value === undefined ? Number.NaN : Date.parse(value);
@@ -85209,7 +85306,7 @@ async function reconcileSkillSession(input2, options = {}) {
85209
85306
  const result2 = replaceSkillSession(skillSessionSnapshotBinding(snapshot2), replacement, { ...plan, planDigest }, options, () => assertPlanWindow(issuedAt, expiresAt, (options.now ?? Date.now)()));
85210
85307
  return { applied: true, plan, planDigest, ...result2 };
85211
85308
  }
85212
- var SESSION_RECONCILIATION_PLAN_TTL_MS, digest3 = (value) => createHash27("sha256").update(JSON.stringify(value)).digest("hex");
85309
+ var SESSION_RECONCILIATION_PLAN_TTL_MS, digest3 = (value) => createHash28("sha256").update(JSON.stringify(value)).digest("hex");
85213
85310
  var init_session_reconciliation = __esm(() => {
85214
85311
  init_profile_client();
85215
85312
  init_selection_cache();
@@ -89851,7 +89948,7 @@ __export(exports_selected_run, {
89851
89948
  prepareSelectedSecretBindings: () => prepareSelectedSecretBindings,
89852
89949
  executeSelectedLocal: () => executeSelectedLocal
89853
89950
  });
89854
- import { createHash as createHash28 } from "crypto";
89951
+ import { createHash as createHash29 } from "crypto";
89855
89952
  import { spawn as spawn3 } from "child_process";
89856
89953
  import { mkdirSync as mkdirSync16, mkdtempSync as mkdtempSync4, writeFileSync as writeFileSync16, realpathSync as realpathSync14 } from "fs";
89857
89954
  import { dirname as dirname25, join as join49, resolve as resolve23 } from "path";
@@ -89977,7 +90074,7 @@ async function executeSelectedLocal(selected, options = {}) {
89977
90074
  selection: selection2,
89978
90075
  target: "local",
89979
90076
  runtime: runtimeName,
89980
- inputDigest: `sha256:${createHash28("sha256").update(input2).digest("hex")}`,
90077
+ inputDigest: `sha256:${createHash29("sha256").update(input2).digest("hex")}`,
89981
90078
  runDirectory,
89982
90079
  ...executionGrant ? { executionGrant } : {},
89983
90080
  ...bindings ? { secretBinding: { schema: bindings.schema, selection: bindings.selection, consumer: bindings.consumer, secretsAuthority: bindings.secretsAuthority, bindings: bindings.bindings } } : {},
@@ -94194,7 +94291,7 @@ var init_runs = __esm(() => {
94194
94291
  });
94195
94292
 
94196
94293
  // src/lib/run-state.ts
94197
- import { createHash as createHash29, randomBytes } from "crypto";
94294
+ import { createHash as createHash30, randomBytes } from "crypto";
94198
94295
  import { existsSync as existsSync28, mkdirSync as mkdirSync17, readFileSync as readFileSync34, readdirSync as readdirSync18, statSync as statSync17, writeFileSync as writeFileSync17 } from "fs";
94199
94296
  import { extname, join as join50, relative as relative8 } from "path";
94200
94297
  function createSkillRun(params, targetDir = process.cwd()) {
@@ -94331,7 +94428,7 @@ function collectRunArtifacts(context) {
94331
94428
  artifacts.push({
94332
94429
  path: toProjectRelative(context.targetDir, path),
94333
94430
  mime: mimeForPath(path),
94334
- sha256: createHash29("sha256").update(bytes).digest("hex"),
94431
+ sha256: createHash30("sha256").update(bytes).digest("hex"),
94335
94432
  sizeBytes: stat2.size
94336
94433
  });
94337
94434
  }
@@ -109579,7 +109676,7 @@ var init_schedule_tools = __esm(() => {
109579
109676
  });
109580
109677
 
109581
109678
  // src/lib/native-storage.ts
109582
- import { createHash as createHash30, createHmac as createHmac3 } from "crypto";
109679
+ import { createHash as createHash31, createHmac as createHmac3 } from "crypto";
109583
109680
  import {
109584
109681
  existsSync as existsSync32,
109585
109682
  mkdirSync as mkdirSync22,
@@ -109656,7 +109753,7 @@ function exportSkillsLocalSnapshot(targetDir = process.cwd(), options = {}) {
109656
109753
  files.push({
109657
109754
  path: relativePath,
109658
109755
  sizeBytes: bytes.byteLength,
109659
- sha256: createHash30("sha256").update(bytes).digest("hex"),
109756
+ sha256: createHash31("sha256").update(bytes).digest("hex"),
109660
109757
  ...options.includeFileContents ? { contentBase64: Buffer.from(bytes).toString("base64") } : {}
109661
109758
  });
109662
109759
  }
@@ -110838,7 +110935,7 @@ var init_remote_account2 = __esm(() => {
110838
110935
  });
110839
110936
 
110840
110937
  // src/cli/commands/reviewed-runtime-lock.ts
110841
- import { createHash as createHash31 } from "crypto";
110938
+ import { createHash as createHash32 } from "crypto";
110842
110939
  function row(value) {
110843
110940
  if (!value || typeof value !== "object" || Array.isArray(value))
110844
110941
  throw new Error("REVIEWED_LOCK_SHAPE_INVALID");
@@ -110892,7 +110989,7 @@ async function metadata(name, context2) {
110892
110989
  async function validateReviewedRuntimeLock(bytes, sha2562, context2) {
110893
110990
  if (!/^[a-f0-9]{64}$/.test(sha2562))
110894
110991
  throw new Error("REVIEWED_LOCK_SHA256_INVALID");
110895
- if (bytes.byteLength > MAX_LOCK_BYTES || createHash31("sha256").update(bytes).digest("hex") !== sha2562)
110992
+ if (bytes.byteLength > MAX_LOCK_BYTES || createHash32("sha256").update(bytes).digest("hex") !== sha2562)
110896
110993
  throw new Error("REVIEWED_LOCK_HASH_MISMATCH");
110897
110994
  if (!Number.isSafeInteger(context2.minReleaseAge) || context2.minReleaseAge < 1)
110898
110995
  throw new Error("REVIEWED_LOCK_RELEASE_AGE_REQUIRED");
@@ -110969,7 +111066,7 @@ var init_reviewed_runtime_lock = __esm(() => {
110969
111066
  });
110970
111067
 
110971
111068
  // src/cli/commands/runtime-copyfile.ts
110972
- import { createHash as createHash32, randomUUID as randomUUID10 } from "crypto";
111069
+ import { createHash as createHash33, randomUUID as randomUUID10 } from "crypto";
110973
111070
  import { Readable } from "stream";
110974
111071
  import { createGunzip as createGunzip2 } from "zlib";
110975
111072
  import {
@@ -110993,7 +111090,7 @@ function object10(value, code2) {
110993
111090
  return value;
110994
111091
  }
110995
111092
  function hash5(bytes) {
110996
- return createHash32("sha256").update(bytes).digest("hex");
111093
+ return createHash33("sha256").update(bytes).digest("hex");
110997
111094
  }
110998
111095
  function isWithin(parent, child) {
110999
111096
  const rel = relative10(parent, child);
@@ -111144,7 +111241,7 @@ function verifyIntegrity(bytes, integrity) {
111144
111241
  const match = /^sha512-([A-Za-z0-9+/]+={0,2})$/.exec(integrity);
111145
111242
  if (!match)
111146
111243
  throw new Error("REGISTRY_INTEGRITY_UNSUPPORTED");
111147
- const actual = createHash32("sha512").update(bytes).digest("base64");
111244
+ const actual = createHash33("sha512").update(bytes).digest("base64");
111148
111245
  if (actual !== match[1])
111149
111246
  throw new Error("TARBALL_INTEGRITY_MISMATCH");
111150
111247
  }
@@ -112248,7 +112345,7 @@ var exports_runtime = {};
112248
112345
  __export(exports_runtime, {
112249
112346
  registerRuntime: () => registerRuntime
112250
112347
  });
112251
- import { createHash as createHash33, randomUUID as randomUUID11 } from "crypto";
112348
+ import { createHash as createHash34, randomUUID as randomUUID11 } from "crypto";
112252
112349
  import { lstatSync as lstatSync32, mkdirSync as mkdirSync26, readFileSync as readFileSync40, realpathSync as realpathSync18, writeFileSync as writeFileSync25 } from "fs";
112253
112350
  import { basename as basename16, isAbsolute as isAbsolute27, join as join60 } from "path";
112254
112351
  import { createInterface } from "readline";
@@ -112289,7 +112386,7 @@ function registerRuntime(parent) {
112289
112386
  if (!expected)
112290
112387
  throw new Error("Cloud artifact not found");
112291
112388
  const bytes = await client2.download(id2, name);
112292
- if (bytes.length !== expected.byteSize || createHash33("sha256").update(bytes).digest("hex") !== expected.sha256)
112389
+ if (bytes.length !== expected.byteSize || createHash34("sha256").update(bytes).digest("hex") !== expected.sha256)
112293
112390
  throw new Error("Cloud artifact integrity verification failed");
112294
112391
  writeFileSync25(options.output, bytes, { flag: "wx", mode: 384 });
112295
112392
  console.log(JSON.stringify({ path: options.output, sha256: expected.sha256, byteSize: bytes.length }));
@@ -113943,7 +114040,7 @@ var init_portable_snapshot_filter = __esm(() => {
113943
114040
  });
113944
114041
 
113945
114042
  // src/lib/station-snapshot.ts
113946
- import { createHash as createHash34 } from "crypto";
114043
+ import { createHash as createHash35 } from "crypto";
113947
114044
  import {
113948
114045
  copyFileSync as copyFileSync2,
113949
114046
  mkdirSync as mkdirSync27,
@@ -113958,7 +114055,7 @@ function validateStationId(stationId) {
113958
114055
  }
113959
114056
  }
113960
114057
  function sha256File(filePath) {
113961
- return createHash34("sha256").update(readFileSync41(filePath)).digest("hex");
114058
+ return createHash35("sha256").update(readFileSync41(filePath)).digest("hex");
113962
114059
  }
113963
114060
  function scanHome(definition, homesRoot) {
113964
114061
  const homePath = homePathFor(definition, homesRoot);
@@ -114648,7 +114745,7 @@ var init_codex_hook_policy_recovery = __esm(() => {
114648
114745
 
114649
114746
  // src/lib/agent-codex-trust.ts
114650
114747
  import { lstatSync as lstatSync34, mkdirSync as mkdirSync28, readdirSync as readdirSync23, readFileSync as readFileSync42, realpathSync as realpathSync20, statSync as statSync22 } from "fs";
114651
- import { createHash as createHash35, randomUUID as randomUUID12 } from "crypto";
114748
+ import { createHash as createHash36, randomUUID as randomUUID12 } from "crypto";
114652
114749
  import { execFileSync as execFileSync2 } from "child_process";
114653
114750
  import { dirname as dirname36, isAbsolute as isAbsolute30, join as join64, resolve as resolve28 } from "path";
114654
114751
  import { homedir as homedir12 } from "os";
@@ -114658,11 +114755,11 @@ function verifyReleaseArtifact(proof, skillsCli) {
114658
114755
  const tarPath = realpathSync20(proof.packageTarPath);
114659
114756
  need5(statSync22(tarPath).isFile(), "RECONCILE_RELEASE_PROVENANCE_PATH");
114660
114757
  const tarBytes = readFileSync42(tarPath);
114661
- need5(tarBytes.byteLength === proof.packageTarBytes && createHash35("sha256").update(tarBytes).digest("hex") === proof.packageTarSha256, "RECONCILE_RELEASE_ARTIFACT_CHANGED");
114758
+ need5(tarBytes.byteLength === proof.packageTarBytes && createHash36("sha256").update(tarBytes).digest("hex") === proof.packageTarSha256, "RECONCILE_RELEASE_ARTIFACT_CHANGED");
114662
114759
  const packageRoot = dirname36(dirname36(realpathSync20(skillsCli.receipt.path)));
114663
114760
  const manifest = readFileSync42(join64(packageRoot, "package.json"));
114664
- need5(createHash35("sha256").update(manifest).digest("hex") === skillsCli.receipt.manifestSha256 && skillsCli.receipt.manifestSha256 === proof.manifestSha256, "RECONCILE_RELEASE_MANIFEST_CHANGED");
114665
- need5(createHash35("sha256").update(readFileSync42(skillsCli.receipt.path)).digest("hex") === proof.executableSha256 && skillsCli.receipt.sha256 === proof.executableSha256, "RECONCILE_RELEASE_EXECUTABLE_CHANGED");
114761
+ need5(createHash36("sha256").update(manifest).digest("hex") === skillsCli.receipt.manifestSha256 && skillsCli.receipt.manifestSha256 === proof.manifestSha256, "RECONCILE_RELEASE_MANIFEST_CHANGED");
114762
+ need5(createHash36("sha256").update(readFileSync42(skillsCli.receipt.path)).digest("hex") === proof.executableSha256 && skillsCli.receipt.sha256 === proof.executableSha256, "RECONCILE_RELEASE_EXECUTABLE_CHANGED");
114666
114763
  const members2 = [["package/package.json", manifest], ["package/bin/index.js", readFileSync42(skillsCli.receipt.path)]];
114667
114764
  for (const [member, expected] of members2) {
114668
114765
  let actual;
@@ -114980,7 +115077,7 @@ async function enrollCodexNativeHooksUnlocked(options, connect) {
114980
115077
  }
114981
115078
  }
114982
115079
  var json2 = (value) => JSON.stringify(value, null, 2) + `
114983
- `, structure3 = (text4) => JSON.parse(JSON.stringify(Bun.TOML.parse(text4))), eventNames, makePlanDigest = (value) => createHash35("sha256").update(json2(value)).digest("hex"), safeNativeHook = (hook) => ({ key: hook.key, eventName: hook.eventName, handlerType: hook.handlerType, command: hook.command, matcher: hook.matcher, timeoutSec: hook.timeoutSec, async: hook.async, statusMessage: hook.statusMessage, additionalContextLimit: hook.additionalContextLimit, sourcePath: hook.sourcePath, source: hook.source, pluginId: hook.pluginId, isManaged: hook.isManaged, currentHash: hook.currentHash, enabled: hook.enabled, trustStatus: hook.trustStatus }), withoutCodexCommand = (value) => {
115080
+ `, structure3 = (text4) => JSON.parse(JSON.stringify(Bun.TOML.parse(text4))), eventNames, makePlanDigest = (value) => createHash36("sha256").update(json2(value)).digest("hex"), safeNativeHook = (hook) => ({ key: hook.key, eventName: hook.eventName, handlerType: hook.handlerType, command: hook.command, matcher: hook.matcher, timeoutSec: hook.timeoutSec, async: hook.async, statusMessage: hook.statusMessage, additionalContextLimit: hook.additionalContextLimit, sourcePath: hook.sourcePath, source: hook.source, pluginId: hook.pluginId, isManaged: hook.isManaged, currentHash: hook.currentHash, enabled: hook.enabled, trustStatus: hook.trustStatus }), withoutCodexCommand = (value) => {
114984
115081
  const copy = structuredClone(value);
114985
115082
  if (copy?.bridge?.commands && Object.hasOwn(copy.bridge.commands, "codex"))
114986
115083
  copy.bridge.commands.codex = "<reviewed-codex-binding>";
@@ -115004,7 +115101,7 @@ var init_agent_codex_trust = __esm(() => {
115004
115101
  });
115005
115102
 
115006
115103
  // src/lib/codex-native-trust.ts
115007
- import { createHash as createHash36 } from "crypto";
115104
+ import { createHash as createHash37 } from "crypto";
115008
115105
  import { readFileSync as readFileSync43 } from "fs";
115009
115106
  import { join as join65, resolve as resolve29 } from "path";
115010
115107
  function refuse5(detail) {
@@ -115077,7 +115174,7 @@ function applyCodexNativeTrust(plan, expectedPolicySha256) {
115077
115174
  receipt.readback = { policySha256: sha6(readback.text), digests, verified: true };
115078
115175
  return receipt;
115079
115176
  }
115080
- var CODEX_NATIVE_TRUST_PLAN_SCHEMA = "skills.codex-native-trust-plan/v1", CODEX_NATIVE_TRUST_RECEIPT_SCHEMA = "skills.codex-native-trust-receipt/v1", PLATFORM_KEY2, HEX_DIGEST2, MAX_DIGESTS = 16, sha6 = (data) => createHash36("sha256").update(data).digest("hex");
115177
+ var CODEX_NATIVE_TRUST_PLAN_SCHEMA = "skills.codex-native-trust-plan/v1", CODEX_NATIVE_TRUST_RECEIPT_SCHEMA = "skills.codex-native-trust-receipt/v1", PLATFORM_KEY2, HEX_DIGEST2, MAX_DIGESTS = 16, sha6 = (data) => createHash37("sha256").update(data).digest("hex");
115081
115178
  var init_codex_native_trust = __esm(() => {
115082
115179
  init_config();
115083
115180
  init_managed_policy();
@@ -115207,7 +115304,7 @@ __export(exports_agent_integration, {
115207
115304
  registerAgentIntegration: () => registerAgentIntegration
115208
115305
  });
115209
115306
  import { existsSync as existsSync36, lstatSync as lstatSync35, readFileSync as readFileSync44, readSync as readSync18, writeFileSync as writeFileSync27 } from "fs";
115210
- import { createHash as createHash37 } from "crypto";
115307
+ import { createHash as createHash38 } from "crypto";
115211
115308
  import { homedir as homedir13 } from "os";
115212
115309
  import { isAbsolute as isAbsolute31 } from "path";
115213
115310
  function pinnedHookProfile(input3, configuredProfile) {
@@ -115332,7 +115429,7 @@ function registerAgentIntegration(parent) {
115332
115429
  skillCount: catalog.skills.length,
115333
115430
  output: options.output,
115334
115431
  bytes: Buffer.byteLength(bytes),
115335
- sha256: createHash37("sha256").update(bytes).digest("hex")
115432
+ sha256: createHash38("sha256").update(bytes).digest("hex")
115336
115433
  };
115337
115434
  await writeCliOutput(options.json ? JSON.stringify(receipt) : `Captured ${receipt.skillCount} native Codex skill(s) in ${receipt.output}.`);
115338
115435
  } catch (error61) {
@@ -115341,16 +115438,16 @@ function registerAgentIntegration(parent) {
115341
115438
  process.exitCode = 1;
115342
115439
  }
115343
115440
  });
115344
- hook.command("witness").requiredOption("--kind <kind>", "claude-settings-v3, claude-settings-v2, codex-settings-v4, codex-settings-v3, codex-settings-v2, codex-settings-v1 or claude-marketplace-registry-v2").requiredOption("--path <path>", "Canonical absolute path to the reviewed settings or registry file").option("--json", "Output the discovery witness as JSON", false).description("Capture an explicit versioned review witness without installing it").action(async (options) => {
115345
- const capture2 = options.kind === "codex-settings-v4" ? captureCodexSettingsV4 : options.kind === "codex-settings-v3" ? captureCodexSettingsV3 : options.kind === "codex-settings-v2" ? captureCodexSettingsV2 : options.kind === "codex-settings-v1" ? captureCodexSettings : options.kind === "claude-settings-v3" ? captureClaudeSettingsV3 : options.kind === "claude-settings-v2" ? captureClaudeSettingsV2 : options.kind === "claude-marketplace-registry-v2" ? captureClaudeMarketplaceRegistryV2 : null;
115441
+ hook.command("witness").requiredOption("--kind <kind>", "sumi-settings-v1, claude-settings-v3, claude-settings-v2, codex-settings-v4, codex-settings-v3, codex-settings-v2, codex-settings-v1 or claude-marketplace-registry-v2").requiredOption("--path <path>", "Canonical absolute path to the reviewed settings or registry file").option("--json", "Output the discovery witness as JSON", false).description("Capture an explicit versioned review witness without installing it").action(async (options) => {
115442
+ const capture2 = options.kind === "sumi-settings-v1" ? captureSumiSettings : options.kind === "codex-settings-v4" ? captureCodexSettingsV4 : options.kind === "codex-settings-v3" ? captureCodexSettingsV3 : options.kind === "codex-settings-v2" ? captureCodexSettingsV2 : options.kind === "codex-settings-v1" ? captureCodexSettings : options.kind === "claude-settings-v3" ? captureClaudeSettingsV3 : options.kind === "claude-settings-v2" ? captureClaudeSettingsV2 : options.kind === "claude-marketplace-registry-v2" ? captureClaudeMarketplaceRegistryV2 : null;
115346
115443
  if (!capture2)
115347
- throw new Error("Unsupported witness kind; select claude-settings-v3, claude-settings-v2, codex-settings-v4, codex-settings-v3, codex-settings-v2, codex-settings-v1 or claude-marketplace-registry-v2");
115444
+ throw new Error("Unsupported witness kind; select sumi-settings-v1, claude-settings-v3, claude-settings-v2, codex-settings-v4, codex-settings-v3, codex-settings-v2, codex-settings-v1 or claude-marketplace-registry-v2");
115348
115445
  await writeCliOutput(JSON.stringify(capture2(options.path), null, 2));
115349
115446
  });
115350
- hook.command("rebind-settings").requiredOption("--agent <agent>", "claude or codex").requiredOption("--reviewed-preimage <path>", "Exact preserved legacy settings.json or config.toml").requiredOption("--expected-policy-sha256 <sha256>", "Exact current managed policy bytes").requiredOption("--expected-settings-sha256 <sha256>", "Exact current native settings bytes").option("--codex-witness-version <version>", "Explicit target: 2 (legacy default) 3 (service tier and model-advertised effort), or 4 (native availability UI counts)").option("--apply", "Apply the explicit semantic witness upgrade with preservation and readback", false).option("--json", "Return the metadata-only plan or receipt", false).description("Explicitly migrate a legacy native settings witness after proving only known preferences changed").action(async (options) => {
115447
+ hook.command("rebind-settings").requiredOption("--agent <agent>", "claude, codex or sumi").requiredOption("--reviewed-preimage <path>", "Exact preserved legacy settings.json, config.toml or sumi.json").requiredOption("--expected-policy-sha256 <sha256>", "Exact current managed policy bytes").requiredOption("--expected-settings-sha256 <sha256>", "Exact current native settings bytes").option("--codex-witness-version <version>", "Explicit target: 2 (legacy default) 3 (service tier and model-advertised effort), or 4 (native availability UI counts)").option("--apply", "Apply the explicit semantic witness upgrade with preservation and readback", false).option("--json", "Return the metadata-only plan or receipt", false).description("Explicitly migrate a legacy native settings witness after proving only known preferences changed").action(async (options) => {
115351
115448
  try {
115352
- if (!["claude", "codex"].includes(options.agent))
115353
- throw new Error("Settings witness rebind accepts claude or codex");
115449
+ if (!["claude", "codex", "sumi"].includes(options.agent))
115450
+ throw new Error("Settings witness rebind accepts claude, codex or sumi");
115354
115451
  if (options.codexWitnessVersion !== undefined && !["2", "3", "4"].includes(options.codexWitnessVersion))
115355
115452
  throw new Error("Codex witness version accepts 2, 3 or 4");
115356
115453
  const plan = planAgentSettingsWitnessUpgrade({ ...options.codexWitnessVersion !== undefined ? { targetCodexVersion: Number(options.codexWitnessVersion) } : {}, agent: options.agent, reviewedPreimage: options.reviewedPreimage, expectedPolicySha256: options.expectedPolicySha256, expectedSettingsSha256: options.expectedSettingsSha256 });
@@ -115578,6 +115675,7 @@ function registerAgentIntegration(parent) {
115578
115675
  }
115579
115676
  var RECOVERABLE_CONTEXT_CACHE_ERRORS;
115580
115677
  var init_agent_integration2 = __esm(() => {
115678
+ init_sumi_settings_witness();
115581
115679
  init_agent_hermes();
115582
115680
  init_context();
115583
115681
  init_agent_adapters();
@@ -115864,7 +115962,7 @@ var init_grants = __esm(() => {
115864
115962
  });
115865
115963
 
115866
115964
  // src/lib/station-hydrate.ts
115867
- import { createHash as createHash38 } from "crypto";
115965
+ import { createHash as createHash39 } from "crypto";
115868
115966
  import {
115869
115967
  copyFileSync as copyFileSync3,
115870
115968
  mkdirSync as mkdirSync29,
@@ -116067,7 +116165,7 @@ function skillSha256(skill) {
116067
116165
  return sha256File(skill.files[0].winner.fullPath);
116068
116166
  }
116069
116167
  const joined = skill.files.map((file2) => sha256File(file2.winner.fullPath));
116070
- return createHash38("sha256").update(joined.sort().join(`
116168
+ return createHash39("sha256").update(joined.sort().join(`
116071
116169
  `)).digest("hex");
116072
116170
  }
116073
116171
  function writeStationHydration(options) {
@@ -116224,7 +116322,7 @@ var init_hydrate = __esm(() => {
116224
116322
  });
116225
116323
 
116226
116324
  // src/lib/prepare-skill.ts
116227
- import { createHash as createHash39, randomUUID as randomUUID13 } from "crypto";
116325
+ import { createHash as createHash40, randomUUID as randomUUID13 } from "crypto";
116228
116326
  import { chmodSync as chmodSync5, existsSync as existsSync37, lstatSync as lstatSync36, mkdirSync as mkdirSync30, mkdtempSync as mkdtempSync6, readFileSync as readFileSync46, readdirSync as readdirSync25, renameSync as renameSync15, rmSync as rmSync9, writeFileSync as writeFileSync31 } from "fs";
116229
116327
  import { tmpdir as tmpdir2 } from "os";
116230
116328
  import { dirname as dirname38, isAbsolute as isAbsolute32, join as join67, relative as relative12, resolve as resolve31, sep as sep15 } from "path";
@@ -116423,7 +116521,7 @@ function snapshot2(root2) {
116423
116521
  if (rootStat.isSymbolicLink() || !rootStat.isDirectory())
116424
116522
  throw new Error("Skill root must be a real directory, not a symlink.");
116425
116523
  const files = [], directories = [];
116426
- const hash6 = createHash39("sha256").update(`${rootStat.dev}:${rootStat.ino}\x00`);
116524
+ const hash6 = createHash40("sha256").update(`${rootStat.dev}:${rootStat.ino}\x00`);
116427
116525
  let count = 0, bytes = 0;
116428
116526
  const walk2 = (relative13) => {
116429
116527
  for (const name of readdirSync25(join67(root2, relative13)).sort()) {