@hasna/skills 0.10.65 → 0.10.67
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 +23 -1
- package/bin/index.js +365 -85
- package/bin/mcp.js +264 -43
- package/bin/migrate.js +1 -1
- package/bin/server.js +1 -1
- package/bin/worker.js +1 -1
- package/dist/index.js +333 -53
- 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/skillinfo.d.ts +12 -2
- package/dist/runtime-prerequisites.js +37 -3
- package/dist/sdk/index.d.ts +1 -0
- package/dist/sdk/index.js +345 -64
- package/package.json +1 -1
package/dist/sdk/index.js
CHANGED
|
@@ -32371,7 +32371,7 @@ var init_event_sink = __esm(() => {
|
|
|
32371
32371
|
init_dist();
|
|
32372
32372
|
});
|
|
32373
32373
|
// package.json
|
|
32374
|
-
var version = "0.10.
|
|
32374
|
+
var version = "0.10.67";
|
|
32375
32375
|
var package_default = {
|
|
32376
32376
|
name: "@hasna/skills",
|
|
32377
32377
|
version,
|
|
@@ -38326,7 +38326,7 @@ import {
|
|
|
38326
38326
|
writeFileSync as writeFileSync8
|
|
38327
38327
|
} from "fs";
|
|
38328
38328
|
import { homedir as homedir5 } from "os";
|
|
38329
|
-
import { basename as
|
|
38329
|
+
import { basename as basename15, dirname as dirname25, join as join35 } from "path";
|
|
38330
38330
|
|
|
38331
38331
|
// src/lib/sumi-settings-witness.ts
|
|
38332
38332
|
import { createHash as createHash8 } from "crypto";
|
|
@@ -40671,7 +40671,7 @@ function upgradeCodexSettingsWitnessV5(previous, reviewedSettingsPath) {
|
|
|
40671
40671
|
// src/lib/codex-semantic-cache-witness.ts
|
|
40672
40672
|
import { createHash as createHash13 } from "crypto";
|
|
40673
40673
|
import { constants as constants9, closeSync as closeSync12, fstatSync as fstatSync12, lstatSync as lstatSync10, openSync as openSync12, readSync as readSync6, readdirSync as readdirSync4, realpathSync as realpathSync9 } from "fs";
|
|
40674
|
-
import { dirname as dirname9, isAbsolute as isAbsolute8, join as join15, relative as relative6, resolve as resolve8, sep as sep5 } from "path";
|
|
40674
|
+
import { basename as basename5, dirname as dirname9, isAbsolute as isAbsolute8, join as join15, relative as relative6, resolve as resolve8, sep as sep5 } from "path";
|
|
40675
40675
|
var CODEX_SEMANTIC_CACHE_WITNESS_SCHEMA = "hasna.codex-semantic-cache-witness.v1";
|
|
40676
40676
|
var identifier4 = (value) => typeof value === "string" && /^[A-Za-z0-9_-]{1,64}$/.test(value);
|
|
40677
40677
|
var digest2 = (value) => typeof value === "string" && /^[a-f0-9]{64}$/.test(value);
|
|
@@ -40680,6 +40680,26 @@ var refuse5 = () => {
|
|
|
40680
40680
|
};
|
|
40681
40681
|
var MAX_DOCUMENT_BYTES = 1024 * 1024;
|
|
40682
40682
|
var MAX_RECEIPT_BYTES = 16 * 1024;
|
|
40683
|
+
function codexLocalMarketplaceMapsPlugin(text, marketplace, plugin) {
|
|
40684
|
+
try {
|
|
40685
|
+
hashNativeJsonControls(text);
|
|
40686
|
+
const value = JSON.parse(text);
|
|
40687
|
+
const marketplaceInterface = plainObject(value) ? value.interface : undefined;
|
|
40688
|
+
const validInterface = typeof marketplaceInterface === "string" || Number.isSafeInteger(marketplaceInterface) || plainObject(marketplaceInterface) && exactKeys2(marketplaceInterface, [], ["displayName"]) && typeof marketplaceInterface.displayName === "string" && marketplaceInterface.displayName.trim().length > 0;
|
|
40689
|
+
if (!plainObject(value) || !exactKeys2(value, ["interface", "name", "plugins"]) || value.name !== marketplace || !validInterface || !Array.isArray(value.plugins) || value.plugins.length < 1 || value.plugins.length > 4096)
|
|
40690
|
+
return false;
|
|
40691
|
+
const rows = value.plugins.filter((row2) => plainObject(row2) && row2.name === plugin);
|
|
40692
|
+
if (rows.length !== 1)
|
|
40693
|
+
return false;
|
|
40694
|
+
const row = rows[0];
|
|
40695
|
+
if (!exactKeys2(row, ["name", "source"]) || !plainObject(row.source) || !exactKeys2(row.source, ["source", "path"]) || row.source.source !== "local" || typeof row.source.path !== "string" || !row.source.path.startsWith("./") || row.source.path.includes("\\"))
|
|
40696
|
+
return false;
|
|
40697
|
+
const parts = row.source.path.split("/");
|
|
40698
|
+
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;
|
|
40699
|
+
} catch {
|
|
40700
|
+
return false;
|
|
40701
|
+
}
|
|
40702
|
+
}
|
|
40683
40703
|
function defaultRead(path) {
|
|
40684
40704
|
const before = lstatSync10(path, { throwIfNoEntry: false, bigint: true });
|
|
40685
40705
|
if (before === undefined)
|
|
@@ -40741,7 +40761,7 @@ function validPluginParent(cacheRoot, pluginParent, namespace, pluginId) {
|
|
|
40741
40761
|
return parts.length === 2 && parts.every(identifier4) && parts[1] === namespace && pluginId === `${namespace}@${parts[0]}`;
|
|
40742
40762
|
}
|
|
40743
40763
|
function assertWitnessShape(value) {
|
|
40744
|
-
if (!plainObject(value) || !exactKeys2(value, ["schema", "cacheRoot", "controls", "appOnlyParents", "skills", "sha256"]) || value.schema !== CODEX_SEMANTIC_CACHE_WITNESS_SCHEMA || typeof value.cacheRoot !== "string" || !isAbsolute8(value.cacheRoot) || resolve8(value.cacheRoot) !== value.cacheRoot || !digest2(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)
|
|
40764
|
+
if (!plainObject(value) || !exactKeys2(value, ["schema", "cacheRoot", "controls", "appOnlyParents", "skills", "sha256"], ["hookParents"]) || value.schema !== CODEX_SEMANTIC_CACHE_WITNESS_SCHEMA || typeof value.cacheRoot !== "string" || !isAbsolute8(value.cacheRoot) || resolve8(value.cacheRoot) !== value.cacheRoot || !digest2(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)
|
|
40745
40765
|
refuse5();
|
|
40746
40766
|
const witness = value;
|
|
40747
40767
|
const controlParents = new Set;
|
|
@@ -40762,6 +40782,20 @@ function assertWitnessShape(value) {
|
|
|
40762
40782
|
refuse5();
|
|
40763
40783
|
appOnlyParentPaths.add(row.pluginParent);
|
|
40764
40784
|
}
|
|
40785
|
+
const hookParentPaths = new Set;
|
|
40786
|
+
const hookParents = witness.hookParents === undefined ? [] : witness.hookParents;
|
|
40787
|
+
if (!Array.isArray(hookParents) || hookParents.length > 4096)
|
|
40788
|
+
refuse5();
|
|
40789
|
+
for (const candidate of hookParents) {
|
|
40790
|
+
if (!plainObject(candidate))
|
|
40791
|
+
refuse5();
|
|
40792
|
+
const row = candidate;
|
|
40793
|
+
const remote = row.installation === "remote-receipt";
|
|
40794
|
+
const local = row.installation === "local-marketplace";
|
|
40795
|
+
if (!exactKeys2(row, ["role", "pluginId", "namespace", "pluginParent", "installation", "manifestSha256", "hooksSha256"], remote ? ["remotePluginId", "receiptSha256"] : local ? ["marketplaceSourcePath", "marketplaceSha256"] : []) || row.role !== "reviewed-hook" || !identifier4(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) || !digest2(row.receiptSha256)) || local && (typeof row.marketplaceSourcePath !== "string" || !isAbsolute8(row.marketplaceSourcePath) || resolve8(row.marketplaceSourcePath) !== row.marketplaceSourcePath || basename5(row.marketplaceSourcePath) !== "marketplace.json" || !digest2(row.marketplaceSha256)) || !remote && !local || !digest2(row.manifestSha256) || !digest2(row.hooksSha256) || hookParentPaths.has(row.pluginParent) || controlParents.has(row.pluginParent) || appOnlyParentPaths.has(row.pluginParent))
|
|
40796
|
+
refuse5();
|
|
40797
|
+
hookParentPaths.add(row.pluginParent);
|
|
40798
|
+
}
|
|
40765
40799
|
const skillNames = new Set;
|
|
40766
40800
|
const qualifiedNames = new Set;
|
|
40767
40801
|
for (const candidate of witness.skills) {
|
|
@@ -40781,6 +40815,7 @@ function assertWitnessShape(value) {
|
|
|
40781
40815
|
cacheRoot: witness.cacheRoot,
|
|
40782
40816
|
controls: witness.controls,
|
|
40783
40817
|
appOnlyParents: witness.appOnlyParents,
|
|
40818
|
+
...witness.hookParents === undefined ? {} : { hookParents: witness.hookParents },
|
|
40784
40819
|
skills: witness.skills
|
|
40785
40820
|
};
|
|
40786
40821
|
if (hash2(projection) !== witness.sha256)
|
|
@@ -40971,10 +41006,147 @@ function appOnlyParentProjection(cacheRoot, parents2, read) {
|
|
|
40971
41006
|
}
|
|
40972
41007
|
return rows.sort((a, b) => a.pluginId.localeCompare(b.pluginId) || a.pluginParent.localeCompare(b.pluginParent));
|
|
40973
41008
|
}
|
|
40974
|
-
|
|
41009
|
+
var codexHookEvents = new Set([
|
|
41010
|
+
"SessionStart",
|
|
41011
|
+
"UserPromptSubmit",
|
|
41012
|
+
"PreToolUse",
|
|
41013
|
+
"PostToolUse",
|
|
41014
|
+
"PostToolUseFailure",
|
|
41015
|
+
"Stop",
|
|
41016
|
+
"SubagentStart",
|
|
41017
|
+
"SubagentStop",
|
|
41018
|
+
"PreCompact",
|
|
41019
|
+
"Notification",
|
|
41020
|
+
"PermissionRequest",
|
|
41021
|
+
"SessionEnd",
|
|
41022
|
+
"ConfigChange",
|
|
41023
|
+
"WorktreeCreate",
|
|
41024
|
+
"WorktreeRemove",
|
|
41025
|
+
"TeammateIdle",
|
|
41026
|
+
"TaskComplete"
|
|
41027
|
+
]);
|
|
41028
|
+
function assertJsonValue(value, depth = 0, budget2 = { members: 0 }) {
|
|
41029
|
+
if (depth > 32 || ++budget2.members > 4096)
|
|
41030
|
+
refuse5();
|
|
41031
|
+
if (value === null || typeof value === "string" || typeof value === "boolean")
|
|
41032
|
+
return;
|
|
41033
|
+
if (typeof value === "number" && Number.isFinite(value))
|
|
41034
|
+
return;
|
|
41035
|
+
if (Array.isArray(value)) {
|
|
41036
|
+
for (const item of value)
|
|
41037
|
+
assertJsonValue(item, depth + 1, budget2);
|
|
41038
|
+
return;
|
|
41039
|
+
}
|
|
41040
|
+
if (!plainObject(value))
|
|
41041
|
+
refuse5();
|
|
41042
|
+
for (const [key, item] of Object.entries(value)) {
|
|
41043
|
+
if (!key || /[\x00-\x1f\x7f]/.test(key))
|
|
41044
|
+
refuse5();
|
|
41045
|
+
assertJsonValue(item, depth + 1, budget2);
|
|
41046
|
+
}
|
|
41047
|
+
}
|
|
41048
|
+
function reviewedHookControls(root, read) {
|
|
41049
|
+
const manifestPath = join15(root, ".codex-plugin/plugin.json"), hooksPath = join15(root, "hooks/hooks.json");
|
|
41050
|
+
let manifest, manifestSha256, hooks, hooksSha256;
|
|
41051
|
+
try {
|
|
41052
|
+
const manifestText = read(manifestPath);
|
|
41053
|
+
manifestSha256 = hashNativeJsonControls(manifestText, "version");
|
|
41054
|
+
manifest = JSON.parse(manifestText);
|
|
41055
|
+
const hooksText = read(hooksPath);
|
|
41056
|
+
hashNativeJsonControls(hooksText);
|
|
41057
|
+
hooksSha256 = createHash13("sha256").update(hooksText).digest("hex");
|
|
41058
|
+
hooks = JSON.parse(hooksText);
|
|
41059
|
+
} catch {
|
|
41060
|
+
return refuse5();
|
|
41061
|
+
}
|
|
41062
|
+
if (!plainObject(manifest) || !exactKeys2(manifest, ["name", "version", "hooks"], ["description"]) || !identifier4(manifest.name) || typeof manifest.version !== "string" || manifest.version !== basename5(root) || manifest.hooks !== "./hooks/hooks.json" || manifest.description !== undefined && (typeof manifest.description !== "string" || !manifest.description.trim() || manifest.description.length > 1024))
|
|
41063
|
+
refuse5();
|
|
41064
|
+
const manifestRecord = manifest;
|
|
41065
|
+
if (!plainObject(hooks) || !exactKeys2(hooks, ["hooks"], ["description"]) || !plainObject(hooks.hooks) || hooks.description !== undefined && typeof hooks.description !== "string")
|
|
41066
|
+
refuse5();
|
|
41067
|
+
const hookTable = hooks.hooks;
|
|
41068
|
+
const events = Object.entries(hookTable);
|
|
41069
|
+
if (!events.length || events.length > 32)
|
|
41070
|
+
refuse5();
|
|
41071
|
+
for (const [event, groups] of events) {
|
|
41072
|
+
if (!codexHookEvents.has(event) || !Array.isArray(groups) || !groups.length || groups.length > 32)
|
|
41073
|
+
refuse5();
|
|
41074
|
+
for (const group of groups) {
|
|
41075
|
+
if (!plainObject(group) || !exactKeys2(group, ["hooks"]) || !Array.isArray(group.hooks) || !group.hooks.length || group.hooks.length > 32)
|
|
41076
|
+
refuse5();
|
|
41077
|
+
const handlers = group.hooks;
|
|
41078
|
+
for (const handler of handlers) {
|
|
41079
|
+
if (!plainObject(handler) || !exactKeys2(handler, ["type", "server", "tool", "input"], ["timeout"]) || handler.type !== "mcp_tool" || !identifier4(handler.server) || !identifier4(handler.tool) || !plainObject(handler.input) || handler.timeout !== undefined && (!Number.isSafeInteger(handler.timeout) || Number(handler.timeout) < 1 || Number(handler.timeout) > 300))
|
|
41080
|
+
refuse5();
|
|
41081
|
+
assertJsonValue(handler.input);
|
|
41082
|
+
}
|
|
41083
|
+
}
|
|
41084
|
+
}
|
|
41085
|
+
return { namespace: manifestRecord.name, manifestSha256, hooksSha256 };
|
|
41086
|
+
}
|
|
41087
|
+
function reviewedHookParentProjection(cacheRoot, parents2, read) {
|
|
41088
|
+
if (!Array.isArray(parents2) || parents2.length > 4096)
|
|
41089
|
+
refuse5();
|
|
41090
|
+
const seen = new Set, rows = [];
|
|
41091
|
+
for (const parent of parents2) {
|
|
41092
|
+
const remote = parent?.installation === "remote-receipt", local = parent?.installation === "local-marketplace";
|
|
41093
|
+
if (!parent || !exactKeys2(parent, ["installation", "namespace", "pluginId", "pluginParent", "role"], remote ? ["remotePluginId"] : local ? ["marketplaceSourcePath", "marketplaceSha256"] : []) || parent.role !== "reviewed-hook" || !identifier4(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" || !isAbsolute8(parent.marketplaceSourcePath) || resolve8(parent.marketplaceSourcePath) !== parent.marketplaceSourcePath || basename5(parent.marketplaceSourcePath) !== "marketplace.json" || !digest2(parent.marketplaceSha256)) || !remote && !local)
|
|
41094
|
+
refuse5();
|
|
41095
|
+
const parts = relative6(cacheRoot, parent.pluginParent).split(sep5);
|
|
41096
|
+
if (!isAbsolute8(parent.pluginParent) || resolve8(parent.pluginParent) !== parent.pluginParent || parts.length !== 2 || parts.some((part) => !identifier4(part)) || parts[1] !== parent.namespace || parent.pluginId !== `${parent.namespace}@${parts[0]}` || seen.has(parent.pluginParent))
|
|
41097
|
+
refuse5();
|
|
41098
|
+
seen.add(parent.pluginParent);
|
|
41099
|
+
const parentStat = lstatSync10(parent.pluginParent, { throwIfNoEntry: false });
|
|
41100
|
+
if (!parentStat?.isDirectory() || parentStat.isSymbolicLink() || realpathSync9(parent.pluginParent) !== parent.pluginParent)
|
|
41101
|
+
refuse5();
|
|
41102
|
+
const receiptPath = join15(parent.pluginParent, ".codex-remote-plugin-install.json"), receiptStat = lstatSync10(receiptPath, { throwIfNoEntry: false });
|
|
41103
|
+
let receiptText;
|
|
41104
|
+
if (remote) {
|
|
41105
|
+
if (!receiptStat?.isFile() || receiptStat.isSymbolicLink() || receiptStat.size > MAX_RECEIPT_BYTES)
|
|
41106
|
+
refuse5();
|
|
41107
|
+
try {
|
|
41108
|
+
receiptText = read(receiptPath);
|
|
41109
|
+
hashNativeJsonControls(receiptText);
|
|
41110
|
+
const receipt = JSON.parse(receiptText);
|
|
41111
|
+
if (!plainObject(receipt) || !exactKeys2(receipt, ["schema_version", "remote_plugin_id"]) || receipt.schema_version !== 1 || receipt.remote_plugin_id !== parent.remotePluginId)
|
|
41112
|
+
refuse5();
|
|
41113
|
+
} catch {
|
|
41114
|
+
refuse5();
|
|
41115
|
+
}
|
|
41116
|
+
} else {
|
|
41117
|
+
const marketplaceSourcePath = parent.marketplaceSourcePath ?? refuse5();
|
|
41118
|
+
if (receiptStat !== undefined || !parent.marketplaceSha256)
|
|
41119
|
+
refuse5();
|
|
41120
|
+
let marketplaceText;
|
|
41121
|
+
try {
|
|
41122
|
+
marketplaceText = read(marketplaceSourcePath);
|
|
41123
|
+
} catch {
|
|
41124
|
+
return refuse5();
|
|
41125
|
+
}
|
|
41126
|
+
if (createHash13("sha256").update(marketplaceText).digest("hex") !== parent.marketplaceSha256 || !codexLocalMarketplaceMapsPlugin(marketplaceText, parts[0], parent.namespace))
|
|
41127
|
+
refuse5();
|
|
41128
|
+
}
|
|
41129
|
+
const materializations = readdirSync4(parent.pluginParent).filter((name) => name !== ".codex-remote-plugin-install.json").map((version2) => {
|
|
41130
|
+
if (!/^[A-Za-z0-9][A-Za-z0-9._+-]{0,127}$/.test(version2))
|
|
41131
|
+
refuse5();
|
|
41132
|
+
const root = join15(parent.pluginParent, version2), stat = lstatSync10(root, { throwIfNoEntry: false });
|
|
41133
|
+
if (!stat?.isDirectory() || stat.isSymbolicLink() || realpathSync9(root) !== root)
|
|
41134
|
+
refuse5();
|
|
41135
|
+
const controls = reviewedHookControls(root, read);
|
|
41136
|
+
if (controls.namespace !== parent.namespace)
|
|
41137
|
+
refuse5();
|
|
41138
|
+
return { manifestSha256: controls.manifestSha256, hooksSha256: controls.hooksSha256 };
|
|
41139
|
+
});
|
|
41140
|
+
if (!materializations.length || materializations.some((item) => canonical4(item) !== canonical4(materializations[0])))
|
|
41141
|
+
refuse5();
|
|
41142
|
+
rows.push({ ...parent, ...receiptText === undefined ? {} : { receiptSha256: createHash13("sha256").update(receiptText).digest("hex") }, ...materializations[0] });
|
|
41143
|
+
}
|
|
41144
|
+
return rows.sort((a, b) => a.pluginId.localeCompare(b.pluginId) || a.pluginParent.localeCompare(b.pluginParent));
|
|
41145
|
+
}
|
|
41146
|
+
function assertParents(cacheRoot, controls, appOnlyParents, hookParents, files, members) {
|
|
40975
41147
|
const expected = new Set;
|
|
40976
41148
|
const expectedMarkets = new Set;
|
|
40977
|
-
for (const control of [...controls, ...appOnlyParents]) {
|
|
41149
|
+
for (const control of [...controls, ...appOnlyParents, ...hookParents]) {
|
|
40978
41150
|
const rel = relative6(cacheRoot, control.pluginParent), parts = rel.split(sep5);
|
|
40979
41151
|
if (resolve8(control.pluginParent) !== control.pluginParent || parts.length !== 2 || parts.some((part) => !identifier4(part)) || control.pluginId !== `${control.namespace}@${parts[0]}` || parts[1] !== control.namespace)
|
|
40980
41152
|
refuse5();
|
|
@@ -41015,7 +41187,9 @@ function assertParents(cacheRoot, controls, appOnlyParents, files, members) {
|
|
|
41015
41187
|
refuse5();
|
|
41016
41188
|
if ([".app.json", ".mcp.json"].includes(base) && (parts.length !== 4 || dirname9(member) !== root))
|
|
41017
41189
|
refuse5();
|
|
41018
|
-
if (
|
|
41190
|
+
if ([".app.json", ".mcp.json"].includes(base) && hookParents.some((reviewed) => reviewed.pluginParent === parent))
|
|
41191
|
+
refuse5();
|
|
41192
|
+
if ((parts[3] === "hooks" || base === "hooks.json") && (![4, 5].includes(parts.length) || parts[3] !== "hooks" || (parts.length === 4 ? base !== "hooks" : base !== "hooks.json") || !hookParents.some((reviewed) => reviewed.pluginParent === join15(cacheRoot, parts[0], parts[1]))))
|
|
41019
41193
|
refuse5();
|
|
41020
41194
|
}
|
|
41021
41195
|
}
|
|
@@ -41125,13 +41299,14 @@ function captureCodexSemanticCacheWitness(options) {
|
|
|
41125
41299
|
const initialTree = treeSnapshot(options.cacheRoot);
|
|
41126
41300
|
const controls = controlProjection(options.controls, read);
|
|
41127
41301
|
const appOnlyParents = appOnlyParentProjection(options.cacheRoot, options.appOnlyParents ?? [], read);
|
|
41302
|
+
const hookParents = reviewedHookParentProjection(options.cacheRoot, options.reviewedHookParents ?? [], read);
|
|
41128
41303
|
const skillParents = new Set(controls.map((control) => control.pluginParent));
|
|
41129
|
-
if (appOnlyParents.some((parent) => skillParents.has(parent.pluginParent)))
|
|
41304
|
+
if (appOnlyParents.some((parent) => skillParents.has(parent.pluginParent)) || hookParents.some((parent) => skillParents.has(parent.pluginParent) || appOnlyParents.some((app) => app.pluginParent === parent.pluginParent)))
|
|
41130
41305
|
refuse5();
|
|
41131
41306
|
if (!reviewedCodexPluginCapabilitiesUnchanged(options.cacheRoot, options.controls, read, options.rules))
|
|
41132
41307
|
refuse5();
|
|
41133
41308
|
const files = initialTree.files;
|
|
41134
|
-
assertParents(options.cacheRoot, controls, appOnlyParents, files, initialTree.state.members);
|
|
41309
|
+
assertParents(options.cacheRoot, controls, appOnlyParents, hookParents, files, initialTree.state.members);
|
|
41135
41310
|
const expectedNamesByRoot = assertSkillMaterializations(options.cacheRoot, options.controls, files, read);
|
|
41136
41311
|
const docs = files.filter((path) => path.endsWith(`${sep5}SKILL.md`));
|
|
41137
41312
|
const skillRows = [];
|
|
@@ -41140,6 +41315,8 @@ function captureCodexSemanticCacheWitness(options) {
|
|
|
41140
41315
|
const rel = relative6(options.cacheRoot, document).split(sep5);
|
|
41141
41316
|
if (appOnlyParents.some((parent) => parent.pluginParent === join15(options.cacheRoot, rel[0], rel[1])))
|
|
41142
41317
|
refuse5();
|
|
41318
|
+
if (hookParents.some((parent) => parent.pluginParent === join15(options.cacheRoot, rel[0], rel[1])))
|
|
41319
|
+
refuse5();
|
|
41143
41320
|
const documentStat = lstatSync10(document, { throwIfNoEntry: false });
|
|
41144
41321
|
if (!documentStat?.isFile() || documentStat.isSymbolicLink() || documentStat.size > MAX_DOCUMENT_BYTES)
|
|
41145
41322
|
refuse5();
|
|
@@ -41203,7 +41380,7 @@ function captureCodexSemanticCacheWitness(options) {
|
|
|
41203
41380
|
tracked.verify();
|
|
41204
41381
|
const finalTree = treeSnapshot(options.cacheRoot);
|
|
41205
41382
|
assertSameTree(initialTree.state, finalTree.state, tracked.paths());
|
|
41206
|
-
const completeProjection = { schema: CODEX_SEMANTIC_CACHE_WITNESS_SCHEMA, cacheRoot: options.cacheRoot, controls, appOnlyParents, skills: uniqueSkills };
|
|
41383
|
+
const completeProjection = { schema: CODEX_SEMANTIC_CACHE_WITNESS_SCHEMA, cacheRoot: options.cacheRoot, controls, appOnlyParents, hookParents, skills: uniqueSkills };
|
|
41207
41384
|
return { ...completeProjection, sha256: hash2(completeProjection) };
|
|
41208
41385
|
} catch (error) {
|
|
41209
41386
|
if (error instanceof Error && error.message.startsWith("CODEX_SEMANTIC_CACHE_WITNESS_UNSUPPORTED"))
|
|
@@ -41219,6 +41396,7 @@ function assertCodexSemanticCacheWitnessUnchanged(previous, current) {
|
|
|
41219
41396
|
cacheRoot: previous.cacheRoot,
|
|
41220
41397
|
controls: previous.controls,
|
|
41221
41398
|
appOnlyParents: previous.appOnlyParents,
|
|
41399
|
+
...previous.hookParents === undefined ? {} : { hookParents: previous.hookParents },
|
|
41222
41400
|
skills: previous.skills
|
|
41223
41401
|
};
|
|
41224
41402
|
const currentProjection = {
|
|
@@ -41226,9 +41404,11 @@ function assertCodexSemanticCacheWitnessUnchanged(previous, current) {
|
|
|
41226
41404
|
cacheRoot: current.cacheRoot,
|
|
41227
41405
|
controls: current.controls,
|
|
41228
41406
|
appOnlyParents: current.appOnlyParents,
|
|
41407
|
+
...current.hookParents === undefined ? {} : { hookParents: current.hookParents },
|
|
41229
41408
|
skills: current.skills
|
|
41230
41409
|
};
|
|
41231
|
-
|
|
41410
|
+
const comparable = (projection) => ({ ...projection, hookParents: projection.hookParents ?? [] });
|
|
41411
|
+
if (hash2(priorProjection) !== previous.sha256 || hash2(currentProjection) !== current.sha256 || canonical4(comparable(priorProjection)) !== canonical4(comparable(currentProjection)))
|
|
41232
41412
|
refuse5();
|
|
41233
41413
|
}
|
|
41234
41414
|
|
|
@@ -41257,7 +41437,7 @@ var NATIVE_SKILL_ROOTS = [
|
|
|
41257
41437
|
import { createHash as createHash28, randomUUID as randomUUID4 } from "crypto";
|
|
41258
41438
|
import { isDeepStrictEqual as isDeepStrictEqual8 } from "util";
|
|
41259
41439
|
import { existsSync as existsSync7, lstatSync as lstatSync26, statSync as statSync8, mkdirSync as mkdirSync7, readFileSync as readFileSync18, readdirSync as readdirSync9, opendirSync as opendirSync5, readlinkSync as readlinkSync7, realpathSync as realpathSync13, renameSync as renameSync4, rmdirSync as rmdirSync3, writeFileSync as writeFileSync5, unlinkSync as unlinkSync5, chmodSync, openSync as openSync21, closeSync as closeSync21, fsyncSync as fsyncSync7, fstatSync as fstatSync21, readSync as readSync14, constants as constants19, linkSync as linkSync3 } from "fs";
|
|
41260
|
-
import { dirname as dirname21, join as join30, resolve as resolve23, relative as relative8, isAbsolute as isAbsolute25, sep as sep10 } from "path";
|
|
41440
|
+
import { basename as basename11, dirname as dirname21, join as join30, resolve as resolve23, relative as relative8, isAbsolute as isAbsolute25, sep as sep10 } from "path";
|
|
41261
41441
|
import { homedir as homedir3 } from "os";
|
|
41262
41442
|
|
|
41263
41443
|
// src/lib/managed-policy.ts
|
|
@@ -41265,11 +41445,11 @@ import { closeSync as closeSync13, constants as constants10, fstatSync as fstatS
|
|
|
41265
41445
|
import { join as join17 } from "path";
|
|
41266
41446
|
|
|
41267
41447
|
// src/lib/agent-policy-limits.ts
|
|
41268
|
-
import { basename as
|
|
41448
|
+
import { basename as basename7, isAbsolute as isAbsolute10, join as join16, resolve as resolve10, sep as sep6 } from "path";
|
|
41269
41449
|
|
|
41270
41450
|
// src/lib/claude-marketplace-entry-witness.ts
|
|
41271
41451
|
import { createHash as createHash14 } from "crypto";
|
|
41272
|
-
import { basename as
|
|
41452
|
+
import { basename as basename6, dirname as dirname10, isAbsolute as isAbsolute9, resolve as resolve9 } from "path";
|
|
41273
41453
|
var CLAUDE_MARKETPLACE_ENTRY_HASH_MODE = "claude-marketplace-entry-v1";
|
|
41274
41454
|
var DOMAIN = "hasna.skills.claude-marketplace-entry.v1\x00";
|
|
41275
41455
|
var PATH_CHARACTERS = 4096;
|
|
@@ -41334,7 +41514,7 @@ var stringArray = (value) => value?.kind === "array" && value.items.every(isStri
|
|
|
41334
41514
|
var stringObject = (value) => value?.kind === "object" && value.entries.every(([, item]) => isString(item));
|
|
41335
41515
|
function claudeMarketplaceEntrySourceValid(source) {
|
|
41336
41516
|
const path = source?.path;
|
|
41337
|
-
return typeof path === "string" && path.length > 0 && path.length <= PATH_CHARACTERS && !/[\x00-\x1f\x7f]/.test(path) && isAbsolute9(path) && resolve9(path) === path &&
|
|
41517
|
+
return typeof path === "string" && path.length > 0 && path.length <= PATH_CHARACTERS && !/[\x00-\x1f\x7f]/.test(path) && isAbsolute9(path) && resolve9(path) === path && basename6(path) === "marketplace.json" && basename6(dirname10(path)) === ".claude-plugin" && typeof source.marketplace === "string" && NAME.test(source.marketplace) && !source.marketplace.includes("..") && typeof source.plugin === "string" && NAME.test(source.plugin);
|
|
41338
41518
|
}
|
|
41339
41519
|
function canonical5(value) {
|
|
41340
41520
|
if (value.kind === "string")
|
|
@@ -41604,10 +41784,10 @@ function assertAgentPolicyCollections(policy) {
|
|
|
41604
41784
|
}
|
|
41605
41785
|
}
|
|
41606
41786
|
if (value.codexSemanticCache !== undefined) {
|
|
41607
|
-
const proof = record3(value.codexSemanticCache,
|
|
41608
|
-
requireBound(agent === "codex" && value.agent === "codex" && value.method === "reviewed" && Object.keys(proof).length
|
|
41787
|
+
const proof = record3(value.codexSemanticCache, 9), witness = record3(proof.witness, 7);
|
|
41788
|
+
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));
|
|
41609
41789
|
text(proof.configPath);
|
|
41610
|
-
requireBound(isAbsolute10(proof.configPath) && resolve10(proof.configPath) === proof.configPath &&
|
|
41790
|
+
requireBound(isAbsolute10(proof.configPath) && resolve10(proof.configPath) === proof.configPath && basename7(proof.configPath) === "config.toml");
|
|
41611
41791
|
text(witness.cacheRoot);
|
|
41612
41792
|
requireBound(isAbsolute10(witness.cacheRoot) && resolve10(witness.cacheRoot) === witness.cacheRoot);
|
|
41613
41793
|
if (proof.hookRootAlias !== null) {
|
|
@@ -41624,6 +41804,20 @@ function assertAgentPolicyCollections(policy) {
|
|
|
41624
41804
|
text(parent[key]);
|
|
41625
41805
|
requireBound(isAbsolute10(parent.pluginParent) && resolve10(parent.pluginParent) === parent.pluginParent);
|
|
41626
41806
|
}
|
|
41807
|
+
if (proof.reviewedHookParents !== undefined)
|
|
41808
|
+
for (const parent of array(proof.reviewedHookParents, 4096)) {
|
|
41809
|
+
requireBound(object4(parent) && parent.role === "reviewed-hook" && (parent.installation === "remote-receipt" && Object.keys(parent).length === 6 || parent.installation === "local-marketplace" && Object.keys(parent).length === 7));
|
|
41810
|
+
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");
|
|
41811
|
+
for (const key of ["pluginId", "namespace", "pluginParent", "installation"])
|
|
41812
|
+
text(parent[key]);
|
|
41813
|
+
if (parent.installation === "remote-receipt")
|
|
41814
|
+
text(parent.remotePluginId);
|
|
41815
|
+
else {
|
|
41816
|
+
text(parent.marketplaceSourcePath);
|
|
41817
|
+
requireBound(typeof parent.marketplaceSha256 === "string" && /^[a-f0-9]{64}$/.test(parent.marketplaceSha256) && isAbsolute10(parent.marketplaceSourcePath) && resolve10(parent.marketplaceSourcePath) === parent.marketplaceSourcePath && basename7(parent.marketplaceSourcePath) === "marketplace.json");
|
|
41818
|
+
}
|
|
41819
|
+
requireBound(isAbsolute10(parent.pluginParent) && resolve10(parent.pluginParent) === parent.pluginParent);
|
|
41820
|
+
}
|
|
41627
41821
|
for (const row of [...array(witness.controls, 4096), ...array(witness.appOnlyParents, 4096)]) {
|
|
41628
41822
|
requireBound(object4(row));
|
|
41629
41823
|
for (const key of ["pluginId", "namespace", "pluginParent"])
|
|
@@ -41632,6 +41826,26 @@ function assertAgentPolicyCollections(policy) {
|
|
|
41632
41826
|
if (row[key] !== undefined)
|
|
41633
41827
|
requireBound(typeof row[key] === "string" && /^[a-f0-9]{64}$/.test(row[key]));
|
|
41634
41828
|
}
|
|
41829
|
+
if (witness.hookParents !== undefined)
|
|
41830
|
+
for (const row of array(witness.hookParents, 4096)) {
|
|
41831
|
+
requireBound(object4(row) && row.role === "reviewed-hook" && (row.installation === "remote-receipt" && Object.keys(row).length === 9 || row.installation === "local-marketplace" && Object.keys(row).length === 9));
|
|
41832
|
+
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");
|
|
41833
|
+
for (const key of ["pluginId", "namespace", "pluginParent", "installation"])
|
|
41834
|
+
text(row[key]);
|
|
41835
|
+
if (row.installation === "remote-receipt")
|
|
41836
|
+
text(row.remotePluginId);
|
|
41837
|
+
else {
|
|
41838
|
+
text(row.marketplaceSourcePath);
|
|
41839
|
+
requireBound(typeof row.marketplaceSha256 === "string" && /^[a-f0-9]{64}$/.test(row.marketplaceSha256) && isAbsolute10(row.marketplaceSourcePath) && resolve10(row.marketplaceSourcePath) === row.marketplaceSourcePath && basename7(row.marketplaceSourcePath) === "marketplace.json");
|
|
41840
|
+
}
|
|
41841
|
+
requireBound(isAbsolute10(row.pluginParent) && resolve10(row.pluginParent) === row.pluginParent);
|
|
41842
|
+
for (const key of ["manifestSha256", "hooksSha256"])
|
|
41843
|
+
requireBound(typeof row[key] === "string" && /^[a-f0-9]{64}$/.test(row[key]));
|
|
41844
|
+
if (row.installation === "remote-receipt")
|
|
41845
|
+
requireBound(typeof row.receiptSha256 === "string" && /^[a-f0-9]{64}$/.test(row.receiptSha256));
|
|
41846
|
+
else
|
|
41847
|
+
requireBound(row.receiptSha256 === undefined);
|
|
41848
|
+
}
|
|
41635
41849
|
for (const skill of array(witness.skills, 4096)) {
|
|
41636
41850
|
requireBound(object4(skill));
|
|
41637
41851
|
for (const key of ["name", "pluginId", "namespace", "pluginParent"])
|
|
@@ -41661,13 +41875,13 @@ function assertAgentPolicyCollections(policy) {
|
|
|
41661
41875
|
if (source.hashMode === "claude-plugin-manifest-v1")
|
|
41662
41876
|
requireBound(agent === "claude" && value.agent === "claude" && ["automatic", "reviewed"].includes(value.method) && !/[\x00-\x1f\x7f]/.test(source.path) && isAbsolute10(source.path) && resolve10(source.path) === source.path && source.path.endsWith(join16(sep6, ".claude-plugin", "plugin.json")) && source.managedPlugins === undefined);
|
|
41663
41877
|
if (source.hashMode === "sumi-settings-v1")
|
|
41664
|
-
requireBound(agent === "sumi" && value.agent === "sumi" && value.method === "reviewed" && !/[\x00-\x1f\x7f]/.test(source.path) && isAbsolute10(source.path) && resolve10(source.path) === source.path &&
|
|
41878
|
+
requireBound(agent === "sumi" && value.agent === "sumi" && value.method === "reviewed" && !/[\x00-\x1f\x7f]/.test(source.path) && isAbsolute10(source.path) && resolve10(source.path) === source.path && basename7(source.path) === "sumi.json");
|
|
41665
41879
|
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"))
|
|
41666
|
-
requireBound(agent === "codex" && value.agent === "codex" && value.method === "reviewed" && !/[\x00-\x1f\x7f]/.test(source.path) && isAbsolute10(source.path) && resolve10(source.path) === source.path &&
|
|
41880
|
+
requireBound(agent === "codex" && value.agent === "codex" && value.method === "reviewed" && !/[\x00-\x1f\x7f]/.test(source.path) && isAbsolute10(source.path) && resolve10(source.path) === source.path && basename7(source.path) === "config.toml");
|
|
41667
41881
|
if (source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || (source.hashMode === "claude-settings-v3" || source.hashMode === "claude-settings-v4"))
|
|
41668
|
-
requireBound(agent === "claude" && value.agent === "claude" && value.method === "reviewed" && !/[\x00-\x1f\x7f]/.test(source.path) && isAbsolute10(source.path) && resolve10(source.path) === source.path &&
|
|
41882
|
+
requireBound(agent === "claude" && value.agent === "claude" && value.method === "reviewed" && !/[\x00-\x1f\x7f]/.test(source.path) && isAbsolute10(source.path) && resolve10(source.path) === source.path && basename7(source.path) === "settings.json");
|
|
41669
41883
|
if (source.hashMode === "claude-marketplace-registry" || source.hashMode === "claude-marketplace-registry-v2")
|
|
41670
|
-
requireBound(agent === "claude" && value.agent === "claude" && value.method === "reviewed" && !/[\x00-\x1f\x7f]/.test(source.path) && isAbsolute10(source.path) && resolve10(source.path) === source.path &&
|
|
41884
|
+
requireBound(agent === "claude" && value.agent === "claude" && value.method === "reviewed" && !/[\x00-\x1f\x7f]/.test(source.path) && isAbsolute10(source.path) && resolve10(source.path) === source.path && basename7(source.path) === "known_marketplaces.json");
|
|
41671
41885
|
if (source.hashMode === "claude-marketplace-entry-v1")
|
|
41672
41886
|
requireBound(agent === "claude" && value.agent === "claude" && value.method === "reviewed" && claudeMarketplaceEntrySourceValid(source));
|
|
41673
41887
|
if (source.hashMode === "claude-plugin-registry") {
|
|
@@ -41832,7 +42046,7 @@ function isOwnedCliBridge(path, expectedPaths) {
|
|
|
41832
42046
|
// src/lib/agent-discovery.ts
|
|
41833
42047
|
import { createHash as createHash26 } from "crypto";
|
|
41834
42048
|
import { lstatSync as lstatSync24, readFileSync as readFileSync16, readdirSync as readdirSync8, realpathSync as realpathSync11 } from "fs";
|
|
41835
|
-
import { basename as
|
|
42049
|
+
import { basename as basename10, dirname as dirname20, isAbsolute as isAbsolute23, join as join29, relative as relative7, resolve as resolve22, sep as sep9 } from "path";
|
|
41836
42050
|
import { isDeepStrictEqual as isDeepStrictEqual6 } from "util";
|
|
41837
42051
|
|
|
41838
42052
|
// node_modules/yaml/dist/index.js
|
|
@@ -42523,7 +42737,7 @@ function projectReviewedClaudePluginManifest(text2, reviewedSha256) {
|
|
|
42523
42737
|
|
|
42524
42738
|
// src/lib/plugin-discovery.ts
|
|
42525
42739
|
import { closeSync as closeSync16, constants as constants13, fstatSync as fstatSync16, lstatSync as lstatSync19, openSync as openSync16, opendirSync as opendirSync4, readSync as readSync10 } from "fs";
|
|
42526
|
-
import { basename as
|
|
42740
|
+
import { basename as basename8, dirname as dirname16, isAbsolute as isAbsolute18, join as join26, resolve as resolve17 } from "path";
|
|
42527
42741
|
|
|
42528
42742
|
// src/lib/plugin-admission.ts
|
|
42529
42743
|
import { homedir as homedir2 } from "os";
|
|
@@ -44004,7 +44218,7 @@ function hashManagedPluginRegistry(path, managed) {
|
|
|
44004
44218
|
pluginNeed(/^(?:[A-Za-z0-9][A-Za-z0-9._+-]*-)?[a-f0-9]{12}$/.test(row.version) && row.installPath === join26(cacheRoot, row.version), "Managed plugin cache path or version is outside its registration");
|
|
44005
44219
|
const approval = (producer) => {
|
|
44006
44220
|
pluginText(producer);
|
|
44007
|
-
const digest3 = `sha256:${
|
|
44221
|
+
const digest3 = `sha256:${basename8(producer)}`;
|
|
44008
44222
|
const receipt2 = readPluginAdmissionReceipt(witness.storeRoot, witness.bindingId, digest3);
|
|
44009
44223
|
pluginNeed(receipt2.materializedPath === producer, "Managed producer path is not an approved immutable projection");
|
|
44010
44224
|
if (!verified.has(producer)) {
|
|
@@ -44068,7 +44282,7 @@ function captureManagedPluginRegistry(path, managedPlugins) {
|
|
|
44068
44282
|
// src/lib/claude-marketplace-registry.ts
|
|
44069
44283
|
import { createHash as createHash22 } from "crypto";
|
|
44070
44284
|
import { closeSync as closeSync17, constants as constants14, fstatSync as fstatSync17, lstatSync as lstatSync20, openSync as openSync17, readSync as readSync11 } from "fs";
|
|
44071
|
-
import { basename as
|
|
44285
|
+
import { basename as basename9, dirname as dirname17, isAbsolute as isAbsolute19, resolve as resolve18 } from "path";
|
|
44072
44286
|
var CLAUDE_MARKETPLACE_REGISTRY_LIMITS = Object.freeze({ bytes: 1024 * 1024, rows: 1024, depth: 32, nodes: 65536, stringCharacters: 16384, pathCharacters: 4096 });
|
|
44073
44287
|
function need6(value, reason2) {
|
|
44074
44288
|
if (!value)
|
|
@@ -44090,7 +44304,7 @@ function parents2(path) {
|
|
|
44090
44304
|
}
|
|
44091
44305
|
function readRegistry2(path, budget2) {
|
|
44092
44306
|
absolutePath3(path);
|
|
44093
|
-
need6(
|
|
44307
|
+
need6(basename9(path) === "known_marketplaces.json", "requires known_marketplaces.json");
|
|
44094
44308
|
need6(Number.isSafeInteger(budget2.remaining) && budget2.remaining >= 0, "has an invalid byte budget");
|
|
44095
44309
|
const ancestors2 = parents2(path), initial = lstatSync20(path, { bigint: true });
|
|
44096
44310
|
need6(initial.isFile() && !initial.isSymbolicLink() && initial.size <= BigInt(CLAUDE_MARKETPLACE_REGISTRY_LIMITS.bytes), "is not a bounded regular file");
|
|
@@ -44914,7 +45128,7 @@ function assertReviewedClaudeCacheClosures(home, config, review, canonical9) {
|
|
|
44914
45128
|
throw new Error("Reviewed Claude enabled plugin registration requires an object with an installPath string");
|
|
44915
45129
|
}
|
|
44916
45130
|
if ([cacheAliasRoot, cacheRoot].some((root2) => row.installPath === root2 || row.installPath.startsWith(root2 + sep9))) {
|
|
44917
|
-
if (!cachePath(row.installPath) || row.installPath.length > AGENT_POLICY_LIMITS.pathCharacters || row.version !== undefined && (typeof row.version !== "string" ||
|
|
45131
|
+
if (!cachePath(row.installPath) || row.installPath.length > AGENT_POLICY_LIMITS.pathCharacters || row.version !== undefined && (typeof row.version !== "string" || basename10(row.installPath) !== row.version)) {
|
|
44918
45132
|
throw new Error("Reviewed Claude discovery has a malformed active cache registration");
|
|
44919
45133
|
}
|
|
44920
45134
|
if (row.scope === "user" && (row.projectPath === undefined || row.projectPath === null)) {} else if (row.scope === "project" && typeof row.projectPath === "string" && isAbsolute23(row.projectPath) && resolve22(row.projectPath) === row.projectPath && row.projectPath.length <= AGENT_POLICY_LIMITS.pathCharacters) {} else
|
|
@@ -45192,7 +45406,7 @@ function absentRetiredClaudeRoots(binding) {
|
|
|
45192
45406
|
if (!targetValid || !targetScopes.has("user\x00"))
|
|
45193
45407
|
continue;
|
|
45194
45408
|
const active = rows[0]?.installPath;
|
|
45195
|
-
if (typeof active !== "string" || rows[0]?.version !==
|
|
45409
|
+
if (typeof active !== "string" || rows[0]?.version !== basename10(active) || dirname20(active) !== dirname20(root2) || active === root2 || !lstatSync24(active, { throwIfNoEntry: false })?.isDirectory() || realpathSync11(active) !== active)
|
|
45196
45410
|
continue;
|
|
45197
45411
|
const activeManifest = full(join29(active, ".claude-plugin/plugin.json"));
|
|
45198
45412
|
if (!activeManifest || projected(activeManifest) !== activeManifest.sha256)
|
|
@@ -45201,14 +45415,15 @@ function absentRetiredClaudeRoots(binding) {
|
|
|
45201
45415
|
}
|
|
45202
45416
|
return [...result];
|
|
45203
45417
|
}
|
|
45204
|
-
function codexSemanticCacheSourceRole(source, cacheRoot, parents3) {
|
|
45418
|
+
function codexSemanticCacheSourceRole(source, cacheRoot, parents3, hookParents = []) {
|
|
45205
45419
|
if (!isAbsolute23(source.path) || resolve22(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")
|
|
45206
45420
|
return false;
|
|
45207
45421
|
const parts = relative7(cacheRoot, source.path).split(sep9);
|
|
45208
45422
|
if (parts.length < 3 || !parents3.includes(join29(cacheRoot, parts[0], parts[1])))
|
|
45209
45423
|
return false;
|
|
45210
45424
|
const tail = parts.slice(3).join("/");
|
|
45211
|
-
|
|
45425
|
+
const parent = join29(cacheRoot, parts[0], parts[1]);
|
|
45426
|
+
return parts.length === 5 && tail === ".codex-plugin/plugin.json" && source.sha256 !== null || parts.length === 4 && [".app.json", ".mcp.json"].includes(tail) && source.sha256 !== null || parts.length === 5 && tail === "hooks/hooks.json" && hookParents.includes(parent) && source.sha256 !== null || source.sha256 === null && (parts.length === 4 && tail === "SKILL.md" || parts.length === 5 && tail === "hooks/hooks.json");
|
|
45212
45427
|
}
|
|
45213
45428
|
function codexSemanticCacheDirectoryRole(path, cacheRoot) {
|
|
45214
45429
|
return isAbsolute23(path) && resolve22(path) === path && !/[\x00-\x1f\x7f]/.test(path) && (path === cacheRoot || path.startsWith(cacheRoot + sep9));
|
|
@@ -45240,20 +45455,28 @@ function verifyCodexSemanticCacheDiscovery(binding, reviewedRootAliases) {
|
|
|
45240
45455
|
const cacheRoot = proof.witness.cacheRoot;
|
|
45241
45456
|
if (controls.some((control) => dirname20(dirname20(control.pluginParent)) !== cacheRoot))
|
|
45242
45457
|
throw new Error("Codex semantic cache names another enrolled cache");
|
|
45243
|
-
const
|
|
45244
|
-
|
|
45458
|
+
const reviewedHookParents = proof.reviewedHookParents ?? [];
|
|
45459
|
+
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 || !isDeepStrictEqual6((proof.witness.hookParents ?? []).map(({ manifestSha256: _manifest, hooksSha256: _hooks, receiptSha256: _receipt, ...parent }) => parent), reviewedHookParents)) {
|
|
45460
|
+
throw new Error("Invalid reviewed native-hook cache role");
|
|
45461
|
+
}
|
|
45462
|
+
for (const parent of reviewedHookParents)
|
|
45463
|
+
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")))
|
|
45464
|
+
throw new Error("Local marketplace hook parent lost its enrolled source witness");
|
|
45465
|
+
const parents3 = [...new Set([...controls.map((control) => control.pluginParent), ...proof.appOnlyParents.map((parent) => parent.pluginParent), ...reviewedHookParents.map((parent) => parent.pluginParent)])];
|
|
45466
|
+
const hookParentPaths = reviewedHookParents.map((parent) => parent.pluginParent);
|
|
45467
|
+
const sources = binding.sources.filter((source) => codexSemanticCacheSourceRole(source, cacheRoot, parents3, hookParentPaths));
|
|
45245
45468
|
const directories = (binding.directories ?? []).filter((directory) => codexSemanticCacheDirectoryRole(directory.path, cacheRoot));
|
|
45246
45469
|
if (!directories.length || !isDeepStrictEqual6(sources, proof.supersededSources) || !isDeepStrictEqual6(directories, proof.supersededDirectories))
|
|
45247
45470
|
throw new Error("Codex semantic cache provenance changed");
|
|
45248
45471
|
const configPath = proof.configPath;
|
|
45249
|
-
if (!isAbsolute23(configPath) || resolve22(configPath) !== configPath ||
|
|
45472
|
+
if (!isAbsolute23(configPath) || resolve22(configPath) !== configPath || basename10(configPath) !== "config.toml" || /[\x00-\x1f\x7f]/.test(configPath))
|
|
45250
45473
|
throw new Error("Invalid semantic cache configuration source");
|
|
45251
45474
|
const configSource = binding.sources.find((source) => source.path === configPath && source.sha256 !== null && source.format === undefined && source.fields === undefined);
|
|
45252
45475
|
if (!configSource || projected(configSource) !== configSource.sha256)
|
|
45253
45476
|
throw new Error("Codex semantic cache requires unchanged reviewed configuration");
|
|
45254
45477
|
assertCodexSemanticCacheHookSafety(cacheRoot, parents3, configPath, proof.hookRootAlias);
|
|
45255
45478
|
const rules = parseConfig(read2(configPath), configPath, true).skills?.config ?? [];
|
|
45256
|
-
const current = captureCodexSemanticCacheWitness({ cacheRoot, controls, appOnlyParents: proof.appOnlyParents, rules });
|
|
45479
|
+
const current = captureCodexSemanticCacheWitness({ cacheRoot, controls, appOnlyParents: proof.appOnlyParents, reviewedHookParents, rules });
|
|
45257
45480
|
assertCodexSemanticCacheWitnessUnchanged(proof.witness, current);
|
|
45258
45481
|
return proof;
|
|
45259
45482
|
}
|
|
@@ -45337,7 +45560,7 @@ function codexInstallationRoots(binding) {
|
|
|
45337
45560
|
const config = join29(dirname20(dirname20(cache)), "config.toml"), home = dirname20(dirname20(dirname20(cache)));
|
|
45338
45561
|
const configSource = binding.sources.find((source) => source.path === config && source.sha256 !== null && (!source.format || source.format === "toml" && source.fields?.includes("plugins")));
|
|
45339
45562
|
const nativeRoots = NATIVE_SKILL_ROOTS.filter(([agent]) => agent === "codex").map(([, path]) => join29(home, path));
|
|
45340
|
-
if (!configSource || proof.plugins.some((input) => nativeRoots.some((root2) => root2 === input.sourceRoot || root2.startsWith(input.sourceRoot + sep9) || input.sourceRoot.startsWith(root2 + sep9)) || binding.sources.some((source) =>
|
|
45563
|
+
if (!configSource || proof.plugins.some((input) => nativeRoots.some((root2) => root2 === input.sourceRoot || root2.startsWith(input.sourceRoot + sep9) || input.sourceRoot.startsWith(root2 + sep9)) || binding.sources.some((source) => basename10(source.path) === "config.toml" && (source.path === input.sourceRoot || source.path.startsWith(input.sourceRoot + sep9)))))
|
|
45341
45564
|
throw new Error("Native installation input overlaps configuration or loading roots");
|
|
45342
45565
|
if (proof.plugins.some((input) => dirname20(dirname20(input.pluginParent)) !== cache || !binding.sources.some((source) => source.path === join29(input.sourceRoot, ".codex-plugin/plugin.json") && source.sha256 !== null && source.format === undefined && source.fields === undefined)))
|
|
45343
45566
|
throw new Error("Missing native installation input source witness");
|
|
@@ -45349,13 +45572,13 @@ function codexInstallationRoots(binding) {
|
|
|
45349
45572
|
});
|
|
45350
45573
|
}
|
|
45351
45574
|
function assertMarketplaceBinding(binding, source) {
|
|
45352
|
-
if (source.hashMode === "claude-plugin-manifest-v1" && (binding.agent !== "claude" ||
|
|
45575
|
+
if (source.hashMode === "claude-plugin-manifest-v1" && (binding.agent !== "claude" || basename10(source.path) !== "plugin.json" || !source.path.endsWith(join29(sep9, ".claude-plugin", "plugin.json"))))
|
|
45353
45576
|
throw new Error("Claude plugin manifest witnesses require Claude plugin discovery");
|
|
45354
|
-
if (source.hashMode === "sumi-settings-v1" && (binding.agent !== "sumi" || binding.method !== "reviewed" ||
|
|
45577
|
+
if (source.hashMode === "sumi-settings-v1" && (binding.agent !== "sumi" || binding.method !== "reviewed" || basename10(source.path) !== "sumi.json"))
|
|
45355
45578
|
throw new Error("Sumi settings witnesses require explicit reviewed Sumi configuration");
|
|
45356
|
-
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" ||
|
|
45579
|
+
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" || basename10(source.path) !== "config.toml"))
|
|
45357
45580
|
throw new Error("Codex settings witnesses require explicit reviewed Codex configuration");
|
|
45358
|
-
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" ||
|
|
45581
|
+
if ((source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || (source.hashMode === "claude-settings-v3" || source.hashMode === "claude-settings-v4")) && (binding.agent !== "claude" || binding.method !== "reviewed" || basename10(source.path) !== "settings.json"))
|
|
45359
45582
|
throw new Error("Claude settings witnesses require explicit reviewed Claude configuration");
|
|
45360
45583
|
if ((source.hashMode === "claude-marketplace-registry" || source.hashMode === "claude-marketplace-registry-v2") && (binding.agent !== "claude" || binding.method !== "reviewed"))
|
|
45361
45584
|
throw new Error("Claude marketplace witnesses require explicit reviewed Claude discovery");
|
|
@@ -45473,7 +45696,7 @@ function verifyAutomaticDiscoveryClosure(binding, options) {
|
|
|
45473
45696
|
const current = resolveAgentDiscovery({ home: options.home, agent: binding.agent, canonical: options.canonical, executable: runtime });
|
|
45474
45697
|
if (JSON.stringify(current) === JSON.stringify(binding))
|
|
45475
45698
|
return;
|
|
45476
|
-
const reviewedWithRuntime = (binding.builtinNames?.length ?? 0) > 0 || binding.sources.some((source) =>
|
|
45699
|
+
const reviewedWithRuntime = (binding.builtinNames?.length ?? 0) > 0 || binding.sources.some((source) => basename10(source.path) === "package.json");
|
|
45477
45700
|
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) => isDeepStrictEqual6(saved, source)));
|
|
45478
45701
|
if (command && gap && runtime === null && reviewedWithRuntime && otherwiseCurrent)
|
|
45479
45702
|
throw discoveryRootUnresolved(binding.agent, command, gap);
|
|
@@ -45616,7 +45839,7 @@ function resolveAgentDiscovery(options) {
|
|
|
45616
45839
|
throw new Error("Discovery review must include the agent configuration source");
|
|
45617
45840
|
const reviewedSources = supersedesSettingsProjection(agent, review.sources, canonical9(configPath)) ? sources.filter((source) => !isSupersededSettingsProjection(agent, canonical9(configPath), source)) : sources;
|
|
45618
45841
|
const reviewedSourcesWithManifestProjection = review.sources.map((source) => {
|
|
45619
|
-
if (agent !== "claude" || source.sha256 === null || source.format !== undefined || source.fields !== undefined || source.managedPlugins !== undefined || source.hashMode !== undefined && source.hashMode !== "bytes" ||
|
|
45842
|
+
if (agent !== "claude" || source.sha256 === null || source.format !== undefined || source.fields !== undefined || source.managedPlugins !== undefined || source.hashMode !== undefined && source.hashMode !== "bytes" || basename10(source.path) !== "plugin.json" || !source.path.endsWith(join29(sep9, ".claude-plugin", "plugin.json")))
|
|
45620
45843
|
return source;
|
|
45621
45844
|
const pluginRoot = dirname20(dirname20(source.path)), hooksPath = join29(pluginRoot, "hooks/hooks.json");
|
|
45622
45845
|
const hookStat = lstatSync24(hooksPath, { throwIfNoEntry: false });
|
|
@@ -47524,7 +47747,7 @@ function planAgentSettingsWitnessUpgrade(options) {
|
|
|
47524
47747
|
return { dataDir: dataDir2, profileId: policy.profileId, changes: [{ path: join30(dataDir2, "agent-policy.json"), before: snapshot2.text, after }], nativeSkills: [], observedPolicy: { path: join30(dataDir2, "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 })) } };
|
|
47525
47748
|
}
|
|
47526
47749
|
function planCodexSemanticCacheWitnessUpgrade(options) {
|
|
47527
|
-
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)
|
|
47750
|
+
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))
|
|
47528
47751
|
throw new Error("Invalid Codex semantic cache upgrade request");
|
|
47529
47752
|
const home = resolve23(options.home ?? homedir3()), dataDir2 = options.dataDir ?? getDataDirReadOnly();
|
|
47530
47753
|
const snapshot2 = readManagedSkillPolicySnapshot(dataDir2);
|
|
@@ -47548,14 +47771,23 @@ function planCodexSemanticCacheWitnessUpgrade(options) {
|
|
|
47548
47771
|
throw new Error("Native settings preimage changed");
|
|
47549
47772
|
const boundedRead = (path) => new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(readNativeBytes(path, 1024 * 1024));
|
|
47550
47773
|
const unchangedFullSource = (path) => {
|
|
47551
|
-
const
|
|
47552
|
-
if (
|
|
47553
|
-
throw new Error("Cache upgrade
|
|
47774
|
+
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"));
|
|
47775
|
+
if (sources.length !== 1)
|
|
47776
|
+
throw new Error("Cache upgrade requires one unambiguous prior full identity source");
|
|
47777
|
+
const source = sources[0];
|
|
47554
47778
|
const text2 = boundedRead(path);
|
|
47555
47779
|
if (sha5(text2) !== source.sha256)
|
|
47556
47780
|
throw new Error("Reviewed cache identity source changed");
|
|
47557
47781
|
return text2;
|
|
47558
47782
|
};
|
|
47783
|
+
const unchangedReviewedHookSource = (path) => {
|
|
47784
|
+
const sources = binding.sources.filter((source) => source.path === path);
|
|
47785
|
+
if (!sources.length)
|
|
47786
|
+
throw new Error("Cache upgrade lacks prior full identity source");
|
|
47787
|
+
if (sources.length !== 1)
|
|
47788
|
+
throw new Error("Reviewed hook identity source is ambiguous");
|
|
47789
|
+
return unchangedFullSource(path);
|
|
47790
|
+
};
|
|
47559
47791
|
const appOnlyParents = options.appOnlyParents.map((parent) => {
|
|
47560
47792
|
const parts = relative8(cacheRoot, parent).split(sep10);
|
|
47561
47793
|
if (!isAbsolute25(parent) || resolve23(parent) !== parent || parts.length !== 2 || parts.some((part) => !/^[A-Za-z0-9_-]{1,64}$/.test(part)) || controls.some((control) => control.pluginParent === parent))
|
|
@@ -47570,11 +47802,60 @@ function planCodexSemanticCacheWitnessUpgrade(options) {
|
|
|
47570
47802
|
unchangedFullSource(source.path);
|
|
47571
47803
|
return { role: "app-only", pluginId: `${parts[1]}@${parts[0]}`, namespace: parts[1], pluginParent: parent, remotePluginId: receipt.remote_plugin_id };
|
|
47572
47804
|
}).sort((a, b) => a.pluginParent.localeCompare(b.pluginParent));
|
|
47573
|
-
const
|
|
47805
|
+
const reviewedHookParents = (options.reviewedHookParents ?? []).map((parent) => {
|
|
47806
|
+
const parts = relative8(cacheRoot, parent).split(sep10);
|
|
47807
|
+
if (!isAbsolute25(parent) || resolve23(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))
|
|
47808
|
+
throw new Error("Unsupported reviewed native-hook parent role");
|
|
47809
|
+
const receiptPath = join30(parent, ".codex-remote-plugin-install.json"), receiptStat = lstatSync26(receiptPath, { throwIfNoEntry: false });
|
|
47810
|
+
let identity5;
|
|
47811
|
+
if (receiptStat) {
|
|
47812
|
+
if (!receiptStat.isFile() || receiptStat.isSymbolicLink() || receiptStat.size > 16 * 1024)
|
|
47813
|
+
throw new Error("Invalid reviewed native-hook install receipt");
|
|
47814
|
+
const receiptText = unchangedReviewedHookSource(receiptPath);
|
|
47815
|
+
let receipt;
|
|
47816
|
+
try {
|
|
47817
|
+
hashNativeJsonControls(receiptText);
|
|
47818
|
+
receipt = JSON.parse(receiptText);
|
|
47819
|
+
} catch {
|
|
47820
|
+
throw new Error("Invalid reviewed native-hook install receipt");
|
|
47821
|
+
}
|
|
47822
|
+
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))
|
|
47823
|
+
throw new Error("Invalid reviewed native-hook install receipt");
|
|
47824
|
+
identity5 = { role: "reviewed-hook", pluginId: `${parts[1]}@${parts[0]}`, namespace: parts[1], pluginParent: parent, installation: "remote-receipt", remotePluginId: receipt.remote_plugin_id };
|
|
47825
|
+
} else {
|
|
47826
|
+
const pluginId2 = `${parts[1]}@${parts[0]}`;
|
|
47827
|
+
const marketplaceSources = binding.sources.filter((source2) => basename11(source2.path) === "marketplace.json" && source2.sha256 !== null && source2.format === undefined && source2.fields === undefined && source2.reviewArtifact === undefined && (source2.hashMode === undefined || source2.hashMode === "bytes"));
|
|
47828
|
+
const matches = marketplaceSources.flatMap((source2) => {
|
|
47829
|
+
const text2 = unchangedFullSource(source2.path);
|
|
47830
|
+
return codexLocalMarketplaceMapsPlugin(text2, parts[0], parts[1]) ? [{ source: source2, text: text2 }] : [];
|
|
47831
|
+
});
|
|
47832
|
+
if (matches.length !== 1)
|
|
47833
|
+
throw new Error("Local marketplace hook parent lacks one exact enrolled marketplace source");
|
|
47834
|
+
const { source } = matches[0];
|
|
47835
|
+
const config = Bun.TOML.parse(settings);
|
|
47836
|
+
if (config.plugins?.[pluginId2]?.enabled !== true)
|
|
47837
|
+
throw new Error("Local marketplace hook parent is not enabled in the unchanged Codex settings");
|
|
47838
|
+
identity5 = { role: "reviewed-hook", pluginId: pluginId2, namespace: parts[1], pluginParent: parent, installation: "local-marketplace", marketplaceSourcePath: source.path, marketplaceSha256: source.sha256 };
|
|
47839
|
+
}
|
|
47840
|
+
const versions = readdirSync9(parent).filter((name) => name !== ".codex-remote-plugin-install.json");
|
|
47841
|
+
if (!versions.length || versions.length > 4096)
|
|
47842
|
+
throw new Error("Reviewed native-hook parent has no bounded materializations");
|
|
47843
|
+
for (const version2 of versions) {
|
|
47844
|
+
if (!/^[A-Za-z0-9][A-Za-z0-9._+-]{0,127}$/.test(version2))
|
|
47845
|
+
throw new Error("Invalid reviewed native-hook version identity");
|
|
47846
|
+
const root2 = join30(parent, version2), stat2 = lstatSync26(root2, { throwIfNoEntry: false });
|
|
47847
|
+
if (!stat2?.isDirectory() || stat2.isSymbolicLink() || realpathSync13(root2) !== root2)
|
|
47848
|
+
throw new Error("Invalid reviewed native-hook materialization");
|
|
47849
|
+
unchangedReviewedHookSource(join30(root2, ".codex-plugin/plugin.json"));
|
|
47850
|
+
unchangedReviewedHookSource(join30(root2, "hooks/hooks.json"));
|
|
47851
|
+
}
|
|
47852
|
+
return identity5;
|
|
47853
|
+
}).sort((a, b) => a.pluginParent.localeCompare(b.pluginParent));
|
|
47854
|
+
const parents3 = [...new Set([...controls.map((control) => control.pluginParent), ...appOnlyParents.map((parent) => parent.pluginParent), ...reviewedHookParents.map((parent) => parent.pluginParent)])];
|
|
47574
47855
|
const reviewedAlias = aliases.find((alias) => alias.agent === "codex");
|
|
47575
47856
|
const hookRootAlias = reviewedAlias ? { alias: reviewedAlias.alias, target: reviewedAlias.target } : null;
|
|
47576
47857
|
assertCodexSemanticCacheHookSafety(cacheRoot, parents3, configPath, hookRootAlias);
|
|
47577
|
-
const supersededSources = binding.sources.filter((source) => codexSemanticCacheSourceRole(source, cacheRoot, parents3));
|
|
47858
|
+
const supersededSources = binding.sources.filter((source) => codexSemanticCacheSourceRole(source, cacheRoot, parents3, reviewedHookParents.map((parent) => parent.pluginParent)));
|
|
47578
47859
|
for (const source of supersededSources)
|
|
47579
47860
|
if ([".app.json", ".mcp.json"].includes(source.path.split(sep10).at(-1)))
|
|
47580
47861
|
unchangedFullSource(source.path);
|
|
@@ -47582,7 +47863,7 @@ function planCodexSemanticCacheWitnessUpgrade(options) {
|
|
|
47582
47863
|
if (!supersededDirectories.some((directory) => directory.path === cacheRoot) || (binding.directories ?? []).some((directory) => cacheRoot.startsWith(directory.path + sep10)))
|
|
47583
47864
|
throw new Error("Cache upgrade requires exact cache directory coverage without an unproved ancestor projection");
|
|
47584
47865
|
const rules = Bun.TOML.parse(settings).skills?.config ?? [];
|
|
47585
|
-
const witness = captureCodexSemanticCacheWitness({ cacheRoot, controls, appOnlyParents, rules, read: boundedRead });
|
|
47866
|
+
const witness = captureCodexSemanticCacheWitness({ cacheRoot, controls, appOnlyParents, reviewedHookParents, rules, read: boundedRead });
|
|
47586
47867
|
if (options.expectedCacheWitnessSha256 !== undefined && witness.sha256 !== options.expectedCacheWitnessSha256)
|
|
47587
47868
|
throw new Error("Reviewed semantic cache preimage changed");
|
|
47588
47869
|
const replacement = { ...binding, codexDisabledPluginSkills: controls, codexSemanticCache: {
|
|
@@ -47591,6 +47872,7 @@ function planCodexSemanticCacheWitnessUpgrade(options) {
|
|
|
47591
47872
|
hookRootAlias,
|
|
47592
47873
|
witness,
|
|
47593
47874
|
appOnlyParents,
|
|
47875
|
+
reviewedHookParents,
|
|
47594
47876
|
previousPolicySha256: options.expectedPolicySha256,
|
|
47595
47877
|
supersededSources,
|
|
47596
47878
|
supersededDirectories
|
|
@@ -47609,7 +47891,7 @@ function planCodexSemanticCacheWitnessUpgrade(options) {
|
|
|
47609
47891
|
rootAliases: aliases,
|
|
47610
47892
|
managedAgentChecks: { home, agents: ["codex"] },
|
|
47611
47893
|
...policy.bridge.discoveryExecutables ? { discoveryExecutables: policy.bridge.discoveryExecutables } : {},
|
|
47612
|
-
cacheWitnessUpgrade: { ...options, home, dataDir: dataDir2, appOnlyParents: appOnlyParents.map((parent) => parent.pluginParent) }
|
|
47894
|
+
cacheWitnessUpgrade: { ...options, home, dataDir: dataDir2, appOnlyParents: appOnlyParents.map((parent) => parent.pluginParent), reviewedHookParents: reviewedHookParents.map((parent) => parent.pluginParent) }
|
|
47613
47895
|
};
|
|
47614
47896
|
}
|
|
47615
47897
|
function planReviewedArtifactMigration(options) {
|
|
@@ -48148,7 +48430,7 @@ import {
|
|
|
48148
48430
|
statSync as statSync11,
|
|
48149
48431
|
writeFileSync as writeFileSync7
|
|
48150
48432
|
} from "fs";
|
|
48151
|
-
import { basename as
|
|
48433
|
+
import { basename as basename14, dirname as dirname24, isAbsolute as isAbsolute26, join as join34, normalize as normalize4, relative as relative10, resolve as resolve25, sep as sep13 } from "path";
|
|
48152
48434
|
|
|
48153
48435
|
// src/lib/registry-data/index.ts
|
|
48154
48436
|
var SKILLS = [];
|
|
@@ -48673,7 +48955,7 @@ import {
|
|
|
48673
48955
|
realpathSync as realpathSync14,
|
|
48674
48956
|
writeFileSync as writeFileSync6
|
|
48675
48957
|
} from "fs";
|
|
48676
|
-
import { basename as
|
|
48958
|
+
import { basename as basename12, dirname as dirname22, join as join32, relative as relative9 } from "path";
|
|
48677
48959
|
var ANY_SEGMENT_COPY_EXCLUDES = new Set([
|
|
48678
48960
|
".git",
|
|
48679
48961
|
".DS_Store",
|
|
@@ -48723,11 +49005,11 @@ function normalizeNewPortableSkillName(name) {
|
|
|
48723
49005
|
throw new Error(`Invalid skill name '${name}'. Include letters or numbers.`);
|
|
48724
49006
|
return normalized;
|
|
48725
49007
|
}
|
|
48726
|
-
function readPortableSkillManifest(skillPath, fallbackName =
|
|
49008
|
+
function readPortableSkillManifest(skillPath, fallbackName = basename12(skillPath)) {
|
|
48727
49009
|
return readManifest(skillPath, fallbackName, normalizePortableSkillName);
|
|
48728
49010
|
}
|
|
48729
49011
|
function readPortableSkillManifestForImport(skillPath) {
|
|
48730
|
-
return readManifest(skillPath,
|
|
49012
|
+
return readManifest(skillPath, basename12(skillPath), normalizeNewPortableSkillName);
|
|
48731
49013
|
}
|
|
48732
49014
|
function readManifest(skillPath, fallbackName, normalizeName) {
|
|
48733
49015
|
const skillJsonPath = join32(skillPath, "skill.json");
|
|
@@ -49281,7 +49563,7 @@ function inferRuntimeFromCommands(commands) {
|
|
|
49281
49563
|
function readJsonObject(path) {
|
|
49282
49564
|
const parsed = JSON.parse(readFileSync20(path, "utf-8"));
|
|
49283
49565
|
if (!isRecord3(parsed))
|
|
49284
|
-
throw new Error(`${
|
|
49566
|
+
throw new Error(`${basename12(path)} must contain a JSON object`);
|
|
49285
49567
|
return parsed;
|
|
49286
49568
|
}
|
|
49287
49569
|
function hasPackageDependencies(pkgPath) {
|
|
@@ -49319,7 +49601,7 @@ function escapeJsString(value) {
|
|
|
49319
49601
|
// src/lib/authoring-path.ts
|
|
49320
49602
|
import { lstatSync as lstatSync28, realpathSync as realpathSync15 } from "fs";
|
|
49321
49603
|
import { homedir as homedir4 } from "os";
|
|
49322
|
-
import { basename as
|
|
49604
|
+
import { basename as basename13, dirname as dirname23, join as join33, resolve as resolve24, sep as sep12 } from "path";
|
|
49323
49605
|
var NATIVE_DISCOVERY_ROOTS = NATIVE_SKILL_ROOTS.map(([, path]) => path.split("/"));
|
|
49324
49606
|
function pathParts(path) {
|
|
49325
49607
|
return resolve24(path).split(sep12).filter(Boolean);
|
|
@@ -49339,7 +49621,7 @@ function physicalPath(path) {
|
|
|
49339
49621
|
let cursor = resolve24(path);
|
|
49340
49622
|
const suffix = [];
|
|
49341
49623
|
while (!lstatSync28(cursor, { throwIfNoEntry: false })) {
|
|
49342
|
-
suffix.unshift(
|
|
49624
|
+
suffix.unshift(basename13(cursor));
|
|
49343
49625
|
const parent = dirname23(cursor);
|
|
49344
49626
|
if (parent === cursor)
|
|
49345
49627
|
return resolve24(path);
|
|
@@ -49558,7 +49840,7 @@ function physicalImportPath(path) {
|
|
|
49558
49840
|
let ancestor = resolve25(path);
|
|
49559
49841
|
const suffix = [];
|
|
49560
49842
|
while (!existsSync10(ancestor)) {
|
|
49561
|
-
suffix.unshift(
|
|
49843
|
+
suffix.unshift(basename14(ancestor));
|
|
49562
49844
|
ancestor = dirname24(ancestor);
|
|
49563
49845
|
}
|
|
49564
49846
|
return join34(realpathSync16(ancestor), ...suffix);
|
|
@@ -49583,8 +49865,8 @@ function portPortableSkill(sourcePath, options = {}) {
|
|
|
49583
49865
|
const explicitName = options.name != null;
|
|
49584
49866
|
const skillName = normalizeNewPortableSkillName(options.name ?? inferred.name);
|
|
49585
49867
|
if (isOfficialSkillName(skillName) && !options.allowShadow) {
|
|
49586
|
-
const sourceSlug = safeNormalizeName(
|
|
49587
|
-
const via = explicitName ? `Name '${skillName}' matches a bundled official skill.` : `Inferred name '${skillName}'${sourceSlug && sourceSlug !== skillName ? ` (from source folder '${
|
|
49868
|
+
const sourceSlug = safeNormalizeName(basename14(absoluteSource));
|
|
49869
|
+
const via = explicitName ? `Name '${skillName}' matches a bundled official skill.` : `Inferred name '${skillName}'${sourceSlug && sourceSlug !== skillName ? ` (from source folder '${basename14(absoluteSource)}')` : ""} matches a bundled official skill.`;
|
|
49588
49870
|
throw new Error(`${via} Importing it would shadow the official '${skillName}'. ` + `Pass --name to choose a different name, or --allow-shadow to override deliberately.`);
|
|
49589
49871
|
}
|
|
49590
49872
|
const readOnlyDestination = join34(resolvePortableSkillsRoot(options, false), skillName);
|
|
@@ -50112,7 +50394,7 @@ function writeManagedSkillDirUnlocked(dir, skillMd, options, assertCurrent) {
|
|
|
50112
50394
|
return { action, path: skillMdPath };
|
|
50113
50395
|
const parentDir = dirname25(dir);
|
|
50114
50396
|
mkdirSync10(parentDir, { recursive: true });
|
|
50115
|
-
const transactionDir = mkdtempSync2(join35(parentDir, `.hasna-skills-write-${
|
|
50397
|
+
const transactionDir = mkdtempSync2(join35(parentDir, `.hasna-skills-write-${basename15(dir)}-`));
|
|
50116
50398
|
const candidateDir = join35(transactionDir, "candidate");
|
|
50117
50399
|
const backupDir = join35(transactionDir, "backup");
|
|
50118
50400
|
const candidateSkillMdPath = join35(candidateDir, "SKILL.md");
|
|
@@ -51274,9 +51556,7 @@ var GENERIC_ENV_PATTERN = /\b((?:OPENAI|ANTHROPIC|GEMINI|XAI|ELEVENLABS|DEEPGRAM
|
|
|
51274
51556
|
function extractEnvVars(text2) {
|
|
51275
51557
|
const envVars = new Set;
|
|
51276
51558
|
for (const pattern of [ENV_VAR_PATTERN, GENERIC_ENV_PATTERN]) {
|
|
51277
|
-
pattern
|
|
51278
|
-
let match;
|
|
51279
|
-
while ((match = pattern.exec(text2)) !== null) {
|
|
51559
|
+
for (const match of text2.matchAll(pattern)) {
|
|
51280
51560
|
envVars.add(match[1]);
|
|
51281
51561
|
}
|
|
51282
51562
|
}
|
|
@@ -97444,6 +97724,7 @@ export {
|
|
|
97444
97724
|
inspectSkillSession,
|
|
97445
97725
|
inspectSkillBundle,
|
|
97446
97726
|
inspectPrivatePublication,
|
|
97727
|
+
getSkillRequirementsFromContent,
|
|
97447
97728
|
getServerSkillMd,
|
|
97448
97729
|
getServerSkill,
|
|
97449
97730
|
expiresAtFor,
|