@hasna/skills 0.8.11 → 0.8.12

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/dist/index.js CHANGED
@@ -9650,7 +9650,7 @@ import { homedir as homedir5 } from "os";
9650
9650
  import {
9651
9651
  cpSync as cpSync2,
9652
9652
  existsSync as existsSync12,
9653
- lstatSync as lstatSync18,
9653
+ lstatSync as lstatSync19,
9654
9654
  mkdirSync as mkdirSync8,
9655
9655
  mkdtempSync as mkdtempSync2,
9656
9656
  readFileSync as readFileSync15,
@@ -9661,12 +9661,12 @@ import {
9661
9661
  writeFileSync as writeFileSync6
9662
9662
  } from "fs";
9663
9663
  import { homedir as homedir4 } from "os";
9664
- import { basename as basename7, dirname as dirname15, join as join26 } from "path";
9664
+ import { basename as basename9, dirname as dirname16, join as join26 } from "path";
9665
9665
 
9666
9666
  // src/lib/agent-integration.ts
9667
- import { createHash as createHash13, randomUUID as randomUUID3 } from "crypto";
9668
- import { existsSync as existsSync11, lstatSync as lstatSync17, statSync as statSync8, mkdirSync as mkdirSync7, readFileSync as readFileSync14, readdirSync as readdirSync10, opendirSync as opendirSync5, readlinkSync as readlinkSync2, realpathSync as realpathSync5, renameSync as renameSync4, rmdirSync as rmdirSync3, writeFileSync as writeFileSync5, unlinkSync as unlinkSync4, chmodSync, openSync as openSync10, closeSync as closeSync10, fsyncSync as fsyncSync3, fstatSync as fstatSync10, readSync as readSync8, constants as constants9, linkSync as linkSync2 } from "fs";
9669
- import { dirname as dirname14, join as join25, resolve as resolve14, relative as relative5, isAbsolute as isAbsolute14, sep as sep6 } from "path";
9667
+ import { createHash as createHash14, randomUUID as randomUUID3 } from "crypto";
9668
+ import { existsSync as existsSync11, lstatSync as lstatSync18, statSync as statSync8, mkdirSync as mkdirSync7, readFileSync as readFileSync14, readdirSync as readdirSync10, opendirSync as opendirSync5, readlinkSync as readlinkSync2, realpathSync as realpathSync5, renameSync as renameSync4, rmdirSync as rmdirSync3, writeFileSync as writeFileSync5, unlinkSync as unlinkSync4, chmodSync, openSync as openSync11, closeSync as closeSync11, fsyncSync as fsyncSync3, fstatSync as fstatSync11, readSync as readSync9, constants as constants10, linkSync as linkSync2 } from "fs";
9669
+ import { dirname as dirname15, join as join25, resolve as resolve15, relative as relative5, isAbsolute as isAbsolute15, sep as sep6 } from "path";
9670
9670
  import { homedir as homedir3 } from "os";
9671
9671
 
9672
9672
  // src/lib/managed-policy.ts
@@ -10807,7 +10807,9 @@ function assertAgentPolicyCollections(policy) {
10807
10807
  text(source.path);
10808
10808
  requireBound(source.sha256 === null || typeof source.sha256 === "string" && /^[a-f0-9]{64}$/.test(source.sha256));
10809
10809
  if (source.hashMode !== undefined)
10810
- requireBound(["bytes", "path-bytes", "claude-plugin-registry", "claude-marketplace-registry"].includes(source.hashMode) && source.format === undefined && source.fields === undefined && (source.hashMode === "bytes" || source.sha256 !== null));
10810
+ requireBound(["bytes", "path-bytes", "claude-plugin-registry", "claude-marketplace-registry", "claude-settings-v1"].includes(source.hashMode) && source.format === undefined && source.fields === undefined && (source.hashMode === "bytes" || source.sha256 !== null));
10811
+ if (source.hashMode === "claude-settings-v1")
10812
+ requireBound(agent === "claude" && value.agent === "claude" && value.method === "reviewed" && !/[\x00-\x1f\x7f]/.test(source.path) && isAbsolute3(source.path) && resolve4(source.path) === source.path && basename3(source.path) === "settings.json");
10811
10813
  if (source.hashMode === "claude-marketplace-registry")
10812
10814
  requireBound(agent === "claude" && value.agent === "claude" && value.method === "reviewed" && !/[\x00-\x1f\x7f]/.test(source.path) && isAbsolute3(source.path) && resolve4(source.path) === source.path && basename3(source.path) === "known_marketplaces.json");
10813
10815
  if (source.hashMode === "claude-plugin-registry") {
@@ -10961,9 +10963,9 @@ function isOwnedCliBridge(path, expectedPaths) {
10961
10963
  }
10962
10964
 
10963
10965
  // src/lib/agent-discovery.ts
10964
- import { createHash as createHash12 } from "crypto";
10965
- import { lstatSync as lstatSync16, readFileSync as readFileSync13, readdirSync as readdirSync9, realpathSync as realpathSync4 } from "fs";
10966
- import { dirname as dirname13, isAbsolute as isAbsolute13, join as join23, resolve as resolve13, sep as sep5 } from "path";
10966
+ import { createHash as createHash13 } from "crypto";
10967
+ import { lstatSync as lstatSync17, readFileSync as readFileSync13, readdirSync as readdirSync9, realpathSync as realpathSync4 } from "fs";
10968
+ import { basename as basename8, dirname as dirname14, isAbsolute as isAbsolute14, join as join23, resolve as resolve14, sep as sep5 } from "path";
10967
10969
 
10968
10970
  // node_modules/yaml/dist/index.js
10969
10971
  var composer = require_composer();
@@ -11439,7 +11441,7 @@ import { isAbsolute as isAbsolute10, join as join20, resolve as resolve10 } from
11439
11441
  // package.json
11440
11442
  var package_default = {
11441
11443
  name: "@hasna/skills",
11442
- version: "0.8.11",
11444
+ version: "0.8.12",
11443
11445
  description: "Skills library for AI coding agents",
11444
11446
  type: "module",
11445
11447
  bin: {
@@ -14931,8 +14933,228 @@ function captureClaudeMarketplaceRegistry(path, budget = { remaining: 256 * 1024
14931
14933
  return { path, hashMode: "claude-marketplace-registry", sha256: sha2562 };
14932
14934
  }
14933
14935
 
14936
+ // src/lib/claude-settings-witness.ts
14937
+ import { createHash as createHash12 } from "crypto";
14938
+ import { closeSync as closeSync10, constants as constants9, fstatSync as fstatSync10, lstatSync as lstatSync16, openSync as openSync10, readSync as readSync8 } from "fs";
14939
+ import { basename as basename7, dirname as dirname13, isAbsolute as isAbsolute13, resolve as resolve13 } from "path";
14940
+ var CLAUDE_SETTINGS_WITNESS_LIMITS = Object.freeze({ bytes: 1024 * 1024, rows: 1024, depth: 32, nodes: 65536, stringCharacters: 16384, pathCharacters: 4096 });
14941
+ function need3(value, reason) {
14942
+ if (!value)
14943
+ throw new Error(`Claude settings witness ${reason}`);
14944
+ }
14945
+ function absolutePath2(value) {
14946
+ need3(typeof value === "string" && value.length > 0 && value.length <= CLAUDE_SETTINGS_WITNESS_LIMITS.pathCharacters && !/[\x00-\x1f\x7f]/.test(value) && isAbsolute13(value) && resolve13(value) === value, "requires a normalized absolute path");
14947
+ }
14948
+ var sameFile2 = (a, b) => a.dev === b.dev && a.ino === b.ino && a.mode === b.mode && a.uid === b.uid && a.gid === b.gid && a.nlink === b.nlink && a.size === b.size && a.mtimeNs === b.mtimeNs && a.ctimeNs === b.ctimeNs;
14949
+ function parents2(path) {
14950
+ const result = [];
14951
+ for (let at = dirname13(path);; at = dirname13(at)) {
14952
+ const stat2 = lstatSync16(at, { bigint: true });
14953
+ need3(stat2.isDirectory() && !stat2.isSymbolicLink(), "path traverses a symlink or non-directory");
14954
+ result.push([at, stat2]);
14955
+ if (at === dirname13(at))
14956
+ return result;
14957
+ }
14958
+ }
14959
+ function readSettings(path, budget) {
14960
+ absolutePath2(path);
14961
+ need3(basename7(path) === "settings.json", "requires settings.json");
14962
+ need3(Number.isSafeInteger(budget.remaining) && budget.remaining >= 0, "has an invalid byte budget");
14963
+ const ancestors2 = parents2(path), initial = lstatSync16(path, { bigint: true });
14964
+ need3(initial.isFile() && !initial.isSymbolicLink() && initial.size <= BigInt(CLAUDE_SETTINGS_WITNESS_LIMITS.bytes), "is not a bounded regular file");
14965
+ need3(initial.size <= BigInt(budget.remaining), "exceeds its aggregate byte limit");
14966
+ const fd = openSync10(path, constants9.O_RDONLY | constants9.O_NOFOLLOW | constants9.O_NONBLOCK);
14967
+ try {
14968
+ const opened = fstatSync10(fd, { bigint: true });
14969
+ need3(opened.isFile() && sameFile2(initial, opened), "changed during open");
14970
+ const bytes = Buffer.alloc(Number(opened.size) + 1);
14971
+ let length = 0;
14972
+ while (length < bytes.length) {
14973
+ const count = readSync8(fd, bytes, length, bytes.length - length, null);
14974
+ if (!count)
14975
+ break;
14976
+ length += count;
14977
+ }
14978
+ const after = fstatSync10(fd, { bigint: true }), current = lstatSync16(path, { bigint: true });
14979
+ need3(current.isFile() && sameFile2(opened, after) && sameFile2(after, current) && BigInt(length) === opened.size, "changed during read");
14980
+ for (const [ancestor, before] of ancestors2) {
14981
+ const now = lstatSync16(ancestor, { bigint: true });
14982
+ need3(now.isDirectory() && before.dev === now.dev && before.ino === now.ino && before.mode === now.mode, "parent changed during read");
14983
+ }
14984
+ budget.remaining -= length;
14985
+ try {
14986
+ return new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(bytes.subarray(0, length));
14987
+ } catch {
14988
+ throw new Error("Claude settings witness is not strict UTF-8");
14989
+ }
14990
+ } finally {
14991
+ closeSync10(fd);
14992
+ }
14993
+ }
14994
+ function parse6(text2) {
14995
+ let at = 0, nodes = 0;
14996
+ const numberPattern = /-?(?:0|[1-9][0-9]*)(?:\.[0-9]+)?(?:[eE][+-]?[0-9]+)?/y;
14997
+ const space = () => {
14998
+ while (at < text2.length && /[\x20\t\r\n]/.test(text2[at]))
14999
+ at++;
15000
+ };
15001
+ function string() {
15002
+ need3(text2[at] === '"', "contains invalid JSON");
15003
+ const start = at++;
15004
+ while (at < text2.length) {
15005
+ const character = text2[at++];
15006
+ if (character === '"') {
15007
+ let value2;
15008
+ try {
15009
+ value2 = JSON.parse(text2.slice(start, at));
15010
+ } catch {
15011
+ throw new Error("Claude settings witness contains invalid JSON string");
15012
+ }
15013
+ need3(value2.length <= CLAUDE_SETTINGS_WITNESS_LIMITS.stringCharacters, "exceeds its string limit");
15014
+ return value2;
15015
+ }
15016
+ if (character === "\\")
15017
+ at++;
15018
+ }
15019
+ throw new Error("Claude settings witness contains an unterminated JSON string");
15020
+ }
15021
+ function value(depth) {
15022
+ need3(depth <= CLAUDE_SETTINGS_WITNESS_LIMITS.depth && ++nodes <= CLAUDE_SETTINGS_WITNESS_LIMITS.nodes, "exceeds its nesting or node limit");
15023
+ space();
15024
+ const character = text2[at];
15025
+ if (character === '"')
15026
+ return { kind: "string", value: string() };
15027
+ if (character === "{" || character === "[") {
15028
+ at++;
15029
+ space();
15030
+ const object4 = character === "{", end = object4 ? "}" : "]", entries = [], items = [], keys = new Set;
15031
+ if (text2[at] !== end)
15032
+ while (true) {
15033
+ if (object4) {
15034
+ space();
15035
+ const key = string();
15036
+ need3(!keys.has(key), "contains a duplicate JSON key");
15037
+ keys.add(key);
15038
+ space();
15039
+ need3(text2[at++] === ":", "contains invalid JSON");
15040
+ entries.push([key, value(depth + 1)]);
15041
+ } else
15042
+ items.push(value(depth + 1));
15043
+ space();
15044
+ if (text2[at] === end)
15045
+ break;
15046
+ need3(text2[at++] === ",", "contains invalid JSON");
15047
+ }
15048
+ at++;
15049
+ return object4 ? { kind: "object", entries } : { kind: "array", items };
15050
+ }
15051
+ for (const literal of ["true", "false", "null"])
15052
+ if (text2.startsWith(literal, at)) {
15053
+ at += literal.length;
15054
+ return { kind: "literal", value: literal };
15055
+ }
15056
+ numberPattern.lastIndex = at;
15057
+ const number = numberPattern.exec(text2);
15058
+ need3(number, "contains invalid JSON");
15059
+ at += number[0].length;
15060
+ return { kind: "number", value: number[0] };
15061
+ }
15062
+ const root2 = value(0);
15063
+ space();
15064
+ need3(at === text2.length && root2.kind === "object", "requires a JSON object without trailing content");
15065
+ need3(root2.entries.length <= CLAUDE_SETTINGS_WITNESS_LIMITS.rows, "exceeds its settings field limit");
15066
+ return root2;
15067
+ }
15068
+ var BOOLEAN_PREFERENCES = new Set([
15069
+ "autoScrollEnabled",
15070
+ "axScreenReader",
15071
+ "emojiCompletionEnabled",
15072
+ "prefersReducedMotion",
15073
+ "showTurnDuration",
15074
+ "spinnerTipsEnabled",
15075
+ "syntaxHighlightingDisabled",
15076
+ "terminalProgressBarEnabled",
15077
+ "terminalTitleFromRename",
15078
+ "verbose",
15079
+ "wheelScrollAccelerationEnabled"
15080
+ ]);
15081
+ var ENUM_PREFERENCES = Object.freeze({
15082
+ editorMode: ["normal", "vim"],
15083
+ tui: ["default", "fullscreen"],
15084
+ viewMode: ["default", "verbose", "focus"]
15085
+ });
15086
+ var BUILTIN_MODEL_SELECTIONS = new Set([
15087
+ "default",
15088
+ "best",
15089
+ "fable",
15090
+ "fable[1m]",
15091
+ "sonnet",
15092
+ "sonnet[1m]",
15093
+ "opus",
15094
+ "opus[1m]",
15095
+ "haiku",
15096
+ "opusplan",
15097
+ "claude-fable-5-1",
15098
+ "claude-fable-5",
15099
+ "claude-fable-5[1m]",
15100
+ "claude-opus-5",
15101
+ "claude-sonnet-5",
15102
+ "claude-haiku-4-5-20251001",
15103
+ "claude-opus-4-6",
15104
+ "claude-sonnet-4-5",
15105
+ "claude-sonnet-4-5-20250929",
15106
+ "claude-opus-4-8",
15107
+ "claude-opus-4-8[1m]",
15108
+ "claude-opus-4-7",
15109
+ "claude-sonnet-4-6",
15110
+ "claude-opus-4-5-20251101",
15111
+ "claude-opus-4-5",
15112
+ "claude-haiku-4-5",
15113
+ "claude-fable-5-1[1m]",
15114
+ "claude-opus-5[1m]",
15115
+ "claude-opus-4-7[1m]",
15116
+ "claude-opus-4-6[1m]",
15117
+ "claude-sonnet-4-6[1m]"
15118
+ ]);
15119
+ function canonical3(value) {
15120
+ if (value.kind === "object")
15121
+ return { kind: "object", entries: value.entries.map(([key, child]) => [key, canonical3(child)]).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0) };
15122
+ if (value.kind === "array")
15123
+ return { kind: "array", items: value.items.map(canonical3) };
15124
+ return value;
15125
+ }
15126
+ function settingsDigest(text2) {
15127
+ const value = parse6(text2);
15128
+ value.entries = value.entries.filter(([key, child]) => {
15129
+ if (key === "model") {
15130
+ need3(child.kind === "string", "contains an invalid model selection");
15131
+ return !BUILTIN_MODEL_SELECTIONS.has(child.value);
15132
+ }
15133
+ if (BOOLEAN_PREFERENCES.has(key)) {
15134
+ need3(child.kind === "literal" && (child.value === "true" || child.value === "false"), "contains an invalid display preference");
15135
+ return false;
15136
+ }
15137
+ if (Object.hasOwn(ENUM_PREFERENCES, key)) {
15138
+ need3(child.kind === "string" && ENUM_PREFERENCES[key].includes(child.value), "contains an invalid display preference");
15139
+ return false;
15140
+ }
15141
+ return true;
15142
+ });
15143
+ return createHash12("sha256").update("hasna.skills.claude-settings.v1\x00").update(JSON.stringify(canonical3(value))).digest("hex");
15144
+ }
15145
+ function hashClaudeSettingsReplacement(text2, budget) {
15146
+ need3(typeof text2 === "string", "requires settings text");
15147
+ const bytes = Buffer.byteLength(text2);
15148
+ need3(bytes <= CLAUDE_SETTINGS_WITNESS_LIMITS.bytes && Number.isSafeInteger(budget.remaining) && budget.remaining >= bytes, "exceeds its byte limit");
15149
+ budget.remaining -= bytes;
15150
+ return settingsDigest(text2);
15151
+ }
15152
+ function captureClaudeSettings(path, budget = { remaining: 256 * 1024 * 1024 }) {
15153
+ return { path, hashMode: "claude-settings-v1", sha256: settingsDigest(readSettings(path, budget)) };
15154
+ }
15155
+
14934
15156
  // src/lib/agent-discovery.ts
14935
- var digest = (text2) => createHash12("sha256").update(text2).digest("hex");
15157
+ var digest = (text2) => createHash13("sha256").update(text2).digest("hex");
14936
15158
  function parseConfig(text2, path, toml = false) {
14937
15159
  try {
14938
15160
  const value = toml ? Bun.TOML.parse(text2) : JSON.parse(text2);
@@ -14944,12 +15166,12 @@ function parseConfig(text2, path, toml = false) {
14944
15166
  }
14945
15167
  }
14946
15168
  function safe4(path) {
14947
- if (!isAbsolute13(path) || path.includes("\x00"))
15169
+ if (!isAbsolute14(path) || path.includes("\x00"))
14948
15170
  throw new Error("Expected an absolute native discovery path");
14949
- for (let cursor = path;; cursor = dirname13(cursor)) {
14950
- if (lstatSync16(cursor, { throwIfNoEntry: false })?.isSymbolicLink())
15171
+ for (let cursor = path;; cursor = dirname14(cursor)) {
15172
+ if (lstatSync17(cursor, { throwIfNoEntry: false })?.isSymbolicLink())
14951
15173
  throw new Error(`Refusing symlink native discovery input: ${cursor}`);
14952
- if (dirname13(cursor) === cursor)
15174
+ if (dirname14(cursor) === cursor)
14953
15175
  break;
14954
15176
  }
14955
15177
  }
@@ -14957,7 +15179,7 @@ function read(path, changes) {
14957
15179
  safe4(path);
14958
15180
  if (changes?.has(path))
14959
15181
  return changes.get(path);
14960
- const stat2 = lstatSync16(path, { throwIfNoEntry: false });
15182
+ const stat2 = lstatSync17(path, { throwIfNoEntry: false });
14961
15183
  if (!stat2)
14962
15184
  return null;
14963
15185
  if (!stat2.isFile() || stat2.size > 16 * 1024 * 1024)
@@ -14965,6 +15187,14 @@ function read(path, changes) {
14965
15187
  return readFileSync13(path, "utf8");
14966
15188
  }
14967
15189
  function projected(source, changes, budget = discoveryByteBudget()) {
15190
+ if (source.hashMode === "claude-settings-v1") {
15191
+ if (source.format !== undefined || source.fields !== undefined || source.managedPlugins !== undefined || typeof source.sha256 !== "string" || !/^[a-f0-9]{64}$/.test(source.sha256))
15192
+ throw new Error("Claude settings witnesses require exact typed metadata");
15193
+ const current = captureClaudeSettings(source.path, budget).sha256;
15194
+ if (current !== source.sha256)
15195
+ throw new Error(`Native discovery input changed; run skills hook install with a fresh discovery review: ${source.path}`);
15196
+ return changes?.has(source.path) ? hashClaudeSettingsReplacement(changes.get(source.path), budget) : current;
15197
+ }
14968
15198
  if (source.hashMode === "claude-marketplace-registry") {
14969
15199
  if (source.format !== undefined || source.fields !== undefined || source.managedPlugins !== undefined || typeof source.sha256 !== "string" || !/^[a-f0-9]{64}$/.test(source.sha256) || changes?.has(source.path))
14970
15200
  throw new Error("Claude marketplace witnesses require an exact reviewed registry without synthetic changes");
@@ -15022,6 +15252,8 @@ function verifyAgentDiscovery(binding) {
15022
15252
  safe4(root2);
15023
15253
  }
15024
15254
  function assertMarketplaceBinding(binding, source) {
15255
+ if (source.hashMode === "claude-settings-v1" && (binding.agent !== "claude" || binding.method !== "reviewed" || basename8(source.path) !== "settings.json"))
15256
+ throw new Error("Claude settings witnesses require explicit reviewed Claude configuration");
15025
15257
  if (source.hashMode === "claude-marketplace-registry" && (binding.agent !== "claude" || binding.method !== "reviewed"))
15026
15258
  throw new Error("Claude marketplace witnesses require explicit reviewed Claude discovery");
15027
15259
  }
@@ -15045,10 +15277,10 @@ function captureDiscoveryPathSources(paths) {
15045
15277
  return paths.map((path) => ({ path, hashMode: "path-bytes", sha256: hashDiscoveryPathFile(path, budget) }));
15046
15278
  }
15047
15279
  function resolveAgentDiscovery(options) {
15048
- const canonical3 = options.canonical ?? resolve13, home = resolve13(options.home), agent = options.agent;
15280
+ const canonical4 = options.canonical ?? resolve14, home = resolve14(options.home), agent = options.agent;
15049
15281
  const sources = [], roots = new Set, builtinNames = [];
15050
15282
  const witness = (path, format, fields) => {
15051
- const source = { path: canonical3(path), sha256: null, ...format ? { format, fields } : {} };
15283
+ const source = { path: canonical4(path), sha256: null, ...format ? { format, fields } : {} };
15052
15284
  source.sha256 = projected(source);
15053
15285
  sources.push(source);
15054
15286
  return read(source.path);
@@ -15076,7 +15308,7 @@ function resolveAgentDiscovery(options) {
15076
15308
  continue;
15077
15309
  if (normalized.startsWith("~") && normalized !== "~" && !normalized.startsWith("~/"))
15078
15310
  unresolved("user-specific tilde expansion requires a separate discovery adapter");
15079
- const path = normalized === "~" ? home : normalized.startsWith("~/") ? join23(home, normalized.slice(2)) : resolve13(home, ".hermes", normalized);
15311
+ const path = normalized === "~" ? home : normalized.startsWith("~/") ? join23(home, normalized.slice(2)) : resolve14(home, ".hermes", normalized);
15080
15312
  safe4(path);
15081
15313
  roots.add(path);
15082
15314
  }
@@ -15085,21 +15317,21 @@ function resolveAgentDiscovery(options) {
15085
15317
  const executable = Bun.which("gemini");
15086
15318
  if (executable) {
15087
15319
  let packageRoot;
15088
- for (let directory = dirname13(realpathSync4(executable)), depth = 0;depth < 8; directory = dirname13(directory), depth++) {
15320
+ for (let directory = dirname14(realpathSync4(executable)), depth = 0;depth < 8; directory = dirname14(directory), depth++) {
15089
15321
  const path = join23(directory, "package.json"), raw = read(path);
15090
15322
  if (raw !== null && parseConfig(raw, path).name === "@google/gemini-cli") {
15091
15323
  packageRoot = directory;
15092
15324
  witness(path);
15093
15325
  break;
15094
15326
  }
15095
- if (dirname13(directory) === directory)
15327
+ if (dirname14(directory) === directory)
15096
15328
  break;
15097
15329
  }
15098
15330
  if (!packageRoot)
15099
15331
  unresolved("installed Gemini package layout is not recognized");
15100
15332
  const builtinRoot = join23(packageRoot, "bundle/builtin");
15101
15333
  safe4(builtinRoot);
15102
- if (!lstatSync16(builtinRoot, { throwIfNoEntry: false })?.isDirectory())
15334
+ if (!lstatSync17(builtinRoot, { throwIfNoEntry: false })?.isDirectory())
15103
15335
  unresolved("installed Gemini builtin root is missing");
15104
15336
  for (const name of readdirSync9(builtinRoot).sort()) {
15105
15337
  const text2 = witness(join23(builtinRoot, name, "SKILL.md"));
@@ -15120,12 +15352,14 @@ function resolveAgentDiscovery(options) {
15120
15352
  if (review.sources.some((source) => source.format !== undefined || source.fields !== undefined))
15121
15353
  throw new Error("Explicit discovery reviews require full source-file hashes");
15122
15354
  verifyAgentDiscovery(supplied);
15123
- if (!review.sources.some((source) => source.path === canonical3(configPath)))
15355
+ if (review.sources.some((source) => source.hashMode === "claude-settings-v1" && source.path !== canonical4(configPath)))
15356
+ throw new Error("Semantic settings witnesses must name the configured Claude configuration source");
15357
+ if (!review.sources.some((source) => source.path === canonical4(configPath)))
15124
15358
  throw new Error("Discovery review must include the agent configuration source");
15125
15359
  return { ...supplied, roots: [...new Set([...roots, ...supplied.roots])].sort(), sources: [...sources, ...review.sources], ...agent === "gemini" ? { builtinNames } : {} };
15126
15360
  }
15127
15361
  function plugin(root2) {
15128
- root2 = canonical3(root2);
15362
+ root2 = canonical4(root2);
15129
15363
  safe4(root2);
15130
15364
  const manifestPath = join23(root2, agent === "claude" ? ".claude-plugin/plugin.json" : ".codex-plugin/plugin.json");
15131
15365
  const raw = witness(manifestPath);
@@ -15137,7 +15371,7 @@ function resolveAgentDiscovery(options) {
15137
15371
  unresolved("plugin hooks require a separate no-skill-injection review");
15138
15372
  const commands = join23(root2, "commands");
15139
15373
  safe4(commands);
15140
- if (agent === "claude" && (manifest.commands !== undefined || lstatSync16(commands, { throwIfNoEntry: false })?.isDirectory() && readdirSync9(commands).length))
15374
+ if (agent === "claude" && (manifest.commands !== undefined || lstatSync17(commands, { throwIfNoEntry: false })?.isDirectory() && readdirSync9(commands).length))
15141
15375
  unresolved("legacy command discovery requires retirement or a dedicated format adapter");
15142
15376
  const rootSkill = witness(join23(root2, "SKILL.md"));
15143
15377
  if (rootSkill !== null)
@@ -15148,18 +15382,18 @@ function resolveAgentDiscovery(options) {
15148
15382
  if (agent === "claude")
15149
15383
  roots.add(join23(root2, "skills"));
15150
15384
  for (const value of declared) {
15151
- const path = resolve13(root2, value);
15385
+ const path = resolve14(root2, value);
15152
15386
  if (path !== root2 && !path.startsWith(root2 + sep5))
15153
15387
  unresolved("plugin skill path escapes its root");
15154
- roots.add(path.endsWith(`${sep5}SKILL.md`) ? dirname13(path) : path);
15388
+ roots.add(path.endsWith(`${sep5}SKILL.md`) ? dirname14(path) : path);
15155
15389
  }
15156
15390
  }
15157
15391
  if (agent === "claude") {
15158
15392
  const registrations = witness(join23(home, ".claude/plugins/installed_plugins.json"));
15159
15393
  const installed = registrations === null ? {} : parseConfig(registrations, join23(home, ".claude/plugins/installed_plugins.json")).plugins;
15160
- const commands = canonical3(join23(home, ".claude/commands"));
15394
+ const commands = canonical4(join23(home, ".claude/commands"));
15161
15395
  safe4(commands);
15162
- if (lstatSync16(commands, { throwIfNoEntry: false })?.isDirectory() && readdirSync9(commands).length)
15396
+ if (lstatSync17(commands, { throwIfNoEntry: false })?.isDirectory() && readdirSync9(commands).length)
15163
15397
  unresolved("legacy home command discovery requires a dedicated format adapter");
15164
15398
  for (const [id, enabled] of Object.entries(config.enabledPlugins ?? {})) {
15165
15399
  if (enabled === false)
@@ -15179,7 +15413,7 @@ function resolveAgentDiscovery(options) {
15179
15413
  unresolved("unsupported plugin enablement");
15180
15414
  const split = id.lastIndexOf("@"), name = id.slice(0, split), marketplace = id.slice(split + 1);
15181
15415
  const market = config.marketplaces?.[marketplace] ?? (marketplace === "personal" ? { source_type: "local", source: home } : undefined);
15182
- if (split < 1 || market?.source_type !== "local" || typeof market.source !== "string" || !isAbsolute13(market.source))
15416
+ if (split < 1 || market?.source_type !== "local" || typeof market.source !== "string" || !isAbsolute14(market.source))
15183
15417
  unresolved("enabled plugin marketplace is not an explicit local source");
15184
15418
  const catalogText = witness(join23(market.source, ".agents/plugins/marketplace.json"));
15185
15419
  if (catalogText === null)
@@ -15187,7 +15421,7 @@ function resolveAgentDiscovery(options) {
15187
15421
  const catalog = parseConfig(catalogText, join23(market.source, ".agents/plugins/marketplace.json")), matches = Array.isArray(catalog.plugins) ? catalog.plugins.filter((item) => item.name === name) : [];
15188
15422
  if (matches.length !== 1 || matches[0]?.source?.source !== "local" || typeof matches[0]?.source?.path !== "string")
15189
15423
  unresolved("plugin catalog source is missing or ambiguous");
15190
- plugin(resolve13(market.source, matches[0].source.path));
15424
+ plugin(resolve14(market.source, matches[0].source.path));
15191
15425
  }
15192
15426
  } else if (agent === "opencode") {
15193
15427
  if (witness(join23(home, ".config/opencode/opencode.jsonc")) !== null || witness(join23(home, ".config/opencode/config.json")) !== null)
@@ -15195,18 +15429,18 @@ function resolveAgentDiscovery(options) {
15195
15429
  if ((config.plugin?.length ?? 0) > 0 || config.skills?.urls?.length)
15196
15430
  unresolved("external plugin or remote skill source");
15197
15431
  for (const path of config.skills?.paths ?? []) {
15198
- if (typeof path !== "string" || !isAbsolute13(path))
15432
+ if (typeof path !== "string" || !isAbsolute14(path))
15199
15433
  unresolved("relative or malformed added skill root");
15200
15434
  roots.add(path);
15201
15435
  }
15202
15436
  const localPlugins = join23(home, ".config/opencode/plugins");
15203
15437
  safe4(localPlugins);
15204
- if (lstatSync16(localPlugins, { throwIfNoEntry: false }) && readdirSync9(localPlugins).some((name) => name !== "skills-cli.js"))
15438
+ if (lstatSync17(localPlugins, { throwIfNoEntry: false }) && readdirSync9(localPlugins).some((name) => name !== "skills-cli.js"))
15205
15439
  unresolved("additional local plugin hooks require review");
15206
15440
  } else if (agent === "hermes") {
15207
15441
  for (const directory of [join23(home, ".hermes/plugins"), join23(home, ".hermes/hermes-agent")]) {
15208
15442
  safe4(directory);
15209
- if (lstatSync16(directory, { throwIfNoEntry: false }))
15443
+ if (lstatSync17(directory, { throwIfNoEntry: false }))
15210
15444
  unresolved("installed runtime/plugin discovery requires reviewed source bindings");
15211
15445
  }
15212
15446
  if (Bun.which("hermes") || Object.keys(config.plugins ?? {}).length)
@@ -15216,11 +15450,11 @@ function resolveAgentDiscovery(options) {
15216
15450
  unresolved("custom extension or skill paths");
15217
15451
  const directory = join23(home, ".gemini/extensions");
15218
15452
  safe4(directory);
15219
- if (lstatSync16(directory, { throwIfNoEntry: false }))
15453
+ if (lstatSync17(directory, { throwIfNoEntry: false }))
15220
15454
  for (const name of readdirSync9(directory)) {
15221
15455
  const root2 = join23(directory, name);
15222
15456
  safe4(root2);
15223
- if (!lstatSync16(root2)?.isDirectory())
15457
+ if (!lstatSync17(root2)?.isDirectory())
15224
15458
  continue;
15225
15459
  const raw = witness(join23(root2, "gemini-extension.json"));
15226
15460
  if (raw === null)
@@ -15231,7 +15465,7 @@ function resolveAgentDiscovery(options) {
15231
15465
  roots.add(join23(root2, "skills"));
15232
15466
  }
15233
15467
  }
15234
- return { agent, roots: [...roots].sort(), sources, method: "automatic", ...agent === "gemini" ? { builtinNames } : {}, ...agent === "hermes" ? { directories: captureDiscoveryDirectories([join23(home, ".hermes/plugins"), join23(home, ".hermes/hermes-agent")].map((path) => canonical3(path))) } : {} };
15468
+ return { agent, roots: [...roots].sort(), sources, method: "automatic", ...agent === "gemini" ? { builtinNames } : {}, ...agent === "hermes" ? { directories: captureDiscoveryDirectories([join23(home, ".hermes/plugins"), join23(home, ".hermes/hermes-agent")].map((path) => canonical4(path))) } : {} };
15235
15469
  }
15236
15470
 
15237
15471
  // src/lib/agent-adapters.ts
@@ -15375,7 +15609,7 @@ function disableCodexBundledSkills(text2) {
15375
15609
  }
15376
15610
 
15377
15611
  // src/lib/agent-integration.ts
15378
- var sha = (data) => createHash13("sha256").update(data).digest("hex");
15612
+ var sha = (data) => createHash14("sha256").update(data).digest("hex");
15379
15613
  var ROOTS = [
15380
15614
  ["claude", ".claude/skills"],
15381
15615
  ["codex", ".codex/skills"],
@@ -15394,11 +15628,11 @@ var ROOTS = [
15394
15628
  ["copilot", ".github/skills"]
15395
15629
  ];
15396
15630
  function assertSafePath(path) {
15397
- let cursor = resolve14(path);
15631
+ let cursor = resolve15(path);
15398
15632
  while (true) {
15399
- if (lstatSync17(cursor, { throwIfNoEntry: false })?.isSymbolicLink())
15633
+ if (lstatSync18(cursor, { throwIfNoEntry: false })?.isSymbolicLink())
15400
15634
  throw new Error(`Refusing symlink path: ${cursor}`);
15401
- const parent = dirname14(cursor);
15635
+ const parent = dirname15(cursor);
15402
15636
  if (parent === cursor)
15403
15637
  return;
15404
15638
  cursor = parent;
@@ -15407,16 +15641,16 @@ function assertSafePath(path) {
15407
15641
  function readRootAlias(home, agent) {
15408
15642
  assertSafePath(home);
15409
15643
  const realHome = realpathSync5(home), alias = join25(realHome, `.${agent}`);
15410
- const stat2 = lstatSync17(alias, { throwIfNoEntry: false, bigint: true });
15644
+ const stat2 = lstatSync18(alias, { throwIfNoEntry: false, bigint: true });
15411
15645
  if (!stat2?.isSymbolicLink())
15412
15646
  throw new Error(`Agent root alias changed after planning: ${alias}`);
15413
- const link = readlinkSync2(alias), targetPath = resolve14(dirname14(alias), link);
15647
+ const link = readlinkSync2(alias), targetPath = resolve15(dirname15(alias), link);
15414
15648
  assertSafePath(targetPath);
15415
- const targetStat = lstatSync17(targetPath, { throwIfNoEntry: false });
15649
+ const targetStat = lstatSync18(targetPath, { throwIfNoEntry: false });
15416
15650
  if (!targetStat?.isDirectory())
15417
15651
  throw new Error(`Agent root alias must target an existing directory: ${alias}`);
15418
15652
  const target = realpathSync5(targetPath), inside = relative5(realHome, target);
15419
- if (!inside || inside === ".." || inside.startsWith(`..${sep6}`) || isAbsolute14(inside))
15653
+ if (!inside || inside === ".." || inside.startsWith(`..${sep6}`) || isAbsolute15(inside))
15420
15654
  throw new Error(`Agent root alias target must be inside the real home: ${alias}`);
15421
15655
  return { agent, home: realHome, alias, target, link, aliasIdentity: `${stat2.dev}:${stat2.ino}:${stat2.ctimeNs}`, targetIdentity: `${targetStat.dev}:${targetStat.ino}` };
15422
15656
  }
@@ -15425,14 +15659,14 @@ function rootAliases(home, allowed = false) {
15425
15659
  return [];
15426
15660
  const result = [];
15427
15661
  for (const agent of ["claude", "codex"])
15428
- if (lstatSync17(join25(home, `.${agent}`), { throwIfNoEntry: false })?.isSymbolicLink())
15662
+ if (lstatSync18(join25(home, `.${agent}`), { throwIfNoEntry: false })?.isSymbolicLink())
15429
15663
  result.push(readRootAlias(home, agent));
15430
15664
  if (result.some((item, index) => result.slice(index + 1).some((other) => item.target === other.target || item.target.startsWith(other.target + sep6) || other.target.startsWith(item.target + sep6))))
15431
15665
  throw new Error("Agent root alias targets must not overlap");
15432
15666
  return result;
15433
15667
  }
15434
15668
  function canonicalAgentPath(path, aliases) {
15435
- const absolute = resolve14(path), binding = aliases.find((item) => absolute === item.alias || absolute.startsWith(item.alias + sep6));
15669
+ const absolute = resolve15(path), binding = aliases.find((item) => absolute === item.alias || absolute.startsWith(item.alias + sep6));
15436
15670
  return binding ? join25(binding.target, relative5(binding.alias, absolute)) : absolute;
15437
15671
  }
15438
15672
  function recheckRootAliases(aliases) {
@@ -15446,35 +15680,35 @@ function recheckRootAliases(aliases) {
15446
15680
  }
15447
15681
  function readNativeBytes(path, maximum = 64 * 1024 * 1024) {
15448
15682
  assertSafePath(path);
15449
- const before = lstatSync17(path);
15683
+ const before = lstatSync18(path);
15450
15684
  if (!before.isFile() || before.size > maximum)
15451
15685
  throw new Error("Unsupported or oversized native skill file");
15452
- const descriptor = openSync10(path, constants9.O_RDONLY | constants9.O_NOFOLLOW | constants9.O_NONBLOCK);
15686
+ const descriptor = openSync11(path, constants10.O_RDONLY | constants10.O_NOFOLLOW | constants10.O_NONBLOCK);
15453
15687
  try {
15454
- const opened = fstatSync10(descriptor);
15688
+ const opened = fstatSync11(descriptor);
15455
15689
  if (!opened.isFile() || opened.dev !== before.dev || opened.ino !== before.ino || opened.size !== before.size)
15456
15690
  throw new Error("Native skill file changed while reading");
15457
15691
  const bytes = Buffer.allocUnsafe(before.size + 1);
15458
15692
  let length = 0;
15459
15693
  while (length < bytes.length) {
15460
- const count = readSync8(descriptor, bytes, length, bytes.length - length, null);
15694
+ const count = readSync9(descriptor, bytes, length, bytes.length - length, null);
15461
15695
  if (!count)
15462
15696
  break;
15463
15697
  length += count;
15464
15698
  }
15465
- const after = fstatSync10(descriptor);
15699
+ const after = fstatSync11(descriptor);
15466
15700
  if (length !== before.size || after.size !== before.size || after.mtimeMs !== opened.mtimeMs || after.ctimeMs !== opened.ctimeMs)
15467
15701
  throw new Error("Native skill file changed while reading");
15468
15702
  return bytes.subarray(0, length);
15469
15703
  } finally {
15470
- closeSync10(descriptor);
15704
+ closeSync11(descriptor);
15471
15705
  }
15472
15706
  }
15473
15707
  function treeHash(root2) {
15474
- const hash2 = createHash13("sha256");
15708
+ const hash2 = createHash14("sha256");
15475
15709
  let bytes = 0, files = 0;
15476
15710
  function visit2(path) {
15477
- const stat2 = lstatSync17(path);
15711
+ const stat2 = lstatSync18(path);
15478
15712
  if (stat2.isSymbolicLink())
15479
15713
  throw new Error(`Refusing symlink in skill: ${path}`);
15480
15714
  const rel = relative5(root2, path);
@@ -15500,11 +15734,11 @@ function treeHash(root2) {
15500
15734
  function projectAncestorDirectories(projects) {
15501
15735
  const directories = new Set;
15502
15736
  for (const project of projects) {
15503
- for (let path = resolve14(project), depth = 0;; depth++) {
15737
+ for (let path = resolve15(project), depth = 0;; depth++) {
15504
15738
  if (depth >= 100)
15505
15739
  throw new Error("NATIVE_SKILL_DRIFT: project ancestor discovery limit exceeded");
15506
15740
  directories.add(path);
15507
- const parent = dirname14(path);
15741
+ const parent = dirname15(path);
15508
15742
  if (parent === path)
15509
15743
  break;
15510
15744
  path = parent;
@@ -15531,10 +15765,10 @@ function inventoryNativeSkills(home = homedir3(), options = {}) {
15531
15765
  throw new Error("Native skill discovery metadata limit exceeded");
15532
15766
  }
15533
15767
  function emptySiblingCacheAlias(path, parent) {
15534
- const link = readlinkSync2(path), target = resolve14(parent, link);
15535
- if (dirname14(target) !== parent || (isAbsolute14(link) ? link !== target : dirname14(link) !== "."))
15768
+ const link = readlinkSync2(path), target = resolve15(parent, link);
15769
+ if (dirname15(target) !== parent || (isAbsolute15(link) ? link !== target : dirname15(link) !== "."))
15536
15770
  return false;
15537
- if (!lstatSync17(target, { throwIfNoEntry: false })?.isDirectory())
15771
+ if (!lstatSync18(target, { throwIfNoEntry: false })?.isDirectory())
15538
15772
  return false;
15539
15773
  const scan = cacheScans.get(target);
15540
15774
  return Boolean(scan?.complete && !scan.hasSkills && scan.entries <= maxAliasProofEntries);
@@ -15546,7 +15780,7 @@ function inventoryNativeSkills(home = homedir3(), options = {}) {
15546
15780
  assertSafePath(path);
15547
15781
  if (!existsSync11(path))
15548
15782
  return scan;
15549
- const stat2 = lstatSync17(path);
15783
+ const stat2 = lstatSync18(path);
15550
15784
  if (stat2.isFile())
15551
15785
  return scan;
15552
15786
  if (!stat2.isDirectory())
@@ -15565,7 +15799,7 @@ function inventoryNativeSkills(home = homedir3(), options = {}) {
15565
15799
  }
15566
15800
  const bridge = !vendor && isOwnedCliBridge(path, bridgePaths);
15567
15801
  const rootAlias = aliases.find((item) => path === item.target || path.startsWith(item.target + sep6));
15568
- entries.push({ agent, path, hash: treeHash(path), managed, vendor, ...agent === "codex" && path.startsWith(canonicalAgentPath(join25(home, ".codex", "skills", ".system"), aliases) + sep6) ? { system: true } : {}, ...bridge ? { bridge: true, bridgeHome: resolve14(home) } : {}, ...rootAlias ? { rootAlias } : {} });
15802
+ entries.push({ agent, path, hash: treeHash(path), managed, vendor, ...agent === "codex" && path.startsWith(canonicalAgentPath(join25(home, ".codex", "skills", ".system"), aliases) + sep6) ? { system: true } : {}, ...bridge ? { bridge: true, bridgeHome: resolve15(home) } : {}, ...rootAlias ? { rootAlias } : {} });
15569
15803
  return scan;
15570
15804
  }
15571
15805
  if (depth > (vendor ? 32 : 3))
@@ -15592,7 +15826,7 @@ function inventoryNativeSkills(home = homedir3(), options = {}) {
15592
15826
  if (isVendor && !options.includeVendor)
15593
15827
  continue;
15594
15828
  const child = join25(path, name);
15595
- if (isVendor && lstatSync17(child, { throwIfNoEntry: false })?.isSymbolicLink()) {
15829
+ if (isVendor && lstatSync18(child, { throwIfNoEntry: false })?.isSymbolicLink()) {
15596
15830
  const target = statSync8(child, { throwIfNoEntry: false });
15597
15831
  if (target?.isFile() || pluginCache && target?.isDirectory() && emptySiblingCacheAlias(child, path)) {
15598
15832
  scan.entries++;
@@ -15714,7 +15948,7 @@ function configureHooks(config, agent, command, profileId, nativeReady) {
15714
15948
  function disableCodexSkills(text2, skills, aliases, bridgePath) {
15715
15949
  const bundled = disableCodexBundledSkills(text2);
15716
15950
  let result = bundled;
15717
- const bridgeSelector = (entry) => typeof entry.name === "string" && entry.name.trim() === CLI_BRIDGE_NAME || typeof entry.path === "string" && [resolve14(bridgePath), resolve14(join25(bridgePath, "SKILL.md"))].includes(canonicalAgentPath(entry.path, aliases));
15951
+ const bridgeSelector = (entry) => typeof entry.name === "string" && entry.name.trim() === CLI_BRIDGE_NAME || typeof entry.path === "string" && [resolve15(bridgePath), resolve15(join25(bridgePath, "SKILL.md"))].includes(canonicalAgentPath(entry.path, aliases));
15718
15952
  const previousConfig = Bun.TOML.parse(bundled).skills?.config;
15719
15953
  if (previousConfig !== undefined && (!Array.isArray(previousConfig) || previousConfig.some((entry) => !entry || typeof entry !== "object" || entry.path !== undefined && entry.name !== undefined)))
15720
15954
  throw new Error("Codex skill controls require one path or name selector per [[skills.config]] entry; review ambiguous entries before running skills hook install");
@@ -15726,7 +15960,7 @@ function disableCodexSkills(text2, skills, aliases, bridgePath) {
15726
15960
  result = result.replace(CODEX_SKILL_CONFIG_SECTIONS, (section) => {
15727
15961
  const parsed = Bun.TOML.parse(section);
15728
15962
  const declared = parsed.skills?.config?.[0];
15729
- if (!declared || !(skill.enabled && bridgeSelector(declared)) && !(typeof declared.path === "string" && [resolve14(path), resolve14(skill.path)].includes(canonicalAgentPath(declared.path, aliases))))
15963
+ if (!declared || !(skill.enabled && bridgeSelector(declared)) && !(typeof declared.path === "string" && [resolve15(path), resolve15(skill.path)].includes(canonicalAgentPath(declared.path, aliases))))
15730
15964
  return section;
15731
15965
  found = true;
15732
15966
  return /^\s*enabled\s*=/m.test(section) ? section.replace(/^\s*enabled\s*=.*$/m, `enabled = ${skill.enabled}`) : `${section.trimEnd()}
@@ -15844,7 +16078,7 @@ function planAgentIntegration(options) {
15844
16078
  version: CLI_BRIDGE_VERSION,
15845
16079
  digest: CLI_BRIDGE_DIGEST,
15846
16080
  agents: [...new Set([...priorAgents, ...options.agents])].sort(),
15847
- home: resolve14(home),
16081
+ home: resolve15(home),
15848
16082
  includeVendor: true,
15849
16083
  ...options.agents.includes("hermes") ? { supervisors: { ...policy.bridge?.supervisors, hermes: { path: join25(dataDir2, "agent-hooks", "hermes.js"), runtime: process.execPath, sha256: sha(renderHermesSupervisor(bindings.get("hermes").command, bindings.get("hermes").profileId)) } } } : {},
15850
16084
  commands: { ...policy.bridge?.commands, ...Object.fromEntries([...bindings].map(([agent, binding]) => [agent, binding.command])) },
@@ -15861,7 +16095,7 @@ function planAgentIntegration(options) {
15861
16095
  }
15862
16096
  function atomicWrite2(path, content) {
15863
16097
  assertSafePath(path);
15864
- mkdirSync7(dirname14(path), { recursive: true, mode: 448 });
16098
+ mkdirSync7(dirname15(path), { recursive: true, mode: 448 });
15865
16099
  const temporary = `${path}.skills-${randomUUID3()}`;
15866
16100
  try {
15867
16101
  writeFileSync5(temporary, content, { mode: 384, flag: "wx" });
@@ -15874,10 +16108,10 @@ function atomicWrite2(path, content) {
15874
16108
  function applyAgentIntegration(plan) {
15875
16109
  const policyPath = join25(plan.dataDir, "agent-policy.json");
15876
16110
  assertSafePath(policyPath);
15877
- const currentText = (path) => resolve14(path) === resolve14(policyPath) ? readManagedSkillPolicySnapshot(plan.dataDir)?.text ?? null : readOptional(path);
16111
+ const currentText = (path) => resolve15(path) === resolve15(policyPath) ? readManagedSkillPolicySnapshot(plan.dataDir)?.text ?? null : readOptional(path);
15878
16112
  readManagedSkillPolicySnapshot(plan.dataDir);
15879
16113
  for (const change of plan.changes)
15880
- if (resolve14(change.path) === resolve14(policyPath))
16114
+ if (resolve15(change.path) === resolve15(policyPath))
15881
16115
  parseManagedSkillPolicy(change.after);
15882
16116
  const aliases = plan.rootAliases ?? [];
15883
16117
  recheckRootAliases(aliases);
@@ -15907,7 +16141,7 @@ function applyAgentIntegration(plan) {
15907
16141
  recheckRootAliases(aliases);
15908
16142
  if (currentText(change.path) !== change.before)
15909
16143
  throw new Error(`Configuration changed after planning: ${change.path}`);
15910
- for (let directory = dirname14(change.path);!existsSync11(directory); directory = dirname14(directory))
16144
+ for (let directory = dirname15(change.path);!existsSync11(directory); directory = dirname15(directory))
15911
16145
  createdDirectories.add(directory);
15912
16146
  const after = change.after;
15913
16147
  atomicWrite2(change.path, after);
@@ -15947,11 +16181,11 @@ function applyAgentIntegration(plan) {
15947
16181
  }
15948
16182
  function syncArchiveDirectory(path) {
15949
16183
  assertSafePath(path);
15950
- const descriptor = openSync10(path, constants9.O_RDONLY | constants9.O_DIRECTORY | constants9.O_NOFOLLOW | constants9.O_NONBLOCK);
16184
+ const descriptor = openSync11(path, constants10.O_RDONLY | constants10.O_DIRECTORY | constants10.O_NOFOLLOW | constants10.O_NONBLOCK);
15951
16185
  try {
15952
16186
  fsyncSync3(descriptor);
15953
16187
  } finally {
15954
- closeSync10(descriptor);
16188
+ closeSync11(descriptor);
15955
16189
  }
15956
16190
  }
15957
16191
  function writeArchiveJournal(path, value) {
@@ -15959,18 +16193,18 @@ function writeArchiveJournal(path, value) {
15959
16193
  const temporary = `${path}.skills-${randomUUID3()}`;
15960
16194
  let descriptor;
15961
16195
  try {
15962
- descriptor = openSync10(temporary, constants9.O_WRONLY | constants9.O_CREAT | constants9.O_EXCL | constants9.O_NOFOLLOW, 384);
16196
+ descriptor = openSync11(temporary, constants10.O_WRONLY | constants10.O_CREAT | constants10.O_EXCL | constants10.O_NOFOLLOW, 384);
15963
16197
  writeFileSync5(descriptor, `${JSON.stringify(value)}
15964
16198
  `);
15965
16199
  fsyncSync3(descriptor);
15966
- closeSync10(descriptor);
16200
+ closeSync11(descriptor);
15967
16201
  descriptor = undefined;
15968
16202
  renameSync4(temporary, path);
15969
- syncArchiveDirectory(dirname14(path));
16203
+ syncArchiveDirectory(dirname15(path));
15970
16204
  } finally {
15971
16205
  if (descriptor !== undefined)
15972
- closeSync10(descriptor);
15973
- if (lstatSync17(temporary, { throwIfNoEntry: false }))
16206
+ closeSync11(descriptor);
16207
+ if (lstatSync18(temporary, { throwIfNoEntry: false }))
15974
16208
  unlinkSync4(temporary);
15975
16209
  }
15976
16210
  }
@@ -16003,7 +16237,7 @@ function archiveNativeSkills(inventory, options) {
16003
16237
  const moved = [];
16004
16238
  const verifyArchive = (entry) => {
16005
16239
  assertSafePath(entry.archive);
16006
- const stat2 = lstatSync17(entry.archive);
16240
+ const stat2 = lstatSync18(entry.archive);
16007
16241
  if (entry.discoveryOnly ? !stat2.isFile() : !stat2.isDirectory())
16008
16242
  throw new Error("Archive type changed");
16009
16243
  if ((entry.discoveryOnly ? sha(readNativeBytes(entry.archive)) : treeHash(entry.archive)) !== entry.hash)
@@ -16011,14 +16245,14 @@ function archiveNativeSkills(inventory, options) {
16011
16245
  };
16012
16246
  assertSafePath(archiveRoot);
16013
16247
  const created = [];
16014
- for (let path = archiveRoot;!existsSync11(path); path = dirname14(path))
16248
+ for (let path = archiveRoot;!existsSync11(path); path = dirname15(path))
16015
16249
  created.push(path);
16016
16250
  mkdirSync7(archiveRoot, { recursive: true, mode: 448 });
16017
16251
  try {
16018
16252
  for (const directory of created)
16019
16253
  syncArchiveDirectory(directory);
16020
16254
  if (created.length)
16021
- syncArchiveDirectory(dirname14(created.at(-1)));
16255
+ syncArchiveDirectory(dirname15(created.at(-1)));
16022
16256
  writeArchiveJournal(receiptPath, journal);
16023
16257
  for (const [index, entry] of selected.entries()) {
16024
16258
  recheckRootAliases(aliases);
@@ -16030,7 +16264,7 @@ function archiveNativeSkills(inventory, options) {
16030
16264
  writeArchiveJournal(receiptPath, journal);
16031
16265
  renameSync4(move.source, move.archive);
16032
16266
  moved.push(move);
16033
- syncArchiveDirectory(dirname14(move.source));
16267
+ syncArchiveDirectory(dirname15(move.source));
16034
16268
  syncArchiveDirectory(archiveRoot);
16035
16269
  verifyArchive(move);
16036
16270
  move.status = "archived";
@@ -16051,7 +16285,7 @@ function archiveNativeSkills(inventory, options) {
16051
16285
  recheckRootAliases(aliases);
16052
16286
  assertSafePath(entry.source);
16053
16287
  assertSafePath(entry.archive);
16054
- if (lstatSync17(entry.source, { throwIfNoEntry: false })) {
16288
+ if (lstatSync18(entry.source, { throwIfNoEntry: false })) {
16055
16289
  entry.status = "recovery-required";
16056
16290
  entry.conflict = "source-occupied";
16057
16291
  continue;
@@ -16065,10 +16299,10 @@ function archiveNativeSkills(inventory, options) {
16065
16299
  }
16066
16300
  if (entry.discoveryOnly) {
16067
16301
  linkSync2(entry.archive, entry.source);
16068
- syncArchiveDirectory(dirname14(entry.source));
16302
+ syncArchiveDirectory(dirname15(entry.source));
16069
16303
  unlinkSync4(entry.archive);
16070
16304
  } else {
16071
- if (lstatSync17(entry.source, { throwIfNoEntry: false })) {
16305
+ if (lstatSync18(entry.source, { throwIfNoEntry: false })) {
16072
16306
  entry.status = "recovery-required";
16073
16307
  entry.conflict = "source-occupied";
16074
16308
  continue;
@@ -16076,7 +16310,7 @@ function archiveNativeSkills(inventory, options) {
16076
16310
  renameSync4(entry.archive, entry.source);
16077
16311
  }
16078
16312
  entry.status = "restored";
16079
- syncArchiveDirectory(dirname14(entry.source));
16313
+ syncArchiveDirectory(dirname15(entry.source));
16080
16314
  syncArchiveDirectory(archiveRoot);
16081
16315
  } catch {
16082
16316
  entry.status = "recovery-required";
@@ -16115,7 +16349,7 @@ function isSkillsOwnershipMarker(marker) {
16115
16349
  function hasSkillsOwnershipMarker(dir) {
16116
16350
  const path = join26(dir, SYNC_MARKER_FILE);
16117
16351
  try {
16118
- if (!lstatSync18(path).isFile())
16352
+ if (!lstatSync19(path).isFile())
16119
16353
  return false;
16120
16354
  const marker = JSON.parse(readFileSync15(path, "utf8"));
16121
16355
  return isSkillsOwnershipMarker(marker);
@@ -16341,9 +16575,9 @@ function writeManagedSkillDir(dir, skillMd, options) {
16341
16575
  const action = dirExists ? "update" : "create";
16342
16576
  if (options.dryRun)
16343
16577
  return { action, path: skillMdPath };
16344
- const parentDir = dirname15(dir);
16578
+ const parentDir = dirname16(dir);
16345
16579
  mkdirSync8(parentDir, { recursive: true });
16346
- const transactionDir = mkdtempSync2(join26(parentDir, `.hasna-skills-write-${basename7(dir)}-`));
16580
+ const transactionDir = mkdtempSync2(join26(parentDir, `.hasna-skills-write-${basename9(dir)}-`));
16347
16581
  const candidateDir = join26(transactionDir, "candidate");
16348
16582
  const backupDir = join26(transactionDir, "backup");
16349
16583
  const candidateSkillMdPath = join26(candidateDir, "SKILL.md");
@@ -16832,7 +17066,7 @@ function loadProjectConfigCompat(targetDir) {
16832
17066
  return loadProjectConfig(targetDir);
16833
17067
  }
16834
17068
  // src/lib/run-state.ts
16835
- import { createHash as createHash14, randomBytes } from "crypto";
17069
+ import { createHash as createHash15, randomBytes } from "crypto";
16836
17070
  import { existsSync as existsSync15, mkdirSync as mkdirSync10, readFileSync as readFileSync18, readdirSync as readdirSync12, statSync as statSync10, writeFileSync as writeFileSync8 } from "fs";
16837
17071
  import { extname, join as join29, relative as relative6 } from "path";
16838
17072
  function createSkillRun(params, targetDir = process.cwd()) {
@@ -16959,7 +17193,7 @@ function collectRunArtifacts(context) {
16959
17193
  artifacts.push({
16960
17194
  path: toProjectRelative(context.targetDir, path),
16961
17195
  mime: mimeForPath(path),
16962
- sha256: createHash14("sha256").update(bytes).digest("hex"),
17196
+ sha256: createHash15("sha256").update(bytes).digest("hex"),
16963
17197
  sizeBytes: stat2.size
16964
17198
  });
16965
17199
  }
@@ -17087,7 +17321,7 @@ __export(exports_external, {
17087
17321
  pipe: () => pipe,
17088
17322
  partialRecord: () => partialRecord,
17089
17323
  parseAsync: () => parseAsync2,
17090
- parse: () => parse8,
17324
+ parse: () => parse9,
17091
17325
  overwrite: () => _overwrite,
17092
17326
  output: () => output,
17093
17327
  optional: () => optional,
@@ -17307,7 +17541,7 @@ __export(exports_core2, {
17307
17541
  prettifyError: () => prettifyError,
17308
17542
  parseURLObject: () => parseURLObject,
17309
17543
  parseAsync: () => parseAsync,
17310
- parse: () => parse6,
17544
+ parse: () => parse7,
17311
17545
  meta: () => meta,
17312
17546
  mergeValues: () => mergeValues,
17313
17547
  memoizer: () => memoizer,
@@ -18761,7 +18995,7 @@ var _parse = (_Err) => {
18761
18995
  };
18762
18996
  return fn;
18763
18997
  };
18764
- var parse6 = /* @__PURE__ */ _parse($ZodRealError);
18998
+ var parse7 = /* @__PURE__ */ _parse($ZodRealError);
18765
18999
  var _parseAsync = (_Err) => {
18766
19000
  const fn = async (schema, value, _ctx, params) => {
18767
19001
  const ctx = _ctx ? { ..._ctx, async: true } : { async: true };
@@ -18832,18 +19066,18 @@ var validateAsync = async (schema, value, _ctx) => {
18832
19066
  return result.issues.length === 0;
18833
19067
  };
18834
19068
  var _encode = (_Err) => {
18835
- const parse7 = _parse(_Err);
19069
+ const parse8 = _parse(_Err);
18836
19070
  const fn = (schema, value, _ctx, _params) => {
18837
19071
  const ctx = _ctx ? { ..._ctx, direction: "backward" } : { direction: "backward" };
18838
- return parse7(schema, value, ctx, finalizeParams(fn, _params));
19072
+ return parse8(schema, value, ctx, finalizeParams(fn, _params));
18839
19073
  };
18840
19074
  return fn;
18841
19075
  };
18842
19076
  var encode = /* @__PURE__ */ _encode($ZodRealError);
18843
19077
  var _decode = (_Err) => {
18844
- const parse7 = _parse(_Err);
19078
+ const parse8 = _parse(_Err);
18845
19079
  const fn = (schema, value, _ctx, _params) => {
18846
- return parse7(schema, value, _ctx, finalizeParams(fn, _params));
19080
+ return parse8(schema, value, _ctx, finalizeParams(fn, _params));
18847
19081
  };
18848
19082
  return fn;
18849
19083
  };
@@ -21766,10 +22000,10 @@ var $ZodFunction = /* @__PURE__ */ $constructor("$ZodFunction", (inst, def) => {
21766
22000
  throw new Error("implement() must be called with a function");
21767
22001
  }
21768
22002
  return Object.defineProperty(function(...args) {
21769
- const parsedArgs = inst._def.input ? parse6(inst._def.input, args) : args;
22003
+ const parsedArgs = inst._def.input ? parse7(inst._def.input, args) : args;
21770
22004
  const result = Reflect.apply(func, this, parsedArgs);
21771
22005
  if (inst._def.output) {
21772
- return parse6(inst._def.output, result);
22006
+ return parse7(inst._def.output, result);
21773
22007
  }
21774
22008
  return result;
21775
22009
  }, "_zod", { value: inst._zod, enumerable: false });
@@ -33407,7 +33641,7 @@ var ZodRealError = /* @__PURE__ */ $constructor("ZodError", initializer2, undefi
33407
33641
  });
33408
33642
 
33409
33643
  // node_modules/zod/v4/classic/parse.js
33410
- var parse8 = /* @__PURE__ */ _parse(ZodRealError);
33644
+ var parse9 = /* @__PURE__ */ _parse(ZodRealError);
33411
33645
  var parseAsync2 = /* @__PURE__ */ _parseAsync(ZodRealError);
33412
33646
  var safeParse2 = /* @__PURE__ */ _safeParse(ZodRealError);
33413
33647
  var safeParseAsync2 = /* @__PURE__ */ _safeParseAsync(ZodRealError);
@@ -33543,7 +33777,7 @@ var ZodType = /* @__PURE__ */ $constructor("ZodType", (inst, def) => {
33543
33777
  exports_util.own(this, "~standard", value);
33544
33778
  },
33545
33779
  parse: function _parse2(data, params) {
33546
- return parse8(this, data, params, { callee: _parse2 });
33780
+ return parse9(this, data, params, { callee: _parse2 });
33547
33781
  },
33548
33782
  parseAsync: async function _parseAsync2(data, params) {
33549
33783
  return await parseAsync2(this, data, params, { callee: _parseAsync2 });
@@ -36374,7 +36608,7 @@ function clone2(value) {
36374
36608
  return value === undefined ? undefined : JSON.parse(JSON.stringify(value));
36375
36609
  }
36376
36610
  // src/lib/canonical-json.ts
36377
- import { createHash as createHash15 } from "crypto";
36611
+ import { createHash as createHash16 } from "crypto";
36378
36612
  function canonicalJson2(value, maximumBytes = 2 * 1024 * 1024) {
36379
36613
  return canonicalJsonAtDepth(value, maximumBytes, 64);
36380
36614
  }
@@ -36418,7 +36652,7 @@ function canonicalJsonAtDepth(value, maximumBytes, maximumDepth) {
36418
36652
  return visit3(value, 0);
36419
36653
  }
36420
36654
  function canonicalJsonSha256(value, maximumBytes) {
36421
- return createHash15("sha256").update(canonicalJson2(value, maximumBytes)).digest("hex");
36655
+ return createHash16("sha256").update(canonicalJson2(value, maximumBytes)).digest("hex");
36422
36656
  }
36423
36657
 
36424
36658
  // src/lib/remote-recurring-contract.ts
@@ -37379,10 +37613,10 @@ async function readQuoteUnavailableCode(response) {
37379
37613
  let timer;
37380
37614
  let deadlineExceeded = false;
37381
37615
  const expired = Symbol("quote body deadline");
37382
- const deadline = new Promise((resolve15) => {
37616
+ const deadline = new Promise((resolve16) => {
37383
37617
  timer = setTimeout(() => {
37384
37618
  deadlineExceeded = true;
37385
- resolve15(expired);
37619
+ resolve16(expired);
37386
37620
  reader.cancel().catch(() => {});
37387
37621
  }, 1500);
37388
37622
  });
@@ -38610,10 +38844,10 @@ function recordScheduleRun(id, status, targetDir) {
38610
38844
  saveSchedules(data, targetDir);
38611
38845
  }
38612
38846
  // src/lib/revision.ts
38613
- import { createHash as createHash16 } from "crypto";
38847
+ import { createHash as createHash17 } from "crypto";
38614
38848
  var REVISION_ID_PATTERN = /^[0-9a-f]{64}$/;
38615
38849
  function revisionIdOf(content) {
38616
- const canonical3 = JSON.stringify({
38850
+ const canonical4 = JSON.stringify({
38617
38851
  slug: content.slug,
38618
38852
  displayName: content.displayName,
38619
38853
  description: content.description,
@@ -38626,14 +38860,14 @@ function revisionIdOf(content) {
38626
38860
  bundleSha256: content.bundleSha256 ?? null,
38627
38861
  bundleByteSize: content.bundleByteSize ?? null
38628
38862
  });
38629
- return createHash16("sha256").update(canonical3).digest("hex");
38863
+ return createHash17("sha256").update(canonical4).digest("hex");
38630
38864
  }
38631
38865
  function revisionIdOfRecord(record7) {
38632
38866
  return revisionIdOf(record7);
38633
38867
  }
38634
38868
  // src/lib/pull.ts
38635
38869
  import { existsSync as existsSync17, mkdirSync as mkdirSync12, mkdtempSync as mkdtempSync3, readFileSync as readFileSync20, renameSync as renameSync6, rmSync as rmSync5, writeFileSync as writeFileSync10 } from "fs";
38636
- import { dirname as dirname16, join as join31 } from "path";
38870
+ import { dirname as dirname17, join as join31 } from "path";
38637
38871
 
38638
38872
  // src/lib/skill-bundles.ts
38639
38873
  import { createHmac, timingSafeEqual } from "crypto";
@@ -38975,7 +39209,7 @@ function installBundleAtomically(name, entries, options = {}, marker = {}) {
38975
39209
  try {
38976
39210
  for (const entry of entries) {
38977
39211
  const destination = join31(staging, entry.path);
38978
- mkdirSync12(dirname16(destination), { recursive: true });
39212
+ mkdirSync12(dirname17(destination), { recursive: true });
38979
39213
  writeFileSync10(destination, entry.bytes, { mode: entry.mode });
38980
39214
  }
38981
39215
  writePullMarker(staging, {
@@ -39069,7 +39303,7 @@ function splitNameVersion(raw) {
39069
39303
  return version2 ? { name, version: version2 } : { name };
39070
39304
  }
39071
39305
  // src/lib/recurring-surface.ts
39072
- import { isAbsolute as isAbsolute15 } from "path";
39306
+ import { isAbsolute as isAbsolute16 } from "path";
39073
39307
 
39074
39308
  // src/lib/remote-invitation-recovery.ts
39075
39309
  class InvitationEmailInputError extends Error {
@@ -39167,7 +39401,7 @@ async function requestInvitationEmail(origin, action, input2) {
39167
39401
  }
39168
39402
 
39169
39403
  // src/lib/remote-private-publications.ts
39170
- import { createHash as createHash17 } from "crypto";
39404
+ import { createHash as createHash18 } from "crypto";
39171
39405
  var PRIVATE_PUBLICATION_MAX_BYTES = 16 * 1024 * 1024;
39172
39406
  var failures2 = {
39173
39407
  INVALID_REQUEST: [400, "The publication request is invalid."],
@@ -39214,7 +39448,7 @@ var hash3 = (v) => typeof v === "string" && /^[a-f0-9]{64}$/.test(v);
39214
39448
  var record8 = (v) => !!v && typeof v === "object" && !Array.isArray(v);
39215
39449
  var exact = (v, keys) => record8(v) && Object.keys(v).sort().join(",") === keys.sort().join(",");
39216
39450
  var date5 = (v) => typeof v === "string" && /^\d{4}-\d\d-\d\dT[0-9:.]+(?:Z|[+-](?:[01]\d|2[0-3]):[0-5]\d)$/.test(v) && Number.isFinite(Date.parse(v));
39217
- var publicationSha256 = (bytes) => createHash17("sha256").update(bytes).digest("hex");
39451
+ var publicationSha256 = (bytes) => createHash18("sha256").update(bytes).digest("hex");
39218
39452
  function checkedPublicationDeclaration(value) {
39219
39453
  if (!exact(value, ["idempotencyKey", "version", "expectedCurrentVersionId", "manifestText", "archiveSha256", "archiveByteSize"]) || !publicationUuid(value.idempotencyKey) || !(value.expectedCurrentVersionId === null || publicationUuid(value.expectedCurrentVersionId)) || typeof value.version !== "string" || !value.version || value.version.length > 128 || /[\p{Cc}\p{Cs}]/u.test(value.version) || typeof value.manifestText !== "string" || Buffer.byteLength(value.manifestText) > 16384 || !hash3(value.archiveSha256) || !Number.isSafeInteger(value.archiveByteSize) || Number(value.archiveByteSize) < 1 || Number(value.archiveByteSize) > PRIVATE_PUBLICATION_MAX_BYTES)
39220
39454
  return bad();
@@ -39459,12 +39693,12 @@ class RemotePrivatePublicationsClient {
39459
39693
  previous = view;
39460
39694
  if (!["queued", "verifying"].includes(view.state) || Date.now() >= until)
39461
39695
  return view;
39462
- await new Promise((resolve15) => {
39696
+ await new Promise((resolve16) => {
39463
39697
  const timer = setTimeout(done, Math.min(1000, until - Date.now()));
39464
39698
  function done() {
39465
39699
  clearTimeout(timer);
39466
39700
  options.signal?.removeEventListener("abort", done);
39467
- resolve15();
39701
+ resolve16();
39468
39702
  }
39469
39703
  options.signal?.addEventListener("abort", done, { once: true });
39470
39704
  });
@@ -39728,7 +39962,7 @@ var stateSchema = exports_external.object({
39728
39962
  var uuid13 = exports_external.string().regex(/^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/);
39729
39963
  var context = { userId: uuid13.optional(), membershipId: uuid13.optional() };
39730
39964
  var page2 = { limit: exports_external.number().int().min(1).max(100).optional(), cursor: exports_external.string().min(1).max(2048).optional() };
39731
- var directory = exports_external.string().max(4096).refine(isAbsolute15, "Use an absolute recovery directory");
39965
+ var directory = exports_external.string().max(4096).refine(isAbsolute16, "Use an absolute recovery directory");
39732
39966
  var email4 = exports_external.string().trim().toLowerCase().email().max(254);
39733
39967
  var code = exports_external.string().regex(/^\d{6}$/);
39734
39968
  var recurringSurfaceSchemas = {
@@ -39879,7 +40113,7 @@ function findSkillsParityForMcpTool(tool) {
39879
40113
  }
39880
40114
  // src/lib/registry-sync.ts
39881
40115
  import { mkdirSync as mkdirSync13, writeFileSync as writeFileSync11 } from "fs";
39882
- import { dirname as dirname17, relative as relative7 } from "path";
40116
+ import { dirname as dirname18, relative as relative7 } from "path";
39883
40117
  function createRegistrySyncArtifact(options = {}) {
39884
40118
  const profile = options.profile ?? "all";
39885
40119
  const includeDocs = options.includeDocs ?? true;
@@ -39936,7 +40170,7 @@ function createRegistrySyncArtifact(options = {}) {
39936
40170
  };
39937
40171
  }
39938
40172
  function writeRegistrySyncArtifact(path, artifact) {
39939
- mkdirSync13(dirname17(path), { recursive: true });
40173
+ mkdirSync13(dirname18(path), { recursive: true });
39940
40174
  writeFileSync11(path, `${JSON.stringify(artifact, null, 2)}
39941
40175
  `);
39942
40176
  }
@@ -41021,14 +41255,14 @@ function clone3(value) {
41021
41255
  }
41022
41256
  // src/lib/feedback.ts
41023
41257
  import { appendFileSync, existsSync as existsSync18, mkdirSync as mkdirSync14 } from "fs";
41024
- import { dirname as dirname18, join as join32 } from "path";
41258
+ import { dirname as dirname19, join as join32 } from "path";
41025
41259
  import { Database } from "bun:sqlite";
41026
41260
  function getFeedbackDbPath() {
41027
41261
  return join32(getDataDir(), "skills.db");
41028
41262
  }
41029
41263
  function getFeedbackDb() {
41030
41264
  const dbPath = getFeedbackDbPath();
41031
- const dir = dirname18(dbPath);
41265
+ const dir = dirname19(dbPath);
41032
41266
  if (!existsSync18(dir))
41033
41267
  mkdirSync14(dir, { recursive: true });
41034
41268
  const db = new Database(dbPath);
@@ -41057,7 +41291,7 @@ function saveFeedback(input2) {
41057
41291
  const category = input2.category ?? "general";
41058
41292
  if (isApiMode()) {
41059
41293
  const path = join32(getDataDir(), "feedback.jsonl");
41060
- const dir = dirname18(path);
41294
+ const dir = dirname19(path);
41061
41295
  if (!existsSync18(dir))
41062
41296
  mkdirSync14(dir, { recursive: true });
41063
41297
  appendFileSync(path, JSON.stringify({ message, category, email: input2.email ?? null, agent: input2.agent ?? null, version: input2.version ?? null, createdAt: new Date().toISOString() }) + `
@@ -41080,7 +41314,7 @@ function isApiMode(env = process.env) {
41080
41314
  }
41081
41315
  }
41082
41316
  // src/lib/native-storage.ts
41083
- import { createHash as createHash18, createHmac as createHmac2 } from "crypto";
41317
+ import { createHash as createHash19, createHmac as createHmac2 } from "crypto";
41084
41318
  import {
41085
41319
  existsSync as existsSync19,
41086
41320
  mkdirSync as mkdirSync15,
@@ -41089,7 +41323,7 @@ import {
41089
41323
  statSync as statSync11,
41090
41324
  writeFileSync as writeFileSync12
41091
41325
  } from "fs";
41092
- import { dirname as dirname19, join as join33, normalize as normalize3, relative as relative8, sep as sep7 } from "path";
41326
+ import { dirname as dirname20, join as join33, normalize as normalize3, relative as relative8, sep as sep7 } from "path";
41093
41327
  var SKILLS_STORAGE_TABLES = [
41094
41328
  "skills_sync_records",
41095
41329
  "skills_sync_cursors"
@@ -41256,7 +41490,7 @@ function exportSkillsLocalSnapshot(targetDir = process.cwd(), options = {}) {
41256
41490
  files.push({
41257
41491
  path: relativePath,
41258
41492
  sizeBytes: bytes.byteLength,
41259
- sha256: createHash18("sha256").update(bytes).digest("hex"),
41493
+ sha256: createHash19("sha256").update(bytes).digest("hex"),
41260
41494
  ...options.includeFileContents ? { contentBase64: Buffer.from(bytes).toString("base64") } : {}
41261
41495
  });
41262
41496
  }
@@ -41275,18 +41509,18 @@ function importSkillsLocalSnapshot(snapshot, targetDir = process.cwd(), options
41275
41509
  skipped += 1;
41276
41510
  continue;
41277
41511
  }
41278
- const absolutePath2 = resolveSnapshotPath(targetDir, file2.path);
41279
- if (existsSync19(absolutePath2) && !options.overwrite) {
41512
+ const absolutePath3 = resolveSnapshotPath(targetDir, file2.path);
41513
+ if (existsSync19(absolutePath3) && !options.overwrite) {
41280
41514
  skipped += 1;
41281
41515
  continue;
41282
41516
  }
41283
41517
  const bytes = Buffer.from(file2.contentBase64, "base64");
41284
- const hash4 = createHash18("sha256").update(bytes).digest("hex");
41518
+ const hash4 = createHash19("sha256").update(bytes).digest("hex");
41285
41519
  if (hash4 !== file2.sha256) {
41286
41520
  throw new Error(`Snapshot file checksum mismatch: ${file2.path}`);
41287
41521
  }
41288
- mkdirSync15(dirname19(absolutePath2), { recursive: true });
41289
- writeFileSync12(absolutePath2, bytes);
41522
+ mkdirSync15(dirname20(absolutePath3), { recursive: true });
41523
+ writeFileSync12(absolutePath3, bytes);
41290
41524
  written += 1;
41291
41525
  }
41292
41526
  return { written, skipped };
@@ -41613,7 +41847,7 @@ function toIsoString(value) {
41613
41847
  return Number.isNaN(date6.getTime()) ? value : date6.toISOString();
41614
41848
  }
41615
41849
  function sha256Hex2(value) {
41616
- return createHash18("sha256").update(value).digest("hex");
41850
+ return createHash19("sha256").update(value).digest("hex");
41617
41851
  }
41618
41852
  function normalizeHeaders(headers) {
41619
41853
  const result = {};
@@ -41665,7 +41899,7 @@ function toArrayBuffer(bytes) {
41665
41899
  return buffer;
41666
41900
  }
41667
41901
  // src/lib/station-snapshot.ts
41668
- import { createHash as createHash19 } from "crypto";
41902
+ import { createHash as createHash20 } from "crypto";
41669
41903
  import {
41670
41904
  copyFileSync,
41671
41905
  mkdirSync as mkdirSync16,
@@ -41673,7 +41907,7 @@ import {
41673
41907
  statSync as statSync13,
41674
41908
  writeFileSync as writeFileSync13
41675
41909
  } from "fs";
41676
- import { dirname as dirname20, isAbsolute as isAbsolute16, relative as relative9, resolve as resolve15, sep as sep9 } from "path";
41910
+ import { dirname as dirname21, isAbsolute as isAbsolute17, relative as relative9, resolve as resolve16, sep as sep9 } from "path";
41677
41911
 
41678
41912
  // src/lib/portable-snapshot-filter.ts
41679
41913
  import { readdirSync as readdirSync14, statSync as statSync12 } from "fs";
@@ -41840,7 +42074,7 @@ function validateStationId(stationId) {
41840
42074
  }
41841
42075
  }
41842
42076
  function sha256File(filePath) {
41843
- return createHash19("sha256").update(readFileSync23(filePath)).digest("hex");
42077
+ return createHash20("sha256").update(readFileSync23(filePath)).digest("hex");
41844
42078
  }
41845
42079
  function scanHome(definition, homesRoot) {
41846
42080
  const homePath = homePathFor(definition, homesRoot);
@@ -41911,7 +42145,7 @@ function humanHomes(scanned) {
41911
42145
  }));
41912
42146
  }
41913
42147
  function writeStationSnapshot(options) {
41914
- const repoRoot = resolve15(options.repoRoot ?? process.cwd());
42148
+ const repoRoot = resolve16(options.repoRoot ?? process.cwd());
41915
42149
  const { scanned, plans, totalBytes } = planStationSnapshot(options);
41916
42150
  const manifestFiles = plans.map((plan) => ({
41917
42151
  relativePath: plan.source.relativePath,
@@ -41937,9 +42171,9 @@ function writeStationSnapshot(options) {
41937
42171
  const conflicts = [];
41938
42172
  const untouched = [];
41939
42173
  for (const plan of plans) {
41940
- const destination = resolve15(repoRoot, plan.destination);
42174
+ const destination = resolve16(repoRoot, plan.destination);
41941
42175
  const destinationRelative = relative9(repoRoot, destination);
41942
- if (destinationRelative.startsWith("..") || destinationRelative.startsWith(sep9) || isAbsolute16(destinationRelative)) {
42176
+ if (destinationRelative.startsWith("..") || destinationRelative.startsWith(sep9) || isAbsolute17(destinationRelative)) {
41943
42177
  throw new StationSnapshotError("DESTINATION_ESCAPE", `destination escapes repo root: ${plan.destination}`);
41944
42178
  }
41945
42179
  let existingDigest = null;
@@ -41960,8 +42194,8 @@ function writeStationSnapshot(options) {
41960
42194
  }
41961
42195
  let written = 0;
41962
42196
  for (const plan of untouched) {
41963
- const destination = resolve15(repoRoot, plan.destination);
41964
- mkdirSync16(dirname20(destination), { recursive: true });
42197
+ const destination = resolve16(repoRoot, plan.destination);
42198
+ mkdirSync16(dirname21(destination), { recursive: true });
41965
42199
  copyFileSync(plan.source.fullPath, destination);
41966
42200
  written += 1;
41967
42201
  }
@@ -41979,8 +42213,8 @@ function writeStationSnapshot(options) {
41979
42213
  },
41980
42214
  files: manifestFiles
41981
42215
  };
41982
- const manifestPath = resolve15(repoRoot, "resources", options.stationId, "skills", "sync-manifest.json");
41983
- mkdirSync16(dirname20(manifestPath), { recursive: true });
42216
+ const manifestPath = resolve16(repoRoot, "resources", options.stationId, "skills", "sync-manifest.json");
42217
+ mkdirSync16(dirname21(manifestPath), { recursive: true });
41984
42218
  writeFileSync13(manifestPath, `${JSON.stringify(manifest, null, 2)}
41985
42219
  `);
41986
42220
  return {
@@ -41991,7 +42225,7 @@ function writeStationSnapshot(options) {
41991
42225
  };
41992
42226
  }
41993
42227
  // src/lib/station-hydrate.ts
41994
- import { createHash as createHash20 } from "crypto";
42228
+ import { createHash as createHash21 } from "crypto";
41995
42229
  import {
41996
42230
  copyFileSync as copyFileSync2,
41997
42231
  mkdirSync as mkdirSync17,
@@ -42000,7 +42234,7 @@ import {
42000
42234
  statSync as statSync14,
42001
42235
  writeFileSync as writeFileSync14
42002
42236
  } from "fs";
42003
- import { dirname as dirname21, join as join35, resolve as resolve16, sep as sep10 } from "path";
42237
+ import { dirname as dirname22, join as join35, resolve as resolve17, sep as sep10 } from "path";
42004
42238
  var STATION_HYDRATION_MANIFEST_SCHEMA = "hasna.fleet-resources.skills-hydration-manifest/v1";
42005
42239
  var STATION_HYDRATION_PRODUCER = { name: "@hasna/skills", version: package_default.version };
42006
42240
  var MANIFEST_HASH_KEY_SEP = String.fromCharCode(0);
@@ -42197,12 +42431,12 @@ function skillSha256(skill) {
42197
42431
  return sha256File(skill.files[0].winner.fullPath);
42198
42432
  }
42199
42433
  const joined = skill.files.map((file2) => sha256File(file2.winner.fullPath));
42200
- return createHash20("sha256").update(joined.sort().join(`
42434
+ return createHash21("sha256").update(joined.sort().join(`
42201
42435
  `)).digest("hex");
42202
42436
  }
42203
42437
  function writeStationHydration(options) {
42204
- const repoRoot = resolve16(options.repoRoot ?? process.cwd());
42205
- const cacheRoot = resolve16(options.cacheRoot ?? resolveCorpusRoot());
42438
+ const repoRoot = resolve17(options.repoRoot ?? process.cwd());
42439
+ const cacheRoot = resolve17(options.cacheRoot ?? resolveCorpusRoot());
42206
42440
  const plan = planStationHydration(options.stationId, repoRoot);
42207
42441
  const resultSkills = plan.winners.map((skill) => ({
42208
42442
  ident: skill.ident,
@@ -42256,7 +42490,7 @@ function writeStationHydration(options) {
42256
42490
  }
42257
42491
  let written = 0;
42258
42492
  for (const entry of toWrite) {
42259
- mkdirSync17(dirname21(entry.destination), { recursive: true });
42493
+ mkdirSync17(dirname22(entry.destination), { recursive: true });
42260
42494
  copyFileSync2(entry.fullPath, entry.destination);
42261
42495
  written += 1;
42262
42496
  }
@@ -42277,8 +42511,8 @@ function writeStationHydration(options) {
42277
42511
  },
42278
42512
  skills: resultSkills
42279
42513
  };
42280
- const hydrationManifestPath = join35(dirname21(cacheRoot), `hydration-${options.stationId}.json`);
42281
- mkdirSync17(dirname21(hydrationManifestPath), { recursive: true });
42514
+ const hydrationManifestPath = join35(dirname22(cacheRoot), `hydration-${options.stationId}.json`);
42515
+ mkdirSync17(dirname22(hydrationManifestPath), { recursive: true });
42282
42516
  writeFileSync14(hydrationManifestPath, `${JSON.stringify(hydration, null, 2)}
42283
42517
  `);
42284
42518
  return {
@@ -42289,23 +42523,23 @@ function writeStationHydration(options) {
42289
42523
  };
42290
42524
  }
42291
42525
  // src/lib/private-publication-recovery.ts
42292
- import { constants as constants10, closeSync as closeSync11, fsyncSync as fsyncSync4, fstatSync as fstatSync11, lstatSync as lstatSync19, mkdirSync as mkdirSync18, openSync as openSync11, readSync as readSync9, realpathSync as realpathSync6, renameSync as renameSync7, unlinkSync as unlinkSync5, writeFileSync as writeFileSync15 } from "fs";
42293
- import { dirname as dirname22, isAbsolute as isAbsolute17, join as join36, resolve as resolve17 } from "path";
42526
+ import { constants as constants11, closeSync as closeSync12, fsyncSync as fsyncSync4, fstatSync as fstatSync12, lstatSync as lstatSync20, mkdirSync as mkdirSync18, openSync as openSync12, readSync as readSync10, realpathSync as realpathSync6, renameSync as renameSync7, unlinkSync as unlinkSync5, writeFileSync as writeFileSync15 } from "fs";
42527
+ import { dirname as dirname23, isAbsolute as isAbsolute18, join as join36, resolve as resolve18 } from "path";
42294
42528
  import { randomUUID as randomUUID4 } from "crypto";
42295
42529
  var fail2 = () => {
42296
42530
  throw new PrivatePublicationError("PUBLICATION_RECOVERY_INVALID", "The recovery directory is invalid or changed. Preserve it and inspect the existing intent; do not start a replacement automatically.");
42297
42531
  };
42298
42532
  function safeDirectory(directory2) {
42299
- if (!isAbsolute17(directory2) || directory2 !== resolve17(directory2) || realpathSync6(directory2) !== directory2)
42533
+ if (!isAbsolute18(directory2) || directory2 !== resolve18(directory2) || realpathSync6(directory2) !== directory2)
42300
42534
  return fail2();
42301
- for (let path = directory2;; path = dirname22(path)) {
42302
- const stat2 = lstatSync19(path);
42535
+ for (let path = directory2;; path = dirname23(path)) {
42536
+ const stat2 = lstatSync20(path);
42303
42537
  if (!stat2.isDirectory() || stat2.isSymbolicLink())
42304
42538
  return fail2();
42305
- if (path === dirname22(path))
42539
+ if (path === dirname23(path))
42306
42540
  break;
42307
42541
  }
42308
- const own2 = lstatSync19(directory2);
42542
+ const own2 = lstatSync20(directory2);
42309
42543
  if ((own2.mode & 63) !== 0 || process.getuid && own2.uid !== process.getuid())
42310
42544
  return fail2();
42311
42545
  return { dev: own2.dev, ino: own2.ino };
@@ -42317,35 +42551,35 @@ function unchangedDirectory(directory2, identity3) {
42317
42551
  }
42318
42552
  function readOwned(directory2, name, max) {
42319
42553
  const identity3 = safeDirectory(directory2), file2 = join36(directory2, name);
42320
- const fd = openSync11(file2, constants10.O_RDONLY | constants10.O_NOFOLLOW);
42554
+ const fd = openSync12(file2, constants11.O_RDONLY | constants11.O_NOFOLLOW);
42321
42555
  try {
42322
- const stat2 = fstatSync11(fd);
42556
+ const stat2 = fstatSync12(fd);
42323
42557
  if (!stat2.isFile() || stat2.nlink !== 1 || stat2.size > max || stat2.size < 1 || (stat2.mode & 63) !== 0 || process.getuid && stat2.uid !== process.getuid())
42324
42558
  return fail2();
42325
42559
  const buffer = Buffer.alloc(Math.min(max, stat2.size) + 1);
42326
42560
  let length = 0;
42327
42561
  while (length < buffer.length) {
42328
- const count = readSync9(fd, buffer, length, buffer.length - length, length);
42562
+ const count = readSync10(fd, buffer, length, buffer.length - length, length);
42329
42563
  if (count === 0)
42330
42564
  break;
42331
42565
  length += count;
42332
42566
  }
42333
- const bytes = buffer.subarray(0, length), after = fstatSync11(fd);
42567
+ const bytes = buffer.subarray(0, length), after = fstatSync12(fd);
42334
42568
  unchangedDirectory(directory2, identity3);
42335
42569
  if (bytes.length !== stat2.size || stat2.size !== after.size || stat2.mtimeMs !== after.mtimeMs || stat2.ctimeMs !== after.ctimeMs)
42336
42570
  return fail2();
42337
42571
  return bytes;
42338
42572
  } finally {
42339
- closeSync11(fd);
42573
+ closeSync12(fd);
42340
42574
  }
42341
42575
  }
42342
42576
  function writeOwned(directory2, name, bytes) {
42343
- const fd = openSync11(join36(directory2, name), constants10.O_WRONLY | constants10.O_CREAT | constants10.O_EXCL | constants10.O_NOFOLLOW, 384);
42577
+ const fd = openSync12(join36(directory2, name), constants11.O_WRONLY | constants11.O_CREAT | constants11.O_EXCL | constants11.O_NOFOLLOW, 384);
42344
42578
  try {
42345
42579
  writeFileSync15(fd, bytes);
42346
42580
  fsyncSync4(fd);
42347
42581
  } finally {
42348
- closeSync11(fd);
42582
+ closeSync12(fd);
42349
42583
  }
42350
42584
  }
42351
42585
  function save(directory2, value) {
@@ -42354,11 +42588,11 @@ function save(directory2, value) {
42354
42588
  `);
42355
42589
  unchangedDirectory(directory2, identity3);
42356
42590
  renameSync7(join36(directory2, temporary), join36(directory2, "receipt.json"));
42357
- const fd = openSync11(directory2, constants10.O_RDONLY | constants10.O_NOFOLLOW);
42591
+ const fd = openSync12(directory2, constants11.O_RDONLY | constants11.O_NOFOLLOW);
42358
42592
  try {
42359
42593
  fsyncSync4(fd);
42360
42594
  } finally {
42361
- closeSync11(fd);
42595
+ closeSync12(fd);
42362
42596
  }
42363
42597
  }
42364
42598
  function bind(client2, receipt) {
@@ -42369,20 +42603,20 @@ async function locked(directory2, action) {
42369
42603
  const identity3 = safeDirectory(directory2), file2 = join36(directory2, "operation.lock");
42370
42604
  let fd;
42371
42605
  try {
42372
- fd = openSync11(file2, constants10.O_WRONLY | constants10.O_CREAT | constants10.O_EXCL | constants10.O_NOFOLLOW, 384);
42606
+ fd = openSync12(file2, constants11.O_WRONLY | constants11.O_CREAT | constants11.O_EXCL | constants11.O_NOFOLLOW, 384);
42373
42607
  } catch {
42374
42608
  throw new PrivatePublicationError("PUBLICATION_RECOVERY_BUSY", "Another operation holds this recovery directory. If it crashed, confirm that process has stopped before explicitly removing operation.lock and resuming.");
42375
42609
  }
42376
- const lock = fstatSync11(fd);
42610
+ const lock = fstatSync12(fd);
42377
42611
  try {
42378
42612
  writeFileSync15(fd, JSON.stringify({ pid: process.pid }) + `
42379
42613
  `);
42380
42614
  fsyncSync4(fd);
42381
42615
  return await action();
42382
42616
  } finally {
42383
- closeSync11(fd);
42617
+ closeSync12(fd);
42384
42618
  unchangedDirectory(directory2, identity3);
42385
- const now = lstatSync19(file2);
42619
+ const now = lstatSync20(file2);
42386
42620
  if (now.dev !== lock.dev || now.ino !== lock.ino || !now.isFile() || now.isSymbolicLink())
42387
42621
  fail2();
42388
42622
  unlinkSync5(file2);
@@ -42434,15 +42668,15 @@ async function preparePrivatePublication(client2, sourceDirectory, recoveryDirec
42434
42668
  phase: "prepared",
42435
42669
  intent: null
42436
42670
  };
42437
- if (!isAbsolute17(recoveryDirectory) || resolve17(recoveryDirectory) !== recoveryDirectory || realpathSync6(dirname22(recoveryDirectory)) !== dirname22(recoveryDirectory))
42671
+ if (!isAbsolute18(recoveryDirectory) || resolve18(recoveryDirectory) !== recoveryDirectory || realpathSync6(dirname23(recoveryDirectory)) !== dirname23(recoveryDirectory))
42438
42672
  return fail2();
42439
42673
  mkdirSync18(recoveryDirectory, { mode: 448 });
42440
42674
  safeDirectory(recoveryDirectory);
42441
- const parent = openSync11(dirname22(recoveryDirectory), constants10.O_RDONLY | constants10.O_NOFOLLOW);
42675
+ const parent = openSync12(dirname23(recoveryDirectory), constants11.O_RDONLY | constants11.O_NOFOLLOW);
42442
42676
  try {
42443
42677
  fsyncSync4(parent);
42444
42678
  } finally {
42445
- closeSync11(parent);
42679
+ closeSync12(parent);
42446
42680
  }
42447
42681
  writeOwned(recoveryDirectory, "bundle.tgz", packed.bytes);
42448
42682
  save(recoveryDirectory, receipt);
@@ -42525,8 +42759,8 @@ async function inspectLocked(client2, directory2, cancel) {
42525
42759
  return privatePublicationResult(directory2, receipt);
42526
42760
  }
42527
42761
  // src/lib/skill-context.ts
42528
- import { createHash as createHash21 } from "crypto";
42529
- import { resolve as resolve18 } from "path";
42762
+ import { createHash as createHash22 } from "crypto";
42763
+ import { resolve as resolve19 } from "path";
42530
42764
  function words(value) {
42531
42765
  return new Set(value.toLowerCase().match(/[a-z0-9]+/g) ?? []);
42532
42766
  }
@@ -42561,7 +42795,7 @@ async function buildSkillContext(input2, options = {}) {
42561
42795
  const promptWords = words(prompt);
42562
42796
  const promptNames = new Set(prompt.toLowerCase().match(/[a-z0-9]+(?:-[a-z0-9]+)*/g) ?? []);
42563
42797
  const loaded = new Set(resolved.session?.loaded ?? []);
42564
- const paths = [...input2.paths ?? [], ...input2.cwd ? [input2.cwd, resolve18(input2.cwd)] : []];
42798
+ const paths = [...input2.paths ?? [], ...input2.cwd ? [input2.cwd, resolve19(input2.cwd)] : []];
42565
42799
  const candidates = profile.selections.map((selection) => {
42566
42800
  const key = selectionKey(selection);
42567
42801
  if (input2.restore && loaded.has(key))
@@ -42614,7 +42848,7 @@ ${content}`;
42614
42848
  `);
42615
42849
  const receipt = {
42616
42850
  schemaVersion: 1,
42617
- id: createHash21("sha256").update(JSON.stringify({ profile: profile.profileRevision, sessionId, selections, omitted })).digest("hex"),
42851
+ id: createHash22("sha256").update(JSON.stringify({ profile: profile.profileRevision, sessionId, selections, omitted })).digest("hex"),
42618
42852
  profileId: profile.profileId,
42619
42853
  profileRevision: profile.profileRevision,
42620
42854
  authority: profile.authority,
@@ -42630,9 +42864,9 @@ ${content}`;
42630
42864
  return { context: context2, selections, omitted, receipt };
42631
42865
  }
42632
42866
  // src/lib/session-reconciliation.ts
42633
- import { createHash as createHash22 } from "crypto";
42867
+ import { createHash as createHash23 } from "crypto";
42634
42868
  var SESSION_RECONCILIATION_PLAN_TTL_MS = 5 * 60 * 1000;
42635
- var digest3 = (value) => createHash22("sha256").update(JSON.stringify(value)).digest("hex");
42869
+ var digest3 = (value) => createHash23("sha256").update(JSON.stringify(value)).digest("hex");
42636
42870
  function exactTimestamp(value) {
42637
42871
  const parsed = value === undefined ? Number.NaN : Date.parse(value);
42638
42872
  if (!Number.isFinite(parsed) || new Date(parsed).toISOString() !== value) {
@@ -42921,6 +43155,7 @@ export {
42921
43155
  captureDiscoveryPathSources,
42922
43156
  captureDiscoveryDirectories,
42923
43157
  captureDiscoveryByteSources,
43158
+ captureClaudeSettings,
42924
43159
  captureClaudeMarketplaceRegistry,
42925
43160
  canonicalizeManifest,
42926
43161
  buildSkillsS3ObjectUrl,