@hasna/skills 0.10.91 → 0.10.92

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.
@@ -1,6 +1,6 @@
1
1
  THIRD-PARTY SOFTWARE NOTICES
2
2
 
3
- @hasna/skills 0.10.91 bundles the 80 third-party packages below into its bin/ and dist/ files.
3
+ @hasna/skills 0.10.92 bundles the 80 third-party packages below into its bin/ and dist/ files.
4
4
  Each is listed with its licence and the licence and notice text it ships with.
5
5
 
6
6
  ================================================================================
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.91",
36891
+ version: "0.10.92",
36892
36892
  description: "Skills library for AI coding agents",
36893
36893
  type: "module",
36894
36894
  bin: {
@@ -65872,9 +65872,94 @@ function nativeDiscoveryAliasTargets(roots, home) {
65872
65872
  }
65873
65873
  return [...targets];
65874
65874
  }
65875
+ function hooksAreManagedBridge(agent, hooks, managed) {
65876
+ const table = (value) => Boolean(value && typeof value === "object" && !Array.isArray(value));
65877
+ const exactKeys4 = (value, keys3) => Object.keys(value).sort().join("\x00") === [...keys3].sort().join("\x00");
65878
+ if (!table(hooks) || typeof managed.command !== "string" || !isAbsolute30(managed.command))
65879
+ return false;
65880
+ const events3 = agent === "gemini" ? ["BeforeAgent", "SessionStart", "BeforeTool"] : ["beforeSubmitPrompt", "sessionStart"];
65881
+ for (const [event, entries] of Object.entries(hooks)) {
65882
+ if (!events3.includes(event) || !Array.isArray(entries) || entries.length !== 1)
65883
+ return false;
65884
+ let expected;
65885
+ try {
65886
+ expected = renderAgentHookCommand(managed.command, agent, managed.profile, event);
65887
+ } catch {
65888
+ return false;
65889
+ }
65890
+ const entry = entries[0];
65891
+ if (!table(entry))
65892
+ return false;
65893
+ if (agent === "cursor") {
65894
+ if (!exactKeys4(entry, ["command", "timeout"]) || entry.timeout !== 15 || entry.command !== expected)
65895
+ return false;
65896
+ continue;
65897
+ }
65898
+ if (!exactKeys4(entry, event === "BeforeTool" ? ["hooks", "matcher"] : ["hooks"]) || event === "BeforeTool" && entry.matcher !== "activate_skill" || !Array.isArray(entry.hooks) || entry.hooks.length !== 1)
65899
+ return false;
65900
+ const hook = entry.hooks[0];
65901
+ if (!table(hook) || !exactKeys4(hook, ["command", "timeout", "type"]) || hook.type !== "command" || hook.timeout !== 15000 || hook.command !== expected)
65902
+ return false;
65903
+ }
65904
+ return true;
65905
+ }
65906
+ function sumiPluginLoadsOnlyBuiltins(text3) {
65907
+ for (const match of text3.matchAll(/\b(?:import|require)\s*\(\s*(.?)/g)) {
65908
+ const rest2 = text3.slice(match.index + match[0].length - match[1].length);
65909
+ if (!/^(['"])node:[A-Za-z0-9_/.-]+\1/.test(rest2))
65910
+ return false;
65911
+ }
65912
+ for (const match of text3.matchAll(/\b(?:from|import)\s*(['"])([^'"]*)\1/g))
65913
+ if (!match[2].startsWith("node:"))
65914
+ return false;
65915
+ return true;
65916
+ }
65917
+ function codexRootFreeControls(config) {
65918
+ const table = (value) => Boolean(value && typeof value === "object" && !Array.isArray(value) && !(value instanceof Date));
65919
+ const adapted = [];
65920
+ const servers = config.mcp_servers;
65921
+ if (table(servers) && Object.keys(servers).length <= AGENT_POLICY_LIMITS.discoveryRoots && Object.entries(servers).every(([name, row]) => name !== "codex_apps" && name !== "_codex_apps" && isCodexLocalStdioMcpServer(name, row)))
65922
+ adapted.push("mcp_servers");
65923
+ const agents = config.agents;
65924
+ if (table(agents) && Object.keys(agents).length <= AGENT_POLICY_LIMITS.fields && Object.values(agents).every((value) => typeof value === "boolean" || typeof value === "number" && Number.isFinite(value)))
65925
+ adapted.push("agents");
65926
+ return adapted;
65927
+ }
65928
+ function codexPluginHookHandlers(value) {
65929
+ const table = (item) => Boolean(item && typeof item === "object" && !Array.isArray(item));
65930
+ const identifier6 = (item) => typeof item === "string" && /^[A-Za-z0-9_-]{1,64}$/.test(item);
65931
+ const text3 = (item) => typeof item === "string" && item.length <= AGENT_POLICY_LIMITS.pathCharacters && !item.includes("\x00");
65932
+ if (!table(value) || !Object.keys(value).every((key2) => key2 === "hooks" || key2 === "description") || value.description !== undefined && !text3(value.description) || !table(value.hooks) || Object.keys(value.hooks).length > 32)
65933
+ return null;
65934
+ const result2 = { commands: 0, servers: new Set };
65935
+ for (const [event, groups] of Object.entries(value.hooks)) {
65936
+ if (!CODEX_HOOK_EVENTS.has(event) || !Array.isArray(groups) || groups.length > 32)
65937
+ return null;
65938
+ for (const group of groups) {
65939
+ if (!table(group) || !Object.keys(group).every((key2) => key2 === "hooks" || key2 === "matcher") || group.matcher !== undefined && !text3(group.matcher) || !Array.isArray(group.hooks) || group.hooks.length > 32)
65940
+ return null;
65941
+ for (const handler of group.hooks) {
65942
+ if (!table(handler) || handler.timeout !== undefined && !(Number.isSafeInteger(handler.timeout) && handler.timeout >= 0) || handler.statusMessage !== undefined && !text3(handler.statusMessage))
65943
+ return null;
65944
+ if (handler.type === "command") {
65945
+ if (!text3(handler.command) || !handler.command || !Object.keys(handler).every((key2) => ["type", "command", "commandWindows", "command_windows", "timeout", "async", "statusMessage", "additionalContextLimit"].includes(key2)))
65946
+ return null;
65947
+ result2.commands++;
65948
+ } else if (handler.type === "mcp_tool") {
65949
+ if (!identifier6(handler.server) || !identifier6(handler.tool) || handler.input !== undefined && !table(handler.input) || !Object.keys(handler).every((key2) => ["type", "server", "tool", "input", "timeout", "statusMessage"].includes(key2)))
65950
+ return null;
65951
+ result2.servers.add(handler.server);
65952
+ } else
65953
+ return null;
65954
+ }
65955
+ }
65956
+ }
65957
+ return result2;
65958
+ }
65875
65959
  function resolveDiscovery(options, exclusion) {
65876
65960
  const canonical9 = options.canonical ?? resolve29, home = resolve29(options.home), agent = options.agent;
65877
65961
  const sources = [], roots = new Set, builtinNames = [];
65962
+ const sumiLocalPluginTexts = new Map;
65878
65963
  const budget3 = discoveryByteBudget();
65879
65964
  let remainingEntries = AGENT_POLICY_LIMITS.discoveryDirectoryEntries;
65880
65965
  const entries = (path) => {
@@ -65951,12 +66036,38 @@ function resolveDiscovery(options, exclusion) {
65951
66036
  const controls = agent === "claude" ? claudeDiscoveryControlKeys(configText ?? "{}") : agent === "codex" ? codexDiscoveryControlKeys(config) : Object.keys(config).filter((key2) => /skill|plugin|hook|marketplace|extension|instruction/i.test(key2));
65952
66037
  const fieldKey = (key2) => /^[A-Za-z_$][A-Za-z0-9_$.-]{0,22}$/.test(key2) && !/(?:sk|rk|pk)_(?:live|test)_|whsec_/i.test(key2) ? JSON.stringify(key2) : "[withheld field key]";
65953
66038
  const unsupportedFields = (names, label) => unresolved(`unknown discovery controls have no root-exclusion adapter for ${label}${names.slice(0, 8).map(fieldKey).join(", ")}${names.length > 8 ? ", additional keys withheld" : ""} in ${quotedPath(canonical9(configPath))}`);
65954
- const unsupportedControls = controls.filter((key2) => !supported[agent].includes(key2));
66039
+ const adapted = agent === "codex" ? codexRootFreeControls(config) : agent === "opencode" && Array.isArray(config.instructions) && config.instructions.length === 0 ? ["instructions"] : [];
66040
+ const unsupportedControls = controls.filter((key2) => !supported[agent].includes(key2) && !adapted.includes(key2));
65955
66041
  if (unsupportedControls.length)
65956
66042
  unsupportedFields(unsupportedControls, "");
65957
66043
  if (config.hooks !== undefined && !object6(config.hooks))
65958
66044
  unresolved("hooks must be an object");
65959
- const hasHooks = controls.includes("hooks") && config.hooks !== undefined && Object.keys(config.hooks).length > 0;
66045
+ const managedSupervisorOnly = () => {
66046
+ const supervisor = exclusion.managedHook?.supervisor;
66047
+ if (agent !== "hermes" || !supervisor || typeof supervisor.sha256 !== "string" || !/^[a-f0-9]{64}$/.test(supervisor.sha256) || !object6(config.hooks))
66048
+ return false;
66049
+ let expected;
66050
+ try {
66051
+ expected = hermesHookDefinitions(supervisor);
66052
+ } catch {
66053
+ return false;
66054
+ }
66055
+ for (const [event, entries2] of Object.entries(config.hooks)) {
66056
+ const want = expected[event];
66057
+ if (!want || !Array.isArray(entries2) || entries2.length !== 1 || !object6(entries2[0]))
66058
+ return false;
66059
+ const entry = entries2[0];
66060
+ if (Object.keys(entry).sort().join("\x00") !== Object.keys(want).sort().join("\x00") || Object.keys(want).some((key2) => entry[key2] !== want[key2]))
66061
+ return false;
66062
+ }
66063
+ try {
66064
+ return hashRawDiscoveryFile(canonical9(supervisor.path), budget3) === supervisor.sha256;
66065
+ } catch {
66066
+ return false;
66067
+ }
66068
+ };
66069
+ const managedBridgeOnly = (agent === "gemini" || agent === "cursor") && exclusion.managedHook !== undefined && hooksAreManagedBridge(agent, config.hooks, exclusion.managedHook) || managedSupervisorOnly();
66070
+ const hasHooks = controls.includes("hooks") && config.hooks !== undefined && Object.keys(config.hooks).length > 0 && !managedBridgeOnly;
65960
66071
  let hasPluginConfigs = false, hasFunctionHookEnvironment = false;
65961
66072
  const verifyCurrentOpaqueSettings = (label) => {
65962
66073
  const retained = exclusion.retained;
@@ -66061,7 +66172,9 @@ function resolveDiscovery(options, exclusion) {
66061
66172
  unresolved("malformed Sumi plugins");
66062
66173
  }
66063
66174
  if (agent === "hermes" && config.skills !== undefined) {
66064
- keys3(config.skills, ["external_dirs"], "Hermes skills");
66175
+ keys3(config.skills, ["external_dirs", "creation_nudge_interval"], "Hermes skills");
66176
+ if (config.skills.creation_nudge_interval !== undefined && !(Number.isSafeInteger(config.skills.creation_nudge_interval) && config.skills.creation_nudge_interval >= 0))
66177
+ unresolved("malformed Hermes skills creation_nudge_interval");
66065
66178
  if (config.skills.external_dirs !== undefined)
66066
66179
  paths(typeof config.skills.external_dirs === "string" ? [config.skills.external_dirs] : config.skills.external_dirs, "Hermes external directories");
66067
66180
  }
@@ -66081,10 +66194,21 @@ function resolveDiscovery(options, exclusion) {
66081
66194
  unresolved(`malformed Codex ${key2}`);
66082
66195
  for (const value of Object.values(config.plugins ?? {}))
66083
66196
  keys3(value, ["enabled"], "Codex plugin registration");
66084
- for (const value of Object.values(config.marketplaces ?? {}))
66085
- keys3(value, ["source_type", "source"], "Codex marketplace registration");
66197
+ for (const value of Object.values(config.marketplaces ?? {})) {
66198
+ keys3(value, ["source_type", "source", "last_updated"], "Codex marketplace registration");
66199
+ if (value.last_updated !== undefined && (typeof value.last_updated !== "string" || !CODEX_MARKETPLACE_TIMESTAMP.test(value.last_updated)))
66200
+ unresolved("malformed Codex marketplace refresh time");
66201
+ }
66086
66202
  if (config.skills !== undefined)
66087
- keys3(config.skills, ["config", "bundled"], "Codex skills");
66203
+ keys3(config.skills, ["config", "bundled", "native_allowed_paths"], "Codex skills");
66204
+ if (config.skills?.native_allowed_paths !== undefined) {
66205
+ for (const value of paths(config.skills.native_allowed_paths, "Codex native allowed skill paths")) {
66206
+ if (!isAbsolute30(value))
66207
+ unresolved("relative Codex native allowed skill path");
66208
+ const path = canonical9(value);
66209
+ roots.add(path.endsWith(`${sep14}SKILL.md`) ? dirname29(path) : path);
66210
+ }
66211
+ }
66088
66212
  if (config.skills?.bundled !== undefined) {
66089
66213
  keys3(config.skills.bundled, ["enabled"], "Codex bundled skills");
66090
66214
  if (typeof config.skills.bundled.enabled !== "boolean")
@@ -66142,7 +66266,9 @@ function resolveDiscovery(options, exclusion) {
66142
66266
  const target = join46(path, name);
66143
66267
  if (!lstatSync35(target).isFile())
66144
66268
  unresolved("local plugin packages need a dedicated discovery adapter");
66145
- witness(target);
66269
+ const text3 = witness(target);
66270
+ if (exclusion && text3 !== null)
66271
+ sumiLocalPluginTexts.set(canonical9(target), text3);
66146
66272
  }
66147
66273
  }
66148
66274
  for (const root2 of roots) {
@@ -66276,16 +66402,88 @@ function resolveDiscovery(options, exclusion) {
66276
66402
  const unique = combined.filter((source, index) => combined.findIndex((candidate2) => isDeepStrictEqual15(candidate2, source)) === index);
66277
66403
  return { ...supplied, roots: [...new Set([...roots, ...supplied.roots])].sort(), sources: unique, ...agent === "gemini" ? { builtinNames } : {} };
66278
66404
  }
66279
- function plugin(root2) {
66405
+ const reviewedManifestAbsence = (root2, manifestPath) => {
66406
+ const retained = exclusion?.retained;
66407
+ if (agent !== "claude" || retained?.method !== "reviewed" || ![join46(root2, "skills"), root2].some((path) => retained.roots.includes(path)))
66408
+ return false;
66409
+ const saved = retained.sources.filter((source) => source.path === canonical9(manifestPath) && source.hashMode === "path-bytes" && source.sha256 !== null && source.format === undefined && source.fields === undefined && source.managedPlugins === undefined);
66410
+ return saved.length > 0 && saved.every((source) => projected(source, undefined, budget3) === source.sha256);
66411
+ };
66412
+ const reviewedInstalledCopy = (root2, path, identity6) => {
66413
+ const retained = exclusion?.retained;
66414
+ if (agent !== "codex" || retained?.method !== "reviewed")
66415
+ return false;
66416
+ const inside = relative9(root2, canonical9(path));
66417
+ if (!inside || inside === ".." || inside.startsWith(`..${sep14}`) || isAbsolute30(inside))
66418
+ return false;
66419
+ const parent = canonical9(join46(nativeHome, "plugins/cache", identity6.marketplace, identity6.name));
66420
+ const current = hashRawDiscoveryFile(canonical9(path), budget3);
66421
+ if (current === null)
66422
+ return false;
66423
+ return retained.sources.some((source) => {
66424
+ if (source.sha256 !== current || source.format !== undefined || source.fields !== undefined || ![undefined, "bytes"].includes(source.hashMode) || source.managedPlugins !== undefined || source.reviewArtifact !== undefined || !source.path.startsWith(parent + sep14))
66425
+ return false;
66426
+ const [version, ...rest2] = source.path.slice(parent.length + 1).split(sep14);
66427
+ return Boolean(version) && version !== "." && version !== ".." && rest2.join(sep14) === inside;
66428
+ });
66429
+ };
66430
+ const verifyCodexPluginHookClosure = (root2, identity6, marketplaceSource, servers, declarations) => {
66431
+ const retained = exclusion.retained;
66432
+ if (retained.codexSemanticCache || retained.codexInstallationInputs || retained.codexRetiredMaterializations)
66433
+ return verifyOpaqueClosure(declarations);
66434
+ const within2 = (base2, path) => path === base2 || path.startsWith(base2 + sep14);
66435
+ const executables = [];
66436
+ for (const server of servers) {
66437
+ const row = config.mcp_servers?.[server];
66438
+ if (server === "codex_apps" || server === "_codex_apps" || !isCodexLocalStdioMcpServer(server, row))
66439
+ unresolved("plugin hook MCP server is not a configured local stdio server");
66440
+ for (const value of [row.command, ...row.args ?? []])
66441
+ for (const candidate2 of [value, value.slice(value.indexOf("=") + 1)]) {
66442
+ if (!isAbsolute30(candidate2) || /[\0$]/.test(candidate2) || executables.length >= AGENT_POLICY_LIMITS.discoveryRoots)
66443
+ continue;
66444
+ const path = canonical9(candidate2);
66445
+ if (lstatSync35(path, { throwIfNoEntry: false })?.isFile())
66446
+ executables.push(path);
66447
+ }
66448
+ }
66449
+ const cacheRoot = canonical9(join46(nativeHome, "plugins/cache"));
66450
+ const ownCache = canonical9(join46(nativeHome, "plugins/cache", identity6.marketplace, identity6.name));
66451
+ const ownCatalog = canonical9(join46(marketplaceSource, ".agents/plugins/marketplace.json"));
66452
+ const account = canonical9(home);
66453
+ const marketplaceRoots = Object.values(config.marketplaces ?? {}).filter((market) => market?.source_type === "local" && typeof market.source === "string" && isAbsolute30(market.source)).map((market) => canonical9(market.source)).filter((path) => !within2(path, account));
66454
+ const otherPlugin = (path) => !within2(root2, path) && !within2(ownCache, path) && path !== ownCatalog && !executables.includes(path) && (within2(cacheRoot, path) || marketplaceRoots.some((base2) => within2(base2, path)));
66455
+ const sources2 = retained.sources.filter((source) => source.path !== canonical9(configPath) && !otherPlugin(source.path));
66456
+ if (sources2.some((source) => source.format !== undefined || source.fields !== undefined || source.managedPlugins !== undefined || source.reviewArtifact !== undefined || ![undefined, "bytes", "path-bytes", "executable-v1"].includes(source.hashMode)))
66457
+ return verifyOpaqueClosure(declarations);
66458
+ const declared = declarations.map((path) => relative9(root2, path));
66459
+ const declaration = (path) => declarations.includes(path) || path.startsWith(ownCache + sep14) && declared.includes(path.slice(ownCache.length + 1).split(sep14).slice(1).join(sep14));
66460
+ if (!sources2.some((source) => !declaration(source.path) && source.sha256 !== null))
66461
+ unresolved("opaque executable dependency closure is unavailable");
66462
+ for (const source of sources2)
66463
+ if (projected(source, undefined, budget3) !== source.sha256) {
66464
+ throw new NativeDiscoveryWitnessChange("input", source.path, `Native discovery input changed; run skills hook install with a fresh discovery review: ${source.path}`);
66465
+ }
66466
+ verifyDiscoveryDirectories((retained.directories ?? []).filter((directory2) => !otherPlugin(directory2.path)));
66467
+ };
66468
+ const readCodexHookDeclaration = (text3, path) => {
66469
+ if (text3 === null)
66470
+ return null;
66471
+ try {
66472
+ return codexPluginHookHandlers(parseConfig(text3, path));
66473
+ } catch {
66474
+ return null;
66475
+ }
66476
+ };
66477
+ function plugin(root2, codex) {
66280
66478
  root2 = canonical9(root2);
66281
66479
  safe6(root2);
66282
66480
  if (exclusion)
66283
66481
  roots.add(root2);
66284
66482
  const manifestPath = join46(root2, agent === "claude" ? ".claude-plugin/plugin.json" : ".codex-plugin/plugin.json");
66285
66483
  const raw = witness(manifestPath, undefined, undefined, agent === "claude" ? "claude-plugin-manifest-v1" : undefined);
66286
- if (raw === null)
66484
+ if (raw === null && !reviewedManifestAbsence(root2, manifestPath))
66287
66485
  unresolved("plugin manifest missing");
66288
- const manifest = parseConfig(raw, manifestPath);
66486
+ const manifest = raw === null ? {} : parseConfig(raw, manifestPath);
66289
66487
  if (exclusion && Object.keys(manifest).some((key2) => /skill|plugin|hook|marketplace|extension|instruction/i.test(key2) && !["skills", "hooks"].includes(key2)))
66290
66488
  unresolved("unknown plugin discovery controls");
66291
66489
  const hooks = witness(join46(root2, "hooks/hooks.json"));
@@ -66293,20 +66491,35 @@ function resolveDiscovery(options, exclusion) {
66293
66491
  if (!exclusion || exclusion.retained?.method !== "reviewed")
66294
66492
  unresolved("plugin hooks require a separate no-skill-injection review");
66295
66493
  const required = [manifestPath, ...hooks !== null ? [join46(root2, "hooks/hooks.json")] : []];
66494
+ const scoped2 = agent === "codex" && codex !== undefined ? [] : undefined;
66296
66495
  if (manifest.hooks !== undefined) {
66297
- if (typeof manifest.hooks !== "string")
66298
- unresolved("unsupported plugin hooks target");
66299
- const hook = resolve29(root2, manifest.hooks);
66300
- if (!hook.startsWith(root2 + sep14))
66301
- unresolved("plugin hooks target escapes its root");
66302
- required.push(hook);
66303
- }
66496
+ if (scoped2 && manifest.hooks && typeof manifest.hooks === "object" && !Array.isArray(manifest.hooks)) {
66497
+ const inline = codexPluginHookHandlers(manifest.hooks);
66498
+ if (!inline)
66499
+ unresolved("unsupported inline plugin hooks");
66500
+ scoped2.push(inline);
66501
+ } else {
66502
+ if (typeof manifest.hooks !== "string")
66503
+ unresolved("unsupported plugin hooks target");
66504
+ const hook = resolve29(root2, manifest.hooks);
66505
+ if (!hook.startsWith(root2 + sep14))
66506
+ unresolved("plugin hooks target escapes its root");
66507
+ required.push(hook);
66508
+ if (scoped2)
66509
+ scoped2.push(readCodexHookDeclaration(witness(hook), hook));
66510
+ }
66511
+ }
66512
+ if (scoped2 && hooks !== null)
66513
+ scoped2.push(readCodexHookDeclaration(hooks, join46(root2, "hooks/hooks.json")));
66304
66514
  for (const path of required) {
66305
66515
  const saved = exclusion.retained.sources.filter((source) => source.path === canonical9(path) && source.sha256 !== null && source.format === undefined && source.fields === undefined);
66306
- if (!saved.length || saved.some((source) => projected(source, undefined, budget3) !== source.sha256))
66516
+ if (saved.length ? saved.some((source) => projected(source, undefined, budget3) !== source.sha256) : !(scoped2 && reviewedInstalledCopy(root2, path, codex)))
66307
66517
  unresolved("plugin hooks require current independently reviewed sources");
66308
66518
  }
66309
- verifyOpaqueClosure(required.map((path) => canonical9(path)));
66519
+ if (scoped2 && scoped2.every((item) => item !== null && item.commands === 0)) {
66520
+ verifyCodexPluginHookClosure(root2, codex, codex.source, new Set(scoped2.flatMap((item) => [...item.servers])), required.map((path) => canonical9(path)));
66521
+ } else
66522
+ verifyOpaqueClosure(required.map((path) => canonical9(path)));
66310
66523
  }
66311
66524
  const commands = join46(root2, "commands");
66312
66525
  safe6(commands);
@@ -66362,7 +66575,7 @@ function resolveDiscovery(options, exclusion) {
66362
66575
  const catalog = parseConfig(catalogText, join46(market.source, ".agents/plugins/marketplace.json")), matches2 = Array.isArray(catalog.plugins) ? catalog.plugins.filter((item) => item.name === name) : [];
66363
66576
  if (matches2.length !== 1 || matches2[0]?.source?.source !== "local" || typeof matches2[0]?.source?.path !== "string")
66364
66577
  unresolved("plugin catalog source is missing or ambiguous");
66365
- plugin(resolve29(market.source, matches2[0].source.path));
66578
+ plugin(resolve29(market.source, matches2[0].source.path), exclusion ? { marketplace, name, source: market.source } : undefined);
66366
66579
  }
66367
66580
  } else if (agent === "opencode") {
66368
66581
  if (witness(join46(home, ".config/opencode/opencode.jsonc")) !== null || witness(join46(home, ".config/opencode/config.json")) !== null)
@@ -66379,7 +66592,11 @@ function resolveDiscovery(options, exclusion) {
66379
66592
  if (lstatSync35(localPlugins, { throwIfNoEntry: false }) && entries(localPlugins).some((name) => name !== "skills-cli.js"))
66380
66593
  unresolved("additional local plugin hooks require review");
66381
66594
  } else if (agent === "sumi") {
66382
- if ((config.plugin?.length ?? 0) > 0 || (config.plugins?.length ?? 0) > 0 || sources.some((source) => source.path !== canonical9(configPath) && source.path !== canonical9(join46(sumiConfigDirectory(home), "sumi.jsonc")) && source.sha256 !== null))
66595
+ const pinnedLocalPlugin = (source) => {
66596
+ const retained = exclusion?.retained, text3 = sumiLocalPluginTexts.get(source.path);
66597
+ return retained?.method === "reviewed" && text3 !== undefined && sumiPluginLoadsOnlyBuiltins(text3) && retained.sources.some((saved) => saved.path === source.path && saved.sha256 === source.sha256 && saved.sha256 !== null && [undefined, "bytes"].includes(saved.hashMode) && saved.format === undefined && saved.fields === undefined && saved.managedPlugins === undefined && saved.reviewArtifact === undefined);
66598
+ };
66599
+ if ((config.plugin?.length ?? 0) > 0 || (config.plugins?.length ?? 0) > 0 || sources.some((source) => source.path !== canonical9(configPath) && source.path !== canonical9(join46(sumiConfigDirectory(home), "sumi.jsonc")) && source.sha256 !== null && !pinnedLocalPlugin(source)))
66383
66600
  unresolved("external or foreign local plugins require review");
66384
66601
  } else if (agent === "hermes") {
66385
66602
  for (const directory2 of [join46(home, ".hermes/plugins"), join46(home, ".hermes/hermes-agent")]) {
@@ -66419,11 +66636,12 @@ var DISCOVERY_RUNTIME_COMMANDS, DISCOVERY_ROOT_UNRESOLVED = "DISCOVERY_ROOT_UNRE
66419
66636
  } catch {
66420
66637
  return null;
66421
66638
  }
66422
- }, digest2 = (text3) => createHash33("sha256").update(text3).digest("hex"), CLAUDE_CONTROL_WITNESS_MODES, CLAUDE_CONTROL_FILES, ADOPTABLE_SETTINGS_MATCHES, CLAUDE_PROJECT_DISCOVERY_KEYS;
66639
+ }, digest2 = (text3) => createHash33("sha256").update(text3).digest("hex"), CLAUDE_CONTROL_WITNESS_MODES, CLAUDE_CONTROL_FILES, ADOPTABLE_SETTINGS_MATCHES, CLAUDE_PROJECT_DISCOVERY_KEYS, CODEX_MARKETPLACE_TIMESTAMP, CODEX_HOOK_EVENTS;
66423
66640
  var init_agent_discovery = __esm(() => {
66424
66641
  init_sumi_settings_witness();
66425
66642
  init_agent_policy_limits();
66426
66643
  init_agent_hermes();
66644
+ init_agent_adapters();
66427
66645
  init_agent_discovery_directories();
66428
66646
  init_agent_discovery_bytes();
66429
66647
  init_plugin_projection_store();
@@ -66453,6 +66671,8 @@ var init_agent_discovery = __esm(() => {
66453
66671
  CLAUDE_CONTROL_FILES = new Set(["settings.json", "settings.local.json", "installed_plugins.json", "known_marketplaces.json"]);
66454
66672
  ADOPTABLE_SETTINGS_MATCHES = Object.freeze(["exact", "screen-reader-receipt"]);
66455
66673
  CLAUDE_PROJECT_DISCOVERY_KEYS = Object.freeze(["enabledPlugins", "extraKnownMarketplaces", "additionalMarketplaces", "skillOverrides"]);
66674
+ CODEX_MARKETPLACE_TIMESTAMP = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{1,9})?(?:Z|[+-]\d{2}:\d{2})$/;
66675
+ CODEX_HOOK_EVENTS = new Set(["PreToolUse", "PermissionRequest", "PostToolUse", "PreCompact", "PostCompact", "SessionStart", "SessionEnd", "UserPromptSubmit", "SubagentStart", "SubagentStop", "Stop", "Interrupt"]);
66456
66676
  });
66457
66677
 
66458
66678
  // src/lib/authoring-path.ts
@@ -66530,7 +66750,10 @@ function configuredRoots(home, explicitHome) {
66530
66750
  if (recorded && (!executable2 || executable2.target !== recorded.target || onPath && onPath.target !== recorded.target) || !executable2 && (binding.builtinNames?.length || binding.agent === "gemini" && binding.sources.some((source) => basename19(source.path) === "package.json"))) {
66531
66751
  throw new Error("Native discovery runtime target is unresolved or changed");
66532
66752
  }
66533
- roots.push(...resolveAgentDiscoveryExclusionRoots({ home, agent: binding.agent, canonical: physicalPath, retained: binding, executable: executable2, narrowed }));
66753
+ const managedCommand = current.commands?.[agent], managedProfile = current.profiles?.[agent];
66754
+ const supervisor = current.supervisors?.[agent];
66755
+ const managedHook = (binding.agent === "gemini" || binding.agent === "cursor") && typeof managedCommand === "string" && typeof managedProfile === "string" ? { command: managedCommand, profile: managedProfile } : binding.agent === "hermes" && typeof managedCommand === "string" && typeof managedProfile === "string" && supervisor && typeof supervisor === "object" && typeof supervisor.path === "string" && typeof supervisor.runtime === "string" && typeof supervisor.sha256 === "string" ? { command: managedCommand, profile: managedProfile, supervisor: { path: supervisor.path, runtime: supervisor.runtime, sha256: supervisor.sha256 } } : undefined;
66756
+ roots.push(...resolveAgentDiscoveryExclusionRoots({ home, agent: binding.agent, canonical: physicalPath, retained: binding, executable: executable2, narrowed, ...managedHook ? { managedHook } : {} }));
66534
66757
  }
66535
66758
  };
66536
66759
  if (homePolicy)