@hasna/skills 0.10.44 → 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/README.md +17 -0
- package/bin/index.js +765 -662
- package/bin/mcp.js +553 -497
- package/bin/migrate.js +1 -1
- package/bin/server.js +1 -1
- package/bin/worker.js +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +763 -662
- package/dist/lib/agent-discovery.d.ts +1 -1
- package/dist/lib/agent-integration.d.ts +2 -2
- package/dist/lib/agent-sumi.d.ts +3 -0
- package/dist/lib/claude-settings-witness.d.ts +5 -1
- package/dist/lib/sumi-settings-witness.d.ts +14 -0
- package/dist/sdk/index.js +361 -262
- package/package.json +1 -1
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.
|
|
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
|
|
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(
|
|
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) &&
|
|
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),
|
|
39986
|
-
requireBound(agent === "codex" && value.agent === "codex" && value.method === "reviewed" && Object.keys(proof).every((key) => ["roots", "parents", "directories"].includes(key)) && roots.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(
|
|
40329
|
+
requireBound(isAbsolute3(root) && resolve4(root) === root);
|
|
39990
40330
|
}
|
|
39991
|
-
for (const parent of
|
|
40331
|
+
for (const parent of parents2) {
|
|
39992
40332
|
text(parent);
|
|
39993
|
-
requireBound(
|
|
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) =>
|
|
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) &&
|
|
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) &&
|
|
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) &&
|
|
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
|
|
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 =
|
|
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
|
|
47062
|
-
import { lstatSync as
|
|
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 (!
|
|
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 && (!
|
|
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 =
|
|
47140
|
-
if (
|
|
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 (
|
|
47484
|
+
if (dirname4(current) === current)
|
|
47143
47485
|
break;
|
|
47144
47486
|
}
|
|
47145
|
-
const stat =
|
|
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 || !
|
|
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 =
|
|
47183
|
-
if (
|
|
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 (
|
|
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 =
|
|
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 (
|
|
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(
|
|
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
|
|
47285
|
-
import { lstatSync as
|
|
47286
|
-
import { dirname as
|
|
47287
|
-
function
|
|
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
|
-
|
|
47293
|
-
for (let cursor = path;; cursor =
|
|
47294
|
-
|
|
47295
|
-
if (
|
|
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,
|
|
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 =
|
|
47648
|
+
const root = lstatSync5(path, { throwIfNoEntry: false });
|
|
47307
47649
|
if (!root)
|
|
47308
47650
|
return { path, sha256: null };
|
|
47309
|
-
|
|
47310
|
-
const hash =
|
|
47651
|
+
need2(root.isDirectory(), "Unsupported native discovery directory input");
|
|
47652
|
+
const hash = createHash4("sha256");
|
|
47311
47653
|
function walk(current, relative2, before2, depth) {
|
|
47312
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
47328
|
-
const stat =
|
|
47329
|
-
|
|
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
|
-
|
|
47333
|
-
|
|
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
|
-
|
|
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
|
-
|
|
47347
|
-
|
|
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
|
|
47692
|
+
const budget2 = { entries: 0, bytes: 0 };
|
|
47351
47693
|
return paths.map((path) => {
|
|
47352
47694
|
const entries = [];
|
|
47353
|
-
return { ...capture(path,
|
|
47695
|
+
return { ...capture(path, budget2, [], omittedRoots, entries), entries };
|
|
47354
47696
|
});
|
|
47355
47697
|
}
|
|
47356
47698
|
function verifyDiscoveryDirectoryProjection(directories, omittedRoots) {
|
|
47357
|
-
|
|
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
|
-
|
|
47362
|
-
const hash =
|
|
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
|
-
|
|
47707
|
+
need2(typeof row === "string" && ++count <= AGENT_POLICY_LIMITS.discoveryDirectoryEntries, "Invalid reviewed directory membership rows");
|
|
47366
47708
|
bytes += Buffer.byteLength(row);
|
|
47367
|
-
|
|
47709
|
+
need2(bytes <= AGENT_POLICY_LIMITS.discoveryDirectoryBytes, "Reviewed directory membership byte limit exceeded");
|
|
47368
47710
|
const value = JSON.parse(row);
|
|
47369
|
-
|
|
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
|
-
|
|
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 :
|
|
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
|
-
|
|
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
|
-
|
|
47385
|
-
const
|
|
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,
|
|
47730
|
+
return paths.map((path) => capture(path, budget2, excludedRoots));
|
|
47389
47731
|
}
|
|
47390
47732
|
function verifyDiscoveryDirectories(directories, excludedRoots = []) {
|
|
47391
|
-
|
|
47733
|
+
need2(Array.isArray(directories) && directories.length <= AGENT_POLICY_LIMITS.discoveryDirectories, "Invalid native discovery directory collection");
|
|
47392
47734
|
for (const directory of directories)
|
|
47393
|
-
|
|
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
|
-
|
|
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
|
|
47404
|
-
import { closeSync, constants as
|
|
47405
|
-
import { dirname as
|
|
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" || !
|
|
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 =
|
|
47413
|
-
if (
|
|
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 (
|
|
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(
|
|
47423
|
-
if (bytes >
|
|
47764
|
+
function consume(budget2, bytes) {
|
|
47765
|
+
if (bytes > budget2.remaining)
|
|
47424
47766
|
throw new Error("Raw discovery aggregate byte limit exceeded");
|
|
47425
|
-
|
|
47767
|
+
budget2.remaining -= bytes;
|
|
47426
47768
|
}
|
|
47427
|
-
function hashRawDiscoveryFile(path,
|
|
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(
|
|
47434
|
-
return
|
|
47775
|
+
consume(budget2, bytes);
|
|
47776
|
+
return createHash5("sha256").update(text2).digest("hex");
|
|
47435
47777
|
}
|
|
47436
|
-
const initial2 =
|
|
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 >
|
|
47783
|
+
if (initial2.size > budget2.remaining)
|
|
47442
47784
|
throw new Error("Raw discovery aggregate byte limit exceeded");
|
|
47443
|
-
const fd =
|
|
47785
|
+
const fd = openSync2(path, constants3.O_RDONLY | constants3.O_NOFOLLOW | constants3.O_NONBLOCK);
|
|
47444
47786
|
try {
|
|
47445
|
-
const opened =
|
|
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 =
|
|
47790
|
+
const hash = createHash5("sha256"), buffer = Buffer.alloc(64 * 1024);
|
|
47449
47791
|
let bytes = 0;
|
|
47450
47792
|
while (true) {
|
|
47451
|
-
const count =
|
|
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(
|
|
47799
|
+
consume(budget2, count);
|
|
47458
47800
|
hash.update(buffer.subarray(0, count));
|
|
47459
47801
|
}
|
|
47460
|
-
const final =
|
|
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
|
-
|
|
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
|
|
47475
|
-
import { lstatSync as
|
|
47476
|
-
import { dirname as
|
|
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
|
|
47488
|
-
if (typeof path !== "string" || !
|
|
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
|
-
|
|
47834
|
+
canonical2(path);
|
|
47493
47835
|
const rows = [], paths = [];
|
|
47494
|
-
let metadataBytes = 0, steps = 0, links = 0, cursor =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 (
|
|
47538
|
-
cursor =
|
|
47879
|
+
if (isAbsolute7(target)) {
|
|
47880
|
+
cursor = parse2(target).root;
|
|
47539
47881
|
root();
|
|
47540
47882
|
}
|
|
47541
|
-
const remainder =
|
|
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,
|
|
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 =
|
|
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
|
-
|
|
47578
|
-
const content = before2.file === null ? null : hashRawDiscoveryFile(before2.file,
|
|
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
|
|
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
|
|
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
|
|
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((
|
|
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
|
|
48555
|
+
import { createHash as createHash8, randomUUID as randomUUID3 } from "crypto";
|
|
48214
48556
|
import { spawnSync } from "child_process";
|
|
48215
|
-
import { closeSync as
|
|
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
|
|
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
|
|
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
|
|
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 =
|
|
48268
|
-
const 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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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
|
-
|
|
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(
|
|
48666
|
+
const temporary = join15(dirname8(path), `.selection-${randomUUID3()}.tmp`);
|
|
48325
48667
|
try {
|
|
48326
|
-
const fd =
|
|
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
|
-
|
|
48674
|
+
closeSync3(fd);
|
|
48333
48675
|
}
|
|
48334
48676
|
renameSync(temporary, path);
|
|
48335
48677
|
if (durable)
|
|
48336
|
-
syncDirectory(
|
|
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(
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
48596
|
-
const stat =
|
|
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(
|
|
48604
|
-
const staged =
|
|
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(
|
|
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 =
|
|
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
|
-
|
|
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 =
|
|
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 =
|
|
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:
|
|
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(
|
|
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(
|
|
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(
|
|
49062
|
+
syncDirectory(dirname8(lock.path));
|
|
48721
49063
|
for (const path of archivedPaths) {
|
|
48722
|
-
const before2 =
|
|
49064
|
+
const before2 = lstatSync8(path, { throwIfNoEntry: false });
|
|
48723
49065
|
const bytes = readRegularFile(path, SESSION_LOCK_MAX_BYTES);
|
|
48724
|
-
const after2 =
|
|
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
|
-
|
|
48737
|
-
const current =
|
|
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 =
|
|
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 =
|
|
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
|
-
|
|
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 =
|
|
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
|
-
|
|
49205
|
+
closeSync3(fd);
|
|
48864
49206
|
}
|
|
48865
49207
|
}
|
|
48866
49208
|
function archiveBytes(path, bytes) {
|
|
48867
49209
|
assertRegularPath(path, true);
|
|
48868
|
-
const fd =
|
|
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
|
-
|
|
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(
|
|
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
|
|
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
|
|
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
|
|
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 =
|
|
49362
|
+
const fd = openSync4(join16(root, "package.json"), O_RDONLY | O_NOFOLLOW | O_NONBLOCK);
|
|
49021
49363
|
let pkg;
|
|
49022
49364
|
try {
|
|
49023
|
-
const stat =
|
|
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
|
-
|
|
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 =
|
|
49390
|
+
let directory = dirname9(fileURLToPath(parentUrl));
|
|
49049
49391
|
for (;; ) {
|
|
49050
|
-
if (
|
|
49392
|
+
if (basename4(directory) !== "node_modules") {
|
|
49051
49393
|
const candidate = join16(directory, "node_modules", PACKAGE);
|
|
49052
49394
|
let absent = false;
|
|
49053
49395
|
try {
|
|
49054
|
-
|
|
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 =
|
|
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 &&
|
|
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
|
|
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
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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,
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
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 (!
|
|
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 (!
|
|
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 =
|
|
50647
|
-
if (!
|
|
50648
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
50778
|
-
import { accessSync, constants as
|
|
50779
|
-
import { basename as
|
|
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 =
|
|
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 ===
|
|
51128
|
+
if (error.code !== "ENOENT" || cursor === dirname10(cursor))
|
|
50787
51129
|
throw error;
|
|
50788
51130
|
try {
|
|
50789
|
-
if (
|
|
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(
|
|
51137
|
+
suffix.unshift(basename5(cursor));
|
|
50796
51138
|
}
|
|
50797
51139
|
}
|
|
50798
51140
|
}
|
|
50799
51141
|
function codexCorpusRootForPath(path) {
|
|
50800
|
-
const target =
|
|
51142
|
+
const target = resolve10(path), physical = physicalTarget(target);
|
|
50801
51143
|
const selected = process.env.CODEX_HOME;
|
|
50802
|
-
const selectedRoots = 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 !== ".." && !
|
|
51153
|
+
if (distance === "" || !distance.startsWith(`..${sep4}`) && distance !== ".." && !isAbsolute9(distance))
|
|
50812
51154
|
return checked(root2);
|
|
50813
51155
|
}
|
|
50814
|
-
for (let cursor = candidate;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 =
|
|
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 (
|
|
51182
|
+
if (isAbsolute9(command))
|
|
50841
51183
|
found = command;
|
|
50842
51184
|
else if (!command.includes(sep4)) {
|
|
50843
|
-
found = (process.env.PATH ?? "").split(delimiter).filter(
|
|
51185
|
+
found = (process.env.PATH ?? "").split(delimiter).filter(isAbsolute9).map((dir) => join18(dir, command)).find((candidate) => {
|
|
50844
51186
|
try {
|
|
50845
|
-
accessSync(candidate,
|
|
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 = () =>
|
|
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" || !
|
|
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
|
|
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 ===
|
|
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
|
|
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:
|
|
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 =
|
|
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
|
|
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,
|
|
52727
|
-
need3(depth <= 32 && --
|
|
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,
|
|
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,
|
|
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,
|
|
52748
|
-
need3(Buffer.byteLength(text2) <= 1024 * 1024 &&
|
|
52749
|
-
|
|
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,
|
|
52769
|
-
const text2 = readNativeSettingsWitnessFile(path,
|
|
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) =>
|
|
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
|
|
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,
|
|
52897
|
-
need4(depth <= 32 && --
|
|
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,
|
|
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,
|
|
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,
|
|
53092
|
-
need4(Buffer.byteLength(text2) <= 1024 * 1024 &&
|
|
53093
|
-
|
|
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,
|
|
53097
|
-
const text2 = readNativeSettingsWitnessFile(path,
|
|
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,
|
|
53101
|
-
return readNativeSettingsWitnessFile(path,
|
|
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
|
|
53106
|
-
const before2 = readNativeSettingsWitnessFile(reviewedSettingsPath,
|
|
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,
|
|
53114
|
-
need4(Buffer.byteLength(text2) <= 1024 * 1024 &&
|
|
53115
|
-
|
|
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,
|
|
53119
|
-
return { path, hashMode: "codex-settings-v3", sha256: settingsDigest2(readNativeSettingsWitnessFile(path,
|
|
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
|
|
53124
|
-
const before2 = readNativeSettingsWitnessFile(reviewedSettingsPath,
|
|
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,
|
|
53133
|
-
need4(Buffer.byteLength(text2) <= 1024 * 1024 &&
|
|
53134
|
-
|
|
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,
|
|
53138
|
-
return { path, hashMode: "codex-settings-v4", sha256: settingsDigest2(readNativeSettingsWitnessFile(path,
|
|
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
|
|
53143
|
-
const before2 = readNativeSettingsWitnessFile(reviewedSettingsPath,
|
|
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) =>
|
|
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
|
|
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 =
|
|
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
|
|
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 =
|
|
53605
|
-
child.stdout.on("data", chunk => { bytes += chunk.length; if (bytes > 1048576) { failure =
|
|
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 ??
|
|
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
|
|
53615
|
-
if (result.decision === "block" || result.continue === false) throw
|
|
53616
|
-
if (Object.keys(result).length && (!result.hookSpecificOutput || result.hookSpecificOutput.hookEventName !== input.hook_event_name)) throw
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
|
53647
|
-
if (event.prompt.skills !== undefined && (!Array.isArray(event.prompt.skills) || event.prompt.skills.some(skill => skill?.id !== "skills-cli"))) throw
|
|
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
|
|
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:
|
|
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
|
|
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 =
|
|
53999
|
+
const hash2 = createHash17("sha256");
|
|
53931
54000
|
let bytes = 0, files = 0;
|
|
53932
54001
|
function visit2(path) {
|
|
53933
54002
|
const stat = lstatSync19(path);
|
|
@@ -54427,6 +54496,7 @@ function planAgentIntegration(options) {
|
|
|
54427
54496
|
const codexPluginSourceInputs = codexPluginControls.sourceInputs.filter((input) => codexDiscovery?.method === "reviewed" && codexDiscovery.roots.some((root) => root === input.sourceRoot || root.startsWith(input.sourceRoot + sep6) || input.sourceRoot.startsWith(root + sep6)) && codexDiscovery.sources.some((source) => source.path === join27(input.sourceRoot, ".codex-plugin/plugin.json") && source.sha256 !== null && source.format === undefined && source.fields === undefined));
|
|
54428
54497
|
assertCodexInstallationInputs(home, [options.projectDir ?? home], codexPluginSourceInputs.map((input) => input.sourceRoot));
|
|
54429
54498
|
const changes = [];
|
|
54499
|
+
let observedSettings;
|
|
54430
54500
|
for (const agent of [...new Set(options.agents)]) {
|
|
54431
54501
|
if (!INTEGRATION_AGENTS.includes(agent))
|
|
54432
54502
|
throw new Error(`Unsupported agent: ${agent}`);
|
|
@@ -54469,7 +54539,7 @@ function planAgentIntegration(options) {
|
|
|
54469
54539
|
const pluginPath = join27(sumiConfigDirectory(home), "plugins", "skills-cli.js"), pluginBefore = readOptional(pluginPath);
|
|
54470
54540
|
const pluginAfter = renderSumiPlugin(command, profileId2);
|
|
54471
54541
|
const priorCommand = policy.bridge?.commands?.sumi, priorProfile = policy.bridge?.profiles?.sumi ?? policy.profileId;
|
|
54472
|
-
if (pluginBefore !== null && pluginBefore !== pluginAfter && !(typeof priorCommand === "string" && typeof priorProfile === "string" && pluginBefore
|
|
54542
|
+
if (pluginBefore !== null && pluginBefore !== pluginAfter && !(typeof priorCommand === "string" && typeof priorProfile === "string" && isManagedSumiPlugin(pluginBefore, priorCommand, priorProfile)))
|
|
54473
54543
|
throw new Error("Refusing to overwrite a modified Sumi Skills plugin; preserve and review it first");
|
|
54474
54544
|
if (pluginBefore !== pluginAfter)
|
|
54475
54545
|
changes.push({ path: pluginPath, before: pluginBefore, after: pluginAfter });
|
|
@@ -54499,8 +54569,12 @@ function planAgentIntegration(options) {
|
|
|
54499
54569
|
if (previous !== codexConfigBefore)
|
|
54500
54570
|
throw new Error(`Configuration changed during planning: ${configPath}`);
|
|
54501
54571
|
const next = disableReviewedCodexPluginNames(codexPathConfig, codexPluginSkills);
|
|
54502
|
-
if (next !== (previous ?? ""))
|
|
54503
|
-
|
|
54572
|
+
if (next !== (previous ?? "")) {
|
|
54573
|
+
if (previous !== null && isDeepStrictEqual7(Bun.TOML.parse(previous), Bun.TOML.parse(next))) {
|
|
54574
|
+
observedSettings = { path: configPath, before: previous };
|
|
54575
|
+
} else
|
|
54576
|
+
changes.push({ path: configPath, before: previous, after: next });
|
|
54577
|
+
}
|
|
54504
54578
|
}
|
|
54505
54579
|
}
|
|
54506
54580
|
const codexPluginSkillReview = options.codexNativeCatalog ? { version: options.codexNativeCatalog.version, cwd: options.codexNativeCatalog.cwd, catalogSha256: sha3(JSON.stringify({ version: options.codexNativeCatalog.version, cwd: options.codexNativeCatalog.cwd, skills: projectCodexNativeSkillCatalog({ data: [{ cwd: options.codexNativeCatalog.cwd, errors: [], skills: options.codexNativeCatalog.skills }] }, options.codexNativeCatalog.cwd), ...options.codexNativeCatalog.plugins === undefined ? {} : { plugins: projectCodexInstalledPluginEntries(options.codexNativeCatalog.plugins) } })), configSha256: changes.find((change) => change.path === canonicalAgentPath(join27(home, ".codex/config.toml"), aliases))?.before === null ? null : sha3(readOptional(canonicalAgentPath(join27(home, ".codex/config.toml"), aliases)) ?? "") } : policy.bridge?.codexPluginSkillReview;
|
|
@@ -54533,7 +54607,7 @@ function planAgentIntegration(options) {
|
|
|
54533
54607
|
if (JSON.stringify(policy) !== JSON.stringify(nextPolicy))
|
|
54534
54608
|
changes.push({ path: policyPath, before: previousPolicy, after: serializedPolicy });
|
|
54535
54609
|
recheckRootAliases(aliases);
|
|
54536
|
-
return { dataDir: dataDir3, profileId, changes, nativeSkills, ...observedNativeSources.length ? { observedNativeSources } : {}, ...nextPolicy.bridge.codexPluginSkillReview ? { codexPluginSkillReview: nextPolicy.bridge.codexPluginSkillReview } : {}, observedPolicy: { path: policyPath, before: previousPolicy }, discoveryBefore: discoveries, discoveryAfter, ...aliases.length ? { rootAliases: aliases } : {}, ...retainedAgents.length ? { retainedReviewChecks: { home, projectDir: options.projectDir ?? home, agents: retainedAgents } } : {} };
|
|
54610
|
+
return { dataDir: dataDir3, profileId, changes, nativeSkills, ...observedSettings ? { observedSettings } : {}, ...observedNativeSources.length ? { observedNativeSources } : {}, ...nextPolicy.bridge.codexPluginSkillReview ? { codexPluginSkillReview: nextPolicy.bridge.codexPluginSkillReview } : {}, observedPolicy: { path: policyPath, before: previousPolicy }, discoveryBefore: discoveries, discoveryAfter, ...aliases.length ? { rootAliases: aliases } : {}, ...retainedAgents.length ? { retainedReviewChecks: { home, projectDir: options.projectDir ?? home, agents: retainedAgents } } : {} };
|
|
54537
54611
|
}
|
|
54538
54612
|
function hookProjectionRefusal(reason) {
|
|
54539
54613
|
throw new Error(`CLAUDE_MANAGED_HOOK_${reason}`);
|
|
@@ -54738,7 +54812,7 @@ function planAgentSettingsWitnessUpgrade(options) {
|
|
|
54738
54812
|
const binding = policy.bridge?.discovery?.[options.agent];
|
|
54739
54813
|
if (!binding || binding.agent !== options.agent || binding.method !== "reviewed")
|
|
54740
54814
|
throw new Error("Settings witness upgrade requires an existing reviewed native binding");
|
|
54741
|
-
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);
|
|
54742
54816
|
const settings = readOptional(configPath);
|
|
54743
54817
|
if (settings === null || sha3(settings) !== options.expectedSettingsSha256)
|
|
54744
54818
|
throw new Error("Native settings preimage changed");
|
|
@@ -54764,7 +54838,19 @@ function planAgentSettingsWitnessUpgrade(options) {
|
|
|
54764
54838
|
replaced.push(source);
|
|
54765
54839
|
}
|
|
54766
54840
|
}
|
|
54767
|
-
|
|
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);
|
|
54768
54854
|
const rebound = [];
|
|
54769
54855
|
for (const source of binding.sources) {
|
|
54770
54856
|
if (!replaced.includes(source)) {
|
|
@@ -55125,7 +55211,7 @@ function assertManagedAgentBridgeWithDiscovery(agent, options = {}, provenDiscov
|
|
|
55125
55211
|
throw new Error("NATIVE_SKILL_DRIFT: Hermes supervisor binding changed; run skills hook install");
|
|
55126
55212
|
assertHermesProtection(home, config, command, profile, supervisor);
|
|
55127
55213
|
} else if (agent === "sumi") {
|
|
55128
|
-
if (JSON.stringify(config.permissions?.filter((rule) => rule.action === "skill")) !== JSON.stringify(SUMI_SKILL_PERMISSIONS) || readOptional(join27(sumiConfigDirectory(home), "plugins", "skills-cli.js"))
|
|
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))
|
|
55129
55215
|
throw new Error("NATIVE_SKILL_DRIFT: Sumi bridge protection changed; run skills hook install");
|
|
55130
55216
|
} else if (agent === "opencode") {
|
|
55131
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))
|
|
@@ -55271,8 +55357,9 @@ function assertNativeExportAllowed(dataDir3 = getDataDirReadOnly()) {
|
|
|
55271
55357
|
if (requiresCliSkillLoading(dataDir3))
|
|
55272
55358
|
throw new Error("NATIVE_SKILL_EXPORT_DISABLED: this station loads skills through the Skills CLI; use skills sync --selection-profile <id>");
|
|
55273
55359
|
}
|
|
55274
|
-
var sha3 = (data) =>
|
|
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.";
|
|
55275
55361
|
var init_agent_integration = __esm(() => {
|
|
55362
|
+
init_sumi_settings_witness();
|
|
55276
55363
|
init_codex_corpus_write();
|
|
55277
55364
|
init_codex_plugin_skill_controls();
|
|
55278
55365
|
init_codex_native_skill_policy();
|
|
@@ -56885,7 +56972,7 @@ var init_selection_resolver = __esm(() => {
|
|
|
56885
56972
|
});
|
|
56886
56973
|
|
|
56887
56974
|
// src/lib/plugin-projection.ts
|
|
56888
|
-
import { createHash as
|
|
56975
|
+
import { createHash as createHash18 } from "crypto";
|
|
56889
56976
|
import { posix } from "path";
|
|
56890
56977
|
function pluginRefusal(message) {
|
|
56891
56978
|
throw new SkillSelectionError("PLUGIN_ADMISSION_REFUSED", message);
|
|
@@ -57078,7 +57165,7 @@ function buildPluginProjection(entries) {
|
|
|
57078
57165
|
files.sort((a, b) => a.path < b.path ? -1 : a.path > b.path ? 1 : 0);
|
|
57079
57166
|
return { manifest, payloads: manifest.payloads, files, witnesses: pluginFileWitnesses(files), originalTreeDigest, projectionTreeDigest: pluginTreeDigest(files), removed: removed.length ? pluginFileWitnesses(removed) : [] };
|
|
57080
57167
|
}
|
|
57081
|
-
var PLUGIN_PROJECTION_MANIFEST = "plugin-projection.json", PLUGIN_PROJECTION_LIMITS, pluginHash = (bytes) =>
|
|
57168
|
+
var PLUGIN_PROJECTION_MANIFEST = "plugin-projection.json", PLUGIN_PROJECTION_LIMITS, pluginHash = (bytes) => createHash18("sha256").update(bytes).digest("hex"), MANIFEST_FIELDS;
|
|
57082
57169
|
var init_plugin_projection = __esm(() => {
|
|
57083
57170
|
init_selection_cache();
|
|
57084
57171
|
PLUGIN_PROJECTION_LIMITS = Object.freeze({ files: 1024, bytes: 64 * 1024 * 1024, fileBytes: 16 * 1024 * 1024, metadataBytes: 512 * 1024, registrations: 64, history: 128 });
|
|
@@ -57086,7 +57173,7 @@ var init_plugin_projection = __esm(() => {
|
|
|
57086
57173
|
});
|
|
57087
57174
|
|
|
57088
57175
|
// src/lib/plugin-projection-store.ts
|
|
57089
|
-
import { createHash as
|
|
57176
|
+
import { createHash as createHash19, randomUUID as randomUUID7 } from "crypto";
|
|
57090
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";
|
|
57091
57178
|
import { dirname as dirname16, isAbsolute as isAbsolute14, join as join33, parse as parse5, resolve as resolve15 } from "path";
|
|
57092
57179
|
function stat(path) {
|
|
@@ -57424,7 +57511,7 @@ function pluginExecutableDigest(path) {
|
|
|
57424
57511
|
const opened = fstatSync11(fd, { bigint: true });
|
|
57425
57512
|
same3(before2, opened);
|
|
57426
57513
|
fileShape(opened, maximum, "executable");
|
|
57427
|
-
const hash2 =
|
|
57514
|
+
const hash2 = createHash19("sha256"), buffer = new Uint8Array(64 * 1024);
|
|
57428
57515
|
let remaining = Number(opened.size);
|
|
57429
57516
|
while (remaining > 0) {
|
|
57430
57517
|
const count = readSync9(fd, buffer, 0, Math.min(buffer.byteLength, remaining), null);
|
|
@@ -58007,7 +58094,7 @@ var init_plugin_discovery = __esm(() => {
|
|
|
58007
58094
|
});
|
|
58008
58095
|
|
|
58009
58096
|
// src/lib/claude-marketplace-registry.ts
|
|
58010
|
-
import { createHash as
|
|
58097
|
+
import { createHash as createHash20 } from "crypto";
|
|
58011
58098
|
import { closeSync as closeSync13, constants as constants14, fstatSync as fstatSync13, lstatSync as lstatSync23, openSync as openSync13, readSync as readSync11 } from "fs";
|
|
58012
58099
|
import { basename as basename9, dirname as dirname18, isAbsolute as isAbsolute17, resolve as resolve18 } from "path";
|
|
58013
58100
|
function need6(value, reason) {
|
|
@@ -58027,13 +58114,13 @@ function parents2(path) {
|
|
|
58027
58114
|
return result2;
|
|
58028
58115
|
}
|
|
58029
58116
|
}
|
|
58030
|
-
function readRegistry2(path,
|
|
58117
|
+
function readRegistry2(path, budget2) {
|
|
58031
58118
|
absolutePath3(path);
|
|
58032
58119
|
need6(basename9(path) === "known_marketplaces.json", "requires known_marketplaces.json");
|
|
58033
|
-
need6(Number.isSafeInteger(
|
|
58120
|
+
need6(Number.isSafeInteger(budget2.remaining) && budget2.remaining >= 0, "has an invalid byte budget");
|
|
58034
58121
|
const ancestors2 = parents2(path), initial2 = lstatSync23(path, { bigint: true });
|
|
58035
58122
|
need6(initial2.isFile() && !initial2.isSymbolicLink() && initial2.size <= BigInt(CLAUDE_MARKETPLACE_REGISTRY_LIMITS.bytes), "is not a bounded regular file");
|
|
58036
|
-
need6(initial2.size <= BigInt(
|
|
58123
|
+
need6(initial2.size <= BigInt(budget2.remaining), "exceeds its aggregate byte limit");
|
|
58037
58124
|
const fd = openSync13(path, constants14.O_RDONLY | constants14.O_NOFOLLOW | constants14.O_NONBLOCK);
|
|
58038
58125
|
try {
|
|
58039
58126
|
const opened = fstatSync13(fd, { bigint: true });
|
|
@@ -58052,7 +58139,7 @@ function readRegistry2(path, budget) {
|
|
|
58052
58139
|
const now3 = lstatSync23(ancestor, { bigint: true });
|
|
58053
58140
|
need6(now3.isDirectory() && before2.dev === now3.dev && before2.ino === now3.ino && before2.mode === now3.mode, "parent changed during read");
|
|
58054
58141
|
}
|
|
58055
|
-
|
|
58142
|
+
budget2.remaining -= length;
|
|
58056
58143
|
try {
|
|
58057
58144
|
return new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(bytes.subarray(0, length));
|
|
58058
58145
|
} catch {
|
|
@@ -58169,18 +58256,18 @@ function normalizeRow(row, version = 1) {
|
|
|
58169
58256
|
need6(Number.isFinite(millis) && new Date(millis).toISOString() === updated, "contains an invalid recognized update timestamp");
|
|
58170
58257
|
row.entries = row.entries.map(([key, value]) => [key, key === "lastUpdated" ? { kind: "validated-update-time" } : value]);
|
|
58171
58258
|
}
|
|
58172
|
-
function captureClaudeMarketplaceRegistry(path,
|
|
58173
|
-
const value = parse6(readRegistry2(path,
|
|
58259
|
+
function captureClaudeMarketplaceRegistry(path, budget2 = { remaining: 256 * 1024 * 1024 }) {
|
|
58260
|
+
const value = parse6(readRegistry2(path, budget2));
|
|
58174
58261
|
for (const [, row] of value.entries)
|
|
58175
58262
|
normalizeRow(row);
|
|
58176
|
-
const sha2562 =
|
|
58263
|
+
const sha2562 = createHash20("sha256").update("hasna.skills.claude-marketplace-registry.v1\x00").update(JSON.stringify(value)).digest("hex");
|
|
58177
58264
|
return { path, hashMode: "claude-marketplace-registry", sha256: sha2562 };
|
|
58178
58265
|
}
|
|
58179
|
-
function captureClaudeMarketplaceRegistryV2(path,
|
|
58180
|
-
const value = parse6(readRegistry2(path,
|
|
58266
|
+
function captureClaudeMarketplaceRegistryV2(path, budget2 = { remaining: 256 * 1024 * 1024 }) {
|
|
58267
|
+
const value = parse6(readRegistry2(path, budget2));
|
|
58181
58268
|
for (const [, row] of value.entries)
|
|
58182
58269
|
normalizeRow(row, 2);
|
|
58183
|
-
const sha2562 =
|
|
58270
|
+
const sha2562 = createHash20("sha256").update("hasna.skills.claude-marketplace-registry.v2\x00").update(JSON.stringify(value)).digest("hex");
|
|
58184
58271
|
return { path, hashMode: "claude-marketplace-registry-v2", sha256: sha2562 };
|
|
58185
58272
|
}
|
|
58186
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];
|
|
@@ -58406,7 +58493,7 @@ var init_codex_hook_additions_review = __esm(() => {
|
|
|
58406
58493
|
});
|
|
58407
58494
|
|
|
58408
58495
|
// src/lib/codex-hook-discovery-recovery.ts
|
|
58409
|
-
import { createHash as
|
|
58496
|
+
import { createHash as createHash21 } from "crypto";
|
|
58410
58497
|
import { isDeepStrictEqual as isDeepStrictEqual10 } from "util";
|
|
58411
58498
|
function createCodexHookDiscoveryRecovery(binding, before2, current, hooks, additions) {
|
|
58412
58499
|
const journalHooks = hooks.map(({ key, currentHash }) => ({ key, currentHash }));
|
|
@@ -58456,7 +58543,7 @@ function verifiesCodexHookDiscoverySource(binding, source, currentDigest, witnes
|
|
|
58456
58543
|
need5(source.sha256 === witness.beforeSha256 && currentDigest === witness.currentSha256, "RECONCILE_DISCOVERY_RECOVERY_CHANGED");
|
|
58457
58544
|
return true;
|
|
58458
58545
|
}
|
|
58459
|
-
var sha4 = (text3) =>
|
|
58546
|
+
var sha4 = (text3) => createHash21("sha256").update(text3).digest("hex"), fields, structure2 = (text3) => JSON.parse(JSON.stringify(Bun.TOML.parse(text3))), proofs2;
|
|
58460
58547
|
var init_codex_hook_discovery_recovery = __esm(() => {
|
|
58461
58548
|
init_codex_hook_trust_files();
|
|
58462
58549
|
init_codex_hook_trust_layout();
|
|
@@ -58467,7 +58554,7 @@ var init_codex_hook_discovery_recovery = __esm(() => {
|
|
|
58467
58554
|
});
|
|
58468
58555
|
|
|
58469
58556
|
// src/lib/agent-discovery.ts
|
|
58470
|
-
import { createHash as
|
|
58557
|
+
import { createHash as createHash22 } from "crypto";
|
|
58471
58558
|
import { lstatSync as lstatSync24, readFileSync as readFileSync20, readdirSync as readdirSync11, realpathSync as realpathSync10 } from "fs";
|
|
58472
58559
|
import { basename as basename10, dirname as dirname19, isAbsolute as isAbsolute19, join as join36, resolve as resolve19, sep as sep7 } from "path";
|
|
58473
58560
|
import { isDeepStrictEqual as isDeepStrictEqual11 } from "util";
|
|
@@ -58508,33 +58595,45 @@ function projectNativeDiscoveryFields(text3, format, fields2, path) {
|
|
|
58508
58595
|
throw new Error("Expected native discovery configuration object");
|
|
58509
58596
|
return digest(JSON.stringify(Object.fromEntries(fields2.map((field2) => [field2, object6[field2] ?? null]))));
|
|
58510
58597
|
}
|
|
58511
|
-
function
|
|
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]);
|
|
58512
58601
|
return agent === "codex" && source.path === configPath && source.format === "toml" && isDeepStrictEqual11(source.fields, [...CODEX_DISCOVERY_PROJECTION_FIELDS]);
|
|
58513
58602
|
}
|
|
58514
|
-
function
|
|
58515
|
-
|
|
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")));
|
|
58516
58607
|
}
|
|
58517
|
-
function projected(source, changes,
|
|
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
|
+
}
|
|
58518
58617
|
if (source.hashMode === "codex-settings-v1" || source.hashMode === "codex-settings-v2" || (source.hashMode === "codex-settings-v3" || source.hashMode === "codex-settings-v4")) {
|
|
58519
58618
|
if (source.format !== undefined || source.fields !== undefined || source.managedPlugins !== undefined || typeof source.sha256 !== "string" || !/^[a-f0-9]{64}$/.test(source.sha256))
|
|
58520
58619
|
throw new Error("Codex settings witnesses require exact typed metadata");
|
|
58521
|
-
const current = (source.hashMode === "codex-settings-v4" ? captureCodexSettingsV4 : source.hashMode === "codex-settings-v3" ? captureCodexSettingsV3 : source.hashMode === "codex-settings-v2" ? captureCodexSettingsV2 : captureCodexSettings)(source.path,
|
|
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;
|
|
58522
58621
|
if (current !== source.sha256)
|
|
58523
58622
|
throw new Error(`Native discovery input changed; run skills hook install with a fresh discovery review: ${source.path}`);
|
|
58524
|
-
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),
|
|
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;
|
|
58525
58624
|
}
|
|
58526
58625
|
if (source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || source.hashMode === "claude-settings-v3") {
|
|
58527
58626
|
if (source.format !== undefined || source.fields !== undefined || source.managedPlugins !== undefined || typeof source.sha256 !== "string" || !/^[a-f0-9]{64}$/.test(source.sha256))
|
|
58528
58627
|
throw new Error("Claude settings witnesses require exact typed metadata");
|
|
58529
|
-
const current = (source.hashMode === "claude-settings-v3" ? captureClaudeSettingsV3 : source.hashMode === "claude-settings-v2" ? captureClaudeSettingsV2 : captureClaudeSettings)(source.path,
|
|
58628
|
+
const current = (source.hashMode === "claude-settings-v3" ? captureClaudeSettingsV3 : source.hashMode === "claude-settings-v2" ? captureClaudeSettingsV2 : captureClaudeSettings)(source.path, budget2).sha256;
|
|
58530
58629
|
if (current !== source.sha256)
|
|
58531
58630
|
throw new Error(`Native discovery input changed; run skills hook install with a fresh discovery review: ${source.path}`);
|
|
58532
|
-
return changes?.has(source.path) ? (source.hashMode === "claude-settings-v3" ? hashClaudeSettingsReplacementV3 : source.hashMode === "claude-settings-v2" ? hashClaudeSettingsReplacementV2 : hashClaudeSettingsReplacement)(changes.get(source.path),
|
|
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;
|
|
58533
58632
|
}
|
|
58534
58633
|
if (source.hashMode === "claude-marketplace-registry" || source.hashMode === "claude-marketplace-registry-v2") {
|
|
58535
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))
|
|
58536
58635
|
throw new Error("Claude marketplace witnesses require an exact reviewed registry without synthetic changes");
|
|
58537
|
-
const sha2562 = (source.hashMode === "claude-marketplace-registry-v2" ? captureClaudeMarketplaceRegistryV2 : captureClaudeMarketplaceRegistry)(source.path,
|
|
58636
|
+
const sha2562 = (source.hashMode === "claude-marketplace-registry-v2" ? captureClaudeMarketplaceRegistryV2 : captureClaudeMarketplaceRegistry)(source.path, budget2).sha256;
|
|
58538
58637
|
if (sha2562 !== source.sha256)
|
|
58539
58638
|
throw new Error(`Native discovery input changed; run skills hook install with a fresh discovery review: ${source.path}`);
|
|
58540
58639
|
return sha2562;
|
|
@@ -58552,8 +58651,8 @@ function projected(source, changes, budget = discoveryByteBudget()) {
|
|
|
58552
58651
|
if (source.format !== undefined || source.fields !== undefined)
|
|
58553
58652
|
throw new Error("Raw discovery witnesses cannot project configuration fields");
|
|
58554
58653
|
if (source.hashMode === "path-bytes")
|
|
58555
|
-
return hashDiscoveryPathFile(source.path,
|
|
58556
|
-
return hashRawDiscoveryFile(source.path,
|
|
58654
|
+
return hashDiscoveryPathFile(source.path, budget2, changes);
|
|
58655
|
+
return hashRawDiscoveryFile(source.path, budget2, changes);
|
|
58557
58656
|
}
|
|
58558
58657
|
const text3 = read2(source.path, changes);
|
|
58559
58658
|
if (text3 === null)
|
|
@@ -58701,7 +58800,7 @@ function verifyAgentDiscovery(binding, codexRecovery) {
|
|
|
58701
58800
|
verifyDiscoveryDirectories(projected2, installationRoots);
|
|
58702
58801
|
}
|
|
58703
58802
|
const absentRoots = [...absentCodexSkillRoots(binding), ...absentRetiredClaudeRoots(binding), ...retiredRoots.filter((root2) => !lstatSync24(root2, { throwIfNoEntry: false }))];
|
|
58704
|
-
const
|
|
58803
|
+
const budget2 = discoveryByteBudget();
|
|
58705
58804
|
for (const source of binding.sources) {
|
|
58706
58805
|
assertMarketplaceBinding(binding, source);
|
|
58707
58806
|
if (source.hashMode === "claude-plugin-registry" && binding.agent !== "claude")
|
|
@@ -58718,7 +58817,7 @@ function verifyAgentDiscovery(binding, codexRecovery) {
|
|
|
58718
58817
|
safe4(source.path);
|
|
58719
58818
|
continue;
|
|
58720
58819
|
}
|
|
58721
|
-
const current = projected(source, undefined,
|
|
58820
|
+
const current = projected(source, undefined, budget2);
|
|
58722
58821
|
if (current !== source.sha256 && !verifiesCodexHookDiscoverySource(binding, source, current, codexRecovery))
|
|
58723
58822
|
throw new Error(`Native discovery input changed; run skills hook install with a fresh discovery review: ${source.path}`);
|
|
58724
58823
|
}
|
|
@@ -58752,6 +58851,8 @@ function codexInstallationRoots(binding) {
|
|
|
58752
58851
|
});
|
|
58753
58852
|
}
|
|
58754
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");
|
|
58755
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"))
|
|
58756
58857
|
throw new Error("Codex settings witnesses require explicit reviewed Codex configuration");
|
|
58757
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"))
|
|
@@ -58760,13 +58861,13 @@ function assertMarketplaceBinding(binding, source) {
|
|
|
58760
58861
|
throw new Error("Claude marketplace witnesses require explicit reviewed Claude discovery");
|
|
58761
58862
|
}
|
|
58762
58863
|
function rebindAgentDiscovery(binding, changes) {
|
|
58763
|
-
const
|
|
58864
|
+
const budget2 = discoveryByteBudget();
|
|
58764
58865
|
const installationRoots = codexInstallationRoots(binding), absentRoots = [...absentCodexSkillRoots(binding), ...absentRetiredClaudeRoots(binding), ...retiredCodexRoots(binding).filter((root2) => !lstatSync24(root2, { throwIfNoEntry: false }))];
|
|
58765
58866
|
const rebound = { ...binding, sources: binding.sources.map((source) => {
|
|
58766
58867
|
assertMarketplaceBinding(binding, source);
|
|
58767
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)))
|
|
58768
58869
|
return source;
|
|
58769
|
-
const sha2562 = projected(source, changes,
|
|
58870
|
+
const sha2562 = projected(source, changes, budget2);
|
|
58770
58871
|
if (!changes.has(source.path) && sha2562 !== source.sha256)
|
|
58771
58872
|
throw new Error(`Native discovery input changed; run skills hook install with a fresh discovery review: ${source.path}`);
|
|
58772
58873
|
return { ...source, sha256: sha2562 };
|
|
@@ -58844,7 +58945,7 @@ function resolveAgentDiscovery(options) {
|
|
|
58844
58945
|
if (agent === "hermes")
|
|
58845
58946
|
assertHermesEnvironment(home);
|
|
58846
58947
|
const configPath = agentDiscoveryConfigPath(home, agent);
|
|
58847
|
-
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" ? [
|
|
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"]);
|
|
58848
58949
|
const config = configText === null ? {} : agent === "hermes" ? parseHermesConfig(configText) : parseConfig(configText, configPath, agent === "codex");
|
|
58849
58950
|
const unresolved = (detail) => {
|
|
58850
58951
|
throw new Error(`Native discovery is unresolved (${agent}: ${detail}); provide a reviewed --discovery-inputs file`);
|
|
@@ -58941,9 +59042,9 @@ function resolveAgentDiscovery(options) {
|
|
|
58941
59042
|
verifyAgentDiscovery(retained);
|
|
58942
59043
|
if (!retained.sources.some((source) => source.path === canonical6(configPath) && source.format === undefined && source.fields === undefined))
|
|
58943
59044
|
unresolved("retained review is missing the full agent configuration source");
|
|
58944
|
-
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)))
|
|
58945
59046
|
unresolved("retained settings witness names another configuration source");
|
|
58946
|
-
const covered =
|
|
59047
|
+
const covered = supersedesSettingsProjection(agent, retained.sources, canonical6(configPath)) ? sources.filter((source) => !isSupersededSettingsProjection(agent, canonical6(configPath), source)) : sources;
|
|
58947
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))
|
|
58948
59049
|
unresolved("retained review is missing current runtime discovery coverage");
|
|
58949
59050
|
return retained;
|
|
@@ -58958,11 +59059,11 @@ function resolveAgentDiscovery(options) {
|
|
|
58958
59059
|
if (review.sources.some((source) => source.format !== undefined || source.fields !== undefined))
|
|
58959
59060
|
throw new Error("Explicit discovery reviews require full source-file hashes");
|
|
58960
59061
|
verifyAgentDiscovery(supplied);
|
|
58961
|
-
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)))
|
|
58962
|
-
throw new Error("Semantic settings witnesses must name the configured
|
|
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");
|
|
58963
59064
|
if (!review.sources.some((source) => source.path === canonical6(configPath)))
|
|
58964
59065
|
throw new Error("Discovery review must include the agent configuration source");
|
|
58965
|
-
const reviewedSources =
|
|
59066
|
+
const reviewedSources = supersedesSettingsProjection(agent, review.sources, canonical6(configPath)) ? sources.filter((source) => !isSupersededSettingsProjection(agent, canonical6(configPath), source)) : sources;
|
|
58966
59067
|
return { ...supplied, roots: [...new Set([...roots, ...supplied.roots])].sort(), sources: [...reviewedSources, ...review.sources], ...agent === "gemini" ? { builtinNames } : {} };
|
|
58967
59068
|
}
|
|
58968
59069
|
function plugin(root2) {
|
|
@@ -59077,8 +59178,9 @@ function resolveAgentDiscovery(options) {
|
|
|
59077
59178
|
}
|
|
59078
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))) } : {} };
|
|
59079
59180
|
}
|
|
59080
|
-
var digest = (text3) =>
|
|
59181
|
+
var digest = (text3) => createHash22("sha256").update(text3).digest("hex");
|
|
59081
59182
|
var init_agent_discovery = __esm(() => {
|
|
59183
|
+
init_sumi_settings_witness();
|
|
59082
59184
|
init_agent_policy_limits();
|
|
59083
59185
|
init_agent_hermes();
|
|
59084
59186
|
init_agent_discovery_directories();
|
|
@@ -62016,7 +62118,7 @@ var init_remote_workspace_selection = __esm(() => {
|
|
|
62016
62118
|
});
|
|
62017
62119
|
|
|
62018
62120
|
// src/lib/remote-private-publications.ts
|
|
62019
|
-
import { createHash as
|
|
62121
|
+
import { createHash as createHash23 } from "crypto";
|
|
62020
62122
|
function checkedPublicationDeclaration(value) {
|
|
62021
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)
|
|
62022
62124
|
return bad();
|
|
@@ -62036,7 +62138,7 @@ function checkedPublicationView(value, skillId, intentId, declaration) {
|
|
|
62036
62138
|
return invalid3();
|
|
62037
62139
|
return Object.freeze({ ...value });
|
|
62038
62140
|
}
|
|
62039
|
-
async function boundedJson(url, init, token, mutation,
|
|
62141
|
+
async function boundedJson(url, init, token, mutation, budget2 = 15000, signal) {
|
|
62040
62142
|
const controller = new AbortController;
|
|
62041
62143
|
let reader;
|
|
62042
62144
|
let response;
|
|
@@ -62091,7 +62193,7 @@ async function boundedJson(url, init, token, mutation, budget = 15000, signal) {
|
|
|
62091
62193
|
controller.abort();
|
|
62092
62194
|
reject2(timeout);
|
|
62093
62195
|
};
|
|
62094
|
-
timer = setTimeout(abort, Math.max(1, Math.min(15000,
|
|
62196
|
+
timer = setTimeout(abort, Math.max(1, Math.min(15000, budget2)));
|
|
62095
62197
|
signal?.addEventListener("abort", abort, { once: true });
|
|
62096
62198
|
})]);
|
|
62097
62199
|
} catch (error) {
|
|
@@ -62277,7 +62379,7 @@ var PRIVATE_PUBLICATION_MAX_BYTES, failures, PrivatePublicationError, bad = () =
|
|
|
62277
62379
|
throw new PrivatePublicationError("INVALID_PUBLICATION_INPUT", "Invalid publication input or recovery data.");
|
|
62278
62380
|
}, invalid3 = () => {
|
|
62279
62381
|
throw new PrivatePublicationError("INVALID_PUBLICATION_RESPONSE", "The server returned an invalid publication result.");
|
|
62280
|
-
}, 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) =>
|
|
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");
|
|
62281
62383
|
var init_remote_private_publications = __esm(() => {
|
|
62282
62384
|
init_fleet_credentials();
|
|
62283
62385
|
init_remote_workspace_selection();
|
|
@@ -81666,7 +81768,7 @@ var init_v4 = __esm(() => {
|
|
|
81666
81768
|
});
|
|
81667
81769
|
|
|
81668
81770
|
// src/lib/canonical-json.ts
|
|
81669
|
-
import { createHash as
|
|
81771
|
+
import { createHash as createHash24 } from "crypto";
|
|
81670
81772
|
function canonicalJson2(value, maximumBytes = 2 * 1024 * 1024) {
|
|
81671
81773
|
return canonicalJsonAtDepth(value, maximumBytes, 64);
|
|
81672
81774
|
}
|
|
@@ -81710,7 +81812,7 @@ function canonicalJsonAtDepth(value, maximumBytes, maximumDepth) {
|
|
|
81710
81812
|
return visit3(value, 0);
|
|
81711
81813
|
}
|
|
81712
81814
|
function canonicalJsonSha256(value, maximumBytes) {
|
|
81713
|
-
return
|
|
81815
|
+
return createHash24("sha256").update(canonicalJson2(value, maximumBytes)).digest("hex");
|
|
81714
81816
|
}
|
|
81715
81817
|
var init_canonical_json = () => {};
|
|
81716
81818
|
|
|
@@ -81889,7 +81991,7 @@ function parseRecurringResult(action, value, input2, identity6) {
|
|
|
81889
81991
|
}
|
|
81890
81992
|
return result2;
|
|
81891
81993
|
}
|
|
81892
|
-
var RecurringInputError, RemoteRecurringUnavailableError, RemoteRecurringReadError, RemoteRecurringUnconfirmedError, failures2, RemoteRecurringError, uuid10, instant2, integer2, digest2, list, inputs, capabilityNames,
|
|
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;
|
|
81893
81995
|
var init_remote_recurring = __esm(() => {
|
|
81894
81996
|
init_v4();
|
|
81895
81997
|
init_canonical_json();
|
|
@@ -81975,7 +82077,7 @@ var init_remote_recurring = __esm(() => {
|
|
|
81975
82077
|
occurrences: "recurring.occurrences",
|
|
81976
82078
|
revoke: "recurring.revoke"
|
|
81977
82079
|
};
|
|
81978
|
-
|
|
82080
|
+
budget2 = exports_external.object({ reservedCredits: integer2, settledCredits: integer2, admittedOccurrences: integer2 });
|
|
81979
82081
|
period = exports_external.object({ startsAt: instant2, endsAt: instant2 });
|
|
81980
82082
|
preview = exports_external.object({
|
|
81981
82083
|
contractVersion: exports_external.literal(1),
|
|
@@ -81997,8 +82099,8 @@ var init_remote_recurring = __esm(() => {
|
|
|
81997
82099
|
state: exports_external.enum(["active", "revoked", "expired"]),
|
|
81998
82100
|
activatedAt: instant2,
|
|
81999
82101
|
revokedAt: instant2.nullable(),
|
|
82000
|
-
total:
|
|
82001
|
-
currentPeriod:
|
|
82102
|
+
total: budget2,
|
|
82103
|
+
currentPeriod: budget2.extend(period.shape).nullable(),
|
|
82002
82104
|
nextDueAt: instant2.nullable()
|
|
82003
82105
|
});
|
|
82004
82106
|
refusal2 = exports_external.enum([
|
|
@@ -83624,7 +83726,7 @@ var init_remote_auth = __esm(() => {
|
|
|
83624
83726
|
});
|
|
83625
83727
|
|
|
83626
83728
|
// src/lib/sign-in.ts
|
|
83627
|
-
import { createHash as
|
|
83729
|
+
import { createHash as createHash25 } from "crypto";
|
|
83628
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";
|
|
83629
83731
|
import { basename as basename14, dirname as dirname23, join as join41 } from "path";
|
|
83630
83732
|
function isRecord7(value) {
|
|
@@ -83775,7 +83877,7 @@ function pendingDeviceSignInStem(env3) {
|
|
|
83775
83877
|
}
|
|
83776
83878
|
function pendingDeviceSignInPath(origin, env3 = process.env) {
|
|
83777
83879
|
const { dir, stem } = pendingDeviceSignInStem(env3);
|
|
83778
|
-
return join41(dir, `${stem}-${
|
|
83880
|
+
return join41(dir, `${stem}-${createHash25("sha256").update(origin).digest("hex").slice(0, 16)}.json`);
|
|
83779
83881
|
}
|
|
83780
83882
|
function savePendingDeviceSignIn(origin, start, env3 = process.env, now3 = Date.now()) {
|
|
83781
83883
|
const path = pendingDeviceSignInPath(origin, env3);
|
|
@@ -84479,7 +84581,7 @@ function optionPrefix(program2, args) {
|
|
|
84479
84581
|
}
|
|
84480
84582
|
|
|
84481
84583
|
// src/lib/revision.ts
|
|
84482
|
-
import { createHash as
|
|
84584
|
+
import { createHash as createHash26 } from "crypto";
|
|
84483
84585
|
function revisionIdOf(content) {
|
|
84484
84586
|
const canonicalContent = {
|
|
84485
84587
|
slug: content.slug,
|
|
@@ -84500,7 +84602,7 @@ function revisionIdOf(content) {
|
|
|
84500
84602
|
canonicalContent.replacementSlug = content.replacementSlug ?? null;
|
|
84501
84603
|
}
|
|
84502
84604
|
const canonical6 = JSON.stringify(canonicalContent);
|
|
84503
|
-
return
|
|
84605
|
+
return createHash26("sha256").update(canonical6).digest("hex");
|
|
84504
84606
|
}
|
|
84505
84607
|
var REVISION_ID_PATTERN;
|
|
84506
84608
|
var init_revision = __esm(() => {
|
|
@@ -84949,7 +85051,7 @@ var init_pull = __esm(() => {
|
|
|
84949
85051
|
});
|
|
84950
85052
|
|
|
84951
85053
|
// src/lib/skill-context.ts
|
|
84952
|
-
import { createHash as
|
|
85054
|
+
import { createHash as createHash27 } from "crypto";
|
|
84953
85055
|
import { resolve as resolve22 } from "path";
|
|
84954
85056
|
function words2(value) {
|
|
84955
85057
|
return new Set(value.toLowerCase().match(/[a-z0-9]+/g) ?? []);
|
|
@@ -85042,7 +85144,7 @@ ${content}`;
|
|
|
85042
85144
|
`);
|
|
85043
85145
|
const receipt = {
|
|
85044
85146
|
schemaVersion: 1,
|
|
85045
|
-
id:
|
|
85147
|
+
id: createHash27("sha256").update(JSON.stringify({ profile: profile.profileRevision, sessionId, selections, omitted })).digest("hex"),
|
|
85046
85148
|
profileId: profile.profileId,
|
|
85047
85149
|
profileRevision: profile.profileRevision,
|
|
85048
85150
|
authority: profile.authority,
|
|
@@ -85064,7 +85166,7 @@ var init_skill_context = __esm(() => {
|
|
|
85064
85166
|
});
|
|
85065
85167
|
|
|
85066
85168
|
// src/lib/session-reconciliation.ts
|
|
85067
|
-
import { createHash as
|
|
85169
|
+
import { createHash as createHash28 } from "crypto";
|
|
85068
85170
|
import { isDeepStrictEqual as isDeepStrictEqual12 } from "util";
|
|
85069
85171
|
function exactTimestamp(value) {
|
|
85070
85172
|
const parsed = value === undefined ? Number.NaN : Date.parse(value);
|
|
@@ -85204,7 +85306,7 @@ async function reconcileSkillSession(input2, options = {}) {
|
|
|
85204
85306
|
const result2 = replaceSkillSession(skillSessionSnapshotBinding(snapshot2), replacement, { ...plan, planDigest }, options, () => assertPlanWindow(issuedAt, expiresAt, (options.now ?? Date.now)()));
|
|
85205
85307
|
return { applied: true, plan, planDigest, ...result2 };
|
|
85206
85308
|
}
|
|
85207
|
-
var SESSION_RECONCILIATION_PLAN_TTL_MS, digest3 = (value) =>
|
|
85309
|
+
var SESSION_RECONCILIATION_PLAN_TTL_MS, digest3 = (value) => createHash28("sha256").update(JSON.stringify(value)).digest("hex");
|
|
85208
85310
|
var init_session_reconciliation = __esm(() => {
|
|
85209
85311
|
init_profile_client();
|
|
85210
85312
|
init_selection_cache();
|
|
@@ -89846,7 +89948,7 @@ __export(exports_selected_run, {
|
|
|
89846
89948
|
prepareSelectedSecretBindings: () => prepareSelectedSecretBindings,
|
|
89847
89949
|
executeSelectedLocal: () => executeSelectedLocal
|
|
89848
89950
|
});
|
|
89849
|
-
import { createHash as
|
|
89951
|
+
import { createHash as createHash29 } from "crypto";
|
|
89850
89952
|
import { spawn as spawn3 } from "child_process";
|
|
89851
89953
|
import { mkdirSync as mkdirSync16, mkdtempSync as mkdtempSync4, writeFileSync as writeFileSync16, realpathSync as realpathSync14 } from "fs";
|
|
89852
89954
|
import { dirname as dirname25, join as join49, resolve as resolve23 } from "path";
|
|
@@ -89972,7 +90074,7 @@ async function executeSelectedLocal(selected, options = {}) {
|
|
|
89972
90074
|
selection: selection2,
|
|
89973
90075
|
target: "local",
|
|
89974
90076
|
runtime: runtimeName,
|
|
89975
|
-
inputDigest: `sha256:${
|
|
90077
|
+
inputDigest: `sha256:${createHash29("sha256").update(input2).digest("hex")}`,
|
|
89976
90078
|
runDirectory,
|
|
89977
90079
|
...executionGrant ? { executionGrant } : {},
|
|
89978
90080
|
...bindings ? { secretBinding: { schema: bindings.schema, selection: bindings.selection, consumer: bindings.consumer, secretsAuthority: bindings.secretsAuthority, bindings: bindings.bindings } } : {},
|
|
@@ -94189,7 +94291,7 @@ var init_runs = __esm(() => {
|
|
|
94189
94291
|
});
|
|
94190
94292
|
|
|
94191
94293
|
// src/lib/run-state.ts
|
|
94192
|
-
import { createHash as
|
|
94294
|
+
import { createHash as createHash30, randomBytes } from "crypto";
|
|
94193
94295
|
import { existsSync as existsSync28, mkdirSync as mkdirSync17, readFileSync as readFileSync34, readdirSync as readdirSync18, statSync as statSync17, writeFileSync as writeFileSync17 } from "fs";
|
|
94194
94296
|
import { extname, join as join50, relative as relative8 } from "path";
|
|
94195
94297
|
function createSkillRun(params, targetDir = process.cwd()) {
|
|
@@ -94326,7 +94428,7 @@ function collectRunArtifacts(context) {
|
|
|
94326
94428
|
artifacts.push({
|
|
94327
94429
|
path: toProjectRelative(context.targetDir, path),
|
|
94328
94430
|
mime: mimeForPath(path),
|
|
94329
|
-
sha256:
|
|
94431
|
+
sha256: createHash30("sha256").update(bytes).digest("hex"),
|
|
94330
94432
|
sizeBytes: stat2.size
|
|
94331
94433
|
});
|
|
94332
94434
|
}
|
|
@@ -109574,7 +109676,7 @@ var init_schedule_tools = __esm(() => {
|
|
|
109574
109676
|
});
|
|
109575
109677
|
|
|
109576
109678
|
// src/lib/native-storage.ts
|
|
109577
|
-
import { createHash as
|
|
109679
|
+
import { createHash as createHash31, createHmac as createHmac3 } from "crypto";
|
|
109578
109680
|
import {
|
|
109579
109681
|
existsSync as existsSync32,
|
|
109580
109682
|
mkdirSync as mkdirSync22,
|
|
@@ -109651,7 +109753,7 @@ function exportSkillsLocalSnapshot(targetDir = process.cwd(), options = {}) {
|
|
|
109651
109753
|
files.push({
|
|
109652
109754
|
path: relativePath,
|
|
109653
109755
|
sizeBytes: bytes.byteLength,
|
|
109654
|
-
sha256:
|
|
109756
|
+
sha256: createHash31("sha256").update(bytes).digest("hex"),
|
|
109655
109757
|
...options.includeFileContents ? { contentBase64: Buffer.from(bytes).toString("base64") } : {}
|
|
109656
109758
|
});
|
|
109657
109759
|
}
|
|
@@ -110833,7 +110935,7 @@ var init_remote_account2 = __esm(() => {
|
|
|
110833
110935
|
});
|
|
110834
110936
|
|
|
110835
110937
|
// src/cli/commands/reviewed-runtime-lock.ts
|
|
110836
|
-
import { createHash as
|
|
110938
|
+
import { createHash as createHash32 } from "crypto";
|
|
110837
110939
|
function row(value) {
|
|
110838
110940
|
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
110839
110941
|
throw new Error("REVIEWED_LOCK_SHAPE_INVALID");
|
|
@@ -110887,7 +110989,7 @@ async function metadata(name, context2) {
|
|
|
110887
110989
|
async function validateReviewedRuntimeLock(bytes, sha2562, context2) {
|
|
110888
110990
|
if (!/^[a-f0-9]{64}$/.test(sha2562))
|
|
110889
110991
|
throw new Error("REVIEWED_LOCK_SHA256_INVALID");
|
|
110890
|
-
if (bytes.byteLength > MAX_LOCK_BYTES ||
|
|
110992
|
+
if (bytes.byteLength > MAX_LOCK_BYTES || createHash32("sha256").update(bytes).digest("hex") !== sha2562)
|
|
110891
110993
|
throw new Error("REVIEWED_LOCK_HASH_MISMATCH");
|
|
110892
110994
|
if (!Number.isSafeInteger(context2.minReleaseAge) || context2.minReleaseAge < 1)
|
|
110893
110995
|
throw new Error("REVIEWED_LOCK_RELEASE_AGE_REQUIRED");
|
|
@@ -110964,7 +111066,7 @@ var init_reviewed_runtime_lock = __esm(() => {
|
|
|
110964
111066
|
});
|
|
110965
111067
|
|
|
110966
111068
|
// src/cli/commands/runtime-copyfile.ts
|
|
110967
|
-
import { createHash as
|
|
111069
|
+
import { createHash as createHash33, randomUUID as randomUUID10 } from "crypto";
|
|
110968
111070
|
import { Readable } from "stream";
|
|
110969
111071
|
import { createGunzip as createGunzip2 } from "zlib";
|
|
110970
111072
|
import {
|
|
@@ -110988,7 +111090,7 @@ function object10(value, code2) {
|
|
|
110988
111090
|
return value;
|
|
110989
111091
|
}
|
|
110990
111092
|
function hash5(bytes) {
|
|
110991
|
-
return
|
|
111093
|
+
return createHash33("sha256").update(bytes).digest("hex");
|
|
110992
111094
|
}
|
|
110993
111095
|
function isWithin(parent, child) {
|
|
110994
111096
|
const rel = relative10(parent, child);
|
|
@@ -111139,7 +111241,7 @@ function verifyIntegrity(bytes, integrity) {
|
|
|
111139
111241
|
const match = /^sha512-([A-Za-z0-9+/]+={0,2})$/.exec(integrity);
|
|
111140
111242
|
if (!match)
|
|
111141
111243
|
throw new Error("REGISTRY_INTEGRITY_UNSUPPORTED");
|
|
111142
|
-
const actual =
|
|
111244
|
+
const actual = createHash33("sha512").update(bytes).digest("base64");
|
|
111143
111245
|
if (actual !== match[1])
|
|
111144
111246
|
throw new Error("TARBALL_INTEGRITY_MISMATCH");
|
|
111145
111247
|
}
|
|
@@ -112243,7 +112345,7 @@ var exports_runtime = {};
|
|
|
112243
112345
|
__export(exports_runtime, {
|
|
112244
112346
|
registerRuntime: () => registerRuntime
|
|
112245
112347
|
});
|
|
112246
|
-
import { createHash as
|
|
112348
|
+
import { createHash as createHash34, randomUUID as randomUUID11 } from "crypto";
|
|
112247
112349
|
import { lstatSync as lstatSync32, mkdirSync as mkdirSync26, readFileSync as readFileSync40, realpathSync as realpathSync18, writeFileSync as writeFileSync25 } from "fs";
|
|
112248
112350
|
import { basename as basename16, isAbsolute as isAbsolute27, join as join60 } from "path";
|
|
112249
112351
|
import { createInterface } from "readline";
|
|
@@ -112284,7 +112386,7 @@ function registerRuntime(parent) {
|
|
|
112284
112386
|
if (!expected)
|
|
112285
112387
|
throw new Error("Cloud artifact not found");
|
|
112286
112388
|
const bytes = await client2.download(id2, name);
|
|
112287
|
-
if (bytes.length !== expected.byteSize ||
|
|
112389
|
+
if (bytes.length !== expected.byteSize || createHash34("sha256").update(bytes).digest("hex") !== expected.sha256)
|
|
112288
112390
|
throw new Error("Cloud artifact integrity verification failed");
|
|
112289
112391
|
writeFileSync25(options.output, bytes, { flag: "wx", mode: 384 });
|
|
112290
112392
|
console.log(JSON.stringify({ path: options.output, sha256: expected.sha256, byteSize: bytes.length }));
|
|
@@ -113938,7 +114040,7 @@ var init_portable_snapshot_filter = __esm(() => {
|
|
|
113938
114040
|
});
|
|
113939
114041
|
|
|
113940
114042
|
// src/lib/station-snapshot.ts
|
|
113941
|
-
import { createHash as
|
|
114043
|
+
import { createHash as createHash35 } from "crypto";
|
|
113942
114044
|
import {
|
|
113943
114045
|
copyFileSync as copyFileSync2,
|
|
113944
114046
|
mkdirSync as mkdirSync27,
|
|
@@ -113953,7 +114055,7 @@ function validateStationId(stationId) {
|
|
|
113953
114055
|
}
|
|
113954
114056
|
}
|
|
113955
114057
|
function sha256File(filePath) {
|
|
113956
|
-
return
|
|
114058
|
+
return createHash35("sha256").update(readFileSync41(filePath)).digest("hex");
|
|
113957
114059
|
}
|
|
113958
114060
|
function scanHome(definition, homesRoot) {
|
|
113959
114061
|
const homePath = homePathFor(definition, homesRoot);
|
|
@@ -114643,7 +114745,7 @@ var init_codex_hook_policy_recovery = __esm(() => {
|
|
|
114643
114745
|
|
|
114644
114746
|
// src/lib/agent-codex-trust.ts
|
|
114645
114747
|
import { lstatSync as lstatSync34, mkdirSync as mkdirSync28, readdirSync as readdirSync23, readFileSync as readFileSync42, realpathSync as realpathSync20, statSync as statSync22 } from "fs";
|
|
114646
|
-
import { createHash as
|
|
114748
|
+
import { createHash as createHash36, randomUUID as randomUUID12 } from "crypto";
|
|
114647
114749
|
import { execFileSync as execFileSync2 } from "child_process";
|
|
114648
114750
|
import { dirname as dirname36, isAbsolute as isAbsolute30, join as join64, resolve as resolve28 } from "path";
|
|
114649
114751
|
import { homedir as homedir12 } from "os";
|
|
@@ -114653,11 +114755,11 @@ function verifyReleaseArtifact(proof, skillsCli) {
|
|
|
114653
114755
|
const tarPath = realpathSync20(proof.packageTarPath);
|
|
114654
114756
|
need5(statSync22(tarPath).isFile(), "RECONCILE_RELEASE_PROVENANCE_PATH");
|
|
114655
114757
|
const tarBytes = readFileSync42(tarPath);
|
|
114656
|
-
need5(tarBytes.byteLength === proof.packageTarBytes &&
|
|
114758
|
+
need5(tarBytes.byteLength === proof.packageTarBytes && createHash36("sha256").update(tarBytes).digest("hex") === proof.packageTarSha256, "RECONCILE_RELEASE_ARTIFACT_CHANGED");
|
|
114657
114759
|
const packageRoot = dirname36(dirname36(realpathSync20(skillsCli.receipt.path)));
|
|
114658
114760
|
const manifest = readFileSync42(join64(packageRoot, "package.json"));
|
|
114659
|
-
need5(
|
|
114660
|
-
need5(
|
|
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");
|
|
114661
114763
|
const members2 = [["package/package.json", manifest], ["package/bin/index.js", readFileSync42(skillsCli.receipt.path)]];
|
|
114662
114764
|
for (const [member, expected] of members2) {
|
|
114663
114765
|
let actual;
|
|
@@ -114975,7 +115077,7 @@ async function enrollCodexNativeHooksUnlocked(options, connect) {
|
|
|
114975
115077
|
}
|
|
114976
115078
|
}
|
|
114977
115079
|
var json2 = (value) => JSON.stringify(value, null, 2) + `
|
|
114978
|
-
`, structure3 = (text4) => JSON.parse(JSON.stringify(Bun.TOML.parse(text4))), eventNames, makePlanDigest = (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) => {
|
|
114979
115081
|
const copy = structuredClone(value);
|
|
114980
115082
|
if (copy?.bridge?.commands && Object.hasOwn(copy.bridge.commands, "codex"))
|
|
114981
115083
|
copy.bridge.commands.codex = "<reviewed-codex-binding>";
|
|
@@ -114999,7 +115101,7 @@ var init_agent_codex_trust = __esm(() => {
|
|
|
114999
115101
|
});
|
|
115000
115102
|
|
|
115001
115103
|
// src/lib/codex-native-trust.ts
|
|
115002
|
-
import { createHash as
|
|
115104
|
+
import { createHash as createHash37 } from "crypto";
|
|
115003
115105
|
import { readFileSync as readFileSync43 } from "fs";
|
|
115004
115106
|
import { join as join65, resolve as resolve29 } from "path";
|
|
115005
115107
|
function refuse5(detail) {
|
|
@@ -115072,7 +115174,7 @@ function applyCodexNativeTrust(plan, expectedPolicySha256) {
|
|
|
115072
115174
|
receipt.readback = { policySha256: sha6(readback.text), digests, verified: true };
|
|
115073
115175
|
return receipt;
|
|
115074
115176
|
}
|
|
115075
|
-
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) =>
|
|
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");
|
|
115076
115178
|
var init_codex_native_trust = __esm(() => {
|
|
115077
115179
|
init_config();
|
|
115078
115180
|
init_managed_policy();
|
|
@@ -115202,7 +115304,7 @@ __export(exports_agent_integration, {
|
|
|
115202
115304
|
registerAgentIntegration: () => registerAgentIntegration
|
|
115203
115305
|
});
|
|
115204
115306
|
import { existsSync as existsSync36, lstatSync as lstatSync35, readFileSync as readFileSync44, readSync as readSync18, writeFileSync as writeFileSync27 } from "fs";
|
|
115205
|
-
import { createHash as
|
|
115307
|
+
import { createHash as createHash38 } from "crypto";
|
|
115206
115308
|
import { homedir as homedir13 } from "os";
|
|
115207
115309
|
import { isAbsolute as isAbsolute31 } from "path";
|
|
115208
115310
|
function pinnedHookProfile(input3, configuredProfile) {
|
|
@@ -115327,7 +115429,7 @@ function registerAgentIntegration(parent) {
|
|
|
115327
115429
|
skillCount: catalog.skills.length,
|
|
115328
115430
|
output: options.output,
|
|
115329
115431
|
bytes: Buffer.byteLength(bytes),
|
|
115330
|
-
sha256:
|
|
115432
|
+
sha256: createHash38("sha256").update(bytes).digest("hex")
|
|
115331
115433
|
};
|
|
115332
115434
|
await writeCliOutput(options.json ? JSON.stringify(receipt) : `Captured ${receipt.skillCount} native Codex skill(s) in ${receipt.output}.`);
|
|
115333
115435
|
} catch (error61) {
|
|
@@ -115336,16 +115438,16 @@ function registerAgentIntegration(parent) {
|
|
|
115336
115438
|
process.exitCode = 1;
|
|
115337
115439
|
}
|
|
115338
115440
|
});
|
|
115339
|
-
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) => {
|
|
115340
|
-
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;
|
|
115341
115443
|
if (!capture2)
|
|
115342
|
-
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");
|
|
115343
115445
|
await writeCliOutput(JSON.stringify(capture2(options.path), null, 2));
|
|
115344
115446
|
});
|
|
115345
|
-
hook.command("rebind-settings").requiredOption("--agent <agent>", "claude or
|
|
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) => {
|
|
115346
115448
|
try {
|
|
115347
|
-
if (!["claude", "codex"].includes(options.agent))
|
|
115348
|
-
throw new Error("Settings witness rebind accepts claude or
|
|
115449
|
+
if (!["claude", "codex", "sumi"].includes(options.agent))
|
|
115450
|
+
throw new Error("Settings witness rebind accepts claude, codex or sumi");
|
|
115349
115451
|
if (options.codexWitnessVersion !== undefined && !["2", "3", "4"].includes(options.codexWitnessVersion))
|
|
115350
115452
|
throw new Error("Codex witness version accepts 2, 3 or 4");
|
|
115351
115453
|
const plan = planAgentSettingsWitnessUpgrade({ ...options.codexWitnessVersion !== undefined ? { targetCodexVersion: Number(options.codexWitnessVersion) } : {}, agent: options.agent, reviewedPreimage: options.reviewedPreimage, expectedPolicySha256: options.expectedPolicySha256, expectedSettingsSha256: options.expectedSettingsSha256 });
|
|
@@ -115573,6 +115675,7 @@ function registerAgentIntegration(parent) {
|
|
|
115573
115675
|
}
|
|
115574
115676
|
var RECOVERABLE_CONTEXT_CACHE_ERRORS;
|
|
115575
115677
|
var init_agent_integration2 = __esm(() => {
|
|
115678
|
+
init_sumi_settings_witness();
|
|
115576
115679
|
init_agent_hermes();
|
|
115577
115680
|
init_context();
|
|
115578
115681
|
init_agent_adapters();
|
|
@@ -115859,7 +115962,7 @@ var init_grants = __esm(() => {
|
|
|
115859
115962
|
});
|
|
115860
115963
|
|
|
115861
115964
|
// src/lib/station-hydrate.ts
|
|
115862
|
-
import { createHash as
|
|
115965
|
+
import { createHash as createHash39 } from "crypto";
|
|
115863
115966
|
import {
|
|
115864
115967
|
copyFileSync as copyFileSync3,
|
|
115865
115968
|
mkdirSync as mkdirSync29,
|
|
@@ -116062,7 +116165,7 @@ function skillSha256(skill) {
|
|
|
116062
116165
|
return sha256File(skill.files[0].winner.fullPath);
|
|
116063
116166
|
}
|
|
116064
116167
|
const joined = skill.files.map((file2) => sha256File(file2.winner.fullPath));
|
|
116065
|
-
return
|
|
116168
|
+
return createHash39("sha256").update(joined.sort().join(`
|
|
116066
116169
|
`)).digest("hex");
|
|
116067
116170
|
}
|
|
116068
116171
|
function writeStationHydration(options) {
|
|
@@ -116219,7 +116322,7 @@ var init_hydrate = __esm(() => {
|
|
|
116219
116322
|
});
|
|
116220
116323
|
|
|
116221
116324
|
// src/lib/prepare-skill.ts
|
|
116222
|
-
import { createHash as
|
|
116325
|
+
import { createHash as createHash40, randomUUID as randomUUID13 } from "crypto";
|
|
116223
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";
|
|
116224
116327
|
import { tmpdir as tmpdir2 } from "os";
|
|
116225
116328
|
import { dirname as dirname38, isAbsolute as isAbsolute32, join as join67, relative as relative12, resolve as resolve31, sep as sep15 } from "path";
|
|
@@ -116418,7 +116521,7 @@ function snapshot2(root2) {
|
|
|
116418
116521
|
if (rootStat.isSymbolicLink() || !rootStat.isDirectory())
|
|
116419
116522
|
throw new Error("Skill root must be a real directory, not a symlink.");
|
|
116420
116523
|
const files = [], directories = [];
|
|
116421
|
-
const hash6 =
|
|
116524
|
+
const hash6 = createHash40("sha256").update(`${rootStat.dev}:${rootStat.ino}\x00`);
|
|
116422
116525
|
let count = 0, bytes = 0;
|
|
116423
116526
|
const walk2 = (relative13) => {
|
|
116424
116527
|
for (const name of readdirSync25(join67(root2, relative13)).sort()) {
|