@hasna/skills 0.10.72 → 0.10.73

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/bin/mcp.js CHANGED
@@ -23,7 +23,7 @@ var package_default;
23
23
  var init_package = __esm(() => {
24
24
  package_default = {
25
25
  name: "@hasna/skills",
26
- version: "0.10.72",
26
+ version: "0.10.73",
27
27
  description: "Skills library for AI coding agents",
28
28
  type: "module",
29
29
  bin: {
@@ -32219,6 +32219,10 @@ function canonical4(value, depth = 0, budget2 = { remaining: 65536 }) {
32219
32219
  function hashCodexSettingsReplacement(text2, budget2 = { remaining: 256 * 1024 * 1024 }) {
32220
32220
  need4(Buffer.byteLength(text2) <= 1024 * 1024 && budget2.remaining >= Buffer.byteLength(text2));
32221
32221
  budget2.remaining -= Buffer.byteLength(text2);
32222
+ const prepared = prepareCodexSettingsV1(text2);
32223
+ return finishCodexSettingsV1(prepared.config, prepared.tokens);
32224
+ }
32225
+ function prepareCodexSettingsV1(text2) {
32222
32226
  let config2;
32223
32227
  try {
32224
32228
  config2 = Bun.TOML.parse(text2);
@@ -32226,6 +32230,9 @@ function hashCodexSettingsReplacement(text2, budget2 = { remaining: 256 * 1024 *
32226
32230
  throw new Error("Invalid Codex settings witness");
32227
32231
  }
32228
32232
  need4(config2 && typeof config2 === "object" && !Array.isArray(config2));
32233
+ return { config: config2, tokens: numericTokens(text2) };
32234
+ }
32235
+ function finishCodexSettingsV1(config2, tokens) {
32229
32236
  if (Object.hasOwn(config2, "model")) {
32230
32237
  need4(typeof config2.model === "string" && /^[A-Za-z0-9][A-Za-z0-9._:/-]{0,127}$/.test(config2.model));
32231
32238
  delete config2.model;
@@ -32235,11 +32242,7 @@ function hashCodexSettingsReplacement(text2, budget2 = { remaining: 256 * 1024 *
32235
32242
  need4(typeof config2[key] === "string" && values.has(config2[key]));
32236
32243
  delete config2[key];
32237
32244
  }
32238
- return sha(`hasna.skills.codex-settings.v1\x00${JSON.stringify([canonical4(config2), numericTokens(text2)])}`);
32239
- }
32240
- function captureCodexSettings(path, budget2 = { remaining: 256 * 1024 * 1024 }) {
32241
- const text2 = readNativeSettingsWitnessFile(path, budget2, "config.toml");
32242
- return { path, hashMode: "codex-settings-v1", sha256: hashCodexSettingsReplacement(text2) };
32245
+ return sha(`hasna.skills.codex-settings.v1\x00${JSON.stringify([canonical4(config2), tokens])}`);
32243
32246
  }
32244
32247
  var sha = (text2) => createHash11("sha256").update(text2).digest("hex"), EFFORT, VERBOSITY;
32245
32248
  var init_codex_settings_witness_v1 = __esm(() => {
@@ -32953,7 +32956,7 @@ function projectStatusLine(config2) {
32953
32956
  if (!Object.keys(tui).length)
32954
32957
  delete config2.tui;
32955
32958
  }
32956
- function settingsDigest2(text2, version2 = 2, dependencies) {
32959
+ function prepareSettings(text2, version2, dependencies) {
32957
32960
  let config2;
32958
32961
  try {
32959
32962
  config2 = Bun.TOML.parse(text2);
@@ -32992,51 +32995,106 @@ function settingsDigest2(text2, version2 = 2, dependencies) {
32992
32995
  delete config2.tui.model_availability_nux;
32993
32996
  if (isRecord3(config2.tui) && typeof config2.tui.screen_reader_detection_done === "boolean")
32994
32997
  delete config2.tui.screen_reader_detection_done;
32995
- config2 = embedCodexNumericTokens(config2, tokens);
32998
+ return { config: embedCodexNumericTokens(config2, tokens), numericSource: text2, dependencies };
32999
+ }
33000
+ const mcp = version2 >= 3 ? projectRegularCodexMcp(config2, text2) : { config: config2, numericSource: text2 };
33001
+ return version2 >= 4 ? projectModelAvailabilityNux(mcp.config, mcp.numericSource) : mcp;
33002
+ }
33003
+ function finishSettings(prepared, version2) {
33004
+ const config2 = prepared.config;
33005
+ if (version2 === 6) {
32996
33006
  normalize2(config2, 6);
32997
33007
  if (isRecord3(config2.tui) && !Object.keys(config2.tui).length)
32998
33008
  delete config2.tui;
32999
- return sha2(`hasna.skills.codex-settings.v6\x00${JSON.stringify([canonical5(config2), canonical5(dependencies)])}`);
33009
+ return sha2(`hasna.skills.codex-settings.v6\x00${JSON.stringify([canonical5(config2), canonical5(prepared.dependencies)])}`);
33000
33010
  }
33001
- const mcp = version2 >= 3 ? projectRegularCodexMcp(config2, text2) : { config: config2, numericSource: text2 };
33002
- const projected = version2 >= 4 ? projectModelAvailabilityNux(mcp.config, mcp.numericSource) : mcp;
33003
- normalize2(projected.config, version2);
33004
- const values = [canonical5(projected.config), numericTokens2(projected.numericSource)];
33011
+ normalize2(config2, version2);
33012
+ const values = [canonical5(config2), numericTokens2(prepared.numericSource)];
33005
33013
  return sha2(`hasna.skills.codex-settings.v${version2}\x00${JSON.stringify(values)}`);
33006
33014
  }
33015
+ function settingsDigest2(text2, version2 = 2, dependencies) {
33016
+ return finishSettings(prepareSettings(text2, version2, dependencies), version2);
33017
+ }
33018
+ function cloneTree(value) {
33019
+ if (Array.isArray(value))
33020
+ return value.map(cloneTree);
33021
+ if (isRecord3(value) && [Object.prototype, null].includes(Object.getPrototypeOf(value)))
33022
+ return Object.fromEntries(Object.entries(value).map(([key2, child2]) => [key2, cloneTree(child2)]));
33023
+ return value;
33024
+ }
33025
+ function receiptEdits(config2) {
33026
+ const tui = config2.tui;
33027
+ const set2 = (value) => (target) => {
33028
+ if (!isRecord3(target.tui))
33029
+ target.tui = {};
33030
+ target.tui[SCREEN_READER_RECEIPT] = value;
33031
+ };
33032
+ if (tui === undefined || isRecord3(tui) && !Object.hasOwn(tui, SCREEN_READER_RECEIPT))
33033
+ return [set2(true), set2(false)];
33034
+ if (!isRecord3(tui) || typeof tui[SCREEN_READER_RECEIPT] !== "boolean")
33035
+ return [];
33036
+ const remove = (dropEmpty) => (target) => {
33037
+ delete target.tui[SCREEN_READER_RECEIPT];
33038
+ if (dropEmpty && !Object.keys(target.tui).length)
33039
+ delete target.tui;
33040
+ };
33041
+ return [remove(true), ...Object.keys(tui).length === 1 ? [remove(false)] : [], set2(!tui[SCREEN_READER_RECEIPT])];
33042
+ }
33043
+ function codexSettingsToleratesScreenReaderReceipt(text2, hashMode, expected) {
33044
+ try {
33045
+ if (Buffer.byteLength(text2) > 1024 * 1024 || !/^[a-f0-9]{64}$/.test(expected))
33046
+ return false;
33047
+ if (hashMode === "codex-settings-v1") {
33048
+ const prepared2 = prepareCodexSettingsV1(text2);
33049
+ return receiptEdits(prepared2.config).some((edit) => {
33050
+ const candidate = cloneTree(prepared2.config);
33051
+ edit(candidate);
33052
+ return finishCodexSettingsV1(candidate, prepared2.tokens) === expected;
33053
+ });
33054
+ }
33055
+ const version2 = Number(hashMode.slice("codex-settings-v".length));
33056
+ if (![2, 3, 4, 5].includes(version2))
33057
+ return false;
33058
+ const prepared = prepareSettings(text2, version2);
33059
+ return receiptEdits(prepared.config).some((edit) => {
33060
+ const candidate = cloneTree(prepared.config);
33061
+ edit(candidate);
33062
+ if (version2 >= 4 && isRecord3(candidate.tui) && !Object.keys(candidate.tui).length)
33063
+ delete candidate.tui;
33064
+ return finishSettings({ ...prepared, config: candidate }, version2) === expected;
33065
+ });
33066
+ } catch {
33067
+ return false;
33068
+ }
33069
+ }
33070
+ function codexSettingsWitnessMatch(path, hashMode, expected, budget2 = { remaining: 256 * 1024 * 1024 }) {
33071
+ const text2 = readNativeSettingsWitnessFile(path, budget2, "config.toml");
33072
+ need7(Buffer.byteLength(text2) <= 1024 * 1024);
33073
+ const exact = hashMode === "codex-settings-v1" ? hashCodexSettingsReplacement(text2) : settingsDigest2(text2, Number(hashMode.slice("codex-settings-v".length)));
33074
+ if (exact === expected)
33075
+ return "exact";
33076
+ return codexSettingsToleratesScreenReaderReceipt(text2, hashMode, expected) ? "screen-reader-receipt" : null;
33077
+ }
33007
33078
  function hashCodexSettingsReplacementV2(text2, budget2 = { remaining: 256 * 1024 * 1024 }) {
33008
33079
  need7(Buffer.byteLength(text2) <= 1024 * 1024 && budget2.remaining >= Buffer.byteLength(text2));
33009
33080
  budget2.remaining -= Buffer.byteLength(text2);
33010
33081
  return settingsDigest2(text2);
33011
33082
  }
33012
- function captureCodexSettingsV2(path, budget2 = { remaining: 256 * 1024 * 1024 }) {
33013
- const text2 = readNativeSettingsWitnessFile(path, budget2, "config.toml");
33014
- return { path, hashMode: "codex-settings-v2", sha256: settingsDigest2(text2) };
33015
- }
33016
33083
  function hashCodexSettingsReplacementV3(text2, budget2 = { remaining: 256 * 1024 * 1024 }) {
33017
33084
  need7(Buffer.byteLength(text2) <= 1024 * 1024 && budget2.remaining >= Buffer.byteLength(text2));
33018
33085
  budget2.remaining -= Buffer.byteLength(text2);
33019
33086
  return settingsDigest2(text2, 3);
33020
33087
  }
33021
- function captureCodexSettingsV3(path, budget2 = { remaining: 256 * 1024 * 1024 }) {
33022
- return { path, hashMode: "codex-settings-v3", sha256: settingsDigest2(readNativeSettingsWitnessFile(path, budget2, "config.toml"), 3) };
33023
- }
33024
33088
  function hashCodexSettingsReplacementV4(text2, budget2 = { remaining: 256 * 1024 * 1024 }) {
33025
33089
  need7(Buffer.byteLength(text2) <= 1024 * 1024 && budget2.remaining >= Buffer.byteLength(text2));
33026
33090
  budget2.remaining -= Buffer.byteLength(text2);
33027
33091
  return settingsDigest2(text2, 4);
33028
33092
  }
33029
- function captureCodexSettingsV4(path, budget2 = { remaining: 256 * 1024 * 1024 }) {
33030
- return { path, hashMode: "codex-settings-v4", sha256: settingsDigest2(readNativeSettingsWitnessFile(path, budget2, "config.toml"), 4) };
33031
- }
33032
33093
  function hashCodexSettingsReplacementV5(text2, budget2 = { remaining: 256 * 1024 * 1024 }) {
33033
33094
  need7(Buffer.byteLength(text2) <= 1024 * 1024 && budget2.remaining >= Buffer.byteLength(text2));
33034
33095
  budget2.remaining -= Buffer.byteLength(text2);
33035
33096
  return settingsDigest2(text2, 5);
33036
33097
  }
33037
- function captureCodexSettingsV5(path, budget2 = { remaining: 256 * 1024 * 1024 }) {
33038
- return { path, hashMode: "codex-settings-v5", sha256: settingsDigest2(readNativeSettingsWitnessFile(path, budget2, "config.toml"), 5) };
33039
- }
33040
33098
  function captureCodexSettingsV6(path, reviewedSources, budget2 = { remaining: 256 * 1024 * 1024 }, changes) {
33041
33099
  const original = readNativeSettingsWitnessFile(path, budget2, "config.toml");
33042
33100
  const text2 = changes?.get(path) ?? original;
@@ -33046,7 +33104,7 @@ function captureCodexSettingsV6(path, reviewedSources, budget2 = { remaining: 25
33046
33104
  need7(dependencies.servers.every((server) => !["codex_apps", "_codex_apps"].includes(server) && isCodexLocalStdioMcpServer(server, config2.mcp_servers?.[server])));
33047
33105
  return { path, hashMode: "codex-settings-v6", sha256: settingsDigest2(text2, 6, dependencies), hookSources: dependencies.sources };
33048
33106
  }
33049
- var sha2 = (text2) => createHash13("sha256").update(text2).digest("hex"), EFFORT2, VERBOSITY2, MODEL, CODEX_DISCOVERY_PROJECTION_FIELDS, INFERENCE;
33107
+ var sha2 = (text2) => createHash13("sha256").update(text2).digest("hex"), EFFORT2, VERBOSITY2, MODEL, CODEX_DISCOVERY_PROJECTION_FIELDS, INFERENCE, SCREEN_READER_RECEIPT = "screen_reader_detection_done";
33050
33108
  var init_codex_settings_witness = __esm(() => {
33051
33109
  init_codex_settings_witness_v1();
33052
33110
  init_codex_settings_witness_v1();
@@ -35310,6 +35368,13 @@ var init_codex_semantic_cache_witness = __esm(() => {
35310
35368
  ]);
35311
35369
  });
35312
35370
 
35371
+ // src/lib/codex-node-modules.ts
35372
+ var PLUGIN_MANIFESTS;
35373
+ var init_codex_node_modules = __esm(() => {
35374
+ init_claude_settings_witness();
35375
+ PLUGIN_MANIFESTS = Object.freeze(["plugin.json", ".codex-plugin/plugin.json", ".claude-plugin/plugin.json", ".cursor-plugin/plugin.json"]);
35376
+ });
35377
+
35313
35378
  // src/lib/managed-policy.ts
35314
35379
  import { closeSync as closeSync14, constants as constants11, fstatSync as fstatSync14, lstatSync as lstatSync17, openSync as openSync14, readSync as readSync8 } from "fs";
35315
35380
  import { join as join22 } from "path";
@@ -35838,6 +35903,7 @@ var init_agent_integration = __esm(() => {
35838
35903
  init_native_discovery_roots();
35839
35904
  init_codex_vendor_refresh();
35840
35905
  init_codex_native_skill_catalog();
35906
+ init_codex_node_modules();
35841
35907
  init_config();
35842
35908
  init_managed_policy();
35843
35909
  init_agent_bridge();
@@ -37313,10 +37379,9 @@ function projected(source, changes, budget2 = discoveryByteBudget()) {
37313
37379
  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")) {
37314
37380
  if (source.format !== undefined || source.fields !== undefined || source.managedPlugins !== undefined || typeof source.sha256 !== "string" || !/^[a-f0-9]{64}$/.test(source.sha256))
37315
37381
  throw new Error("Codex settings witnesses require exact typed metadata");
37316
- const current = (source.hashMode === "codex-settings-v5" ? captureCodexSettingsV5 : source.hashMode === "codex-settings-v4" ? captureCodexSettingsV4 : source.hashMode === "codex-settings-v3" ? captureCodexSettingsV3 : source.hashMode === "codex-settings-v2" ? captureCodexSettingsV2 : captureCodexSettings)(source.path, budget2).sha256;
37317
- if (current !== source.sha256)
37382
+ if (codexSettingsWitnessMatch(source.path, source.hashMode, source.sha256, budget2) === null)
37318
37383
  throw new NativeDiscoveryWitnessChange("input", source.path, `Native discovery input changed; run skills hook install with a fresh discovery review: ${source.path}`);
37319
- return changes?.has(source.path) ? (source.hashMode === "codex-settings-v5" ? hashCodexSettingsReplacementV5 : source.hashMode === "codex-settings-v4" ? hashCodexSettingsReplacementV4 : source.hashMode === "codex-settings-v3" ? hashCodexSettingsReplacementV3 : source.hashMode === "codex-settings-v2" ? hashCodexSettingsReplacementV2 : hashCodexSettingsReplacement)(changes.get(source.path), budget2) : current;
37384
+ return changes?.has(source.path) ? (source.hashMode === "codex-settings-v5" ? hashCodexSettingsReplacementV5 : source.hashMode === "codex-settings-v4" ? hashCodexSettingsReplacementV4 : source.hashMode === "codex-settings-v3" ? hashCodexSettingsReplacementV3 : source.hashMode === "codex-settings-v2" ? hashCodexSettingsReplacementV2 : hashCodexSettingsReplacement)(changes.get(source.path), budget2) : source.sha256;
37320
37385
  }
37321
37386
  if (source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || (source.hashMode === "claude-settings-v3" || source.hashMode === "claude-settings-v4")) {
37322
37387
  if (source.format !== undefined || source.fields !== undefined || source.managedPlugins !== undefined || typeof source.sha256 !== "string" || !/^[a-f0-9]{64}$/.test(source.sha256))
@@ -37429,10 +37494,22 @@ function retiredCodexRoots(binding, tolerance) {
37429
37494
  }
37430
37495
  return proof.roots;
37431
37496
  }
37432
- function retainableAbsentSource(source) {
37497
+ function retainableAbsentWitness(source) {
37433
37498
  if (source.format !== undefined || source.fields !== undefined || source.managedPlugins !== undefined)
37434
- return false;
37435
- return [undefined, "bytes"].includes(source.hashMode) || source.hashMode === "claude-plugin-manifest-v1" && source.sha256 !== null && source.path.endsWith(join30(sep11, ".claude-plugin", "plugin.json")) || source.hashMode === CLAUDE_ORPHAN_MARKER_MODE && source.sha256 !== null && isClaudePluginCacheOrphanMarker(source.path);
37499
+ return null;
37500
+ if ([undefined, "bytes"].includes(source.hashMode))
37501
+ return "bytes";
37502
+ if (source.hashMode === "claude-plugin-manifest-v1" && source.sha256 !== null && source.path.endsWith(join30(sep11, ".claude-plugin", "plugin.json")))
37503
+ return "claude-plugin-manifest-v1";
37504
+ if (source.hashMode === CLAUDE_ORPHAN_MARKER_MODE && source.sha256 !== null && isClaudePluginCacheOrphanMarker(source.path))
37505
+ return CLAUDE_ORPHAN_MARKER_MODE;
37506
+ return null;
37507
+ }
37508
+ function retainableAbsentSource(source) {
37509
+ return retainableAbsentWitness(source) !== null;
37510
+ }
37511
+ function retainedAbsentRoot(absentRoots, source) {
37512
+ return retainableAbsentSource(source) ? absentRoots.find((root) => source.path.startsWith(root + sep11)) : undefined;
37436
37513
  }
37437
37514
  function absentRetiredClaudeRoots(binding) {
37438
37515
  if (binding.agent !== "claude" || binding.method !== "reviewed")
@@ -37625,7 +37702,7 @@ function verifyAgentDiscovery(binding, codexRecovery, reviewedRootAliases, witne
37625
37702
  safe6(source.path);
37626
37703
  continue;
37627
37704
  }
37628
- if (absentRoots.some((root) => source.path.startsWith(root + sep11)) && retainableAbsentSource(source)) {
37705
+ if (retainedAbsentRoot(absentRoots, source) !== undefined) {
37629
37706
  safe6(source.path);
37630
37707
  continue;
37631
37708
  }
@@ -37999,7 +38076,7 @@ var DISCOVERY_RUNTIME_COMMANDS, realpathOrNull = (path) => {
37999
38076
  } catch {
38000
38077
  return null;
38001
38078
  }
38002
- }, digest2 = (text2) => createHash24("sha256").update(text2).digest("hex");
38079
+ }, digest2 = (text2) => createHash24("sha256").update(text2).digest("hex"), CLAUDE_CONTROL_WITNESS_MODES, CLAUDE_CONTROL_FILES, ADOPTABLE_SETTINGS_MATCHES, CLAUDE_PROJECT_DISCOVERY_KEYS;
38003
38080
  var init_agent_discovery = __esm(() => {
38004
38081
  init_sumi_settings_witness();
38005
38082
  init_agent_policy_limits();
@@ -38029,6 +38106,10 @@ var init_agent_discovery = __esm(() => {
38029
38106
  init_codex_semantic_cache_witness();
38030
38107
  init_agent_discovery_directories();
38031
38108
  DISCOVERY_RUNTIME_COMMANDS = Object.freeze({ gemini: "gemini" });
38109
+ CLAUDE_CONTROL_WITNESS_MODES = new Set(["claude-settings-v1", "claude-settings-v2", "claude-settings-v3", "claude-settings-v4", "claude-marketplace-registry", "claude-marketplace-registry-v2", "claude-marketplace-entry-v1", "claude-plugin-registry"]);
38110
+ CLAUDE_CONTROL_FILES = new Set(["settings.json", "settings.local.json", "installed_plugins.json", "known_marketplaces.json"]);
38111
+ ADOPTABLE_SETTINGS_MATCHES = Object.freeze(["exact", "screen-reader-receipt"]);
38112
+ CLAUDE_PROJECT_DISCOVERY_KEYS = Object.freeze(["enabledPlugins", "extraKnownMarketplaces", "additionalMarketplaces", "skillOverrides"]);
38032
38113
  });
38033
38114
 
38034
38115
  // src/lib/authoring-path.ts
package/bin/migrate.js CHANGED
@@ -25,7 +25,7 @@ import { join as join5 } from "path";
25
25
  // package.json
26
26
  var package_default = {
27
27
  name: "@hasna/skills",
28
- version: "0.10.72",
28
+ version: "0.10.73",
29
29
  description: "Skills library for AI coding agents",
30
30
  type: "module",
31
31
  bin: {
package/bin/server.js CHANGED
@@ -24140,7 +24140,7 @@ restoreLaunchCwd();
24140
24140
  // package.json
24141
24141
  var package_default = {
24142
24142
  name: "@hasna/skills",
24143
- version: "0.10.72",
24143
+ version: "0.10.73",
24144
24144
  description: "Skills library for AI coding agents",
24145
24145
  type: "module",
24146
24146
  bin: {
package/bin/worker.js CHANGED
@@ -24143,7 +24143,7 @@ import { randomUUID as randomUUID6 } from "crypto";
24143
24143
  // package.json
24144
24144
  var package_default = {
24145
24145
  name: "@hasna/skills",
24146
- version: "0.10.72",
24146
+ version: "0.10.73",
24147
24147
  description: "Skills library for AI coding agents",
24148
24148
  type: "module",
24149
24149
  bin: {