@hasna/skills 0.10.49 → 0.10.51
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 +40 -6
- package/bin/index.js +82 -50
- package/bin/maintenance.js +199 -2
- package/bin/mcp.js +53 -36
- package/bin/migrate.js +1 -1
- package/bin/server.js +1 -1
- package/bin/worker.js +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +71 -39
- package/dist/lib/agent-discovery.d.ts +2 -2
- package/dist/lib/agent-integration.d.ts +1 -0
- package/dist/lib/claude-settings-witness.d.ts +19 -0
- package/dist/lib/codex-native-compatibility.d.ts +4 -1
- package/dist/sdk/index.js +49 -21
- package/dist/server/maintenance-entry.d.ts +14 -0
- package/dist/server/schema-census.d.ts +77 -0
- package/docs/plugin-admission.md +44 -5
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -559,7 +559,8 @@ The plan proves the preserved original matches every witness being replaced,
|
|
|
559
559
|
permits only the documented non-discovery differences, and labels the replacement
|
|
560
560
|
witness (the JSON receipt lists them under `replacedWitnesses`). `--apply`
|
|
561
561
|
preserves and reads back the original policy before writing, and never writes the
|
|
562
|
-
native configuration. Claude upgrades to `claude-settings-v3
|
|
562
|
+
native configuration. Claude upgrades to `claude-settings-v3`, or to
|
|
563
|
+
`claude-settings-v4` with `--claude-witness-version 4`; Codex uses
|
|
563
564
|
`codex-settings-v2`, which also replaces the narrower automatic
|
|
564
565
|
`plugins`/`marketplaces`/`skills` projection of the same file once the preserved
|
|
565
566
|
original is proved to explain it. That projection is order-sensitive, so it keeps
|
|
@@ -591,10 +592,13 @@ skills hook native-catalog --cwd /absolute/project --output /private/catalog.jso
|
|
|
591
592
|
skills hook install --agent codex --codex-native-catalog /private/catalog.json --json
|
|
592
593
|
```
|
|
593
594
|
|
|
594
|
-
Codex 0.159.2 and 0.160.
|
|
595
|
-
transport, capture and review use one capability registry
|
|
596
|
-
|
|
597
|
-
|
|
595
|
+
Codex 0.159.2, 0.160.0 and 0.160.1 have measured qualified-name catalog support.
|
|
596
|
+
Native transport, capture and review use one capability registry of exact
|
|
597
|
+
releases. Unmeasured releases, including 0.160.2 and 0.161.0, refuse until the
|
|
598
|
+
native catalog/name-denial and hook-dispatch acceptance tests pass; an RPC
|
|
599
|
+
handshake alone does not establish those semantics. Admitting a release does not
|
|
600
|
+
admit its corpus: the transport still requires the existing native corpus
|
|
601
|
+
admission (see `docs/codex-corpus-writers.md`).
|
|
598
602
|
|
|
599
603
|
The capture refuses an existing output file, writes mode `0600`, verifies the
|
|
600
604
|
exact bytes, and reports only version, directory, count, file path and SHA-256.
|
|
@@ -642,7 +646,7 @@ different extant, witnessed user version. Individual missing files, current
|
|
|
642
646
|
registered roots, aliases and registration changes still refuse; historical
|
|
643
647
|
source hashes and typed settings witnesses remain intact.
|
|
644
648
|
|
|
645
|
-
For a Codex 0.160.0 remote refresh omitted by an existing qualified-name disable,
|
|
649
|
+
For a Codex 0.160.0 or 0.160.1 remote refresh omitted by an existing qualified-name disable,
|
|
646
650
|
a fresh native catalog and discovery review can plan the new exact path disable
|
|
647
651
|
in the same transaction. The remote installation receipt, namespace and capability
|
|
648
652
|
controls must match; conflicting enable rules, unknown names and ambiguous
|
|
@@ -1304,6 +1308,21 @@ the backup keeps the exact previous launcher (symlink text or pinned bytes), and
|
|
|
1304
1308
|
projection and `skills self-update` read a managed pinned launcher as the exact
|
|
1305
1309
|
entry it runs and bind the launcher's own bytes as well.
|
|
1306
1310
|
|
|
1311
|
+
An updater from before pinned launchers (0.10.48 and earlier) writes bare symlinks,
|
|
1312
|
+
including when it installs a version that has them, and an exact-version update to
|
|
1313
|
+
the version already installed is refused. `skills self-update --adopt-aliases` pins
|
|
1314
|
+
those launchers in place: in `~/.local/bin`, `~/.bun/bin`, `/opt/homebrew/bin` and
|
|
1315
|
+
`/usr/local/bin`, a bare symlink that already reaches the current runtime's entry is
|
|
1316
|
+
adopted like an alias still pointing at an older install. The same refusals apply
|
|
1317
|
+
(an unsafe or unwritable directory, a launcher owned by another account, a foreign
|
|
1318
|
+
file, an unsupported link chain), the exact symlink is kept as
|
|
1319
|
+
`<launcher>.skills-alias-prev-<receipt id>`, the receipt records it as the old
|
|
1320
|
+
`symlink` shape, and `--rollback-aliases <receipt id>` restores it exactly. A
|
|
1321
|
+
launcher already pinned to the current runtime is left unchanged. Undo in reverse
|
|
1322
|
+
order: roll back the adoption before rolling back the runtime update that wrote
|
|
1323
|
+
those symlinks, because that update's `--rollback` refuses with
|
|
1324
|
+
`LAUNCHER_DRIFT_ROLLBACK_REFUSED` while the adopted pinned launchers are in place.
|
|
1325
|
+
|
|
1307
1326
|
To require a minimum dependency age, pass a positive integer number of days and
|
|
1308
1327
|
repeat the exclusion option for package names or package globs:
|
|
1309
1328
|
|
|
@@ -2568,3 +2587,18 @@ Upgrade an existing review with `skills hook rebind-settings --agent codex
|
|
|
2568
2587
|
Review the plan before adding `--apply`; the original review preimage must match
|
|
2569
2588
|
its original mode, and unrelated changes refuse. This preserves the native
|
|
2570
2589
|
configuration, root aliases, other witnesses and active session pins.
|
|
2590
|
+
|
|
2591
|
+
`claude-settings-v4` is an explicit successor to `claude-settings-v3`. It
|
|
2592
|
+
additionally ignores only a top-level `theme` whose value is exactly one of the
|
|
2593
|
+
documented built-in values (`auto`, `dark`, `light`, `dark-daltonized`,
|
|
2594
|
+
`light-daltonized`, `dark-ansi`, `light-ansi`). Custom and plugin themes, other
|
|
2595
|
+
values or types, nested `theme` keys, `skipDangerousModePermissionPrompt` and
|
|
2596
|
+
every permission, hook, environment, helper and unknown setting stay bound.
|
|
2597
|
+
Existing raw/V1/V2/V3 reviews retain their original meaning.
|
|
2598
|
+
|
|
2599
|
+
Capture with `skills hook witness --kind claude-settings-v4 --path <settings.json>`.
|
|
2600
|
+
Upgrade an existing review with `skills hook rebind-settings --agent claude
|
|
2601
|
+
--claude-witness-version 4 --reviewed-preimage <preserved-settings.json>
|
|
2602
|
+
--expected-policy-sha256 <policy-hash> --expected-settings-sha256 <settings-hash>`.
|
|
2603
|
+
Review the plan before adding `--apply`. See
|
|
2604
|
+
[built-in theme reviews](docs/plugin-admission.md#explicit-v4-built-in-theme-reviews).
|
package/bin/index.js
CHANGED
|
@@ -36888,7 +36888,7 @@ var package_default;
|
|
|
36888
36888
|
var init_package = __esm(() => {
|
|
36889
36889
|
package_default = {
|
|
36890
36890
|
name: "@hasna/skills",
|
|
36891
|
-
version: "0.10.
|
|
36891
|
+
version: "0.10.51",
|
|
36892
36892
|
description: "Skills library for AI coding agents",
|
|
36893
36893
|
type: "module",
|
|
36894
36894
|
bin: {
|
|
@@ -40066,7 +40066,9 @@ function inferencePreference(key, child, version) {
|
|
|
40066
40066
|
function settingsDigest(text, version = 1) {
|
|
40067
40067
|
const value = parse(text);
|
|
40068
40068
|
value.entries = value.entries.filter(([key, child]) => {
|
|
40069
|
-
if (version
|
|
40069
|
+
if (version === 4 && key === "theme" && child.kind === "string" && BUILTIN_THEMES.has(child.value))
|
|
40070
|
+
return false;
|
|
40071
|
+
if (version !== 1 && inferencePreference(key, child, version === 4 ? 3 : version))
|
|
40070
40072
|
return false;
|
|
40071
40073
|
if (key === "model") {
|
|
40072
40074
|
need(child.kind === "string", "contains an invalid model selection");
|
|
@@ -40124,6 +40126,26 @@ function upgradeClaudeSettingsWitness(previous, reviewedSettingsPath) {
|
|
|
40124
40126
|
need(settingsDigest(before2, 3) === sha256, "non-preference settings changed; explicit discovery review required");
|
|
40125
40127
|
return { path: previous.path, hashMode: "claude-settings-v3", sha256 };
|
|
40126
40128
|
}
|
|
40129
|
+
function captureClaudeSettingsV4(path, budget = { remaining: 256 * 1024 * 1024 }) {
|
|
40130
|
+
return { path, hashMode: "claude-settings-v4", sha256: settingsDigest(readNativeSettingsWitnessFile(path, budget), 4) };
|
|
40131
|
+
}
|
|
40132
|
+
function hashClaudeSettingsReplacementV4(text, budget) {
|
|
40133
|
+
need(typeof text === "string", "requires settings text");
|
|
40134
|
+
const bytes = Buffer.byteLength(text);
|
|
40135
|
+
need(bytes <= CLAUDE_SETTINGS_WITNESS_LIMITS.bytes && Number.isSafeInteger(budget.remaining) && budget.remaining >= bytes, "exceeds its byte limit");
|
|
40136
|
+
budget.remaining -= bytes;
|
|
40137
|
+
return settingsDigest(text, 4);
|
|
40138
|
+
}
|
|
40139
|
+
function upgradeClaudeSettingsWitnessV4(previous, reviewedSettingsPath) {
|
|
40140
|
+
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" || previous.hashMode === "claude-settings-v3") && typeof previous.sha256 === "string" && /^[a-f0-9]{64}$/.test(previous.sha256), "requires an exact prior settings witness");
|
|
40141
|
+
const budget = { remaining: 2 * CLAUDE_SETTINGS_WITNESS_LIMITS.bytes };
|
|
40142
|
+
const before2 = readNativeSettingsWitnessFile(reviewedSettingsPath, budget), current = readNativeSettingsWitnessFile(previous.path, budget);
|
|
40143
|
+
const beforeDigest = previous.hashMode === undefined || previous.hashMode === "bytes" ? createHash2("sha256").update(before2).digest("hex") : settingsDigest(before2, previous.hashMode === "claude-settings-v1" ? 1 : previous.hashMode === "claude-settings-v2" ? 2 : 3);
|
|
40144
|
+
need(beforeDigest === previous.sha256, "reviewed preimage does not match the prior witness");
|
|
40145
|
+
const sha256 = settingsDigest(current, 4);
|
|
40146
|
+
need(settingsDigest(before2, 4) === sha256, "non-preference settings changed; explicit discovery review required");
|
|
40147
|
+
return { path: previous.path, hashMode: "claude-settings-v4", sha256 };
|
|
40148
|
+
}
|
|
40127
40149
|
function hashNativeJsonControls(text, excludedMetadata) {
|
|
40128
40150
|
need(Buffer.byteLength(text) <= CLAUDE_SETTINGS_WITNESS_LIMITS.bytes, "exceeds its byte limit");
|
|
40129
40151
|
const value = parse(text);
|
|
@@ -40156,7 +40178,7 @@ function hashSumiNativeJsonControls(text) {
|
|
|
40156
40178
|
});
|
|
40157
40179
|
return createHash2("sha256").update("hasna.skills.sumi-settings.v1\x00").update(JSON.stringify(value)).digest("hex");
|
|
40158
40180
|
}
|
|
40159
|
-
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;
|
|
40181
|
+
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, CLAUDE_BUILTIN_THEMES, BUILTIN_THEMES, PERSISTED_EFFORT_LEVELS;
|
|
40160
40182
|
var init_claude_settings_witness = __esm(() => {
|
|
40161
40183
|
CLAUDE_SETTINGS_WITNESS_LIMITS = Object.freeze({ bytes: 1024 * 1024, rows: 1024, depth: 32, nodes: 65536, stringCharacters: 16384, pathCharacters: 4096 });
|
|
40162
40184
|
BOOLEAN_PREFERENCES = new Set([
|
|
@@ -40210,6 +40232,8 @@ var init_claude_settings_witness = __esm(() => {
|
|
|
40210
40232
|
"claude-opus-4-6[1m]",
|
|
40211
40233
|
"claude-sonnet-4-6[1m]"
|
|
40212
40234
|
]);
|
|
40235
|
+
CLAUDE_BUILTIN_THEMES = Object.freeze(["auto", "dark", "light", "dark-daltonized", "light-daltonized", "dark-ansi", "light-ansi"]);
|
|
40236
|
+
BUILTIN_THEMES = new Set(CLAUDE_BUILTIN_THEMES);
|
|
40213
40237
|
PERSISTED_EFFORT_LEVELS = new Set(["low", "medium", "high", "xhigh"]);
|
|
40214
40238
|
});
|
|
40215
40239
|
|
|
@@ -40245,6 +40269,29 @@ var init_sumi_settings_witness = __esm(() => {
|
|
|
40245
40269
|
SUMI_DISCOVERY_PROJECTION_FIELDS = ["skills", "plugin", "plugins", "permissions"];
|
|
40246
40270
|
});
|
|
40247
40271
|
|
|
40272
|
+
// src/lib/codex-native-compatibility.ts
|
|
40273
|
+
function supportsCodexNativeCapability(version, capability) {
|
|
40274
|
+
return typeof version === "string" && Object.hasOwn(MEASURED_CODEX_CAPABILITIES, version) && MEASURED_CODEX_CAPABILITIES[version].includes(capability);
|
|
40275
|
+
}
|
|
40276
|
+
var MEASURED_CODEX_CAPABILITIES, SUPPORTED_CODEX_HOOK_VERSIONS;
|
|
40277
|
+
var init_codex_native_compatibility = __esm(() => {
|
|
40278
|
+
MEASURED_CODEX_CAPABILITIES = {
|
|
40279
|
+
"codex-cli 0.153.0": ["hooks"],
|
|
40280
|
+
"codex-cli 0.154.0": ["hooks"],
|
|
40281
|
+
"codex-cli 0.155.0": ["hooks"],
|
|
40282
|
+
"codex-cli 0.155.1": ["hooks"],
|
|
40283
|
+
"codex-cli 0.156.1": ["hooks"],
|
|
40284
|
+
"codex-cli 0.157.0": ["hooks"],
|
|
40285
|
+
"codex-cli 0.157.1": ["hooks"],
|
|
40286
|
+
"codex-cli 0.158.0": ["hooks"],
|
|
40287
|
+
"codex-cli 0.159.0": ["hooks"],
|
|
40288
|
+
"codex-cli 0.159.2": ["hooks", "qualified-skill-catalog"],
|
|
40289
|
+
"codex-cli 0.160.0": ["hooks", "qualified-skill-catalog", "installed-plugin-review"],
|
|
40290
|
+
"codex-cli 0.160.1": ["hooks", "qualified-skill-catalog", "installed-plugin-review"]
|
|
40291
|
+
};
|
|
40292
|
+
SUPPORTED_CODEX_HOOK_VERSIONS = Object.freeze(Object.keys(MEASURED_CODEX_CAPABILITIES).filter((version) => supportsCodexNativeCapability(version, "hooks")));
|
|
40293
|
+
});
|
|
40294
|
+
|
|
40248
40295
|
// src/lib/agent-policy-limits.ts
|
|
40249
40296
|
import { basename as basename3, isAbsolute as isAbsolute3, join as join11, resolve as resolve4, sep as sep2 } from "path";
|
|
40250
40297
|
function object(value) {
|
|
@@ -40311,7 +40358,7 @@ function assertAgentPolicyCollections(policy) {
|
|
|
40311
40358
|
}
|
|
40312
40359
|
if (bridge.codexInactivePlugins !== undefined) {
|
|
40313
40360
|
const controls = array(bridge.codexInactivePlugins, 4096), ids = new Set;
|
|
40314
|
-
requireBound(controls.length === 0 || object(bridge.codexPluginSkillReview) && bridge.codexPluginSkillReview.version
|
|
40361
|
+
requireBound(controls.length === 0 || object(bridge.codexPluginSkillReview) && supportsCodexNativeCapability(bridge.codexPluginSkillReview.version, "installed-plugin-review") && typeof bridge.codexPluginSkillReview.catalogSha256 === "string" && /^[a-f0-9]{64}$/.test(bridge.codexPluginSkillReview.catalogSha256));
|
|
40315
40362
|
for (const control of controls) {
|
|
40316
40363
|
requireBound(object(control) && Object.keys(control).every((key) => ["pluginId", "namespace", "pluginParent", "sourceType", "sourceSha256"].includes(key)));
|
|
40317
40364
|
text(control.pluginId, 1024);
|
|
@@ -40363,7 +40410,7 @@ function assertAgentPolicyCollections(policy) {
|
|
|
40363
40410
|
}
|
|
40364
40411
|
if (value.codexInstallationInputs !== undefined) {
|
|
40365
40412
|
const proof = record(value.codexInstallationInputs, 4), inputs = array(proof.plugins, 4096), ids = new Set;
|
|
40366
|
-
requireBound(agent === "codex" && value.agent === "codex" && value.method === "reviewed" && proof.version
|
|
40413
|
+
requireBound(agent === "codex" && value.agent === "codex" && value.method === "reviewed" && supportsCodexNativeCapability(proof.version, "installed-plugin-review") && typeof proof.catalogSha256 === "string" && /^[a-f0-9]{64}$/.test(proof.catalogSha256) && inputs.length > 0 && object(bridge.codexPluginSkillReview) && bridge.codexPluginSkillReview.version === proof.version && bridge.codexPluginSkillReview.catalogSha256 === proof.catalogSha256);
|
|
40367
40414
|
for (const input of inputs) {
|
|
40368
40415
|
requireBound(object(input) && Object.keys(input).every((key) => ["pluginId", "namespace", "pluginParent", "sourceRoot", "sourceSha256"].includes(key)));
|
|
40369
40416
|
text(input.pluginId, 1024);
|
|
@@ -40387,14 +40434,14 @@ function assertAgentPolicyCollections(policy) {
|
|
|
40387
40434
|
text(source.path);
|
|
40388
40435
|
requireBound(source.sha256 === null || typeof source.sha256 === "string" && /^[a-f0-9]{64}$/.test(source.sha256));
|
|
40389
40436
|
if (source.hashMode !== undefined)
|
|
40390
|
-
requireBound(["bytes", "path-bytes", "claude-plugin-manifest-v1", "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));
|
|
40437
|
+
requireBound(["bytes", "path-bytes", "claude-plugin-manifest-v1", "claude-plugin-registry", "claude-marketplace-registry", "claude-settings-v1", "claude-settings-v2", "claude-settings-v3", "claude-settings-v4", "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));
|
|
40391
40438
|
if (source.hashMode === "claude-plugin-manifest-v1")
|
|
40392
40439
|
requireBound(agent === "claude" && value.agent === "claude" && ["automatic", "reviewed"].includes(value.method) && !/[\x00-\x1f\x7f]/.test(source.path) && isAbsolute3(source.path) && resolve4(source.path) === source.path && source.path.endsWith(join11(sep2, ".claude-plugin", "plugin.json")) && source.managedPlugins === undefined);
|
|
40393
40440
|
if (source.hashMode === "sumi-settings-v1")
|
|
40394
40441
|
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");
|
|
40395
40442
|
if (source.hashMode === "codex-settings-v1" || source.hashMode === "codex-settings-v2" || (source.hashMode === "codex-settings-v3" || source.hashMode === "codex-settings-v4"))
|
|
40396
40443
|
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");
|
|
40397
|
-
if (source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || source.hashMode === "claude-settings-v3")
|
|
40444
|
+
if (source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || (source.hashMode === "claude-settings-v3" || source.hashMode === "claude-settings-v4"))
|
|
40398
40445
|
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");
|
|
40399
40446
|
if (source.hashMode === "claude-marketplace-registry" || source.hashMode === "claude-marketplace-registry-v2")
|
|
40400
40447
|
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");
|
|
@@ -40428,6 +40475,7 @@ function assertAgentPolicyCollections(policy) {
|
|
|
40428
40475
|
}
|
|
40429
40476
|
var AGENT_POLICY_LIMITS;
|
|
40430
40477
|
var init_agent_policy_limits = __esm(() => {
|
|
40478
|
+
init_codex_native_compatibility();
|
|
40431
40479
|
AGENT_POLICY_LIMITS = Object.freeze({ bytes: 1024 * 1024, agents: 16, discoverySources: 2048, discoveryRawSourceBytes: 64 * 1024 * 1024, discoveryRawTotalBytes: 256 * 1024 * 1024, discoveryPathLinks: 40, discoveryPathSteps: 256, discoveryPathSourceMetadataBytes: 64 * 1024, discoveryPathTotalMetadataBytes: 8 * 1024 * 1024, discoveryRoots: 512, discoveryDirectories: 64, discoveryDirectoryEntries: 20000, discoveryDirectoryBytes: 8 * 1024 * 1024, builtinNames: 2048, rootAliases: 2, fields: 64, pathCharacters: 4096 });
|
|
40432
40480
|
});
|
|
40433
40481
|
|
|
@@ -51551,28 +51599,6 @@ function isCodexLocalStdioMcpServer(name, server) {
|
|
|
51551
51599
|
}
|
|
51552
51600
|
}
|
|
51553
51601
|
|
|
51554
|
-
// src/lib/codex-native-compatibility.ts
|
|
51555
|
-
function supportsCodexNativeCapability(version, capability) {
|
|
51556
|
-
return typeof version === "string" && Object.hasOwn(MEASURED_CODEX_CAPABILITIES, version) && MEASURED_CODEX_CAPABILITIES[version].includes(capability);
|
|
51557
|
-
}
|
|
51558
|
-
var MEASURED_CODEX_CAPABILITIES, SUPPORTED_CODEX_HOOK_VERSIONS;
|
|
51559
|
-
var init_codex_native_compatibility = __esm(() => {
|
|
51560
|
-
MEASURED_CODEX_CAPABILITIES = {
|
|
51561
|
-
"codex-cli 0.153.0": ["hooks"],
|
|
51562
|
-
"codex-cli 0.154.0": ["hooks"],
|
|
51563
|
-
"codex-cli 0.155.0": ["hooks"],
|
|
51564
|
-
"codex-cli 0.155.1": ["hooks"],
|
|
51565
|
-
"codex-cli 0.156.1": ["hooks"],
|
|
51566
|
-
"codex-cli 0.157.0": ["hooks"],
|
|
51567
|
-
"codex-cli 0.157.1": ["hooks"],
|
|
51568
|
-
"codex-cli 0.158.0": ["hooks"],
|
|
51569
|
-
"codex-cli 0.159.0": ["hooks"],
|
|
51570
|
-
"codex-cli 0.159.2": ["hooks", "qualified-skill-catalog"],
|
|
51571
|
-
"codex-cli 0.160.0": ["hooks", "qualified-skill-catalog"]
|
|
51572
|
-
};
|
|
51573
|
-
SUPPORTED_CODEX_HOOK_VERSIONS = Object.freeze(Object.keys(MEASURED_CODEX_CAPABILITIES).filter((version) => supportsCodexNativeCapability(version, "hooks")));
|
|
51574
|
-
});
|
|
51575
|
-
|
|
51576
51602
|
// src/lib/codex-hook-rpc.ts
|
|
51577
51603
|
import { join as join20 } from "path";
|
|
51578
51604
|
import { execFile, spawn as spawn2 } from "child_process";
|
|
@@ -52169,6 +52195,7 @@ function reviewedCodexPluginCapabilitiesUnchanged(cache3, controls, read2, rules
|
|
|
52169
52195
|
function reviewCodexPluginControls(catalog, documents, cache3, cwd2, read2, rules, pluginSettings, plannedRules, denials = []) {
|
|
52170
52196
|
if (!supportsCodexNativeCapability(catalog?.version, "qualified-skill-catalog") || catalog.cwd !== cwd2)
|
|
52171
52197
|
refuse2();
|
|
52198
|
+
const installedPluginReview = supportsCodexNativeCapability(catalog.version, "installed-plugin-review");
|
|
52172
52199
|
if (!Array.isArray(denials) || denials.length > 4096 || new Set(denials.map((item) => item?.path)).size !== denials.length || denials.some((item) => !item || Object.keys(item).sort().join(",") !== "name,path,sha256" || typeof item.name !== "string" || typeof item.path !== "string" || !/^[a-f0-9]{64}$/.test(item.sha256)))
|
|
52173
52200
|
refuse2();
|
|
52174
52201
|
const usedDenials = new Set;
|
|
@@ -52200,7 +52227,7 @@ function reviewCodexPluginControls(catalog, documents, cache3, cwd2, read2, rule
|
|
|
52200
52227
|
if (listed.length > 1)
|
|
52201
52228
|
refuse2();
|
|
52202
52229
|
const installed = installedPlugins.filter((plugin) => plugin.id === expectedPluginId && plugin.name === pluginName);
|
|
52203
|
-
if (
|
|
52230
|
+
if (installedPluginReview && installed.length === 1 && installed[0].installed && installed[0].localVersion === basename6(located.root) && installed[0].sourceType === "local" && codexPluginSourceIsConfigControlled(installed[0])) {
|
|
52204
52231
|
const plugin = installed[0], input = { pluginId: expectedPluginId, namespace: located.namespace, pluginParent: located.pluginParent, sourceRoot: plugin.sourcePath, sourceSha256: plugin.sourceSha256 };
|
|
52205
52232
|
if (input.sourceRoot !== located.root && !input.sourceRoot.startsWith(cache3 + sep6) && (lstatSync13(input.sourceRoot, { throwIfNoEntry: false }) || documents.some((path) => path.startsWith(input.sourceRoot + sep6)))) {
|
|
52206
52233
|
if (skills.some((skill) => skill.path === input.sourceRoot || skill.path.startsWith(input.sourceRoot + sep6)) || !sourceInputUnchanged(input, cache3, read2))
|
|
@@ -52209,7 +52236,7 @@ function reviewCodexPluginControls(catalog, documents, cache3, cwd2, read2, rule
|
|
|
52209
52236
|
}
|
|
52210
52237
|
}
|
|
52211
52238
|
const settings = pluginSettings && typeof pluginSettings === "object" && !Array.isArray(pluginSettings) ? pluginSettings : undefined;
|
|
52212
|
-
if (
|
|
52239
|
+
if (installedPluginReview && !listed.length && !skills.some((skill) => skill.pluginId === expectedPluginId) && installed.length === 1 && installed[0].installed && !installed[0].enabled && codexPluginSourceIsConfigControlled(installed[0]) && settings && Object.hasOwn(settings, expectedPluginId) && settings[expectedPluginId]?.enabled === false) {
|
|
52213
52240
|
if (!Array.isArray(rules))
|
|
52214
52241
|
refuse2();
|
|
52215
52242
|
const exactPathDeny = rules.some((rule) => rule?.path === document3 && rule?.enabled === false);
|
|
@@ -52242,12 +52269,12 @@ function reviewCodexPluginControls(catalog, documents, cache3, cwd2, read2, rule
|
|
|
52242
52269
|
const exactPathDeny = Array.isArray(rules) && rules.some((rule) => rule?.path === document3 && rule?.enabled === false);
|
|
52243
52270
|
const nativeSkill = { name: parsed.name, path: document3, pluginId: expectedPluginId, enabled: true };
|
|
52244
52271
|
const denial = denials.find((item) => item.path === document3);
|
|
52245
|
-
const explicitDeny = denial !== undefined && remotePluginId !== undefined &&
|
|
52272
|
+
const explicitDeny = denial !== undefined && remotePluginId !== undefined && installedPluginReview && denial.name === parsed.name && denial.sha256 === createHash12("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);
|
|
52246
52273
|
if (denial && !explicitDeny)
|
|
52247
52274
|
refuse2();
|
|
52248
52275
|
if (explicitDeny)
|
|
52249
52276
|
usedDenials.add(document3);
|
|
52250
|
-
const plannedPathDeny =
|
|
52277
|
+
const plannedPathDeny = installedPluginReview && remotePluginId !== undefined && Array.isArray(rules) && rules.some((rule) => typeof rule?.name === "string" && rule.name.trim() === parsed.name && rule.enabled === false) && !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) && isCodexNativeSkillDisabled(nativeSkill, plannedRules);
|
|
52251
52278
|
if (!explicitDeny && (!exactPathDeny && !plannedPathDeny || !isCodexNativeSkillDisabled(nativeSkill, rules)))
|
|
52252
52279
|
refuse2();
|
|
52253
52280
|
}
|
|
@@ -55028,7 +55055,7 @@ function planAgentIntegration(options) {
|
|
|
55028
55055
|
const { codexInstallationInputs: previousInputs, ...current } = rebound;
|
|
55029
55056
|
const inputs = codexPluginSourceInputs.map((input) => input.sourceRoot);
|
|
55030
55057
|
const directories = options.codexNativeCatalog || !previousInputs ? captureDiscoveryDirectories((binding.directories ?? []).filter((directory) => inputs.some((root) => root.startsWith(directory.path + sep7))).map((directory) => directory.path), inputs) : previousInputs.directories;
|
|
55031
|
-
const installed = codexPluginSourceInputs.length ? { ...current, codexInstallationInputs: { version:
|
|
55058
|
+
const installed = codexPluginSourceInputs.length ? { ...current, codexInstallationInputs: { version: codexPluginSkillReview.version, catalogSha256: codexPluginSkillReview.catalogSha256, plugins: codexPluginSourceInputs, ...directories?.length ? { directories } : {} } } : current;
|
|
55032
55059
|
return captureRetiredCodexDiscovery(installed, codexPluginSkills, Bun.TOML.parse(changes.find((change) => change.path === canonicalAgentPath(join28(home, ".codex/config.toml"), aliases))?.after ?? codexConfigBefore ?? "").skills?.config ?? []);
|
|
55033
55060
|
});
|
|
55034
55061
|
const nextPolicy = { ...policy, version: 1, loading: "cli", profileId, bridge: {
|
|
@@ -55262,6 +55289,8 @@ function atomicWrite2(path, content) {
|
|
|
55262
55289
|
function planAgentSettingsWitnessUpgrade(options) {
|
|
55263
55290
|
if (options.targetCodexVersion !== undefined && (options.agent !== "codex" || ![2, 3, 4].includes(options.targetCodexVersion)))
|
|
55264
55291
|
throw new Error("Invalid Codex witness target version");
|
|
55292
|
+
if (options.targetClaudeVersion !== undefined && (options.agent !== "claude" || ![3, 4].includes(options.targetClaudeVersion)))
|
|
55293
|
+
throw new Error("Invalid Claude witness target version");
|
|
55265
55294
|
const home = resolve14(options.home ?? homedir3()), dataDir3 = options.dataDir ?? getDataDirReadOnly();
|
|
55266
55295
|
const snapshot2 = readManagedSkillPolicySnapshot(dataDir3);
|
|
55267
55296
|
if (!snapshot2 || sha3(snapshot2.text) !== options.expectedPolicySha256)
|
|
@@ -55309,7 +55338,7 @@ function planAgentSettingsWitnessUpgrade(options) {
|
|
|
55309
55338
|
replaced.push(source);
|
|
55310
55339
|
}
|
|
55311
55340
|
}
|
|
55312
|
-
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);
|
|
55341
|
+
const next = options.agent === "sumi" ? upgradeSumiSettingsWitness(previous, options.reviewedPreimage) : options.agent === "claude" ? options.targetClaudeVersion === 4 ? upgradeClaudeSettingsWitnessV4(previous, options.reviewedPreimage) : upgradeClaudeSettingsWitness(previous, options.reviewedPreimage) : options.targetCodexVersion === 4 ? upgradeCodexSettingsWitnessV4(previous, options.reviewedPreimage) : options.targetCodexVersion === 3 ? upgradeCodexSettingsWitnessV3(previous, options.reviewedPreimage) : upgradeCodexSettingsWitness(previous, options.reviewedPreimage);
|
|
55313
55342
|
const rebound = [];
|
|
55314
55343
|
for (const source of binding.sources) {
|
|
55315
55344
|
if (!replaced.includes(source)) {
|
|
@@ -55355,7 +55384,7 @@ function applyAgentIntegrationUnlocked(plan, options = {}, assertCurrent) {
|
|
|
55355
55384
|
const upgrade = plan.settingsWitnessUpgrade;
|
|
55356
55385
|
if (!plan.managedAgentChecks || !plan.observedPolicy?.before)
|
|
55357
55386
|
throw new Error("Invalid settings witness upgrade plan");
|
|
55358
|
-
const verified = planAgentSettingsWitnessUpgrade({ agent: upgrade.agent, ...upgrade.agent === "codex" ? { targetCodexVersion: upgrade.toHashMode === "codex-settings-v4" ? 4 : upgrade.toHashMode === "codex-settings-v3" ? 3 : 2 } : {}, reviewedPreimage: upgrade.reviewedPreimage, home: plan.managedAgentChecks.home, dataDir: plan.dataDir, expectedPolicySha256: sha3(plan.observedPolicy.before), expectedSettingsSha256: upgrade.currentSettingsSha256 });
|
|
55387
|
+
const verified = planAgentSettingsWitnessUpgrade({ agent: upgrade.agent, ...upgrade.agent === "codex" ? { targetCodexVersion: upgrade.toHashMode === "codex-settings-v4" ? 4 : upgrade.toHashMode === "codex-settings-v3" ? 3 : 2 } : {}, ...upgrade.agent === "claude" && upgrade.toHashMode === "claude-settings-v4" ? { targetClaudeVersion: 4 } : {}, reviewedPreimage: upgrade.reviewedPreimage, home: plan.managedAgentChecks.home, dataDir: plan.dataDir, expectedPolicySha256: sha3(plan.observedPolicy.before), expectedSettingsSha256: upgrade.currentSettingsSha256 });
|
|
55359
55388
|
if (JSON.stringify(verified.changes) !== JSON.stringify(plan.changes) || JSON.stringify(verified.settingsWitnessUpgrade) !== JSON.stringify(upgrade))
|
|
55360
55389
|
throw new Error("Settings witness upgrade plan changed");
|
|
55361
55390
|
provenDiscovery = verified.discoveryBefore[0];
|
|
@@ -59082,13 +59111,13 @@ function projected(source, changes, budget2 = discoveryByteBudget()) {
|
|
|
59082
59111
|
throw new Error(`Native discovery input changed; run skills hook install with a fresh discovery review: ${source.path}`);
|
|
59083
59112
|
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;
|
|
59084
59113
|
}
|
|
59085
|
-
if (source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || source.hashMode === "claude-settings-v3") {
|
|
59114
|
+
if (source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || (source.hashMode === "claude-settings-v3" || source.hashMode === "claude-settings-v4")) {
|
|
59086
59115
|
if (source.format !== undefined || source.fields !== undefined || source.managedPlugins !== undefined || typeof source.sha256 !== "string" || !/^[a-f0-9]{64}$/.test(source.sha256))
|
|
59087
59116
|
throw new Error("Claude settings witnesses require exact typed metadata");
|
|
59088
|
-
const current = (source.hashMode === "claude-settings-v3" ? captureClaudeSettingsV3 : source.hashMode === "claude-settings-v2" ? captureClaudeSettingsV2 : captureClaudeSettings)(source.path, budget2).sha256;
|
|
59117
|
+
const current = (source.hashMode === "claude-settings-v4" ? captureClaudeSettingsV4 : source.hashMode === "claude-settings-v3" ? captureClaudeSettingsV3 : source.hashMode === "claude-settings-v2" ? captureClaudeSettingsV2 : captureClaudeSettings)(source.path, budget2).sha256;
|
|
59089
59118
|
if (current !== source.sha256)
|
|
59090
59119
|
throw new Error(`Native discovery input changed; run skills hook install with a fresh discovery review: ${source.path}`);
|
|
59091
|
-
return changes?.has(source.path) ? (source.hashMode === "claude-settings-v3" ? hashClaudeSettingsReplacementV3 : source.hashMode === "claude-settings-v2" ? hashClaudeSettingsReplacementV2 : hashClaudeSettingsReplacement)(changes.get(source.path), budget2) : current;
|
|
59120
|
+
return changes?.has(source.path) ? (source.hashMode === "claude-settings-v4" ? hashClaudeSettingsReplacementV4 : source.hashMode === "claude-settings-v3" ? hashClaudeSettingsReplacementV3 : source.hashMode === "claude-settings-v2" ? hashClaudeSettingsReplacementV2 : hashClaudeSettingsReplacement)(changes.get(source.path), budget2) : current;
|
|
59092
59121
|
}
|
|
59093
59122
|
if (source.hashMode === "claude-marketplace-registry" || source.hashMode === "claude-marketplace-registry-v2") {
|
|
59094
59123
|
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))
|
|
@@ -59299,7 +59328,7 @@ function codexInstallationRoots(binding) {
|
|
|
59299
59328
|
const proof = binding.codexInstallationInputs;
|
|
59300
59329
|
if (proof === undefined)
|
|
59301
59330
|
return [];
|
|
59302
|
-
if (binding.agent !== "codex" || binding.method !== "reviewed" || proof.version
|
|
59331
|
+
if (binding.agent !== "codex" || binding.method !== "reviewed" || !supportsCodexNativeCapability(proof.version, "installed-plugin-review") || !/^[a-f0-9]{64}$/.test(proof.catalogSha256) || !Array.isArray(proof.plugins) || !proof.plugins.length)
|
|
59303
59332
|
throw new Error("Invalid native installation input proof");
|
|
59304
59333
|
const cache3 = dirname19(dirname19(proof.plugins[0].pluginParent));
|
|
59305
59334
|
const config = join37(dirname19(dirname19(cache3)), "config.toml"), home = dirname19(dirname19(dirname19(cache3)));
|
|
@@ -59323,7 +59352,7 @@ function assertMarketplaceBinding(binding, source) {
|
|
|
59323
59352
|
throw new Error("Sumi settings witnesses require explicit reviewed Sumi configuration");
|
|
59324
59353
|
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"))
|
|
59325
59354
|
throw new Error("Codex settings witnesses require explicit reviewed Codex configuration");
|
|
59326
|
-
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"))
|
|
59355
|
+
if ((source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || (source.hashMode === "claude-settings-v3" || source.hashMode === "claude-settings-v4")) && (binding.agent !== "claude" || binding.method !== "reviewed" || basename10(source.path) !== "settings.json"))
|
|
59327
59356
|
throw new Error("Claude settings witnesses require explicit reviewed Claude configuration");
|
|
59328
59357
|
if ((source.hashMode === "claude-marketplace-registry" || source.hashMode === "claude-marketplace-registry-v2") && (binding.agent !== "claude" || binding.method !== "reviewed"))
|
|
59329
59358
|
throw new Error("Claude marketplace witnesses require explicit reviewed Claude discovery");
|
|
@@ -59513,7 +59542,7 @@ function resolveAgentDiscovery(options) {
|
|
|
59513
59542
|
verifyAgentDiscovery(retained);
|
|
59514
59543
|
if (!retained.sources.some((source) => source.path === canonical7(configPath) && source.format === undefined && source.fields === undefined))
|
|
59515
59544
|
unresolved("retained review is missing the full agent configuration source");
|
|
59516
|
-
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 !== canonical7(configPath)))
|
|
59545
|
+
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 === "claude-settings-v4" || (source.hashMode === "codex-settings-v1" || source.hashMode === "codex-settings-v2" || (source.hashMode === "codex-settings-v3" || source.hashMode === "codex-settings-v4")))) && source.path !== canonical7(configPath)))
|
|
59517
59546
|
unresolved("retained settings witness names another configuration source");
|
|
59518
59547
|
const covered = supersedesSettingsProjection(agent, retained.sources, canonical7(configPath)) ? sources.filter((source) => !isSupersededSettingsProjection(agent, canonical7(configPath), source)) : sources;
|
|
59519
59548
|
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))
|
|
@@ -59527,7 +59556,7 @@ function resolveAgentDiscovery(options) {
|
|
|
59527
59556
|
if (review.sources.some((source) => source.format !== undefined || source.fields !== undefined))
|
|
59528
59557
|
throw new Error("Explicit discovery reviews require full source-file hashes");
|
|
59529
59558
|
verifyAgentDiscovery(supplied);
|
|
59530
|
-
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 !== canonical7(configPath)))
|
|
59559
|
+
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 === "claude-settings-v4" || (source.hashMode === "codex-settings-v1" || source.hashMode === "codex-settings-v2" || (source.hashMode === "codex-settings-v3" || source.hashMode === "codex-settings-v4")))) && source.path !== canonical7(configPath)))
|
|
59531
59560
|
throw new Error("Semantic settings witnesses must name the configured agent configuration source");
|
|
59532
59561
|
if (!review.sources.some((source) => source.path === canonical7(configPath)))
|
|
59533
59562
|
throw new Error("Discovery review must include the agent configuration source");
|
|
@@ -59694,6 +59723,7 @@ var init_agent_discovery = __esm(() => {
|
|
|
59694
59723
|
init_codex_plugin_skill_controls();
|
|
59695
59724
|
init_agent_sumi();
|
|
59696
59725
|
init_native_discovery_roots();
|
|
59726
|
+
init_codex_native_compatibility();
|
|
59697
59727
|
init_agent_discovery_directories();
|
|
59698
59728
|
});
|
|
59699
59729
|
|
|
@@ -112470,7 +112500,7 @@ function adoptCopyfileAliases(options = {}) {
|
|
|
112470
112500
|
const actual = launcher.target;
|
|
112471
112501
|
const oldLinkTarget = launcher.kind === "symlink" ? launcher.linkTarget : actual;
|
|
112472
112502
|
const newTarget = join60(layout.currentPackageRoot, target);
|
|
112473
|
-
if (actual === newTarget)
|
|
112503
|
+
if (actual === newTarget && launcher.kind === "pinned")
|
|
112474
112504
|
continue;
|
|
112475
112505
|
const chain = inspectAliasPackageChain(home, path, oldLinkTarget, actual, target);
|
|
112476
112506
|
const source = validateAliasSource(home, name, actual);
|
|
@@ -112627,7 +112657,7 @@ function rollbackCopyfileAliases(receiptId, options = {}) {
|
|
|
112627
112657
|
if (entryExists(item.backupPath)) {
|
|
112628
112658
|
if (!launcherIs(item.backupPath, oldLauncherState(item)))
|
|
112629
112659
|
throw new Error("ALIAS_PREIMAGE_DRIFT");
|
|
112630
|
-
} else if (current !== item.oldTarget) {
|
|
112660
|
+
} else if (current !== item.oldTarget || !launcherIs(item.path, oldLauncherState(item))) {
|
|
112631
112661
|
throw new Error("ALIAS_BACKUP_MISSING_FOR_SWITCH");
|
|
112632
112662
|
}
|
|
112633
112663
|
}
|
|
@@ -116159,19 +116189,21 @@ function registerAgentIntegration(parent) {
|
|
|
116159
116189
|
process.exitCode = 1;
|
|
116160
116190
|
}
|
|
116161
116191
|
});
|
|
116162
|
-
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) => {
|
|
116163
|
-
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;
|
|
116192
|
+
hook.command("witness").requiredOption("--kind <kind>", "sumi-settings-v1, claude-settings-v4, 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) => {
|
|
116193
|
+
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-v4" ? captureClaudeSettingsV4 : options.kind === "claude-settings-v3" ? captureClaudeSettingsV3 : options.kind === "claude-settings-v2" ? captureClaudeSettingsV2 : options.kind === "claude-marketplace-registry-v2" ? captureClaudeMarketplaceRegistryV2 : null;
|
|
116164
116194
|
if (!capture2)
|
|
116165
|
-
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");
|
|
116195
|
+
throw new Error("Unsupported witness kind; select sumi-settings-v1, claude-settings-v4, claude-settings-v3, claude-settings-v2, codex-settings-v4, codex-settings-v3, codex-settings-v2, codex-settings-v1 or claude-marketplace-registry-v2");
|
|
116166
116196
|
await writeCliOutput(JSON.stringify(capture2(options.path), null, 2));
|
|
116167
116197
|
});
|
|
116168
|
-
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) => {
|
|
116198
|
+
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("--claude-witness-version <version>", "Explicit target: 3 (default) or 4 (also permits a built-in top-level theme)").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) => {
|
|
116169
116199
|
try {
|
|
116170
116200
|
if (!["claude", "codex", "sumi"].includes(options.agent))
|
|
116171
116201
|
throw new Error("Settings witness rebind accepts claude, codex or sumi");
|
|
116172
116202
|
if (options.codexWitnessVersion !== undefined && !["2", "3", "4"].includes(options.codexWitnessVersion))
|
|
116173
116203
|
throw new Error("Codex witness version accepts 2, 3 or 4");
|
|
116174
|
-
|
|
116204
|
+
if (options.claudeWitnessVersion !== undefined && !["3", "4"].includes(options.claudeWitnessVersion))
|
|
116205
|
+
throw new Error("Claude witness version accepts 3 or 4");
|
|
116206
|
+
const plan = planAgentSettingsWitnessUpgrade({ ...options.codexWitnessVersion !== undefined ? { targetCodexVersion: Number(options.codexWitnessVersion) } : {}, ...options.claudeWitnessVersion !== undefined ? { targetClaudeVersion: Number(options.claudeWitnessVersion) } : {}, agent: options.agent, reviewedPreimage: options.reviewedPreimage, expectedPolicySha256: options.expectedPolicySha256, expectedSettingsSha256: options.expectedSettingsSha256 });
|
|
116175
116207
|
const result2 = options.apply ? applyAgentIntegration(plan) : { changed: [], backups: [] };
|
|
116176
116208
|
const receipt = { applied: options.apply, settingsWitnessUpgrade: plan.settingsWitnessUpgrade, ...result2 };
|
|
116177
116209
|
await writeCliOutput(options.json ? JSON.stringify(receipt) : `Settings witness ${options.apply ? "upgraded" : "planned"} for ${options.agent}. Native configuration was not changed.`);
|