@hasna/skills 0.10.64 → 0.10.66
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 +7 -1
- package/bin/index.js +511 -211
- package/bin/mcp.js +335 -40
- package/bin/migrate.js +1 -1
- package/bin/server.js +1 -1
- package/bin/worker.js +1 -1
- package/dist/index.js +426 -61
- package/dist/lib/agent-discovery.d.ts +3 -2
- package/dist/lib/agent-integration.d.ts +2 -0
- package/dist/lib/codex-semantic-cache-witness.d.ts +23 -0
- package/dist/lib/hook-diagnostics.d.ts +2 -0
- package/dist/runtime-prerequisites.js +133 -14
- package/dist/sdk/index.js +437 -72
- package/package.json +1 -1
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.66",
|
|
36892
36892
|
description: "Skills library for AI coding agents",
|
|
36893
36893
|
type: "module",
|
|
36894
36894
|
bin: {
|
|
@@ -40633,8 +40633,8 @@ function assertAgentPolicyCollections(policy) {
|
|
|
40633
40633
|
}
|
|
40634
40634
|
}
|
|
40635
40635
|
if (value.codexSemanticCache !== undefined) {
|
|
40636
|
-
const proof = record(value.codexSemanticCache,
|
|
40637
|
-
requireBound(agent === "codex" && value.agent === "codex" && value.method === "reviewed" && Object.keys(proof).length
|
|
40636
|
+
const proof = record(value.codexSemanticCache, 9), witness = record(proof.witness, 7);
|
|
40637
|
+
requireBound(agent === "codex" && value.agent === "codex" && value.method === "reviewed" && [8, 9].includes(Object.keys(proof).length) && Object.keys(proof).every((key) => ["schema", "configPath", "hookRootAlias", "witness", "appOnlyParents", "previousPolicySha256", "supersededSources", "supersededDirectories", "reviewedHookParents"].includes(key)) && proof.schema === "hasna.codex-semantic-cache-discovery.v1" && typeof proof.previousPolicySha256 === "string" && /^[a-f0-9]{64}$/.test(proof.previousPolicySha256) && [6, 7].includes(Object.keys(witness).length) && Object.keys(witness).every((key) => ["schema", "cacheRoot", "controls", "appOnlyParents", "skills", "sha256", "hookParents"].includes(key)) && witness.schema === "hasna.codex-semantic-cache-witness.v1" && typeof witness.sha256 === "string" && /^[a-f0-9]{64}$/.test(witness.sha256));
|
|
40638
40638
|
text(proof.configPath);
|
|
40639
40639
|
requireBound(isAbsolute4(proof.configPath) && resolve5(proof.configPath) === proof.configPath && basename4(proof.configPath) === "config.toml");
|
|
40640
40640
|
text(witness.cacheRoot);
|
|
@@ -40653,6 +40653,20 @@ function assertAgentPolicyCollections(policy) {
|
|
|
40653
40653
|
text(parent[key]);
|
|
40654
40654
|
requireBound(isAbsolute4(parent.pluginParent) && resolve5(parent.pluginParent) === parent.pluginParent);
|
|
40655
40655
|
}
|
|
40656
|
+
if (proof.reviewedHookParents !== undefined)
|
|
40657
|
+
for (const parent of array(proof.reviewedHookParents, 4096)) {
|
|
40658
|
+
requireBound(object(parent) && parent.role === "reviewed-hook" && (parent.installation === "remote-receipt" && Object.keys(parent).length === 6 || parent.installation === "local-marketplace" && Object.keys(parent).length === 7));
|
|
40659
|
+
requireBound(parent.installation === "remote-receipt" ? Object.keys(parent).sort().join(",") === "installation,namespace,pluginId,pluginParent,remotePluginId,role" : Object.keys(parent).sort().join(",") === "installation,marketplaceSha256,marketplaceSourcePath,namespace,pluginId,pluginParent,role");
|
|
40660
|
+
for (const key of ["pluginId", "namespace", "pluginParent", "installation"])
|
|
40661
|
+
text(parent[key]);
|
|
40662
|
+
if (parent.installation === "remote-receipt")
|
|
40663
|
+
text(parent.remotePluginId);
|
|
40664
|
+
else {
|
|
40665
|
+
text(parent.marketplaceSourcePath);
|
|
40666
|
+
requireBound(typeof parent.marketplaceSha256 === "string" && /^[a-f0-9]{64}$/.test(parent.marketplaceSha256) && isAbsolute4(parent.marketplaceSourcePath) && resolve5(parent.marketplaceSourcePath) === parent.marketplaceSourcePath && basename4(parent.marketplaceSourcePath) === "marketplace.json");
|
|
40667
|
+
}
|
|
40668
|
+
requireBound(isAbsolute4(parent.pluginParent) && resolve5(parent.pluginParent) === parent.pluginParent);
|
|
40669
|
+
}
|
|
40656
40670
|
for (const row of [...array(witness.controls, 4096), ...array(witness.appOnlyParents, 4096)]) {
|
|
40657
40671
|
requireBound(object(row));
|
|
40658
40672
|
for (const key of ["pluginId", "namespace", "pluginParent"])
|
|
@@ -40661,6 +40675,26 @@ function assertAgentPolicyCollections(policy) {
|
|
|
40661
40675
|
if (row[key] !== undefined)
|
|
40662
40676
|
requireBound(typeof row[key] === "string" && /^[a-f0-9]{64}$/.test(row[key]));
|
|
40663
40677
|
}
|
|
40678
|
+
if (witness.hookParents !== undefined)
|
|
40679
|
+
for (const row of array(witness.hookParents, 4096)) {
|
|
40680
|
+
requireBound(object(row) && row.role === "reviewed-hook" && (row.installation === "remote-receipt" && Object.keys(row).length === 9 || row.installation === "local-marketplace" && Object.keys(row).length === 9));
|
|
40681
|
+
requireBound(row.installation === "remote-receipt" ? Object.keys(row).sort().join(",") === "hooksSha256,installation,manifestSha256,namespace,pluginId,pluginParent,receiptSha256,remotePluginId,role" : Object.keys(row).sort().join(",") === "hooksSha256,installation,manifestSha256,marketplaceSha256,marketplaceSourcePath,namespace,pluginId,pluginParent,role");
|
|
40682
|
+
for (const key of ["pluginId", "namespace", "pluginParent", "installation"])
|
|
40683
|
+
text(row[key]);
|
|
40684
|
+
if (row.installation === "remote-receipt")
|
|
40685
|
+
text(row.remotePluginId);
|
|
40686
|
+
else {
|
|
40687
|
+
text(row.marketplaceSourcePath);
|
|
40688
|
+
requireBound(typeof row.marketplaceSha256 === "string" && /^[a-f0-9]{64}$/.test(row.marketplaceSha256) && isAbsolute4(row.marketplaceSourcePath) && resolve5(row.marketplaceSourcePath) === row.marketplaceSourcePath && basename4(row.marketplaceSourcePath) === "marketplace.json");
|
|
40689
|
+
}
|
|
40690
|
+
requireBound(isAbsolute4(row.pluginParent) && resolve5(row.pluginParent) === row.pluginParent);
|
|
40691
|
+
for (const key of ["manifestSha256", "hooksSha256"])
|
|
40692
|
+
requireBound(typeof row[key] === "string" && /^[a-f0-9]{64}$/.test(row[key]));
|
|
40693
|
+
if (row.installation === "remote-receipt")
|
|
40694
|
+
requireBound(typeof row.receiptSha256 === "string" && /^[a-f0-9]{64}$/.test(row.receiptSha256));
|
|
40695
|
+
else
|
|
40696
|
+
requireBound(row.receiptSha256 === undefined);
|
|
40697
|
+
}
|
|
40664
40698
|
for (const skill of array(witness.skills, 4096)) {
|
|
40665
40699
|
requireBound(object(skill));
|
|
40666
40700
|
for (const key of ["name", "pluginId", "namespace", "pluginParent"])
|
|
@@ -53789,7 +53823,25 @@ var init_codex_settings_witness = __esm(() => {
|
|
|
53789
53823
|
// src/lib/codex-semantic-cache-witness.ts
|
|
53790
53824
|
import { createHash as createHash17 } from "crypto";
|
|
53791
53825
|
import { constants as constants10, closeSync as closeSync9, fstatSync as fstatSync9, lstatSync as lstatSync16, openSync as openSync9, readSync as readSync7, readdirSync as readdirSync7, realpathSync as realpathSync8 } from "fs";
|
|
53792
|
-
import { dirname as dirname15, isAbsolute as isAbsolute15, join as join25, relative as relative6, resolve as resolve15, sep as sep7 } from "path";
|
|
53826
|
+
import { basename as basename9, dirname as dirname15, isAbsolute as isAbsolute15, join as join25, relative as relative6, resolve as resolve15, sep as sep7 } from "path";
|
|
53827
|
+
function codexLocalMarketplaceMapsPlugin(text2, marketplace, plugin) {
|
|
53828
|
+
try {
|
|
53829
|
+
hashNativeJsonControls(text2);
|
|
53830
|
+
const value = JSON.parse(text2);
|
|
53831
|
+
if (!plainObject(value) || !exactKeys(value, ["interface", "name", "plugins"]) || value.name !== marketplace || !(typeof value.interface === "string" || Number.isSafeInteger(value.interface)) || !Array.isArray(value.plugins) || value.plugins.length < 1 || value.plugins.length > 4096)
|
|
53832
|
+
return false;
|
|
53833
|
+
const rows = value.plugins.filter((row2) => plainObject(row2) && row2.name === plugin);
|
|
53834
|
+
if (rows.length !== 1)
|
|
53835
|
+
return false;
|
|
53836
|
+
const row = rows[0];
|
|
53837
|
+
if (!exactKeys(row, ["name", "source"]) || !plainObject(row.source) || !exactKeys(row.source, ["source", "path"]) || row.source.source !== "local" || typeof row.source.path !== "string" || !row.source.path.startsWith("./") || row.source.path.includes("\\"))
|
|
53838
|
+
return false;
|
|
53839
|
+
const parts = row.source.path.split("/");
|
|
53840
|
+
return parts[0] === "." && parts.length > 1 && parts.slice(1).every((part) => /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/.test(part)) && parts.at(-1) === plugin;
|
|
53841
|
+
} catch {
|
|
53842
|
+
return false;
|
|
53843
|
+
}
|
|
53844
|
+
}
|
|
53793
53845
|
function defaultRead(path) {
|
|
53794
53846
|
const before2 = lstatSync16(path, { throwIfNoEntry: false, bigint: true });
|
|
53795
53847
|
if (before2 === undefined)
|
|
@@ -53851,7 +53903,7 @@ function validPluginParent(cacheRoot, pluginParent, namespace, pluginId) {
|
|
|
53851
53903
|
return parts.length === 2 && parts.every(identifier3) && parts[1] === namespace && pluginId === `${namespace}@${parts[0]}`;
|
|
53852
53904
|
}
|
|
53853
53905
|
function assertWitnessShape(value) {
|
|
53854
|
-
if (!plainObject(value) || !exactKeys(value, ["schema", "cacheRoot", "controls", "appOnlyParents", "skills", "sha256"]) || value.schema !== CODEX_SEMANTIC_CACHE_WITNESS_SCHEMA || typeof value.cacheRoot !== "string" || !isAbsolute15(value.cacheRoot) || resolve15(value.cacheRoot) !== value.cacheRoot || !digest(value.sha256) || !Array.isArray(value.controls) || value.controls.length === 0 || value.controls.length > 4096 || !Array.isArray(value.appOnlyParents) || value.appOnlyParents.length > 4096 || !Array.isArray(value.skills) || value.skills.length === 0 || value.skills.length > 4096)
|
|
53906
|
+
if (!plainObject(value) || !exactKeys(value, ["schema", "cacheRoot", "controls", "appOnlyParents", "skills", "sha256"], ["hookParents"]) || value.schema !== CODEX_SEMANTIC_CACHE_WITNESS_SCHEMA || typeof value.cacheRoot !== "string" || !isAbsolute15(value.cacheRoot) || resolve15(value.cacheRoot) !== value.cacheRoot || !digest(value.sha256) || !Array.isArray(value.controls) || value.controls.length === 0 || value.controls.length > 4096 || !Array.isArray(value.appOnlyParents) || value.appOnlyParents.length > 4096 || !Array.isArray(value.skills) || value.skills.length === 0 || value.skills.length > 4096)
|
|
53855
53907
|
refuse4();
|
|
53856
53908
|
const witness = value;
|
|
53857
53909
|
const controlParents = new Set;
|
|
@@ -53872,6 +53924,20 @@ function assertWitnessShape(value) {
|
|
|
53872
53924
|
refuse4();
|
|
53873
53925
|
appOnlyParentPaths.add(row.pluginParent);
|
|
53874
53926
|
}
|
|
53927
|
+
const hookParentPaths = new Set;
|
|
53928
|
+
const hookParents = witness.hookParents === undefined ? [] : witness.hookParents;
|
|
53929
|
+
if (!Array.isArray(hookParents) || hookParents.length > 4096)
|
|
53930
|
+
refuse4();
|
|
53931
|
+
for (const candidate of hookParents) {
|
|
53932
|
+
if (!plainObject(candidate))
|
|
53933
|
+
refuse4();
|
|
53934
|
+
const row = candidate;
|
|
53935
|
+
const remote = row.installation === "remote-receipt";
|
|
53936
|
+
const local = row.installation === "local-marketplace";
|
|
53937
|
+
if (!exactKeys(row, ["role", "pluginId", "namespace", "pluginParent", "installation", "manifestSha256", "hooksSha256"], remote ? ["remotePluginId", "receiptSha256"] : local ? ["marketplaceSourcePath", "marketplaceSha256"] : []) || row.role !== "reviewed-hook" || !identifier3(row.namespace) || typeof row.pluginId !== "string" || !/^[A-Za-z0-9_-]{1,64}@[A-Za-z0-9_-]{1,64}$/.test(row.pluginId) || typeof row.pluginParent !== "string" || !validPluginParent(String(witness.cacheRoot), row.pluginParent, row.namespace, row.pluginId) || remote && (typeof row.remotePluginId !== "string" || !/^[A-Za-z0-9_~-]{1,1024}$/.test(row.remotePluginId) || !digest(row.receiptSha256)) || local && (typeof row.marketplaceSourcePath !== "string" || !isAbsolute15(row.marketplaceSourcePath) || resolve15(row.marketplaceSourcePath) !== row.marketplaceSourcePath || basename9(row.marketplaceSourcePath) !== "marketplace.json" || !digest(row.marketplaceSha256)) || !remote && !local || !digest(row.manifestSha256) || !digest(row.hooksSha256) || hookParentPaths.has(row.pluginParent) || controlParents.has(row.pluginParent) || appOnlyParentPaths.has(row.pluginParent))
|
|
53938
|
+
refuse4();
|
|
53939
|
+
hookParentPaths.add(row.pluginParent);
|
|
53940
|
+
}
|
|
53875
53941
|
const skillNames = new Set;
|
|
53876
53942
|
const qualifiedNames = new Set;
|
|
53877
53943
|
for (const candidate of witness.skills) {
|
|
@@ -53891,6 +53957,7 @@ function assertWitnessShape(value) {
|
|
|
53891
53957
|
cacheRoot: witness.cacheRoot,
|
|
53892
53958
|
controls: witness.controls,
|
|
53893
53959
|
appOnlyParents: witness.appOnlyParents,
|
|
53960
|
+
...witness.hookParents === undefined ? {} : { hookParents: witness.hookParents },
|
|
53894
53961
|
skills: witness.skills
|
|
53895
53962
|
};
|
|
53896
53963
|
if (hash2(projection) !== witness.sha256)
|
|
@@ -54081,10 +54148,128 @@ function appOnlyParentProjection(cacheRoot, parents2, read2) {
|
|
|
54081
54148
|
}
|
|
54082
54149
|
return rows.sort((a, b) => a.pluginId.localeCompare(b.pluginId) || a.pluginParent.localeCompare(b.pluginParent));
|
|
54083
54150
|
}
|
|
54084
|
-
function
|
|
54151
|
+
function assertJsonValue(value, depth = 0, budget2 = { members: 0 }) {
|
|
54152
|
+
if (depth > 32 || ++budget2.members > 4096)
|
|
54153
|
+
refuse4();
|
|
54154
|
+
if (value === null || typeof value === "string" || typeof value === "boolean")
|
|
54155
|
+
return;
|
|
54156
|
+
if (typeof value === "number" && Number.isFinite(value))
|
|
54157
|
+
return;
|
|
54158
|
+
if (Array.isArray(value)) {
|
|
54159
|
+
for (const item of value)
|
|
54160
|
+
assertJsonValue(item, depth + 1, budget2);
|
|
54161
|
+
return;
|
|
54162
|
+
}
|
|
54163
|
+
if (!plainObject(value))
|
|
54164
|
+
refuse4();
|
|
54165
|
+
for (const [key, item] of Object.entries(value)) {
|
|
54166
|
+
if (!key || /[\x00-\x1f\x7f]/.test(key))
|
|
54167
|
+
refuse4();
|
|
54168
|
+
assertJsonValue(item, depth + 1, budget2);
|
|
54169
|
+
}
|
|
54170
|
+
}
|
|
54171
|
+
function reviewedHookControls(root, read2) {
|
|
54172
|
+
const manifestPath = join25(root, ".codex-plugin/plugin.json"), hooksPath = join25(root, "hooks/hooks.json");
|
|
54173
|
+
let manifest, manifestSha256, hooks, hooksSha256;
|
|
54174
|
+
try {
|
|
54175
|
+
const manifestText = read2(manifestPath);
|
|
54176
|
+
manifestSha256 = hashNativeJsonControls(manifestText, "version");
|
|
54177
|
+
manifest = JSON.parse(manifestText);
|
|
54178
|
+
const hooksText = read2(hooksPath);
|
|
54179
|
+
hashNativeJsonControls(hooksText);
|
|
54180
|
+
hooksSha256 = createHash17("sha256").update(hooksText).digest("hex");
|
|
54181
|
+
hooks = JSON.parse(hooksText);
|
|
54182
|
+
} catch {
|
|
54183
|
+
return refuse4();
|
|
54184
|
+
}
|
|
54185
|
+
if (!plainObject(manifest) || !exactKeys(manifest, ["name", "version", "hooks"], ["description"]) || !identifier3(manifest.name) || typeof manifest.version !== "string" || manifest.version !== basename9(root) || manifest.hooks !== "./hooks/hooks.json" || manifest.description !== undefined && (typeof manifest.description !== "string" || !manifest.description.trim() || manifest.description.length > 1024))
|
|
54186
|
+
refuse4();
|
|
54187
|
+
const manifestRecord = manifest;
|
|
54188
|
+
if (!plainObject(hooks) || !exactKeys(hooks, ["hooks"]) || !plainObject(hooks.hooks))
|
|
54189
|
+
refuse4();
|
|
54190
|
+
const hookTable = hooks.hooks;
|
|
54191
|
+
const events = Object.entries(hookTable);
|
|
54192
|
+
if (!events.length || events.length > 32)
|
|
54193
|
+
refuse4();
|
|
54194
|
+
for (const [event, groups] of events) {
|
|
54195
|
+
if (!codexHookEvents.has(event) || !Array.isArray(groups) || !groups.length || groups.length > 32)
|
|
54196
|
+
refuse4();
|
|
54197
|
+
for (const group of groups) {
|
|
54198
|
+
if (!plainObject(group) || !exactKeys(group, ["hooks"]) || !Array.isArray(group.hooks) || !group.hooks.length || group.hooks.length > 32)
|
|
54199
|
+
refuse4();
|
|
54200
|
+
const handlers = group.hooks;
|
|
54201
|
+
for (const handler of handlers) {
|
|
54202
|
+
if (!plainObject(handler) || !exactKeys(handler, ["type", "server", "tool", "input"], ["timeout"]) || handler.type !== "mcp_tool" || !identifier3(handler.server) || !identifier3(handler.tool) || !plainObject(handler.input) || handler.timeout !== undefined && (!Number.isSafeInteger(handler.timeout) || Number(handler.timeout) < 1 || Number(handler.timeout) > 300))
|
|
54203
|
+
refuse4();
|
|
54204
|
+
assertJsonValue(handler.input);
|
|
54205
|
+
}
|
|
54206
|
+
}
|
|
54207
|
+
}
|
|
54208
|
+
return { namespace: manifestRecord.name, manifestSha256, hooksSha256 };
|
|
54209
|
+
}
|
|
54210
|
+
function reviewedHookParentProjection(cacheRoot, parents2, read2) {
|
|
54211
|
+
if (!Array.isArray(parents2) || parents2.length > 4096)
|
|
54212
|
+
refuse4();
|
|
54213
|
+
const seen = new Set, rows = [];
|
|
54214
|
+
for (const parent of parents2) {
|
|
54215
|
+
const remote = parent?.installation === "remote-receipt", local = parent?.installation === "local-marketplace";
|
|
54216
|
+
if (!parent || !exactKeys(parent, ["installation", "namespace", "pluginId", "pluginParent", "role"], remote ? ["remotePluginId"] : local ? ["marketplaceSourcePath", "marketplaceSha256"] : []) || parent.role !== "reviewed-hook" || !identifier3(parent.namespace) || !/^[A-Za-z0-9_-]{1,64}@[A-Za-z0-9_-]{1,64}$/.test(parent.pluginId) || typeof parent.pluginParent !== "string" || remote && (typeof parent.remotePluginId !== "string" || !/^[A-Za-z0-9_~-]{1,1024}$/.test(parent.remotePluginId)) || local && (typeof parent.marketplaceSourcePath !== "string" || !isAbsolute15(parent.marketplaceSourcePath) || resolve15(parent.marketplaceSourcePath) !== parent.marketplaceSourcePath || basename9(parent.marketplaceSourcePath) !== "marketplace.json" || !digest(parent.marketplaceSha256)) || !remote && !local)
|
|
54217
|
+
refuse4();
|
|
54218
|
+
const parts = relative6(cacheRoot, parent.pluginParent).split(sep7);
|
|
54219
|
+
if (!isAbsolute15(parent.pluginParent) || resolve15(parent.pluginParent) !== parent.pluginParent || parts.length !== 2 || parts.some((part) => !identifier3(part)) || parts[1] !== parent.namespace || parent.pluginId !== `${parent.namespace}@${parts[0]}` || seen.has(parent.pluginParent))
|
|
54220
|
+
refuse4();
|
|
54221
|
+
seen.add(parent.pluginParent);
|
|
54222
|
+
const parentStat = lstatSync16(parent.pluginParent, { throwIfNoEntry: false });
|
|
54223
|
+
if (!parentStat?.isDirectory() || parentStat.isSymbolicLink() || realpathSync8(parent.pluginParent) !== parent.pluginParent)
|
|
54224
|
+
refuse4();
|
|
54225
|
+
const receiptPath = join25(parent.pluginParent, ".codex-remote-plugin-install.json"), receiptStat = lstatSync16(receiptPath, { throwIfNoEntry: false });
|
|
54226
|
+
let receiptText;
|
|
54227
|
+
if (remote) {
|
|
54228
|
+
if (!receiptStat?.isFile() || receiptStat.isSymbolicLink() || receiptStat.size > MAX_RECEIPT_BYTES)
|
|
54229
|
+
refuse4();
|
|
54230
|
+
try {
|
|
54231
|
+
receiptText = read2(receiptPath);
|
|
54232
|
+
hashNativeJsonControls(receiptText);
|
|
54233
|
+
const receipt = JSON.parse(receiptText);
|
|
54234
|
+
if (!plainObject(receipt) || !exactKeys(receipt, ["schema_version", "remote_plugin_id"]) || receipt.schema_version !== 1 || receipt.remote_plugin_id !== parent.remotePluginId)
|
|
54235
|
+
refuse4();
|
|
54236
|
+
} catch {
|
|
54237
|
+
refuse4();
|
|
54238
|
+
}
|
|
54239
|
+
} else {
|
|
54240
|
+
const marketplaceSourcePath = parent.marketplaceSourcePath ?? refuse4();
|
|
54241
|
+
if (receiptStat !== undefined || !parent.marketplaceSha256)
|
|
54242
|
+
refuse4();
|
|
54243
|
+
let marketplaceText;
|
|
54244
|
+
try {
|
|
54245
|
+
marketplaceText = read2(marketplaceSourcePath);
|
|
54246
|
+
} catch {
|
|
54247
|
+
return refuse4();
|
|
54248
|
+
}
|
|
54249
|
+
if (createHash17("sha256").update(marketplaceText).digest("hex") !== parent.marketplaceSha256 || !codexLocalMarketplaceMapsPlugin(marketplaceText, parts[0], parent.namespace))
|
|
54250
|
+
refuse4();
|
|
54251
|
+
}
|
|
54252
|
+
const materializations = readdirSync7(parent.pluginParent).filter((name) => name !== ".codex-remote-plugin-install.json").map((version) => {
|
|
54253
|
+
if (!/^[A-Za-z0-9][A-Za-z0-9._+-]{0,127}$/.test(version))
|
|
54254
|
+
refuse4();
|
|
54255
|
+
const root = join25(parent.pluginParent, version), stat = lstatSync16(root, { throwIfNoEntry: false });
|
|
54256
|
+
if (!stat?.isDirectory() || stat.isSymbolicLink() || realpathSync8(root) !== root)
|
|
54257
|
+
refuse4();
|
|
54258
|
+
const controls = reviewedHookControls(root, read2);
|
|
54259
|
+
if (controls.namespace !== parent.namespace)
|
|
54260
|
+
refuse4();
|
|
54261
|
+
return { manifestSha256: controls.manifestSha256, hooksSha256: controls.hooksSha256 };
|
|
54262
|
+
});
|
|
54263
|
+
if (!materializations.length || materializations.some((item) => canonical7(item) !== canonical7(materializations[0])))
|
|
54264
|
+
refuse4();
|
|
54265
|
+
rows.push({ ...parent, ...receiptText === undefined ? {} : { receiptSha256: createHash17("sha256").update(receiptText).digest("hex") }, ...materializations[0] });
|
|
54266
|
+
}
|
|
54267
|
+
return rows.sort((a, b) => a.pluginId.localeCompare(b.pluginId) || a.pluginParent.localeCompare(b.pluginParent));
|
|
54268
|
+
}
|
|
54269
|
+
function assertParents(cacheRoot, controls, appOnlyParents, hookParents, files, members) {
|
|
54085
54270
|
const expected = new Set;
|
|
54086
54271
|
const expectedMarkets = new Set;
|
|
54087
|
-
for (const control of [...controls, ...appOnlyParents]) {
|
|
54272
|
+
for (const control of [...controls, ...appOnlyParents, ...hookParents]) {
|
|
54088
54273
|
const rel = relative6(cacheRoot, control.pluginParent), parts = rel.split(sep7);
|
|
54089
54274
|
if (resolve15(control.pluginParent) !== control.pluginParent || parts.length !== 2 || parts.some((part) => !identifier3(part)) || control.pluginId !== `${control.namespace}@${parts[0]}` || parts[1] !== control.namespace)
|
|
54090
54275
|
refuse4();
|
|
@@ -54125,7 +54310,9 @@ function assertParents(cacheRoot, controls, appOnlyParents, files, members) {
|
|
|
54125
54310
|
refuse4();
|
|
54126
54311
|
if ([".app.json", ".mcp.json"].includes(base2) && (parts.length !== 4 || dirname15(member) !== root))
|
|
54127
54312
|
refuse4();
|
|
54128
|
-
if (
|
|
54313
|
+
if ([".app.json", ".mcp.json"].includes(base2) && hookParents.some((reviewed) => reviewed.pluginParent === parent))
|
|
54314
|
+
refuse4();
|
|
54315
|
+
if (parts.includes("hooks") && (![4, 5].includes(parts.length) || parts[3] !== "hooks" || (parts.length === 4 ? base2 !== "hooks" : base2 !== "hooks.json") || !hookParents.some((reviewed) => reviewed.pluginParent === join25(cacheRoot, parts[0], parts[1]))))
|
|
54129
54316
|
refuse4();
|
|
54130
54317
|
}
|
|
54131
54318
|
}
|
|
@@ -54235,13 +54422,14 @@ function captureCodexSemanticCacheWitness(options) {
|
|
|
54235
54422
|
const initialTree = treeSnapshot(options.cacheRoot);
|
|
54236
54423
|
const controls = controlProjection(options.controls, read2);
|
|
54237
54424
|
const appOnlyParents = appOnlyParentProjection(options.cacheRoot, options.appOnlyParents ?? [], read2);
|
|
54425
|
+
const hookParents = reviewedHookParentProjection(options.cacheRoot, options.reviewedHookParents ?? [], read2);
|
|
54238
54426
|
const skillParents = new Set(controls.map((control) => control.pluginParent));
|
|
54239
|
-
if (appOnlyParents.some((parent) => skillParents.has(parent.pluginParent)))
|
|
54427
|
+
if (appOnlyParents.some((parent) => skillParents.has(parent.pluginParent)) || hookParents.some((parent) => skillParents.has(parent.pluginParent) || appOnlyParents.some((app) => app.pluginParent === parent.pluginParent)))
|
|
54240
54428
|
refuse4();
|
|
54241
54429
|
if (!reviewedCodexPluginCapabilitiesUnchanged(options.cacheRoot, options.controls, read2, options.rules))
|
|
54242
54430
|
refuse4();
|
|
54243
54431
|
const files = initialTree.files;
|
|
54244
|
-
assertParents(options.cacheRoot, controls, appOnlyParents, files, initialTree.state.members);
|
|
54432
|
+
assertParents(options.cacheRoot, controls, appOnlyParents, hookParents, files, initialTree.state.members);
|
|
54245
54433
|
const expectedNamesByRoot = assertSkillMaterializations(options.cacheRoot, options.controls, files, read2);
|
|
54246
54434
|
const docs = files.filter((path) => path.endsWith(`${sep7}SKILL.md`));
|
|
54247
54435
|
const skillRows = [];
|
|
@@ -54250,6 +54438,8 @@ function captureCodexSemanticCacheWitness(options) {
|
|
|
54250
54438
|
const rel = relative6(options.cacheRoot, document3).split(sep7);
|
|
54251
54439
|
if (appOnlyParents.some((parent) => parent.pluginParent === join25(options.cacheRoot, rel[0], rel[1])))
|
|
54252
54440
|
refuse4();
|
|
54441
|
+
if (hookParents.some((parent) => parent.pluginParent === join25(options.cacheRoot, rel[0], rel[1])))
|
|
54442
|
+
refuse4();
|
|
54253
54443
|
const documentStat = lstatSync16(document3, { throwIfNoEntry: false });
|
|
54254
54444
|
if (!documentStat?.isFile() || documentStat.isSymbolicLink() || documentStat.size > MAX_DOCUMENT_BYTES)
|
|
54255
54445
|
refuse4();
|
|
@@ -54313,7 +54503,7 @@ function captureCodexSemanticCacheWitness(options) {
|
|
|
54313
54503
|
tracked.verify();
|
|
54314
54504
|
const finalTree = treeSnapshot(options.cacheRoot);
|
|
54315
54505
|
assertSameTree(initialTree.state, finalTree.state, tracked.paths());
|
|
54316
|
-
const completeProjection = { schema: CODEX_SEMANTIC_CACHE_WITNESS_SCHEMA, cacheRoot: options.cacheRoot, controls, appOnlyParents, skills: uniqueSkills };
|
|
54506
|
+
const completeProjection = { schema: CODEX_SEMANTIC_CACHE_WITNESS_SCHEMA, cacheRoot: options.cacheRoot, controls, appOnlyParents, hookParents, skills: uniqueSkills };
|
|
54317
54507
|
return { ...completeProjection, sha256: hash2(completeProjection) };
|
|
54318
54508
|
} catch (error) {
|
|
54319
54509
|
if (error instanceof Error && error.message.startsWith("CODEX_SEMANTIC_CACHE_WITNESS_UNSUPPORTED"))
|
|
@@ -54329,6 +54519,7 @@ function assertCodexSemanticCacheWitnessUnchanged(previous, current) {
|
|
|
54329
54519
|
cacheRoot: previous.cacheRoot,
|
|
54330
54520
|
controls: previous.controls,
|
|
54331
54521
|
appOnlyParents: previous.appOnlyParents,
|
|
54522
|
+
...previous.hookParents === undefined ? {} : { hookParents: previous.hookParents },
|
|
54332
54523
|
skills: previous.skills
|
|
54333
54524
|
};
|
|
54334
54525
|
const currentProjection = {
|
|
@@ -54336,20 +54527,41 @@ function assertCodexSemanticCacheWitnessUnchanged(previous, current) {
|
|
|
54336
54527
|
cacheRoot: current.cacheRoot,
|
|
54337
54528
|
controls: current.controls,
|
|
54338
54529
|
appOnlyParents: current.appOnlyParents,
|
|
54530
|
+
...current.hookParents === undefined ? {} : { hookParents: current.hookParents },
|
|
54339
54531
|
skills: current.skills
|
|
54340
54532
|
};
|
|
54341
|
-
|
|
54533
|
+
const comparable = (projection) => ({ ...projection, hookParents: projection.hookParents ?? [] });
|
|
54534
|
+
if (hash2(priorProjection) !== previous.sha256 || hash2(currentProjection) !== current.sha256 || canonical7(comparable(priorProjection)) !== canonical7(comparable(currentProjection)))
|
|
54342
54535
|
refuse4();
|
|
54343
54536
|
}
|
|
54344
54537
|
var CODEX_SEMANTIC_CACHE_WITNESS_SCHEMA = "hasna.codex-semantic-cache-witness.v1", identifier3 = (value) => typeof value === "string" && /^[A-Za-z0-9_-]{1,64}$/.test(value), digest = (value) => typeof value === "string" && /^[a-f0-9]{64}$/.test(value), refuse4 = () => {
|
|
54345
54538
|
throw new Error("CODEX_SEMANTIC_CACHE_WITNESS_UNSUPPORTED: review Codex plugin cache identity and controls");
|
|
54346
|
-
}, MAX_DOCUMENT_BYTES, MAX_RECEIPT_BYTES;
|
|
54539
|
+
}, MAX_DOCUMENT_BYTES, MAX_RECEIPT_BYTES, codexHookEvents;
|
|
54347
54540
|
var init_codex_semantic_cache_witness = __esm(() => {
|
|
54348
54541
|
init_claude_settings_witness();
|
|
54349
54542
|
init_codex_plugin_skill_controls();
|
|
54350
54543
|
init_codex_native_skill_catalog();
|
|
54351
54544
|
MAX_DOCUMENT_BYTES = 1024 * 1024;
|
|
54352
54545
|
MAX_RECEIPT_BYTES = 16 * 1024;
|
|
54546
|
+
codexHookEvents = new Set([
|
|
54547
|
+
"SessionStart",
|
|
54548
|
+
"UserPromptSubmit",
|
|
54549
|
+
"PreToolUse",
|
|
54550
|
+
"PostToolUse",
|
|
54551
|
+
"PostToolUseFailure",
|
|
54552
|
+
"Stop",
|
|
54553
|
+
"SubagentStart",
|
|
54554
|
+
"SubagentStop",
|
|
54555
|
+
"PreCompact",
|
|
54556
|
+
"Notification",
|
|
54557
|
+
"PermissionRequest",
|
|
54558
|
+
"SessionEnd",
|
|
54559
|
+
"ConfigChange",
|
|
54560
|
+
"WorktreeCreate",
|
|
54561
|
+
"WorktreeRemove",
|
|
54562
|
+
"TeammateIdle",
|
|
54563
|
+
"TaskComplete"
|
|
54564
|
+
]);
|
|
54353
54565
|
});
|
|
54354
54566
|
|
|
54355
54567
|
// src/lib/managed-policy.ts
|
|
@@ -54750,6 +54962,130 @@ var init_agent_codex = __esm(() => {
|
|
|
54750
54962
|
CODEX_SKILL_CONFIG_SECTIONS = /^\[\[skills\.config\]\][^\n]*(?:\n(?!\s*\[)[^\n]*)*/gm;
|
|
54751
54963
|
});
|
|
54752
54964
|
|
|
54965
|
+
// src/lib/hook-diagnostics.ts
|
|
54966
|
+
function hookChildError(stdout, stage) {
|
|
54967
|
+
let code;
|
|
54968
|
+
if (stdout.length <= 16 * 1024) {
|
|
54969
|
+
try {
|
|
54970
|
+
code = JSON.parse(stdout)?.error?.code;
|
|
54971
|
+
} catch {}
|
|
54972
|
+
}
|
|
54973
|
+
return new HookDiagnosticError(typeof code === "string" && CONTEXT_ERROR_CODES.has(code) ? code : "SKILLS_CONTEXT_FAILED", stage);
|
|
54974
|
+
}
|
|
54975
|
+
function hookFailureReason(error, profileId) {
|
|
54976
|
+
const owned = error instanceof HookDiagnosticError;
|
|
54977
|
+
const code = owned && (CONTEXT_ERROR_CODES.has(error.code) || ["SKILLS_HOOK_TIMEOUT", "SKILLS_HOOK_INVALID_RESPONSE"].includes(error.code)) ? error.code : "SKILLS_HOOK_FAILED";
|
|
54978
|
+
const profile = typeof profileId === "string" && /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/.test(profileId) && !profileId.includes("..") ? profileId : undefined;
|
|
54979
|
+
const identity6 = [profile ? `profile=${profile}` : undefined, owned ? `stage=${error.stage}` : undefined].filter(Boolean).join(", ");
|
|
54980
|
+
const prefix = `Skills context is unavailable [${code}]${identity6 ? ` (${identity6})` : ""}.`;
|
|
54981
|
+
if (code === "SKILLS_STORAGE_FULL") {
|
|
54982
|
+
return `${prefix} The filesystem is full or its quota is exhausted. Free space through your approved recoverable cleanup process, then retry the same session. Do not delete session receipts or change credentials to bypass this failure.`;
|
|
54983
|
+
}
|
|
54984
|
+
if (code === "PROFILE_LOCK_MISMATCH") {
|
|
54985
|
+
return `${prefix} This session or project is pinned to a different profile. Inspect the session with skills sessions show <session-id> --json; review skills sessions reconcile for an intentional session change, or explicit project sync for a project change. Sync alone does not change that pin.`;
|
|
54986
|
+
}
|
|
54987
|
+
if (code === "SESSION_RECONCILIATION_REQUIRED") {
|
|
54988
|
+
return `${prefix} A loaded skill changed or was removed. Inspect this session with skills sessions show <session-id> --json, then review skills sessions reconcile for an intentional change. Sync alone does not change this pin. A refusal is re-checked with the authority within five minutes, or sooner after the receipt or the synced profile revision changes.`;
|
|
54989
|
+
}
|
|
54990
|
+
if (code === "SESSION_RENEWAL_TIMEOUT") {
|
|
54991
|
+
return `${prefix} Renewing this session's expired authorization did not finish within the hook's renewal window; no request was refused. Sync and diagnosis do not change this window. The existing pin is unchanged and the next prompt retries the renewal. If it keeps recurring, inspect the session with skills sessions show <session-id> --json and review skills sessions reconcile.`;
|
|
54992
|
+
}
|
|
54993
|
+
if (code.startsWith("SESSION_")) {
|
|
54994
|
+
return `${prefix} Inspect the session with skills sessions show <session-id> --json and review its parent or concurrent writer before retrying. Do not remove or rewrite its receipt to bypass this refusal.`;
|
|
54995
|
+
}
|
|
54996
|
+
if (["PROFILE_IDENTITY_MISMATCH", "BUNDLE_DIGEST_MISMATCH", "BUNDLE_IDENTITY_MISMATCH", "INVALID_RECEIPT", "INVALID_CACHE_FILE", "UNSAFE_CACHE_PATH"].includes(code)) {
|
|
54997
|
+
return `${prefix} Verify the selected authority and receipt integrity before repairing the profile; do not bypass verification or substitute another cache.`;
|
|
54998
|
+
}
|
|
54999
|
+
const selected = profile ?? "<id>";
|
|
55000
|
+
return `${prefix} Run skills sync --selection-profile ${selected} --json, then diagnose with skills context --stdin --json --cached --selection-profile ${selected} using the same hook session and working-directory fields. Do not include credentials in diagnostic input.`;
|
|
55001
|
+
}
|
|
55002
|
+
function isOptionalHookContextFailure(error) {
|
|
55003
|
+
return error instanceof HookDiagnosticError && OPTIONAL_CONTEXT_FAILURES.has(error.code);
|
|
55004
|
+
}
|
|
55005
|
+
function hookUnavailableContext(error, profileId) {
|
|
55006
|
+
return `${hookFailureReason(error, profileId)} No Skills instructions were delivered by this hook. Ordinary work may continue. Do not perform actions that depend on unavailable Skills instructions, including previously loaded instructions. Explicit skills load, context and run still require verification. Do not substitute native, unmanaged or stale payloads.`;
|
|
55007
|
+
}
|
|
55008
|
+
var CONTEXT_ERROR_CODES, HOOK_REFUSAL_REASON_CODES, HookDiagnosticError, OPTIONAL_CONTEXT_FAILURES;
|
|
55009
|
+
var init_hook_diagnostics = __esm(() => {
|
|
55010
|
+
CONTEXT_ERROR_CODES = new Set([
|
|
55011
|
+
"SKILLS_API_CREDENTIAL_UNAVAILABLE",
|
|
55012
|
+
"SKILLS_API_UNAVAILABLE",
|
|
55013
|
+
"SKILLS_API_UNAUTHORIZED",
|
|
55014
|
+
"SKILLS_API_FORBIDDEN",
|
|
55015
|
+
"SKILLS_API_RESOURCE_UNAVAILABLE",
|
|
55016
|
+
"SESSION_WRITE_BUSY",
|
|
55017
|
+
"SKILLS_CONTEXT_FAILED",
|
|
55018
|
+
"SKILLS_STORAGE_FULL",
|
|
55019
|
+
"PROFILE_LOCK_MISMATCH",
|
|
55020
|
+
"PROFILE_IDENTITY_MISMATCH",
|
|
55021
|
+
"PROFILE_APPLIED_REPORT_FAILED",
|
|
55022
|
+
"CACHED_AUTHORITY_REQUIRED",
|
|
55023
|
+
"CACHED_PROFILE_EXPIRED",
|
|
55024
|
+
"CACHED_PROFILE_MISSING",
|
|
55025
|
+
"CACHED_BUNDLE_MISSING",
|
|
55026
|
+
"INVALID_CONTEXT_INPUT",
|
|
55027
|
+
"CONTEXT_INPUT_TOO_LARGE",
|
|
55028
|
+
"INVALID_CONTEXT_BUDGET",
|
|
55029
|
+
"INVALID_SELECTION",
|
|
55030
|
+
"INVALID_SELECTION_ALIASES",
|
|
55031
|
+
"INVALID_RECEIPT",
|
|
55032
|
+
"INVALID_CACHE_FILE",
|
|
55033
|
+
"UNSAFE_CACHE_PATH",
|
|
55034
|
+
"RECEIPT_TOO_LARGE",
|
|
55035
|
+
"BUNDLE_DIGEST_MISMATCH",
|
|
55036
|
+
"BUNDLE_IDENTITY_MISMATCH",
|
|
55037
|
+
"BUNDLE_UNAVAILABLE",
|
|
55038
|
+
"BUNDLE_TOO_LARGE",
|
|
55039
|
+
"SKILL_NOT_SELECTED",
|
|
55040
|
+
"INVALID_SESSION",
|
|
55041
|
+
"SESSION_PARENT_NOT_FOUND",
|
|
55042
|
+
"SESSION_PARENT_MISMATCH",
|
|
55043
|
+
"SESSION_NOT_FOUND",
|
|
55044
|
+
"SESSION_GENERATION_CHANGED",
|
|
55045
|
+
"SESSION_GENERATION_EXHAUSTED",
|
|
55046
|
+
"SESSION_PARENT_CHANGED",
|
|
55047
|
+
"SESSION_RECEIPT_CHANGED",
|
|
55048
|
+
"SESSION_RECONCILIATION_REQUIRED",
|
|
55049
|
+
"SESSION_RENEWAL_TIMEOUT",
|
|
55050
|
+
"SESSION_CONTEXT_CONFLICT",
|
|
55051
|
+
"SESSION_RECONCILIATION_INCOMPLETE",
|
|
55052
|
+
"SESSION_WRITE_LOCKED",
|
|
55053
|
+
"SESSION_WRITE_LOCK_CHANGED",
|
|
55054
|
+
"SESSION_LOCK_RECOVERY_INCOMPLETE"
|
|
55055
|
+
]);
|
|
55056
|
+
HOOK_REFUSAL_REASON_CODES = Object.freeze([
|
|
55057
|
+
...CONTEXT_ERROR_CODES,
|
|
55058
|
+
"SKILLS_HOOK_FAILED",
|
|
55059
|
+
"SKILLS_HOOK_TIMEOUT",
|
|
55060
|
+
"SKILLS_HOOK_INVALID_RESPONSE"
|
|
55061
|
+
]);
|
|
55062
|
+
HookDiagnosticError = class HookDiagnosticError extends Error {
|
|
55063
|
+
code;
|
|
55064
|
+
stage;
|
|
55065
|
+
constructor(code, stage) {
|
|
55066
|
+
super("Skills hook operation failed");
|
|
55067
|
+
this.code = code;
|
|
55068
|
+
this.stage = stage;
|
|
55069
|
+
}
|
|
55070
|
+
};
|
|
55071
|
+
OPTIONAL_CONTEXT_FAILURES = new Set([
|
|
55072
|
+
"SKILLS_API_CREDENTIAL_UNAVAILABLE",
|
|
55073
|
+
"SKILLS_API_UNAVAILABLE",
|
|
55074
|
+
"SKILLS_API_UNAUTHORIZED",
|
|
55075
|
+
"SKILLS_API_FORBIDDEN",
|
|
55076
|
+
"SKILLS_API_RESOURCE_UNAVAILABLE",
|
|
55077
|
+
"CACHED_PROFILE_EXPIRED",
|
|
55078
|
+
"CACHED_PROFILE_MISSING",
|
|
55079
|
+
"CACHED_BUNDLE_MISSING",
|
|
55080
|
+
"SESSION_RECONCILIATION_REQUIRED",
|
|
55081
|
+
"SESSION_RENEWAL_TIMEOUT",
|
|
55082
|
+
"SESSION_WRITE_BUSY",
|
|
55083
|
+
"SESSION_PARENT_CHANGED",
|
|
55084
|
+
"SESSION_CONTEXT_CONFLICT",
|
|
55085
|
+
"SKILLS_HOOK_TIMEOUT"
|
|
55086
|
+
]);
|
|
55087
|
+
});
|
|
55088
|
+
|
|
54753
55089
|
// src/lib/agent-sumi.ts
|
|
54754
55090
|
import { spawnSync as spawnSync3 } from "child_process";
|
|
54755
55091
|
import { accessSync as accessSync2, constants as constants12, existsSync as existsSync12, lstatSync as lstatSync19, realpathSync as realpathSync9, statSync as statSync9 } from "fs";
|
|
@@ -54883,24 +55219,33 @@ function sumiConfigPath(home, cwd2 = process.cwd(), env3 = process.env) {
|
|
|
54883
55219
|
return join28(sumiConfigDirectory(home, env3, cwd2), "sumi.json");
|
|
54884
55220
|
}
|
|
54885
55221
|
function renderSumiPlugin(command, profile) {
|
|
54886
|
-
return renderSumiPluginVersion(command, profile,
|
|
55222
|
+
return renderSumiPluginVersion(command, profile, 3);
|
|
54887
55223
|
}
|
|
54888
55224
|
function isManagedSumiPlugin(text2, command, profile) {
|
|
54889
|
-
return text2 === renderSumiPlugin(command, profile) || text2 === renderSumiPluginVersion(command, profile,
|
|
55225
|
+
return text2 === renderSumiPlugin(command, profile) || text2 === renderSumiPluginVersion(command, profile, 2) || text2 === renderSumiPluginVersion(command, profile, 1);
|
|
54890
55226
|
}
|
|
54891
|
-
function renderSumiPluginVersion(command, profile,
|
|
55227
|
+
function renderSumiPluginVersion(command, profile, version) {
|
|
55228
|
+
const legacy = version === 1;
|
|
54892
55229
|
const failure = (message) => legacy ? `new Error(${JSON.stringify(message)})` : "refusal()";
|
|
54893
55230
|
return `// Managed by @hasna/skills. Regenerate with skills hook install --agent sumi.
|
|
54894
55231
|
import { spawn } from "node:child_process";
|
|
54895
55232
|
const command = ${JSON.stringify(command)};
|
|
54896
55233
|
const profile = ${JSON.stringify(profile)};
|
|
54897
|
-
${legacy ? "" : `function refusal() {
|
|
54898
|
-
const error = new Error("Skills verification blocked this request. Review the Sumi Skills hook configuration, then retry.");
|
|
55234
|
+
${legacy ? "" : `function refusal(${version === 3 ? "reasonCode" : ""}) {
|
|
55235
|
+
const error = new Error("Skills verification blocked this request. Review the Sumi Skills hook configuration, then retry."${version === 3 ? ' + (reasonCode ? " [" + reasonCode + "]" : "")' : ""});
|
|
54899
55236
|
error.name = "SkillsHookRefusal";
|
|
54900
|
-
error.skillsHookRefusal = { version: 1, code: "SKILLS_HOOK_REFUSED" };
|
|
55237
|
+
error.skillsHookRefusal = { version: 1, code: "SKILLS_HOOK_REFUSED"${version === 3 ? ", ...(reasonCode ? { reasonCode } : {})" : ""} };
|
|
54901
55238
|
return error;
|
|
54902
55239
|
}
|
|
54903
|
-
`}
|
|
55240
|
+
`}${version === 3 ? `const reasonCodes = new Set(${JSON.stringify(HOOK_REFUSAL_REASON_CODES)});
|
|
55241
|
+
function refusedResult(result) {
|
|
55242
|
+
const reason = result.reason ?? result.stopReason ?? result.systemMessage;
|
|
55243
|
+
if (typeof reason !== "string" || reason.length > 16384) return refusal();
|
|
55244
|
+
if (reason.startsWith("NATIVE_SKILL_DRIFT:")) return refusal("NATIVE_SKILL_DRIFT");
|
|
55245
|
+
const code = /^Skills context is unavailable \\[([A-Z_]+)\\]/.exec(reason)?.[1];
|
|
55246
|
+
return refusal(reasonCodes.has(code) ? code : undefined);
|
|
55247
|
+
}
|
|
55248
|
+
` : ""}function context(input) {
|
|
54904
55249
|
return new Promise((resolve, reject) => {
|
|
54905
55250
|
const child = spawn(command, ["hook", "user-prompt", "--agent", "sumi", "--selection-profile", profile], { cwd: input.cwd, stdio: ["pipe", "pipe", "pipe"] });
|
|
54906
55251
|
const chunks = []; let bytes = 0, failure;
|
|
@@ -54915,12 +55260,12 @@ ${legacy ? "" : `function refusal() {
|
|
|
54915
55260
|
try {
|
|
54916
55261
|
const result = JSON.parse(Buffer.concat(chunks).toString("utf8"));
|
|
54917
55262
|
if (!result || typeof result !== "object" || Array.isArray(result)) throw ${failure("Invalid Skills hook response")};
|
|
54918
|
-
if (result.decision === "block" || result.continue === false) throw ${failure("Skills prompt hook refused")};
|
|
55263
|
+
if (result.decision === "block" || result.continue === false) throw ${version === 3 ? "refusedResult(result)" : failure("Skills prompt hook refused")};
|
|
54919
55264
|
if (Object.keys(result).length && (!result.hookSpecificOutput || result.hookSpecificOutput.hookEventName !== input.hook_event_name)) throw ${failure("Invalid Skills hook response")};
|
|
54920
55265
|
const text = result.hookSpecificOutput?.additionalContext ?? "";
|
|
54921
55266
|
if (typeof text !== "string") throw ${failure("Invalid Skills prompt context")};
|
|
54922
55267
|
resolve(text);
|
|
54923
|
-
} catch (error) { reject(${legacy ? "error" : "refusal()"}); }
|
|
55268
|
+
} catch (error) { reject(${legacy ? "error" : version === 3 ? 'error instanceof Error && error.name === "SkillsHookRefusal" ? error : refusal()' : "refusal()"}); }
|
|
54924
55269
|
});
|
|
54925
55270
|
child.stdin.end(JSON.stringify(input));
|
|
54926
55271
|
});
|
|
@@ -54953,9 +55298,13 @@ export default {
|
|
|
54953
55298
|
sessions.add(event.sessionID);
|
|
54954
55299
|
}));
|
|
54955
55300
|
registrations.push(await ctx.session.hook("context", async event => {
|
|
54956
|
-
|
|
55301
|
+
${version === 3 ? ` // Model messages also contain checkpoints, attachments and synthetic
|
|
55302
|
+
// user-role history, with no owner-prompt provenance. Prompt admission
|
|
55303
|
+
// already matched and persisted Skills; restore that verified state only.
|
|
55304
|
+
const prompt = "";
|
|
55305
|
+
` : ` const last = event.messages.findLast(message => message.role === "user");
|
|
54957
55306
|
const prompt = (last?.content ?? []).filter(part => part.type === "text").map(part => part.text).join("\\n");
|
|
54958
|
-
// Recheck on every primary request, including resumed and synthetic
|
|
55307
|
+
`} // Recheck on every primary request, including resumed and synthetic
|
|
54959
55308
|
// sessions. The CLI owns optional failures versus explicit refusals.
|
|
54960
55309
|
const text = await context(await input(event.sessionID, prompt, !sessions.has(event.sessionID)));
|
|
54961
55310
|
if (text) event.system.push({ type: "text", text });
|
|
@@ -54968,6 +55317,7 @@ export default {
|
|
|
54968
55317
|
}
|
|
54969
55318
|
var SUMI_PATH_SELECTORS, SUMI_PATH_KEYS, SUMI_PATH_OUTPUT_LIMIT, SumiPathResolverError, SUMI_SKILL_PERMISSIONS;
|
|
54970
55319
|
var init_agent_sumi = __esm(() => {
|
|
55320
|
+
init_hook_diagnostics();
|
|
54971
55321
|
SUMI_PATH_SELECTORS = ["SUMI_HOME", "SUMI_CONFIG_DIR", "XDG_DATA_HOME", "XDG_CACHE_HOME", "XDG_CONFIG_HOME", "XDG_STATE_HOME"];
|
|
54972
55322
|
SUMI_PATH_KEYS = ["data", "cache", "config", "state"];
|
|
54973
55323
|
SUMI_PATH_OUTPUT_LIMIT = 128 * 1024;
|
|
@@ -55607,7 +55957,7 @@ var init_retained_review_artifacts = __esm(() => {
|
|
|
55607
55957
|
import { createHash as createHash22, randomUUID as randomUUID6 } from "crypto";
|
|
55608
55958
|
import { isDeepStrictEqual as isDeepStrictEqual7 } from "util";
|
|
55609
55959
|
import { existsSync as existsSync13, lstatSync as lstatSync23, statSync as statSync10, mkdirSync as mkdirSync7, readFileSync as readFileSync16, readdirSync as readdirSync9, opendirSync as opendirSync3, readlinkSync as readlinkSync7, realpathSync as realpathSync11, renameSync as renameSync3, rmdirSync as rmdirSync2, writeFileSync as writeFileSync6, unlinkSync as unlinkSync4, chmodSync, openSync as openSync14, closeSync as closeSync14, fsyncSync as fsyncSync6, fstatSync as fstatSync14, readSync as readSync11, constants as constants16, linkSync as linkSync2 } from "fs";
|
|
55610
|
-
import { dirname as dirname18, join as join30, resolve as resolve19, relative as relative7, isAbsolute as isAbsolute20, sep as sep9 } from "path";
|
|
55960
|
+
import { basename as basename10, dirname as dirname18, join as join30, resolve as resolve19, relative as relative7, isAbsolute as isAbsolute20, sep as sep9 } from "path";
|
|
55611
55961
|
import { homedir as homedir3 } from "os";
|
|
55612
55962
|
function nativeAgentRoot(home, agent, cwd2 = process.cwd()) {
|
|
55613
55963
|
if (agent === "sumi")
|
|
@@ -56758,7 +57108,7 @@ function planAgentSettingsWitnessUpgrade(options) {
|
|
|
56758
57108
|
return { dataDir: dataDir3, profileId: policy.profileId, changes: [{ path: join30(dataDir3, "agent-policy.json"), before: snapshot2.text, after: after2 }], nativeSkills: [], observedPolicy: { path: join30(dataDir3, "agent-policy.json"), before: snapshot2.text }, observedSettings: { path: configPath, before: settings }, discoveryBefore: [replacement], discoveryAfter: [replacement], ...policy.bridge.discoveryExecutables ? { discoveryExecutables: policy.bridge.discoveryExecutables } : {}, rootAliases: aliases, managedAgentChecks: { home, agents: [options.agent] }, settingsWitnessUpgrade: { agent: options.agent, path: configPath, fromHashMode: previous.hashMode ?? "bytes", fromSha256: previous.sha256, toHashMode: next.hashMode, toSha256: next.sha256, reviewedPreimage: options.reviewedPreimage, currentSettingsSha256: options.expectedSettingsSha256, replacedWitnesses: replaced.map((source) => ({ hashMode: source.hashMode ?? "bytes", sha256: source.sha256 })) } };
|
|
56759
57109
|
}
|
|
56760
57110
|
function planCodexSemanticCacheWitnessUpgrade(options) {
|
|
56761
|
-
if (options.agent !== "codex" || !/^[a-f0-9]{64}$/.test(options.expectedPolicySha256) || !/^[a-f0-9]{64}$/.test(options.expectedSettingsSha256) || options.expectedCacheWitnessSha256 !== undefined && !/^[a-f0-9]{64}$/.test(options.expectedCacheWitnessSha256) || !Array.isArray(options.appOnlyParents) || options.appOnlyParents.length > 4096 || new Set(options.appOnlyParents).size !== options.appOnlyParents.length)
|
|
57111
|
+
if (options.agent !== "codex" || !/^[a-f0-9]{64}$/.test(options.expectedPolicySha256) || !/^[a-f0-9]{64}$/.test(options.expectedSettingsSha256) || options.expectedCacheWitnessSha256 !== undefined && !/^[a-f0-9]{64}$/.test(options.expectedCacheWitnessSha256) || !Array.isArray(options.appOnlyParents) || options.appOnlyParents.length > 4096 || new Set(options.appOnlyParents).size !== options.appOnlyParents.length || options.reviewedHookParents !== undefined && (!Array.isArray(options.reviewedHookParents) || options.reviewedHookParents.length > 4096 || new Set(options.reviewedHookParents).size !== options.reviewedHookParents.length))
|
|
56762
57112
|
throw new Error("Invalid Codex semantic cache upgrade request");
|
|
56763
57113
|
const home = resolve19(options.home ?? homedir3()), dataDir3 = options.dataDir ?? getDataDirReadOnly();
|
|
56764
57114
|
const snapshot2 = readManagedSkillPolicySnapshot(dataDir3);
|
|
@@ -56782,14 +57132,23 @@ function planCodexSemanticCacheWitnessUpgrade(options) {
|
|
|
56782
57132
|
throw new Error("Native settings preimage changed");
|
|
56783
57133
|
const boundedRead = (path) => new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(readNativeBytes(path, 1024 * 1024));
|
|
56784
57134
|
const unchangedFullSource = (path) => {
|
|
56785
|
-
const
|
|
56786
|
-
if (
|
|
56787
|
-
throw new Error("Cache upgrade
|
|
57135
|
+
const sources = binding.sources.filter((source2) => source2.path === path && source2.sha256 !== null && source2.format === undefined && source2.fields === undefined && source2.reviewArtifact === undefined && (source2.hashMode === undefined || source2.hashMode === "bytes"));
|
|
57136
|
+
if (sources.length !== 1)
|
|
57137
|
+
throw new Error("Cache upgrade requires one unambiguous prior full identity source");
|
|
57138
|
+
const source = sources[0];
|
|
56788
57139
|
const text2 = boundedRead(path);
|
|
56789
57140
|
if (sha4(text2) !== source.sha256)
|
|
56790
57141
|
throw new Error("Reviewed cache identity source changed");
|
|
56791
57142
|
return text2;
|
|
56792
57143
|
};
|
|
57144
|
+
const unchangedReviewedHookSource = (path) => {
|
|
57145
|
+
const sources = binding.sources.filter((source) => source.path === path);
|
|
57146
|
+
if (!sources.length)
|
|
57147
|
+
throw new Error("Cache upgrade lacks prior full identity source");
|
|
57148
|
+
if (sources.length !== 1)
|
|
57149
|
+
throw new Error("Reviewed hook identity source is ambiguous");
|
|
57150
|
+
return unchangedFullSource(path);
|
|
57151
|
+
};
|
|
56793
57152
|
const appOnlyParents = options.appOnlyParents.map((parent) => {
|
|
56794
57153
|
const parts = relative7(cacheRoot, parent).split(sep9);
|
|
56795
57154
|
if (!isAbsolute20(parent) || resolve19(parent) !== parent || parts.length !== 2 || parts.some((part) => !/^[A-Za-z0-9_-]{1,64}$/.test(part)) || controls.some((control) => control.pluginParent === parent))
|
|
@@ -56804,11 +57163,60 @@ function planCodexSemanticCacheWitnessUpgrade(options) {
|
|
|
56804
57163
|
unchangedFullSource(source.path);
|
|
56805
57164
|
return { role: "app-only", pluginId: `${parts[1]}@${parts[0]}`, namespace: parts[1], pluginParent: parent, remotePluginId: receipt.remote_plugin_id };
|
|
56806
57165
|
}).sort((a, b) => a.pluginParent.localeCompare(b.pluginParent));
|
|
56807
|
-
const
|
|
57166
|
+
const reviewedHookParents = (options.reviewedHookParents ?? []).map((parent) => {
|
|
57167
|
+
const parts = relative7(cacheRoot, parent).split(sep9);
|
|
57168
|
+
if (!isAbsolute20(parent) || resolve19(parent) !== parent || parts.length !== 2 || parts.some((part) => !/^[A-Za-z0-9_-]{1,64}$/.test(part)) || controls.some((control) => control.pluginParent === parent) || appOnlyParents.some((role) => role.pluginParent === parent))
|
|
57169
|
+
throw new Error("Unsupported reviewed native-hook parent role");
|
|
57170
|
+
const receiptPath = join30(parent, ".codex-remote-plugin-install.json"), receiptStat = lstatSync23(receiptPath, { throwIfNoEntry: false });
|
|
57171
|
+
let identity6;
|
|
57172
|
+
if (receiptStat) {
|
|
57173
|
+
if (!receiptStat.isFile() || receiptStat.isSymbolicLink() || receiptStat.size > 16 * 1024)
|
|
57174
|
+
throw new Error("Invalid reviewed native-hook install receipt");
|
|
57175
|
+
const receiptText = unchangedReviewedHookSource(receiptPath);
|
|
57176
|
+
let receipt;
|
|
57177
|
+
try {
|
|
57178
|
+
hashNativeJsonControls(receiptText);
|
|
57179
|
+
receipt = JSON.parse(receiptText);
|
|
57180
|
+
} catch {
|
|
57181
|
+
throw new Error("Invalid reviewed native-hook install receipt");
|
|
57182
|
+
}
|
|
57183
|
+
if (!receipt || Array.isArray(receipt) || Object.keys(receipt).length !== 2 || receipt.schema_version !== 1 || typeof receipt.remote_plugin_id !== "string" || !/^[A-Za-z0-9_~-]{1,1024}$/.test(receipt.remote_plugin_id))
|
|
57184
|
+
throw new Error("Invalid reviewed native-hook install receipt");
|
|
57185
|
+
identity6 = { role: "reviewed-hook", pluginId: `${parts[1]}@${parts[0]}`, namespace: parts[1], pluginParent: parent, installation: "remote-receipt", remotePluginId: receipt.remote_plugin_id };
|
|
57186
|
+
} else {
|
|
57187
|
+
const pluginId = `${parts[1]}@${parts[0]}`;
|
|
57188
|
+
const marketplaceSources = binding.sources.filter((source2) => basename10(source2.path) === "marketplace.json" && source2.sha256 !== null && source2.format === undefined && source2.fields === undefined && source2.reviewArtifact === undefined && (source2.hashMode === undefined || source2.hashMode === "bytes"));
|
|
57189
|
+
const matches2 = marketplaceSources.flatMap((source2) => {
|
|
57190
|
+
const text2 = unchangedFullSource(source2.path);
|
|
57191
|
+
return codexLocalMarketplaceMapsPlugin(text2, parts[0], parts[1]) ? [{ source: source2, text: text2 }] : [];
|
|
57192
|
+
});
|
|
57193
|
+
if (matches2.length !== 1)
|
|
57194
|
+
throw new Error("Local marketplace hook parent lacks one exact enrolled marketplace source");
|
|
57195
|
+
const { source } = matches2[0];
|
|
57196
|
+
const config = Bun.TOML.parse(settings);
|
|
57197
|
+
if (config.plugins?.[pluginId]?.enabled !== true)
|
|
57198
|
+
throw new Error("Local marketplace hook parent is not enabled in the unchanged Codex settings");
|
|
57199
|
+
identity6 = { role: "reviewed-hook", pluginId, namespace: parts[1], pluginParent: parent, installation: "local-marketplace", marketplaceSourcePath: source.path, marketplaceSha256: source.sha256 };
|
|
57200
|
+
}
|
|
57201
|
+
const versions = readdirSync9(parent).filter((name) => name !== ".codex-remote-plugin-install.json");
|
|
57202
|
+
if (!versions.length || versions.length > 4096)
|
|
57203
|
+
throw new Error("Reviewed native-hook parent has no bounded materializations");
|
|
57204
|
+
for (const version of versions) {
|
|
57205
|
+
if (!/^[A-Za-z0-9][A-Za-z0-9._+-]{0,127}$/.test(version))
|
|
57206
|
+
throw new Error("Invalid reviewed native-hook version identity");
|
|
57207
|
+
const root = join30(parent, version), stat = lstatSync23(root, { throwIfNoEntry: false });
|
|
57208
|
+
if (!stat?.isDirectory() || stat.isSymbolicLink() || realpathSync11(root) !== root)
|
|
57209
|
+
throw new Error("Invalid reviewed native-hook materialization");
|
|
57210
|
+
unchangedReviewedHookSource(join30(root, ".codex-plugin/plugin.json"));
|
|
57211
|
+
unchangedReviewedHookSource(join30(root, "hooks/hooks.json"));
|
|
57212
|
+
}
|
|
57213
|
+
return identity6;
|
|
57214
|
+
}).sort((a, b) => a.pluginParent.localeCompare(b.pluginParent));
|
|
57215
|
+
const parents2 = [...new Set([...controls.map((control) => control.pluginParent), ...appOnlyParents.map((parent) => parent.pluginParent), ...reviewedHookParents.map((parent) => parent.pluginParent)])];
|
|
56808
57216
|
const reviewedAlias = aliases.find((alias) => alias.agent === "codex");
|
|
56809
57217
|
const hookRootAlias = reviewedAlias ? { alias: reviewedAlias.alias, target: reviewedAlias.target } : null;
|
|
56810
57218
|
assertCodexSemanticCacheHookSafety(cacheRoot, parents2, configPath, hookRootAlias);
|
|
56811
|
-
const supersededSources = binding.sources.filter((source) => codexSemanticCacheSourceRole(source, cacheRoot, parents2));
|
|
57219
|
+
const supersededSources = binding.sources.filter((source) => codexSemanticCacheSourceRole(source, cacheRoot, parents2, reviewedHookParents.map((parent) => parent.pluginParent)));
|
|
56812
57220
|
for (const source of supersededSources)
|
|
56813
57221
|
if ([".app.json", ".mcp.json"].includes(source.path.split(sep9).at(-1)))
|
|
56814
57222
|
unchangedFullSource(source.path);
|
|
@@ -56816,7 +57224,7 @@ function planCodexSemanticCacheWitnessUpgrade(options) {
|
|
|
56816
57224
|
if (!supersededDirectories.some((directory) => directory.path === cacheRoot) || (binding.directories ?? []).some((directory) => cacheRoot.startsWith(directory.path + sep9)))
|
|
56817
57225
|
throw new Error("Cache upgrade requires exact cache directory coverage without an unproved ancestor projection");
|
|
56818
57226
|
const rules = Bun.TOML.parse(settings).skills?.config ?? [];
|
|
56819
|
-
const witness = captureCodexSemanticCacheWitness({ cacheRoot, controls, appOnlyParents, rules, read: boundedRead });
|
|
57227
|
+
const witness = captureCodexSemanticCacheWitness({ cacheRoot, controls, appOnlyParents, reviewedHookParents, rules, read: boundedRead });
|
|
56820
57228
|
if (options.expectedCacheWitnessSha256 !== undefined && witness.sha256 !== options.expectedCacheWitnessSha256)
|
|
56821
57229
|
throw new Error("Reviewed semantic cache preimage changed");
|
|
56822
57230
|
const replacement = { ...binding, codexDisabledPluginSkills: controls, codexSemanticCache: {
|
|
@@ -56825,6 +57233,7 @@ function planCodexSemanticCacheWitnessUpgrade(options) {
|
|
|
56825
57233
|
hookRootAlias,
|
|
56826
57234
|
witness,
|
|
56827
57235
|
appOnlyParents,
|
|
57236
|
+
reviewedHookParents,
|
|
56828
57237
|
previousPolicySha256: options.expectedPolicySha256,
|
|
56829
57238
|
supersededSources,
|
|
56830
57239
|
supersededDirectories
|
|
@@ -56843,7 +57252,7 @@ function planCodexSemanticCacheWitnessUpgrade(options) {
|
|
|
56843
57252
|
rootAliases: aliases,
|
|
56844
57253
|
managedAgentChecks: { home, agents: ["codex"] },
|
|
56845
57254
|
...policy.bridge.discoveryExecutables ? { discoveryExecutables: policy.bridge.discoveryExecutables } : {},
|
|
56846
|
-
cacheWitnessUpgrade: { ...options, home, dataDir: dataDir3, appOnlyParents: appOnlyParents.map((parent) => parent.pluginParent) }
|
|
57255
|
+
cacheWitnessUpgrade: { ...options, home, dataDir: dataDir3, appOnlyParents: appOnlyParents.map((parent) => parent.pluginParent), reviewedHookParents: reviewedHookParents.map((parent) => parent.pluginParent) }
|
|
56847
57256
|
};
|
|
56848
57257
|
}
|
|
56849
57258
|
function planReviewedArtifactMigration(options) {
|
|
@@ -57578,7 +57987,7 @@ import {
|
|
|
57578
57987
|
writeFileSync as writeFileSync8
|
|
57579
57988
|
} from "fs";
|
|
57580
57989
|
import { homedir as homedir4 } from "os";
|
|
57581
|
-
import { basename as
|
|
57990
|
+
import { basename as basename11, dirname as dirname19, join as join32 } from "path";
|
|
57582
57991
|
function isSkillsOwnershipMarker(marker) {
|
|
57583
57992
|
return typeof marker === "object" && marker !== null && Object.hasOwn(marker, "managedBy") && marker.managedBy === SYNC_MARKER_MANAGED_BY;
|
|
57584
57993
|
}
|
|
@@ -57820,7 +58229,7 @@ function writeManagedSkillDirUnlocked(dir, skillMd, options, assertCurrent) {
|
|
|
57820
58229
|
return { action, path: skillMdPath };
|
|
57821
58230
|
const parentDir = dirname19(dir);
|
|
57822
58231
|
mkdirSync9(parentDir, { recursive: true });
|
|
57823
|
-
const transactionDir = mkdtempSync(join32(parentDir, `.hasna-skills-write-${
|
|
58232
|
+
const transactionDir = mkdtempSync(join32(parentDir, `.hasna-skills-write-${basename11(dir)}-`));
|
|
57824
58233
|
const candidateDir = join32(transactionDir, "candidate");
|
|
57825
58234
|
const backupDir = join32(transactionDir, "backup");
|
|
57826
58235
|
const candidateSkillMdPath = join32(candidateDir, "SKILL.md");
|
|
@@ -59994,7 +60403,7 @@ var init_plugin_admission = __esm(() => {
|
|
|
59994
60403
|
|
|
59995
60404
|
// src/lib/plugin-discovery.ts
|
|
59996
60405
|
import { closeSync as closeSync16, constants as constants18, fstatSync as fstatSync16, lstatSync as lstatSync26, openSync as openSync16, opendirSync as opendirSync5, readSync as readSync13 } from "fs";
|
|
59997
|
-
import { basename as
|
|
60406
|
+
import { basename as basename12, dirname as dirname21, isAbsolute as isAbsolute23, join as join38, resolve as resolve22 } from "path";
|
|
59998
60407
|
function validateManagedPluginWitnesses(value) {
|
|
59999
60408
|
pluginNeed(Array.isArray(value) && value.length > 0 && value.length <= PLUGIN_PROJECTION_LIMITS.registrations, "Invalid managed plugin witness collection");
|
|
60000
60409
|
const seen = new Set;
|
|
@@ -60077,7 +60486,7 @@ function hashManagedPluginRegistry(path, managed) {
|
|
|
60077
60486
|
pluginNeed(/^(?:[A-Za-z0-9][A-Za-z0-9._+-]*-)?[a-f0-9]{12}$/.test(row.version) && row.installPath === join38(cacheRoot, row.version), "Managed plugin cache path or version is outside its registration");
|
|
60078
60487
|
const approval = (producer) => {
|
|
60079
60488
|
pluginText(producer);
|
|
60080
|
-
const digest2 = `sha256:${
|
|
60489
|
+
const digest2 = `sha256:${basename12(producer)}`;
|
|
60081
60490
|
const receipt2 = readPluginAdmissionReceipt(witness.storeRoot, witness.bindingId, digest2);
|
|
60082
60491
|
pluginNeed(receipt2.materializedPath === producer, "Managed producer path is not an approved immutable projection");
|
|
60083
60492
|
if (!verified.has(producer)) {
|
|
@@ -60146,7 +60555,7 @@ var init_plugin_discovery = __esm(() => {
|
|
|
60146
60555
|
// src/lib/claude-marketplace-registry.ts
|
|
60147
60556
|
import { createHash as createHash25 } from "crypto";
|
|
60148
60557
|
import { closeSync as closeSync17, constants as constants19, fstatSync as fstatSync17, lstatSync as lstatSync27, openSync as openSync17, readSync as readSync14 } from "fs";
|
|
60149
|
-
import { basename as
|
|
60558
|
+
import { basename as basename13, dirname as dirname22, isAbsolute as isAbsolute24, resolve as resolve23 } from "path";
|
|
60150
60559
|
function need8(value, reason2) {
|
|
60151
60560
|
if (!value)
|
|
60152
60561
|
throw new Error(`Claude marketplace registry ${reason2}`);
|
|
@@ -60166,7 +60575,7 @@ function parents2(path) {
|
|
|
60166
60575
|
}
|
|
60167
60576
|
function readRegistry2(path, budget2) {
|
|
60168
60577
|
absolutePath4(path);
|
|
60169
|
-
need8(
|
|
60578
|
+
need8(basename13(path) === "known_marketplaces.json", "requires known_marketplaces.json");
|
|
60170
60579
|
need8(Number.isSafeInteger(budget2.remaining) && budget2.remaining >= 0, "has an invalid byte budget");
|
|
60171
60580
|
const ancestors2 = parents2(path), initial2 = lstatSync27(path, { bigint: true });
|
|
60172
60581
|
need8(initial2.isFile() && !initial2.isSymbolicLink() && initial2.size <= BigInt(CLAUDE_MARKETPLACE_REGISTRY_LIMITS.bytes), "is not a bounded regular file");
|
|
@@ -60613,7 +61022,7 @@ var init_codex_hook_discovery_recovery = __esm(() => {
|
|
|
60613
61022
|
// src/lib/agent-discovery.ts
|
|
60614
61023
|
import { createHash as createHash27 } from "crypto";
|
|
60615
61024
|
import { lstatSync as lstatSync28, readFileSync as readFileSync21, readdirSync as readdirSync12, realpathSync as realpathSync12 } from "fs";
|
|
60616
|
-
import { basename as
|
|
61025
|
+
import { basename as basename14, dirname as dirname23, isAbsolute as isAbsolute26, join as join39, relative as relative8, resolve as resolve24, sep as sep10 } from "path";
|
|
60617
61026
|
import { isDeepStrictEqual as isDeepStrictEqual11 } from "util";
|
|
60618
61027
|
function discoveryRootUnresolved(agent, command, detail) {
|
|
60619
61028
|
return new Error(`${DISCOVERY_ROOT_UNRESOLVED}: ${agent} discovery cannot resolve its "${command}" executable: ${detail}. The reviewed discovery is unchanged; this is an environment gap, not drift.`);
|
|
@@ -60693,7 +61102,7 @@ function assertReviewedClaudeCacheClosures(home, config, review, canonical9) {
|
|
|
60693
61102
|
throw new Error("Reviewed Claude enabled plugin registration requires an object with an installPath string");
|
|
60694
61103
|
}
|
|
60695
61104
|
if ([cacheAliasRoot, cacheRoot].some((root2) => row.installPath === root2 || row.installPath.startsWith(root2 + sep10))) {
|
|
60696
|
-
if (!cachePath(row.installPath) || row.installPath.length > AGENT_POLICY_LIMITS.pathCharacters || row.version !== undefined && (typeof row.version !== "string" ||
|
|
61105
|
+
if (!cachePath(row.installPath) || row.installPath.length > AGENT_POLICY_LIMITS.pathCharacters || row.version !== undefined && (typeof row.version !== "string" || basename14(row.installPath) !== row.version)) {
|
|
60697
61106
|
throw new Error("Reviewed Claude discovery has a malformed active cache registration");
|
|
60698
61107
|
}
|
|
60699
61108
|
if (row.scope === "user" && (row.projectPath === undefined || row.projectPath === null)) {} else if (row.scope === "project" && typeof row.projectPath === "string" && isAbsolute26(row.projectPath) && resolve24(row.projectPath) === row.projectPath && row.projectPath.length <= AGENT_POLICY_LIMITS.pathCharacters) {} else
|
|
@@ -60971,7 +61380,7 @@ function absentRetiredClaudeRoots(binding) {
|
|
|
60971
61380
|
if (!targetValid || !targetScopes.has("user\x00"))
|
|
60972
61381
|
continue;
|
|
60973
61382
|
const active = rows[0]?.installPath;
|
|
60974
|
-
if (typeof active !== "string" || rows[0]?.version !==
|
|
61383
|
+
if (typeof active !== "string" || rows[0]?.version !== basename14(active) || dirname23(active) !== dirname23(root2) || active === root2 || !lstatSync28(active, { throwIfNoEntry: false })?.isDirectory() || realpathSync12(active) !== active)
|
|
60975
61384
|
continue;
|
|
60976
61385
|
const activeManifest = full(join39(active, ".claude-plugin/plugin.json"));
|
|
60977
61386
|
if (!activeManifest || projected(activeManifest) !== activeManifest.sha256)
|
|
@@ -60980,14 +61389,15 @@ function absentRetiredClaudeRoots(binding) {
|
|
|
60980
61389
|
}
|
|
60981
61390
|
return [...result2];
|
|
60982
61391
|
}
|
|
60983
|
-
function codexSemanticCacheSourceRole(source, cacheRoot, parents3) {
|
|
61392
|
+
function codexSemanticCacheSourceRole(source, cacheRoot, parents3, hookParents = []) {
|
|
60984
61393
|
if (!isAbsolute26(source.path) || resolve24(source.path) !== source.path || /[\x00-\x1f\x7f]/.test(source.path) || source.format !== undefined || source.fields !== undefined || source.managedPlugins !== undefined || source.reviewArtifact !== undefined || source.hashMode !== undefined && source.hashMode !== "bytes")
|
|
60985
61394
|
return false;
|
|
60986
61395
|
const parts = relative8(cacheRoot, source.path).split(sep10);
|
|
60987
61396
|
if (parts.length < 3 || !parents3.includes(join39(cacheRoot, parts[0], parts[1])))
|
|
60988
61397
|
return false;
|
|
60989
61398
|
const tail2 = parts.slice(3).join("/");
|
|
60990
|
-
|
|
61399
|
+
const parent = join39(cacheRoot, parts[0], parts[1]);
|
|
61400
|
+
return parts.length === 5 && tail2 === ".codex-plugin/plugin.json" && source.sha256 !== null || parts.length === 4 && [".app.json", ".mcp.json"].includes(tail2) && source.sha256 !== null || parts.length === 5 && tail2 === "hooks/hooks.json" && hookParents.includes(parent) && source.sha256 !== null || source.sha256 === null && (parts.length === 4 && tail2 === "SKILL.md" || parts.length === 5 && tail2 === "hooks/hooks.json");
|
|
60991
61401
|
}
|
|
60992
61402
|
function codexSemanticCacheDirectoryRole(path, cacheRoot) {
|
|
60993
61403
|
return isAbsolute26(path) && resolve24(path) === path && !/[\x00-\x1f\x7f]/.test(path) && (path === cacheRoot || path.startsWith(cacheRoot + sep10));
|
|
@@ -61019,20 +61429,28 @@ function verifyCodexSemanticCacheDiscovery(binding, reviewedRootAliases) {
|
|
|
61019
61429
|
const cacheRoot = proof.witness.cacheRoot;
|
|
61020
61430
|
if (controls.some((control) => dirname23(dirname23(control.pluginParent)) !== cacheRoot))
|
|
61021
61431
|
throw new Error("Codex semantic cache names another enrolled cache");
|
|
61022
|
-
const
|
|
61023
|
-
|
|
61432
|
+
const reviewedHookParents = proof.reviewedHookParents ?? [];
|
|
61433
|
+
if (!Array.isArray(reviewedHookParents) || reviewedHookParents.length > 4096 || reviewedHookParents.some((parent) => !parent || !(parent.installation === "remote-receipt" && Object.keys(parent).sort().join(",") === "installation,namespace,pluginId,pluginParent,remotePluginId,role" && typeof parent.remotePluginId === "string" || parent.installation === "local-marketplace" && Object.keys(parent).sort().join(",") === "installation,marketplaceSha256,marketplaceSourcePath,namespace,pluginId,pluginParent,role" && typeof parent.marketplaceSourcePath === "string" && /^[a-f0-9]{64}$/.test(parent.marketplaceSha256 ?? "")) || parent.role !== "reviewed-hook" || typeof parent.pluginId !== "string" || typeof parent.namespace !== "string" || typeof parent.pluginParent !== "string") || new Set(reviewedHookParents.map((parent) => parent.pluginParent)).size !== reviewedHookParents.length || !isDeepStrictEqual11((proof.witness.hookParents ?? []).map(({ manifestSha256: _manifest, hooksSha256: _hooks, receiptSha256: _receipt, ...parent }) => parent), reviewedHookParents)) {
|
|
61434
|
+
throw new Error("Invalid reviewed native-hook cache role");
|
|
61435
|
+
}
|
|
61436
|
+
for (const parent of reviewedHookParents)
|
|
61437
|
+
if (parent.installation === "local-marketplace" && !binding.sources.some((source) => source.path === parent.marketplaceSourcePath && source.sha256 === parent.marketplaceSha256 && source.sha256 !== null && source.format === undefined && source.fields === undefined && source.reviewArtifact === undefined && (source.hashMode === undefined || source.hashMode === "bytes")))
|
|
61438
|
+
throw new Error("Local marketplace hook parent lost its enrolled source witness");
|
|
61439
|
+
const parents3 = [...new Set([...controls.map((control) => control.pluginParent), ...proof.appOnlyParents.map((parent) => parent.pluginParent), ...reviewedHookParents.map((parent) => parent.pluginParent)])];
|
|
61440
|
+
const hookParentPaths = reviewedHookParents.map((parent) => parent.pluginParent);
|
|
61441
|
+
const sources = binding.sources.filter((source) => codexSemanticCacheSourceRole(source, cacheRoot, parents3, hookParentPaths));
|
|
61024
61442
|
const directories = (binding.directories ?? []).filter((directory) => codexSemanticCacheDirectoryRole(directory.path, cacheRoot));
|
|
61025
61443
|
if (!directories.length || !isDeepStrictEqual11(sources, proof.supersededSources) || !isDeepStrictEqual11(directories, proof.supersededDirectories))
|
|
61026
61444
|
throw new Error("Codex semantic cache provenance changed");
|
|
61027
61445
|
const configPath = proof.configPath;
|
|
61028
|
-
if (!isAbsolute26(configPath) || resolve24(configPath) !== configPath ||
|
|
61446
|
+
if (!isAbsolute26(configPath) || resolve24(configPath) !== configPath || basename14(configPath) !== "config.toml" || /[\x00-\x1f\x7f]/.test(configPath))
|
|
61029
61447
|
throw new Error("Invalid semantic cache configuration source");
|
|
61030
61448
|
const configSource = binding.sources.find((source) => source.path === configPath && source.sha256 !== null && source.format === undefined && source.fields === undefined);
|
|
61031
61449
|
if (!configSource || projected(configSource) !== configSource.sha256)
|
|
61032
61450
|
throw new Error("Codex semantic cache requires unchanged reviewed configuration");
|
|
61033
61451
|
assertCodexSemanticCacheHookSafety(cacheRoot, parents3, configPath, proof.hookRootAlias);
|
|
61034
61452
|
const rules = parseConfig(read2(configPath), configPath, true).skills?.config ?? [];
|
|
61035
|
-
const current = captureCodexSemanticCacheWitness({ cacheRoot, controls, appOnlyParents: proof.appOnlyParents, rules });
|
|
61453
|
+
const current = captureCodexSemanticCacheWitness({ cacheRoot, controls, appOnlyParents: proof.appOnlyParents, reviewedHookParents, rules });
|
|
61036
61454
|
assertCodexSemanticCacheWitnessUnchanged(proof.witness, current);
|
|
61037
61455
|
return proof;
|
|
61038
61456
|
}
|
|
@@ -61116,7 +61534,7 @@ function codexInstallationRoots(binding) {
|
|
|
61116
61534
|
const config = join39(dirname23(dirname23(cache3)), "config.toml"), home = dirname23(dirname23(dirname23(cache3)));
|
|
61117
61535
|
const configSource = binding.sources.find((source) => source.path === config && source.sha256 !== null && (!source.format || source.format === "toml" && source.fields?.includes("plugins")));
|
|
61118
61536
|
const nativeRoots = NATIVE_SKILL_ROOTS.filter(([agent]) => agent === "codex").map(([, path]) => join39(home, path));
|
|
61119
|
-
if (!configSource || proof.plugins.some((input) => nativeRoots.some((root2) => root2 === input.sourceRoot || root2.startsWith(input.sourceRoot + sep10) || input.sourceRoot.startsWith(root2 + sep10)) || binding.sources.some((source) =>
|
|
61537
|
+
if (!configSource || proof.plugins.some((input) => nativeRoots.some((root2) => root2 === input.sourceRoot || root2.startsWith(input.sourceRoot + sep10) || input.sourceRoot.startsWith(root2 + sep10)) || binding.sources.some((source) => basename14(source.path) === "config.toml" && (source.path === input.sourceRoot || source.path.startsWith(input.sourceRoot + sep10)))))
|
|
61120
61538
|
throw new Error("Native installation input overlaps configuration or loading roots");
|
|
61121
61539
|
if (proof.plugins.some((input) => dirname23(dirname23(input.pluginParent)) !== cache3 || !binding.sources.some((source) => source.path === join39(input.sourceRoot, ".codex-plugin/plugin.json") && source.sha256 !== null && source.format === undefined && source.fields === undefined)))
|
|
61122
61540
|
throw new Error("Missing native installation input source witness");
|
|
@@ -61128,13 +61546,13 @@ function codexInstallationRoots(binding) {
|
|
|
61128
61546
|
});
|
|
61129
61547
|
}
|
|
61130
61548
|
function assertMarketplaceBinding(binding, source) {
|
|
61131
|
-
if (source.hashMode === "claude-plugin-manifest-v1" && (binding.agent !== "claude" ||
|
|
61549
|
+
if (source.hashMode === "claude-plugin-manifest-v1" && (binding.agent !== "claude" || basename14(source.path) !== "plugin.json" || !source.path.endsWith(join39(sep10, ".claude-plugin", "plugin.json"))))
|
|
61132
61550
|
throw new Error("Claude plugin manifest witnesses require Claude plugin discovery");
|
|
61133
|
-
if (source.hashMode === "sumi-settings-v1" && (binding.agent !== "sumi" || binding.method !== "reviewed" ||
|
|
61551
|
+
if (source.hashMode === "sumi-settings-v1" && (binding.agent !== "sumi" || binding.method !== "reviewed" || basename14(source.path) !== "sumi.json"))
|
|
61134
61552
|
throw new Error("Sumi settings witnesses require explicit reviewed Sumi configuration");
|
|
61135
|
-
if ((source.hashMode === "codex-settings-v1" || source.hashMode === "codex-settings-v2" || (source.hashMode === "codex-settings-v3" || source.hashMode === "codex-settings-v4" || source.hashMode === "codex-settings-v5")) && (binding.agent !== "codex" || binding.method !== "reviewed" ||
|
|
61553
|
+
if ((source.hashMode === "codex-settings-v1" || source.hashMode === "codex-settings-v2" || (source.hashMode === "codex-settings-v3" || source.hashMode === "codex-settings-v4" || source.hashMode === "codex-settings-v5")) && (binding.agent !== "codex" || binding.method !== "reviewed" || basename14(source.path) !== "config.toml"))
|
|
61136
61554
|
throw new Error("Codex settings witnesses require explicit reviewed Codex configuration");
|
|
61137
|
-
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" ||
|
|
61555
|
+
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" || basename14(source.path) !== "settings.json"))
|
|
61138
61556
|
throw new Error("Claude settings witnesses require explicit reviewed Claude configuration");
|
|
61139
61557
|
if ((source.hashMode === "claude-marketplace-registry" || source.hashMode === "claude-marketplace-registry-v2") && (binding.agent !== "claude" || binding.method !== "reviewed"))
|
|
61140
61558
|
throw new Error("Claude marketplace witnesses require explicit reviewed Claude discovery");
|
|
@@ -61246,7 +61664,7 @@ function verifyAutomaticDiscoveryClosure(binding, options) {
|
|
|
61246
61664
|
const current = resolveAgentDiscovery({ home: options.home, agent: binding.agent, canonical: options.canonical, executable: runtime });
|
|
61247
61665
|
if (JSON.stringify(current) === JSON.stringify(binding))
|
|
61248
61666
|
return;
|
|
61249
|
-
const reviewedWithRuntime = (binding.builtinNames?.length ?? 0) > 0 || binding.sources.some((source) =>
|
|
61667
|
+
const reviewedWithRuntime = (binding.builtinNames?.length ?? 0) > 0 || binding.sources.some((source) => basename14(source.path) === "package.json");
|
|
61250
61668
|
const otherwiseCurrent = current.method === binding.method && JSON.stringify(current.roots) === JSON.stringify(binding.roots) && JSON.stringify(current.directories) === JSON.stringify(binding.directories) && current.sources.every((source) => binding.sources.some((saved) => isDeepStrictEqual11(saved, source)));
|
|
61251
61669
|
if (command && gap && runtime === null && reviewedWithRuntime && otherwiseCurrent)
|
|
61252
61670
|
throw discoveryRootUnresolved(binding.agent, command, gap);
|
|
@@ -61389,7 +61807,7 @@ function resolveAgentDiscovery(options) {
|
|
|
61389
61807
|
throw new Error("Discovery review must include the agent configuration source");
|
|
61390
61808
|
const reviewedSources = supersedesSettingsProjection(agent, review.sources, canonical9(configPath)) ? sources.filter((source) => !isSupersededSettingsProjection(agent, canonical9(configPath), source)) : sources;
|
|
61391
61809
|
const reviewedSourcesWithManifestProjection = review.sources.map((source) => {
|
|
61392
|
-
if (agent !== "claude" || source.sha256 === null || source.format !== undefined || source.fields !== undefined || source.managedPlugins !== undefined || source.hashMode !== undefined && source.hashMode !== "bytes" ||
|
|
61810
|
+
if (agent !== "claude" || source.sha256 === null || source.format !== undefined || source.fields !== undefined || source.managedPlugins !== undefined || source.hashMode !== undefined && source.hashMode !== "bytes" || basename14(source.path) !== "plugin.json" || !source.path.endsWith(join39(sep10, ".claude-plugin", "plugin.json")))
|
|
61393
61811
|
return source;
|
|
61394
61812
|
const pluginRoot = dirname23(dirname23(source.path)), hooksPath = join39(pluginRoot, "hooks/hooks.json");
|
|
61395
61813
|
const hookStat = lstatSync28(hooksPath, { throwIfNoEntry: false });
|
|
@@ -61569,7 +61987,7 @@ var init_agent_discovery = __esm(() => {
|
|
|
61569
61987
|
// src/lib/authoring-path.ts
|
|
61570
61988
|
import { lstatSync as lstatSync29, realpathSync as realpathSync13 } from "fs";
|
|
61571
61989
|
import { homedir as homedir7 } from "os";
|
|
61572
|
-
import { basename as
|
|
61990
|
+
import { basename as basename15, dirname as dirname24, join as join40, resolve as resolve25, sep as sep11 } from "path";
|
|
61573
61991
|
function pathParts(path) {
|
|
61574
61992
|
return resolve25(path).split(sep11).filter(Boolean);
|
|
61575
61993
|
}
|
|
@@ -61588,7 +62006,7 @@ function physicalPath(path) {
|
|
|
61588
62006
|
let cursor = resolve25(path);
|
|
61589
62007
|
const suffix = [];
|
|
61590
62008
|
while (!lstatSync29(cursor, { throwIfNoEntry: false })) {
|
|
61591
|
-
suffix.unshift(
|
|
62009
|
+
suffix.unshift(basename15(cursor));
|
|
61592
62010
|
const parent = dirname24(cursor);
|
|
61593
62011
|
if (parent === cursor)
|
|
61594
62012
|
return resolve25(path);
|
|
@@ -61683,7 +62101,7 @@ import {
|
|
|
61683
62101
|
statSync as statSync13,
|
|
61684
62102
|
writeFileSync as writeFileSync10
|
|
61685
62103
|
} from "fs";
|
|
61686
|
-
import { basename as
|
|
62104
|
+
import { basename as basename16, dirname as dirname25, isAbsolute as isAbsolute27, join as join41, normalize as normalize4, relative as relative9, resolve as resolve26, sep as sep12 } from "path";
|
|
61687
62105
|
function getPortableSkillsRoot(options = {}) {
|
|
61688
62106
|
return resolvePortableSkillsRoot(options, true);
|
|
61689
62107
|
}
|
|
@@ -61831,7 +62249,7 @@ function physicalImportPath(path) {
|
|
|
61831
62249
|
let ancestor = resolve26(path);
|
|
61832
62250
|
const suffix = [];
|
|
61833
62251
|
while (!existsSync19(ancestor)) {
|
|
61834
|
-
suffix.unshift(
|
|
62252
|
+
suffix.unshift(basename16(ancestor));
|
|
61835
62253
|
ancestor = dirname25(ancestor);
|
|
61836
62254
|
}
|
|
61837
62255
|
return join41(realpathSync14(ancestor), ...suffix);
|
|
@@ -61856,8 +62274,8 @@ function portPortableSkill(sourcePath, options = {}) {
|
|
|
61856
62274
|
const explicitName = options.name != null;
|
|
61857
62275
|
const skillName = normalizeNewPortableSkillName(options.name ?? inferred.name);
|
|
61858
62276
|
if (isOfficialSkillName(skillName) && !options.allowShadow) {
|
|
61859
|
-
const sourceSlug = safeNormalizeName(
|
|
61860
|
-
const via = explicitName ? `Name '${skillName}' matches a bundled official skill.` : `Inferred name '${skillName}'${sourceSlug && sourceSlug !== skillName ? ` (from source folder '${
|
|
62277
|
+
const sourceSlug = safeNormalizeName(basename16(absoluteSource));
|
|
62278
|
+
const via = explicitName ? `Name '${skillName}' matches a bundled official skill.` : `Inferred name '${skillName}'${sourceSlug && sourceSlug !== skillName ? ` (from source folder '${basename16(absoluteSource)}')` : ""} matches a bundled official skill.`;
|
|
61861
62279
|
throw new Error(`${via} Importing it would shadow the official '${skillName}'. ` + `Pass --name to choose a different name, or --allow-shadow to override deliberately.`);
|
|
61862
62280
|
}
|
|
61863
62281
|
const readOnlyDestination = join41(resolvePortableSkillsRoot(options, false), skillName);
|
|
@@ -64066,13 +64484,13 @@ var require_cli_spinners = __commonJS((exports, module) => {
|
|
|
64066
64484
|
|
|
64067
64485
|
// src/lib/auth-store.ts
|
|
64068
64486
|
import { chmodSync as chmodSync2, existsSync as existsSync21, mkdirSync as mkdirSync13, readFileSync as readFileSync25, renameSync as renameSync8, statSync as statSync14, unlinkSync as unlinkSync6, writeFileSync as writeFileSync11 } from "fs";
|
|
64069
|
-
import { basename as
|
|
64487
|
+
import { basename as basename17, dirname as dirname26, join as join43 } from "path";
|
|
64070
64488
|
function getAuthFilePath(env3 = process.env) {
|
|
64071
64489
|
return skillsCredentialFilePath(env3);
|
|
64072
64490
|
}
|
|
64073
64491
|
function getIdentityFilePath(env3 = process.env) {
|
|
64074
64492
|
const file = skillsCredentialFilePath(env3);
|
|
64075
|
-
return join43(dirname26(file),
|
|
64493
|
+
return join43(dirname26(file), basename17(file).replace(/^credentials/, "identity") + ".json");
|
|
64076
64494
|
}
|
|
64077
64495
|
function getAuthIdentity(env3 = process.env) {
|
|
64078
64496
|
return readIdentity(env3);
|
|
@@ -86096,7 +86514,7 @@ var init_remote_auth = __esm(() => {
|
|
|
86096
86514
|
// src/lib/sign-in.ts
|
|
86097
86515
|
import { createHash as createHash30 } from "crypto";
|
|
86098
86516
|
import { chmodSync as chmodSync3, mkdirSync as mkdirSync14, readFileSync as readFileSync26, readdirSync as readdirSync15, renameSync as renameSync9, unlinkSync as unlinkSync7, writeFileSync as writeFileSync12 } from "fs";
|
|
86099
|
-
import { basename as
|
|
86517
|
+
import { basename as basename18, dirname as dirname27, join as join44 } from "path";
|
|
86100
86518
|
function isRecord7(value) {
|
|
86101
86519
|
return Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
86102
86520
|
}
|
|
@@ -86241,7 +86659,7 @@ async function pollDeviceAuthorization(input2) {
|
|
|
86241
86659
|
}
|
|
86242
86660
|
function pendingDeviceSignInStem(env3) {
|
|
86243
86661
|
const file2 = skillsCredentialFilePath(env3);
|
|
86244
|
-
return { dir: dirname27(file2), stem:
|
|
86662
|
+
return { dir: dirname27(file2), stem: basename18(file2).replace(/^credentials/, "device-login") };
|
|
86245
86663
|
}
|
|
86246
86664
|
function pendingDeviceSignInPath(origin, env3 = process.env) {
|
|
86247
86665
|
const { dir, stem } = pendingDeviceSignInStem(env3);
|
|
@@ -113635,7 +114053,7 @@ import {
|
|
|
113635
114053
|
renameSync as renameSync14,
|
|
113636
114054
|
writeFileSync as writeFileSync24
|
|
113637
114055
|
} from "fs";
|
|
113638
|
-
import { basename as
|
|
114056
|
+
import { basename as basename19, delimiter as delimiter3, dirname as dirname36, isAbsolute as isAbsolute33, join as join63, relative as relative12, resolve as resolve31, sep as sep14 } from "path";
|
|
113639
114057
|
function oldLauncherState(item) {
|
|
113640
114058
|
if (item.oldShape === "pinned")
|
|
113641
114059
|
return { shape: "pinned", runtime: item.oldRuntime, cwd: item.oldCwd, target: item.oldTarget, sha256: item.oldSha256, format: item.oldFormat, profile: item.oldProfile };
|
|
@@ -114467,7 +114885,7 @@ function inspectAliasPackageChain(home, aliasPath, oldLinkTarget, oldTarget, bin
|
|
|
114467
114885
|
function validateAliasSource(home, name, actual) {
|
|
114468
114886
|
const packageRoot = dirname36(dirname36(actual));
|
|
114469
114887
|
const roots = [join63(home, ".hasna", "skills", "runtime"), join63(home, ".bun", "install"), join63(home, ".local", "lib", "node_modules")];
|
|
114470
|
-
if (
|
|
114888
|
+
if (basename19(packageRoot) !== "skills" || basename19(dirname36(packageRoot)) !== "@hasna" || !roots.some((root2) => isWithin(root2, packageRoot))) {
|
|
114471
114889
|
throw new Error("ALIAS_SOURCE_ROOT_UNSUPPORTED");
|
|
114472
114890
|
}
|
|
114473
114891
|
assertOwnedSafePath(packageRoot, home);
|
|
@@ -114562,8 +114980,8 @@ function adoptCopyfileAliases(options = {}) {
|
|
|
114562
114980
|
for (const item of aliases) {
|
|
114563
114981
|
if (!launcherIs(item.path, oldLauncherState(item)))
|
|
114564
114982
|
throw new Error("ALIAS_CHANGED_BEFORE_SWITCH");
|
|
114565
|
-
inspectAliasPackageChain(home, item.path, item.oldLinkTarget, item.oldTarget, layout.bin[
|
|
114566
|
-
const source = validateAliasSource(home,
|
|
114983
|
+
inspectAliasPackageChain(home, item.path, item.oldLinkTarget, item.oldTarget, layout.bin[basename19(item.path)], item.chain, true);
|
|
114984
|
+
const source = validateAliasSource(home, basename19(item.path), item.oldTarget);
|
|
114567
114985
|
if (source.version !== item.oldVersion || source.binarySha256 !== item.oldBinarySha256)
|
|
114568
114986
|
throw new Error("ALIAS_SOURCE_DRIFT");
|
|
114569
114987
|
receipt.state = "switching";
|
|
@@ -114572,11 +114990,11 @@ function adoptCopyfileAliases(options = {}) {
|
|
|
114572
114990
|
replaceLauncher(item);
|
|
114573
114991
|
if (!launcherIs(item.path, newLauncherState(item)) || !launcherIs(item.backupPath, oldLauncherState(item)))
|
|
114574
114992
|
throw new Error("ALIAS_SWITCH_READBACK_MISMATCH");
|
|
114575
|
-
inspectAliasPackageChain(home, item.path, item.oldLinkTarget, item.oldTarget, layout.bin[
|
|
114993
|
+
inspectAliasPackageChain(home, item.path, item.oldLinkTarget, item.oldTarget, layout.bin[basename19(item.path)], item.chain, true);
|
|
114576
114994
|
options.onAliasSwitched?.(item.path);
|
|
114577
114995
|
}
|
|
114578
114996
|
for (const item of aliases) {
|
|
114579
|
-
inspectAliasPackageChain(home, item.path, item.oldLinkTarget, item.oldTarget, layout.bin[
|
|
114997
|
+
inspectAliasPackageChain(home, item.path, item.oldLinkTarget, item.oldTarget, layout.bin[basename19(item.path)], item.chain, true);
|
|
114580
114998
|
if (!launcherIs(item.backupPath, oldLauncherState(item)))
|
|
114581
114999
|
throw new Error("ALIAS_BACKUP_DRIFT");
|
|
114582
115000
|
}
|
|
@@ -114589,16 +115007,16 @@ function adoptCopyfileAliases(options = {}) {
|
|
|
114589
115007
|
for (const item of [...aliases].reverse()) {
|
|
114590
115008
|
try {
|
|
114591
115009
|
if (!entryExists(item.backupPath)) {
|
|
114592
|
-
inspectAliasPackageChain(home, item.path, item.oldLinkTarget, item.oldTarget, layout.bin[
|
|
114593
|
-
const source2 = validateAliasSource(home,
|
|
115010
|
+
inspectAliasPackageChain(home, item.path, item.oldLinkTarget, item.oldTarget, layout.bin[basename19(item.path)], item.chain, true);
|
|
115011
|
+
const source2 = validateAliasSource(home, basename19(item.path), item.oldTarget);
|
|
114594
115012
|
if (!entryExists(item.path) || !launcherIs(item.path, oldLauncherState(item)) || source2.version !== item.oldVersion || source2.binarySha256 !== item.oldBinarySha256)
|
|
114595
115013
|
failed = true;
|
|
114596
115014
|
continue;
|
|
114597
115015
|
}
|
|
114598
115016
|
if (!launcherIs(item.backupPath, oldLauncherState(item)))
|
|
114599
115017
|
throw new Error("ALIAS_BACKUP_DRIFT");
|
|
114600
|
-
inspectAliasPackageChain(home, item.path, item.oldLinkTarget, item.oldTarget, layout.bin[
|
|
114601
|
-
const source = validateAliasSource(home,
|
|
115018
|
+
inspectAliasPackageChain(home, item.path, item.oldLinkTarget, item.oldTarget, layout.bin[basename19(item.path)], item.chain, true);
|
|
115019
|
+
const source = validateAliasSource(home, basename19(item.path), item.oldTarget);
|
|
114602
115020
|
if (source.version !== item.oldVersion || source.binarySha256 !== item.oldBinarySha256)
|
|
114603
115021
|
throw new Error("ALIAS_SOURCE_DRIFT");
|
|
114604
115022
|
if (launcherIs(item.path, oldLauncherState(item)))
|
|
@@ -114651,7 +115069,7 @@ function rollbackCopyfileAliases(receiptId, options = {}) {
|
|
|
114651
115069
|
throw new Error("ALIAS_RECEIPT_BINDING_INVALID");
|
|
114652
115070
|
const seen = new Set;
|
|
114653
115071
|
for (const item of receipt.aliases) {
|
|
114654
|
-
const name =
|
|
115072
|
+
const name = basename19(item.path), target = layout.bin[name];
|
|
114655
115073
|
if (!target || seen.has(item.path) || !aliasDirs(home).includes(dirname36(item.path)) || item.newTarget !== join63(layout.currentPackageRoot, target) || item.backupPath !== `${item.path}.skills-alias-prev-${receiptId}` || item.chain !== undefined && (!item.chain || typeof item.chain !== "object" || typeof item.chain.packageLinkPath !== "string" || typeof item.chain.packageLinkTarget !== "string")) {
|
|
114656
115074
|
throw new Error("ALIAS_RECEIPT_LAUNCHER_INVALID");
|
|
114657
115075
|
}
|
|
@@ -114707,7 +115125,7 @@ function rollbackCopyfileAliases(receiptId, options = {}) {
|
|
|
114707
115125
|
restored++;
|
|
114708
115126
|
}
|
|
114709
115127
|
for (const item of receipt.aliases) {
|
|
114710
|
-
inspectAliasPackageChain(home, item.path, item.oldLinkTarget, item.oldTarget, layout.bin[
|
|
115128
|
+
inspectAliasPackageChain(home, item.path, item.oldLinkTarget, item.oldTarget, layout.bin[basename19(item.path)], item.chain, true);
|
|
114711
115129
|
}
|
|
114712
115130
|
receipt.state = "rolled-back";
|
|
114713
115131
|
persistAliasReceipt(receiptPath, receipt);
|
|
@@ -114760,8 +115178,8 @@ async function updateCopyfileRuntime(version2, options = {}) {
|
|
|
114760
115178
|
const finalPath = join63(layout.runtimeRoot, `${version2}-copyfile`);
|
|
114761
115179
|
const launcherRuntime = pinnedLauncherRuntime();
|
|
114762
115180
|
const launchers = layout.launchers.map((item) => {
|
|
114763
|
-
const newTarget = join63(finalPath, "node_modules", "@hasna", "skills", layout.bin[
|
|
114764
|
-
return { ...item, newTarget, ...pinnedRecordFields(launcherRuntime, finalPath, newTarget, launcherProfileForBin(
|
|
115181
|
+
const newTarget = join63(finalPath, "node_modules", "@hasna", "skills", layout.bin[basename19(item.path)]);
|
|
115182
|
+
return { ...item, newTarget, ...pinnedRecordFields(launcherRuntime, finalPath, newTarget, launcherProfileForBin(basename19(item.path), layout.bin[basename19(item.path)])) };
|
|
114765
115183
|
});
|
|
114766
115184
|
const releaseLock = acquireRuntimeLock(layout.runtimeRoot);
|
|
114767
115185
|
let switched = [];
|
|
@@ -114983,11 +115401,11 @@ function rollbackCopyfileRuntime(receiptId, options = {}) {
|
|
|
114983
115401
|
const switched = [];
|
|
114984
115402
|
const seen = new Set;
|
|
114985
115403
|
for (const item of receipt.launchers) {
|
|
114986
|
-
const bin = oldBins[
|
|
115404
|
+
const bin = oldBins[basename19(item.path)];
|
|
114987
115405
|
if (!bin || !isAbsolute33(item.path) || seen.has(item.path) || item.oldTarget !== join63(receipt.currentPackageRoot, bin) || item.newTarget !== join63(receipt.targetPackageRoot, bin) || !/^.+\.skills-prev-[0-9a-f-]{36}$/.test(item.backupPath) || !item.backupPath.startsWith(`${item.path}.skills-prev-`) || typeof item.oldLinkTarget !== "string" || resolve31(dirname36(item.path), item.oldLinkTarget) !== item.oldTarget)
|
|
114988
115406
|
throw new Error("RECEIPT_LAUNCHER_BINDING_INVALID");
|
|
114989
115407
|
assertNoSymlinkAncestors(dirname36(item.path));
|
|
114990
|
-
assertLauncherRecordShapes(item, launcherProfileForBin(
|
|
115408
|
+
assertLauncherRecordShapes(item, launcherProfileForBin(basename19(item.path), bin));
|
|
114991
115409
|
seen.add(item.path);
|
|
114992
115410
|
const oldState = oldLauncherState(item), newState = newLauncherState(item);
|
|
114993
115411
|
let activeTarget;
|
|
@@ -115053,7 +115471,7 @@ __export(exports_runtime, {
|
|
|
115053
115471
|
});
|
|
115054
115472
|
import { createHash as createHash39, randomUUID as randomUUID11 } from "crypto";
|
|
115055
115473
|
import { lstatSync as lstatSync36, mkdirSync as mkdirSync27, readFileSync as readFileSync41, writeFileSync as writeFileSync25 } from "fs";
|
|
115056
|
-
import { basename as
|
|
115474
|
+
import { basename as basename20, isAbsolute as isAbsolute34, join as join64 } from "path";
|
|
115057
115475
|
import { createInterface } from "readline";
|
|
115058
115476
|
function registerRuntime(parent) {
|
|
115059
115477
|
parent.command("run").argument("<skill>", "Skill name").argument("[args...]", "Arguments to pass to the skill; use -- to end Skills options").allowUnknownOption(true).passThroughOptions(true).option("--json", "Output result as JSON", false).option("--remote", "Run on the configured server, using its catalog and quote", false).option("--target <target>", "Execution target: local or cloud").option("--secret-bindings <path>", "Reviewed, exact-selection local execution vault bindings (JSON file)").option("--secret-bindings-template", "Print a scoped bindings template without resolving secrets or running the skill", false).option("--input <json>", "Structured cloud execution input").option("--skill-version <version>", "Exact selected skill version").option("--selection-profile <id>", "Selected Skills profile").option("--session <id>", "Pinned Skills session").option("--cached", "Use the explicit verified selected cache", false).option("--yes", "Approve the server's quoted credit cost for this run", false).option("--idempotency-key <key>", "Reuse this key when retrying the same remote submission").option("--file <path>", "Attach a local input file to a remote run (repeatable)", (value, prior) => [...prior, value], []).option("--wait", "Poll remote runs until a terminal status", false).option("--poll-interval-ms <ms>", "Remote polling interval in milliseconds", "1000").option("--poll-timeout-ms <ms>", "Maximum time to wait for a remote run", "300000").description("Run a skill directly").action(async (name, args2, options, command) => {
|
|
@@ -115586,7 +116004,7 @@ async function handleRun(name, args2, options, separatorBeforeSkill) {
|
|
|
115586
116004
|
const info = lstatSync36(path);
|
|
115587
116005
|
if (!info.isFile() || info.size > 20 * 1024 * 1024)
|
|
115588
116006
|
throw new Error("Input must be a regular file no larger than 20 MiB");
|
|
115589
|
-
return { name:
|
|
116007
|
+
return { name: basename20(path), bytes: new Uint8Array(readFileSync41(path)) };
|
|
115590
116008
|
});
|
|
115591
116009
|
describeRemoteFiles(inputFiles);
|
|
115592
116010
|
client2 = new RemoteSkillsClient(routing.apiKey, routing.apiOrigin);
|
|
@@ -118034,128 +118452,10 @@ var init_codex_native_trust = __esm(() => {
|
|
|
118034
118452
|
HEX_DIGEST2 = /^[0-9a-f]{64}$/;
|
|
118035
118453
|
});
|
|
118036
118454
|
|
|
118037
|
-
// src/lib/hook-diagnostics.ts
|
|
118038
|
-
function hookChildError(stdout, stage) {
|
|
118039
|
-
let code2;
|
|
118040
|
-
if (stdout.length <= 16 * 1024) {
|
|
118041
|
-
try {
|
|
118042
|
-
code2 = JSON.parse(stdout)?.error?.code;
|
|
118043
|
-
} catch {}
|
|
118044
|
-
}
|
|
118045
|
-
return new HookDiagnosticError(typeof code2 === "string" && CONTEXT_ERROR_CODES.has(code2) ? code2 : "SKILLS_CONTEXT_FAILED", stage);
|
|
118046
|
-
}
|
|
118047
|
-
function hookFailureReason(error61, profileId) {
|
|
118048
|
-
const owned = error61 instanceof HookDiagnosticError;
|
|
118049
|
-
const code2 = owned && (CONTEXT_ERROR_CODES.has(error61.code) || ["SKILLS_HOOK_TIMEOUT", "SKILLS_HOOK_INVALID_RESPONSE"].includes(error61.code)) ? error61.code : "SKILLS_HOOK_FAILED";
|
|
118050
|
-
const profile = typeof profileId === "string" && /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/.test(profileId) && !profileId.includes("..") ? profileId : undefined;
|
|
118051
|
-
const identity6 = [profile ? `profile=${profile}` : undefined, owned ? `stage=${error61.stage}` : undefined].filter(Boolean).join(", ");
|
|
118052
|
-
const prefix = `Skills context is unavailable [${code2}]${identity6 ? ` (${identity6})` : ""}.`;
|
|
118053
|
-
if (code2 === "SKILLS_STORAGE_FULL") {
|
|
118054
|
-
return `${prefix} The filesystem is full or its quota is exhausted. Free space through your approved recoverable cleanup process, then retry the same session. Do not delete session receipts or change credentials to bypass this failure.`;
|
|
118055
|
-
}
|
|
118056
|
-
if (code2 === "PROFILE_LOCK_MISMATCH") {
|
|
118057
|
-
return `${prefix} This session or project is pinned to a different profile. Inspect the session with skills sessions show <session-id> --json; review skills sessions reconcile for an intentional session change, or explicit project sync for a project change. Sync alone does not change that pin.`;
|
|
118058
|
-
}
|
|
118059
|
-
if (code2 === "SESSION_RECONCILIATION_REQUIRED") {
|
|
118060
|
-
return `${prefix} A loaded skill changed or was removed. Inspect this session with skills sessions show <session-id> --json, then review skills sessions reconcile for an intentional change. Sync alone does not change this pin. A refusal is re-checked with the authority within five minutes, or sooner after the receipt or the synced profile revision changes.`;
|
|
118061
|
-
}
|
|
118062
|
-
if (code2 === "SESSION_RENEWAL_TIMEOUT") {
|
|
118063
|
-
return `${prefix} Renewing this session's expired authorization did not finish within the hook's renewal window; no request was refused. Sync and diagnosis do not change this window. The existing pin is unchanged and the next prompt retries the renewal. If it keeps recurring, inspect the session with skills sessions show <session-id> --json and review skills sessions reconcile.`;
|
|
118064
|
-
}
|
|
118065
|
-
if (code2.startsWith("SESSION_")) {
|
|
118066
|
-
return `${prefix} Inspect the session with skills sessions show <session-id> --json and review its parent or concurrent writer before retrying. Do not remove or rewrite its receipt to bypass this refusal.`;
|
|
118067
|
-
}
|
|
118068
|
-
if (["PROFILE_IDENTITY_MISMATCH", "BUNDLE_DIGEST_MISMATCH", "BUNDLE_IDENTITY_MISMATCH", "INVALID_RECEIPT", "INVALID_CACHE_FILE", "UNSAFE_CACHE_PATH"].includes(code2)) {
|
|
118069
|
-
return `${prefix} Verify the selected authority and receipt integrity before repairing the profile; do not bypass verification or substitute another cache.`;
|
|
118070
|
-
}
|
|
118071
|
-
const selected = profile ?? "<id>";
|
|
118072
|
-
return `${prefix} Run skills sync --selection-profile ${selected} --json, then diagnose with skills context --stdin --json --cached --selection-profile ${selected} using the same hook session and working-directory fields. Do not include credentials in diagnostic input.`;
|
|
118073
|
-
}
|
|
118074
|
-
function isOptionalHookContextFailure(error61) {
|
|
118075
|
-
return error61 instanceof HookDiagnosticError && OPTIONAL_CONTEXT_FAILURES.has(error61.code);
|
|
118076
|
-
}
|
|
118077
|
-
function hookUnavailableContext(error61, profileId) {
|
|
118078
|
-
return `${hookFailureReason(error61, profileId)} No Skills instructions were delivered by this hook. Ordinary work may continue. Do not perform actions that depend on unavailable Skills instructions, including previously loaded instructions. Explicit skills load, context and run still require verification. Do not substitute native, unmanaged or stale payloads.`;
|
|
118079
|
-
}
|
|
118080
|
-
var CONTEXT_ERROR_CODES, HookDiagnosticError, OPTIONAL_CONTEXT_FAILURES;
|
|
118081
|
-
var init_hook_diagnostics = __esm(() => {
|
|
118082
|
-
CONTEXT_ERROR_CODES = new Set([
|
|
118083
|
-
"SKILLS_API_CREDENTIAL_UNAVAILABLE",
|
|
118084
|
-
"SKILLS_API_UNAVAILABLE",
|
|
118085
|
-
"SKILLS_API_UNAUTHORIZED",
|
|
118086
|
-
"SKILLS_API_FORBIDDEN",
|
|
118087
|
-
"SKILLS_API_RESOURCE_UNAVAILABLE",
|
|
118088
|
-
"SESSION_WRITE_BUSY",
|
|
118089
|
-
"SKILLS_CONTEXT_FAILED",
|
|
118090
|
-
"SKILLS_STORAGE_FULL",
|
|
118091
|
-
"PROFILE_LOCK_MISMATCH",
|
|
118092
|
-
"PROFILE_IDENTITY_MISMATCH",
|
|
118093
|
-
"PROFILE_APPLIED_REPORT_FAILED",
|
|
118094
|
-
"CACHED_AUTHORITY_REQUIRED",
|
|
118095
|
-
"CACHED_PROFILE_EXPIRED",
|
|
118096
|
-
"CACHED_PROFILE_MISSING",
|
|
118097
|
-
"CACHED_BUNDLE_MISSING",
|
|
118098
|
-
"INVALID_CONTEXT_INPUT",
|
|
118099
|
-
"CONTEXT_INPUT_TOO_LARGE",
|
|
118100
|
-
"INVALID_CONTEXT_BUDGET",
|
|
118101
|
-
"INVALID_SELECTION",
|
|
118102
|
-
"INVALID_SELECTION_ALIASES",
|
|
118103
|
-
"INVALID_RECEIPT",
|
|
118104
|
-
"INVALID_CACHE_FILE",
|
|
118105
|
-
"UNSAFE_CACHE_PATH",
|
|
118106
|
-
"RECEIPT_TOO_LARGE",
|
|
118107
|
-
"BUNDLE_DIGEST_MISMATCH",
|
|
118108
|
-
"BUNDLE_IDENTITY_MISMATCH",
|
|
118109
|
-
"BUNDLE_UNAVAILABLE",
|
|
118110
|
-
"BUNDLE_TOO_LARGE",
|
|
118111
|
-
"SKILL_NOT_SELECTED",
|
|
118112
|
-
"INVALID_SESSION",
|
|
118113
|
-
"SESSION_PARENT_NOT_FOUND",
|
|
118114
|
-
"SESSION_PARENT_MISMATCH",
|
|
118115
|
-
"SESSION_NOT_FOUND",
|
|
118116
|
-
"SESSION_GENERATION_CHANGED",
|
|
118117
|
-
"SESSION_GENERATION_EXHAUSTED",
|
|
118118
|
-
"SESSION_PARENT_CHANGED",
|
|
118119
|
-
"SESSION_RECEIPT_CHANGED",
|
|
118120
|
-
"SESSION_RECONCILIATION_REQUIRED",
|
|
118121
|
-
"SESSION_RENEWAL_TIMEOUT",
|
|
118122
|
-
"SESSION_CONTEXT_CONFLICT",
|
|
118123
|
-
"SESSION_RECONCILIATION_INCOMPLETE",
|
|
118124
|
-
"SESSION_WRITE_LOCKED",
|
|
118125
|
-
"SESSION_WRITE_LOCK_CHANGED",
|
|
118126
|
-
"SESSION_LOCK_RECOVERY_INCOMPLETE"
|
|
118127
|
-
]);
|
|
118128
|
-
HookDiagnosticError = class HookDiagnosticError extends Error {
|
|
118129
|
-
code;
|
|
118130
|
-
stage;
|
|
118131
|
-
constructor(code2, stage) {
|
|
118132
|
-
super("Skills hook operation failed");
|
|
118133
|
-
this.code = code2;
|
|
118134
|
-
this.stage = stage;
|
|
118135
|
-
}
|
|
118136
|
-
};
|
|
118137
|
-
OPTIONAL_CONTEXT_FAILURES = new Set([
|
|
118138
|
-
"SKILLS_API_CREDENTIAL_UNAVAILABLE",
|
|
118139
|
-
"SKILLS_API_UNAVAILABLE",
|
|
118140
|
-
"SKILLS_API_UNAUTHORIZED",
|
|
118141
|
-
"SKILLS_API_FORBIDDEN",
|
|
118142
|
-
"SKILLS_API_RESOURCE_UNAVAILABLE",
|
|
118143
|
-
"CACHED_PROFILE_EXPIRED",
|
|
118144
|
-
"CACHED_PROFILE_MISSING",
|
|
118145
|
-
"CACHED_BUNDLE_MISSING",
|
|
118146
|
-
"SESSION_RECONCILIATION_REQUIRED",
|
|
118147
|
-
"SESSION_RENEWAL_TIMEOUT",
|
|
118148
|
-
"SESSION_WRITE_BUSY",
|
|
118149
|
-
"SESSION_PARENT_CHANGED",
|
|
118150
|
-
"SESSION_CONTEXT_CONFLICT",
|
|
118151
|
-
"SKILLS_HOOK_TIMEOUT"
|
|
118152
|
-
]);
|
|
118153
|
-
});
|
|
118154
|
-
|
|
118155
118455
|
// src/lib/claude-prospective-review.ts
|
|
118156
118456
|
import { createHash as createHash43 } from "crypto";
|
|
118157
118457
|
import { lstatSync as lstatSync41, readFileSync as readFileSync45, readdirSync as readdirSync25, realpathSync as realpathSync22 } from "fs";
|
|
118158
|
-
import { basename as
|
|
118458
|
+
import { basename as basename21, dirname as dirname42, isAbsolute as isAbsolute38, join as join71, relative as relative14, resolve as resolve37, sep as sep17 } from "path";
|
|
118159
118459
|
import { isDeepStrictEqual as isDeepStrictEqual18 } from "util";
|
|
118160
118460
|
function hashClaudeDiscoveryBinding(binding) {
|
|
118161
118461
|
return sha8(JSON.stringify(binding));
|
|
@@ -118172,7 +118472,7 @@ function object11(value) {
|
|
|
118172
118472
|
function hasOwn2(value, key) {
|
|
118173
118473
|
return object11(value) && Object.hasOwn(value, key);
|
|
118174
118474
|
}
|
|
118175
|
-
function
|
|
118475
|
+
function assertJsonValue2(value, name, depth = 0) {
|
|
118176
118476
|
if (depth > 32)
|
|
118177
118477
|
refuse8(`${name} exceeds the JSON nesting bound`);
|
|
118178
118478
|
if (value === null || typeof value === "string" || typeof value === "boolean")
|
|
@@ -118184,12 +118484,12 @@ function assertJsonValue(value, name, depth = 0) {
|
|
|
118184
118484
|
}
|
|
118185
118485
|
if (Array.isArray(value)) {
|
|
118186
118486
|
for (const item of value)
|
|
118187
|
-
|
|
118487
|
+
assertJsonValue2(item, name, depth + 1);
|
|
118188
118488
|
return;
|
|
118189
118489
|
}
|
|
118190
118490
|
if (object11(value)) {
|
|
118191
118491
|
for (const item of Object.values(value))
|
|
118192
|
-
|
|
118492
|
+
assertJsonValue2(item, name, depth + 1);
|
|
118193
118493
|
return;
|
|
118194
118494
|
}
|
|
118195
118495
|
refuse8(`${name} contains a non-JSON value`);
|
|
@@ -118480,13 +118780,13 @@ function reviewClaudeProspectiveCandidate(request2, requestFileSha256) {
|
|
|
118480
118780
|
pluginNames.add(selected.plugin);
|
|
118481
118781
|
if (!object11(selected.optionsPatch))
|
|
118482
118782
|
refuse8("selected plugin optionsPatch must be a JSON object");
|
|
118483
|
-
|
|
118783
|
+
assertJsonValue2(selected.optionsPatch, "selected plugin optionsPatch");
|
|
118484
118784
|
if (selected.optionsPatch.enabled !== true)
|
|
118485
118785
|
refuse8("selected plugin optionsPatch must explicitly declare enabled: true");
|
|
118486
118786
|
if (Buffer.byteLength(canonicalJson3(selected.optionsPatch), "utf8") > 16 * 1024)
|
|
118487
118787
|
refuse8("selected plugin optionsPatch exceeds its byte bound");
|
|
118488
118788
|
abs(selected.manifestPath, "manifest path");
|
|
118489
|
-
if (!selected.manifestPath.startsWith(candidate2.root + sep17) ||
|
|
118789
|
+
if (!selected.manifestPath.startsWith(candidate2.root + sep17) || basename21(dirname42(selected.manifestPath)) !== ".claude-plugin" || selected.manifestPath !== join71(dirname42(dirname42(selected.manifestPath)), ".claude-plugin", "plugin.json"))
|
|
118490
118790
|
refuse8("plugin manifest must be under a plugin root inside the frozen marketplace closure");
|
|
118491
118791
|
const pluginRoot2 = dirname42(dirname42(selected.manifestPath));
|
|
118492
118792
|
const relativePluginRoot = relative14(candidate2.root, pluginRoot2);
|
|
@@ -119229,13 +119529,13 @@ function registerAgentIntegration(parent) {
|
|
|
119229
119529
|
process.exitCode = 1;
|
|
119230
119530
|
}
|
|
119231
119531
|
});
|
|
119232
|
-
hook.command("rebind-cache").requiredOption("--agent <agent>", "codex").requiredOption("--expected-policy-sha256 <sha256>", "Exact current managed policy bytes").requiredOption("--expected-settings-sha256 <sha256>", "Exact current Codex configuration bytes").option("--app-only-parent <path>", "Explicit canonical remote cache parent with app capabilities and no Skill docs", (value, previous) => [...previous, value], []).option("--expected-cache-witness-sha256 <sha256>", "Exact semantic cache digest from the reviewed preview; required with --apply").option("--apply", "Apply the reviewed policy-only cache witness migration", false).option("--json", "Return metadata-only preview or receipt", false).description("Explicitly migrate an enrolled Codex cache to semantic skill and capability identity").action(async (options) => {
|
|
119532
|
+
hook.command("rebind-cache").requiredOption("--agent <agent>", "codex").requiredOption("--expected-policy-sha256 <sha256>", "Exact current managed policy bytes").requiredOption("--expected-settings-sha256 <sha256>", "Exact current Codex configuration bytes").option("--app-only-parent <path>", "Explicit canonical remote cache parent with app capabilities and no Skill docs", (value, previous) => [...previous, value], []).option("--reviewed-hook-parent <path>", "Explicit canonical cache parent with already-reviewed native mcp_tool hooks", (value, previous) => [...previous, value], []).option("--expected-cache-witness-sha256 <sha256>", "Exact semantic cache digest from the reviewed preview; required with --apply").option("--apply", "Apply the reviewed policy-only cache witness migration", false).option("--json", "Return metadata-only preview or receipt", false).description("Explicitly migrate an enrolled Codex cache to semantic skill and capability identity").action(async (options) => {
|
|
119233
119533
|
try {
|
|
119234
119534
|
if (options.agent !== "codex")
|
|
119235
119535
|
throw new Error("Cache witness rebind accepts codex only");
|
|
119236
119536
|
if (options.apply && options.expectedCacheWitnessSha256 === undefined)
|
|
119237
119537
|
throw new Error("Cache witness apply requires --expected-cache-witness-sha256 from an exact reviewed preview");
|
|
119238
|
-
const plan = planCodexSemanticCacheWitnessUpgrade({ agent: "codex", appOnlyParents: options.appOnlyParent, expectedPolicySha256: options.expectedPolicySha256, expectedSettingsSha256: options.expectedSettingsSha256, ...options.expectedCacheWitnessSha256 !== undefined ? { expectedCacheWitnessSha256: options.expectedCacheWitnessSha256 } : {} });
|
|
119538
|
+
const plan = planCodexSemanticCacheWitnessUpgrade({ agent: "codex", appOnlyParents: options.appOnlyParent, reviewedHookParents: options.reviewedHookParent, expectedPolicySha256: options.expectedPolicySha256, expectedSettingsSha256: options.expectedSettingsSha256, ...options.expectedCacheWitnessSha256 !== undefined ? { expectedCacheWitnessSha256: options.expectedCacheWitnessSha256 } : {} });
|
|
119239
119539
|
const result2 = options.apply ? applyAgentIntegration(plan) : { changed: [], backups: [] };
|
|
119240
119540
|
const proof = plan.discoveryAfter[0].codexSemanticCache;
|
|
119241
119541
|
await writeCliOutput(options.json ? JSON.stringify({ applied: options.apply, cacheWitnessUpgrade: plan.cacheWitnessUpgrade, witness: proof.witness, previousDirectories: proof.supersededDirectories, previousSources: proof.supersededSources, ...result2 }) : `Codex semantic cache witness ${options.apply ? "upgraded" : "planned"}; native configuration and cache were not changed.`);
|
|
@@ -120833,7 +121133,7 @@ var init_registry_sync = __esm(() => {
|
|
|
120833
121133
|
|
|
120834
121134
|
// src/lib/review-export.ts
|
|
120835
121135
|
import { constants as constants30, closeSync as closeSync31, existsSync as existsSync38, fstatSync as fstatSync31, fsyncSync as fsyncSync10, lstatSync as lstatSync45, openSync as openSync31, realpathSync as realpathSync24, statSync as statSync25, writeFileSync as writeFileSync33 } from "fs";
|
|
120836
|
-
import { basename as
|
|
121136
|
+
import { basename as basename22, dirname as dirname47, isAbsolute as isAbsolute43, join as join74, parse as parse13, resolve as resolve41, sep as sep21 } from "path";
|
|
120837
121137
|
function exactVersion(spec) {
|
|
120838
121138
|
const at2 = spec.indexOf("@");
|
|
120839
121139
|
const slug2 = spec.slice(0, at2);
|
|
@@ -120844,7 +121144,7 @@ function exactVersion(spec) {
|
|
|
120844
121144
|
return { slug: slug2, version: version2 };
|
|
120845
121145
|
}
|
|
120846
121146
|
function assertPrivateDestination(output2) {
|
|
120847
|
-
if (!isAbsolute43(output2) || resolve41(output2) !== output2 || !
|
|
121147
|
+
if (!isAbsolute43(output2) || resolve41(output2) !== output2 || !basename22(output2).endsWith(".tar.gz")) {
|
|
120848
121148
|
throw new Error("Review output must be an absolute, normalized .tar.gz path.");
|
|
120849
121149
|
}
|
|
120850
121150
|
const parent = dirname47(output2);
|