@hasna/skills 0.8.10 → 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/bin/index.js CHANGED
@@ -36868,7 +36868,7 @@ var package_default;
36868
36868
  var init_package = __esm(() => {
36869
36869
  package_default = {
36870
36870
  name: "@hasna/skills",
36871
- version: "0.8.10",
36871
+ version: "0.8.12",
36872
36872
  description: "Skills library for AI coding agents",
36873
36873
  type: "module",
36874
36874
  bin: {
@@ -36930,10 +36930,11 @@ var init_package = __esm(() => {
36930
36930
  typecheck: "tsc --noEmit",
36931
36931
  "verify:release": "bun run scripts/release-guard.ts",
36932
36932
  "verify:consumer-types": "bun run scripts/consumer-types.ts",
36933
- prepare: "bun run build:js",
36934
- prepack: "bun run build && bun run verify:release && bun run verify:consumer-types",
36933
+ prepack: "bun run verify:generated && bun run verify:release && bun run verify:consumer-types",
36935
36934
  prepublishOnly: "bun run verify:producer && bun run typecheck && bun run test",
36936
- "verify:producer": "bun run scripts/release-dependencies.ts"
36935
+ "verify:producer": "bun run scripts/release-dependencies.ts",
36936
+ "verify:generated": "HASNA_SKILLS_RELEASE_ARTIFACT_TEST=1 bun test src/lib/release-artifacts.test.ts",
36937
+ "verify:consumer-credentials": "bun run scripts/consumer-credentials.ts"
36937
36938
  },
36938
36939
  keywords: [
36939
36940
  "skills",
@@ -36955,7 +36956,6 @@ var init_package = __esm(() => {
36955
36956
  license: "Apache-2.0",
36956
36957
  devDependencies: {
36957
36958
  "@hasna/contracts": "1.1.0",
36958
- "@hasna/secrets": "0.4.2",
36959
36959
  "@types/bun": "1.3.14",
36960
36960
  "@types/node": "25.2.3",
36961
36961
  "@types/react": "^18.2.0",
@@ -36968,6 +36968,7 @@ var init_package = __esm(() => {
36968
36968
  "@aws-sdk/client-ecs": "^3.1079.0",
36969
36969
  "@aws-sdk/client-s3": "^3.1079.0",
36970
36970
  "@hasna/events": "0.1.18",
36971
+ "@hasna/secrets": "0.4.2",
36971
36972
  "@modelcontextprotocol/sdk": "^1.26.0",
36972
36973
  chalk: "^5.3.0",
36973
36974
  commander: "^12.1.0",
@@ -42784,14 +42785,15 @@ function profileSelectionSnapshot(selections) {
42784
42785
  var MAX_PROFILE_SELECTIONS = 4096, MAX_PROFILE_DOCUMENT_BYTES, MAX_SKILL_SESSION_ID_CHARS = 256, PROFILE_SESSION_ENVELOPE_BYTES, MAX_RESOLVED_PROFILE_BYTES, LEGACY_PROFILE_SELECTIONS = 256, LEGACY_PROFILE_DOCUMENT_BYTES = 1e6;
42785
42786
  var init_profile_limits = __esm(() => {
42786
42787
  MAX_PROFILE_DOCUMENT_BYTES = 8 * 1024 * 1024;
42787
- PROFILE_SESSION_ENVELOPE_BYTES = MAX_PROFILE_SELECTIONS * 67 + MAX_SKILL_SESSION_ID_CHARS * 6 + 256;
42788
+ PROFILE_SESSION_ENVELOPE_BYTES = MAX_PROFILE_SELECTIONS * 67 + MAX_SKILL_SESSION_ID_CHARS * 12 + 512;
42788
42789
  MAX_RESOLVED_PROFILE_BYTES = MAX_PROFILE_DOCUMENT_BYTES - PROFILE_SESSION_ENVELOPE_BYTES;
42789
42790
  });
42790
42791
 
42791
42792
  // src/lib/selection-cache.ts
42792
42793
  import { createHash as createHash3, randomUUID as randomUUID3 } from "crypto";
42793
- import { closeSync, constants as constants2, fstatSync, lstatSync as lstatSync3, mkdirSync as mkdirSync4, openSync, readSync, renameSync as renameSync2, unlinkSync, writeFileSync as writeFileSync4 } from "fs";
42794
+ import { closeSync, constants as constants2, fstatSync, fsyncSync, lstatSync as lstatSync3, mkdirSync as mkdirSync4, openSync, readSync, renameSync as renameSync2, unlinkSync, writeFileSync as writeFileSync4 } from "fs";
42794
42795
  import { dirname as dirname4, join as join14, parse, resolve as resolve4 } from "path";
42796
+ import { isDeepStrictEqual as isDeepStrictEqual2 } from "util";
42795
42797
  function selectionCacheRoot(options = {}) {
42796
42798
  return resolve4(options.cacheDir ?? join14(getDataDirReadOnly(), "selection-cache"));
42797
42799
  }
@@ -42895,12 +42897,21 @@ function writeSelectionJson(path, value) {
42895
42897
  throw new SkillSelectionError("RECEIPT_TOO_LARGE", "The Skills selection receipt exceeds its size limit.");
42896
42898
  atomicWrite(path, bytes, 384);
42897
42899
  }
42898
- function atomicWrite(path, bytes, mode) {
42900
+ function atomicWrite(path, bytes, mode, durable = false) {
42899
42901
  assertRegularPath(path, true);
42900
42902
  const temporary = join14(dirname4(path), `.selection-${randomUUID3()}.tmp`);
42901
42903
  try {
42902
- writeFileSync4(temporary, bytes, { flag: "wx", mode });
42904
+ const fd = openSync(temporary, constants2.O_WRONLY | constants2.O_CREAT | constants2.O_EXCL | constants2.O_NOFOLLOW, mode);
42905
+ try {
42906
+ writeFileSync4(fd, bytes);
42907
+ if (durable)
42908
+ fsyncSync(fd);
42909
+ } finally {
42910
+ closeSync(fd);
42911
+ }
42903
42912
  renameSync2(temporary, path);
42913
+ if (durable)
42914
+ syncDirectory(dirname4(path));
42904
42915
  } finally {
42905
42916
  try {
42906
42917
  unlinkSync(temporary);
@@ -43019,16 +43030,190 @@ function sessionReceiptPath(sessionId, options = {}) {
43019
43030
  throw new SkillSelectionError("INVALID_SESSION", `A Skills session id must contain 1\u2013${MAX_SKILL_SESSION_ID_CHARS} characters.`);
43020
43031
  return join14(selectionCacheRoot(options), "sessions", `${hash(sessionId)}.json`);
43021
43032
  }
43022
- function readSkillSession(sessionId, options = {}) {
43023
- const receipt = readSelectionJson(sessionReceiptPath(sessionId, options));
43024
- if (receipt) {
43025
- validateSelectionReceipt(receipt);
43026
- const keys2 = new Set(receipt.profile.selections.map(selectionKey));
43027
- if (receipt.sessionId !== sessionId || !Array.isArray(receipt.loaded) || receipt.loaded.length > keys2.size || new Set(receipt.loaded).size !== receipt.loaded.length || !receipt.loaded.every((key) => keys2.has(key))) {
43028
- throw new SkillSelectionError("INVALID_RECEIPT", "The Skills session receipt is invalid.");
43033
+ function skillSessionGeneration(receipt) {
43034
+ return receipt.generation ?? 0;
43035
+ }
43036
+ function validateSkillSessionBinding(binding) {
43037
+ if (!binding || typeof binding.sessionId !== "string" || !binding.sessionId.trim() || binding.sessionId.length > MAX_SKILL_SESSION_ID_CHARS || !Number.isSafeInteger(binding.generation) || binding.generation < 0 || !/^[a-f0-9]{64}$/.test(binding.receiptSha256)) {
43038
+ throw new SkillSelectionError("INVALID_RECEIPT", "The Skills session receipt contains an invalid parent snapshot binding.");
43039
+ }
43040
+ }
43041
+ function validateSkillSessionReceipt(receipt, sessionId) {
43042
+ validateSelectionReceipt(receipt);
43043
+ const keys2 = new Set(receipt.profile.selections.map(selectionKey));
43044
+ if (receipt.sessionId !== sessionId || !Array.isArray(receipt.loaded) || receipt.loaded.length > keys2.size || new Set(receipt.loaded).size !== receipt.loaded.length || !receipt.loaded.every((key) => keys2.has(key)) || receipt.generation !== undefined && (!Number.isSafeInteger(receipt.generation) || receipt.generation < 1)) {
43045
+ throw new SkillSelectionError("INVALID_RECEIPT", "The Skills session receipt is invalid.");
43046
+ }
43047
+ if (receipt.parent) {
43048
+ validateSkillSessionBinding(receipt.parent);
43049
+ if (receipt.parent.sessionId === sessionId)
43050
+ throw new SkillSelectionError("INVALID_RECEIPT", "A Skills child session cannot name itself as its parent.");
43051
+ }
43052
+ }
43053
+ function readSkillSessionSnapshotIfExists(sessionId, options = {}) {
43054
+ const path = sessionReceiptPath(sessionId, options), bytes = readRegularFile(path, MAX_PROFILE_DOCUMENT_BYTES);
43055
+ if (!bytes)
43056
+ return null;
43057
+ let receipt;
43058
+ try {
43059
+ receipt = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(bytes));
43060
+ } catch {
43061
+ throw new SkillSelectionError("INVALID_RECEIPT", "The Skills session receipt is unreadable.");
43062
+ }
43063
+ validateSkillSessionReceipt(receipt, sessionId);
43064
+ const sha256 = sha256Hex(bytes);
43065
+ return { path, bytes, receipt, sha256, sessionId, generation: skillSessionGeneration(receipt), receiptSha256: sha256 };
43066
+ }
43067
+ function readSkillSessionSnapshot(sessionId, options = {}) {
43068
+ const snapshot = readSkillSessionSnapshotIfExists(sessionId, options);
43069
+ if (!snapshot)
43070
+ throw new SkillSelectionError("SESSION_NOT_FOUND", "The requested Skills session receipt does not exist.");
43071
+ return snapshot;
43072
+ }
43073
+ function skillSessionSnapshotBinding(snapshot) {
43074
+ return { sessionId: snapshot.sessionId, generation: snapshot.generation, receiptSha256: snapshot.receiptSha256 };
43075
+ }
43076
+ function withSessionWriteLocks(sessionIds, options, action) {
43077
+ const operationId = randomUUID3();
43078
+ const locks = [...new Set(sessionIds)].map((sessionId) => ({ sessionId, path: `${sessionReceiptPath(sessionId, options)}.write-lock` })).sort((a, b) => a.path < b.path ? -1 : a.path > b.path ? 1 : 0);
43079
+ const owned = [];
43080
+ const assertOwned = () => {
43081
+ for (const lock of owned) {
43082
+ const current = lstatSync3(lock.path, { throwIfNoEntry: false });
43083
+ if (!current?.isFile() || current.dev !== lock.dev || current.ino !== lock.ino) {
43084
+ throw new SkillSelectionError("SESSION_WRITE_LOCK_CHANGED", "A session write lock changed during the operation; no replacement is permitted.");
43085
+ }
43086
+ }
43087
+ };
43088
+ try {
43089
+ for (const lock of locks) {
43090
+ assertRegularPath(lock.path, true);
43091
+ let fd;
43092
+ try {
43093
+ fd = openSync(lock.path, constants2.O_WRONLY | constants2.O_CREAT | constants2.O_EXCL | constants2.O_NOFOLLOW, 384);
43094
+ } catch (error) {
43095
+ if (error.code === "EEXIST")
43096
+ throw new SkillSelectionError("SESSION_WRITE_LOCKED", "Another Skills process owns a required session write lock; retry after it completes. A surviving lock requires explicit recovery review.");
43097
+ throw error;
43098
+ }
43099
+ const stat = fstatSync(fd);
43100
+ owned.push({ path: lock.path, fd, dev: stat.dev, ino: stat.ino });
43101
+ writeFileSync4(fd, `${JSON.stringify({ schemaVersion: 1, operationId, sessionId: lock.sessionId, pid: process.pid })}
43102
+ `);
43103
+ }
43104
+ return action(assertOwned);
43105
+ } finally {
43106
+ for (const lock of owned.reverse()) {
43107
+ closeSync(lock.fd);
43108
+ const current = lstatSync3(lock.path, { throwIfNoEntry: false });
43109
+ if (current?.isFile() && current.dev === lock.dev && current.ino === lock.ino)
43110
+ unlinkSync(lock.path);
43029
43111
  }
43030
43112
  }
43031
- return receipt;
43113
+ }
43114
+ function withSessionWriteLock(sessionId, options, action) {
43115
+ return withSessionWriteLocks([sessionId], options, action);
43116
+ }
43117
+ function sameSnapshot(actual, expected) {
43118
+ return actual === null ? expected === null : expected !== null && actual.sessionId === expected.sessionId && actual.generation === expected.generation && actual.receiptSha256 === expected.receiptSha256;
43119
+ }
43120
+ function nextSkillSessionGeneration(generation) {
43121
+ if (!Number.isSafeInteger(generation) || generation < 0 || generation >= Number.MAX_SAFE_INTEGER) {
43122
+ throw new SkillSelectionError("SESSION_GENERATION_EXHAUSTED", "The Skills session generation cannot advance safely; preserve the receipt and review recovery before continuing.");
43123
+ }
43124
+ return generation + 1;
43125
+ }
43126
+ function parentChanged() {
43127
+ throw new SkillSelectionError("SESSION_PARENT_CHANGED", "The parent Skills session changed while the child was resolving; resolve the child again from the current parent pin.");
43128
+ }
43129
+ function writeSkillSession(receipt, expected, options = {}) {
43130
+ validateSkillSessionReceipt(receipt, receipt.sessionId);
43131
+ if (expected.parent)
43132
+ validateSkillSessionBinding(expected.parent);
43133
+ if (expected.parent?.sessionId === receipt.sessionId)
43134
+ throw new SkillSelectionError("INVALID_RECEIPT", "A Skills child session cannot name itself as its parent.");
43135
+ const lockIds = expected.parent ? [receipt.sessionId, expected.parent.sessionId] : [receipt.sessionId];
43136
+ withSessionWriteLocks(lockIds, options, (assertOwned) => {
43137
+ const current = readSkillSessionSnapshotIfExists(receipt.sessionId, options);
43138
+ if (!sameSnapshot(current, expected.current) || current && !isDeepStrictEqual2(current.receipt.profile, receipt.profile)) {
43139
+ throw new SkillSelectionError("SESSION_RECEIPT_CHANGED", "The Skills session receipt changed while context was loading; resolve context again without replacing the current pin.");
43140
+ }
43141
+ let parent = null;
43142
+ if (expected.parent) {
43143
+ parent = readSkillSessionSnapshotIfExists(expected.parent.sessionId, options);
43144
+ if (!sameSnapshot(parent, expected.parent) || !parent || !isDeepStrictEqual2(parent.receipt.profile, receipt.profile))
43145
+ parentChanged();
43146
+ }
43147
+ const generation = nextSkillSessionGeneration(current?.generation ?? 0);
43148
+ const next = current ? { ...current.receipt, generation, loaded: [...new Set([...current.receipt.loaded, ...receipt.loaded])] } : { ...receipt, generation, ...expected.parent ? { parent: expected.parent } : {} };
43149
+ assertOwned();
43150
+ if (expected.parent) {
43151
+ parent = readSkillSessionSnapshotIfExists(expected.parent.sessionId, options);
43152
+ if (!sameSnapshot(parent, expected.parent))
43153
+ parentChanged();
43154
+ }
43155
+ writeSelectionJson(sessionReceiptPath(receipt.sessionId, options), next);
43156
+ });
43157
+ }
43158
+ function syncDirectory(path) {
43159
+ assertRegularPath(path);
43160
+ const fd = openSync(path, constants2.O_RDONLY | constants2.O_DIRECTORY | constants2.O_NOFOLLOW);
43161
+ try {
43162
+ fsyncSync(fd);
43163
+ } finally {
43164
+ closeSync(fd);
43165
+ }
43166
+ }
43167
+ function archiveBytes(path, bytes) {
43168
+ assertRegularPath(path, true);
43169
+ const fd = openSync(path, constants2.O_WRONLY | constants2.O_CREAT | constants2.O_EXCL | constants2.O_NOFOLLOW, 384);
43170
+ try {
43171
+ writeFileSync4(fd, bytes);
43172
+ fsyncSync(fd);
43173
+ } finally {
43174
+ closeSync(fd);
43175
+ }
43176
+ }
43177
+ function replaceSkillSession(expected, replacement, plan, options = {}, beforeCommit = () => {}) {
43178
+ validateSkillSessionReceipt(replacement, replacement.sessionId);
43179
+ const bytes = Buffer.from(`${JSON.stringify(replacement)}
43180
+ `);
43181
+ if (bytes.length > MAX_PROFILE_DOCUMENT_BYTES)
43182
+ throw new SkillSelectionError("RECEIPT_TOO_LARGE", "The Skills selection receipt exceeds its size limit.");
43183
+ return withSessionWriteLock(replacement.sessionId, options, (assertOwned) => {
43184
+ const before2 = readSkillSessionSnapshot(replacement.sessionId, options);
43185
+ if (!sameSnapshot(before2, expected))
43186
+ throw new SkillSelectionError("SESSION_RECEIPT_CHANGED", "The Skills session receipt generation or bytes changed after review; inspect it and prepare a new plan.");
43187
+ if (replacement.generation !== nextSkillSessionGeneration(before2.generation))
43188
+ throw new SkillSelectionError("SESSION_GENERATION_CHANGED", "The replacement Skills session must advance exactly one generation.");
43189
+ if (before2.receipt.profile.authority !== replacement.profile.authority || before2.receipt.profile.workspaceId !== replacement.profile.workspaceId) {
43190
+ throw new SkillSelectionError("PROFILE_IDENTITY_MISMATCH", "A session reconciliation cannot change its Skills authority or workspace.");
43191
+ }
43192
+ const directory = join14(selectionCacheRoot(options), "session-reconciliations", randomUUID3());
43193
+ const archivePath = join14(directory, "original.json"), replacementPath = join14(directory, "replacement.json"), receiptPath = join14(directory, "receipt.json");
43194
+ const afterSha256 = sha256Hex(bytes);
43195
+ archiveBytes(archivePath, before2.bytes);
43196
+ archiveBytes(replacementPath, bytes);
43197
+ const receipt = { schemaVersion: 1, status: "prepared", sessionId: replacement.sessionId, beforeGeneration: before2.generation, afterGeneration: replacement.generation, beforeSha256: before2.sha256, afterSha256, archivePath, replacementPath, plan };
43198
+ archiveBytes(receiptPath, Buffer.from(`${JSON.stringify(receipt)}
43199
+ `));
43200
+ syncDirectory(directory);
43201
+ syncDirectory(dirname4(directory));
43202
+ syncDirectory(selectionCacheRoot(options));
43203
+ if (sha256Hex(readRegularFile(archivePath, MAX_PROFILE_DOCUMENT_BYTES)) !== before2.sha256 || !sameSnapshot(readSkillSessionSnapshot(replacement.sessionId, options), expected)) {
43204
+ throw new SkillSelectionError("SESSION_RECEIPT_CHANGED", "The session or its preservation archive changed before replacement; retained evidence must be reviewed.");
43205
+ }
43206
+ beforeCommit();
43207
+ assertOwned();
43208
+ try {
43209
+ atomicWrite(before2.path, bytes, 384, true);
43210
+ atomicWrite(receiptPath, Buffer.from(`${JSON.stringify({ ...receipt, status: "applied" })}
43211
+ `), 384, true);
43212
+ } catch {
43213
+ throw new SkillSelectionError("SESSION_RECONCILIATION_INCOMPLETE", `Inspect sessions show and the preserved operation receipt at ${receiptPath} before any retry; replacement may already have committed.`);
43214
+ }
43215
+ return { archivePath, receiptPath, beforeSha256: before2.sha256, afterSha256 };
43216
+ });
43032
43217
  }
43033
43218
  var SkillSelectionError, MAX_CACHED_PROFILE_AGE_MS, SELECTION_LOCK_FILE = "selection.lock.json";
43034
43219
  var init_selection_cache = __esm(() => {
@@ -43048,6 +43233,7 @@ var init_selection_cache = __esm(() => {
43048
43233
  });
43049
43234
 
43050
43235
  // src/lib/agent-policy-limits.ts
43236
+ import { basename as basename3, isAbsolute as isAbsolute3, resolve as resolve5 } from "path";
43051
43237
  function object(value) {
43052
43238
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
43053
43239
  }
@@ -43112,7 +43298,11 @@ function assertAgentPolicyCollections(policy) {
43112
43298
  text(source.path);
43113
43299
  requireBound(source.sha256 === null || typeof source.sha256 === "string" && /^[a-f0-9]{64}$/.test(source.sha256));
43114
43300
  if (source.hashMode !== undefined)
43115
- requireBound(["bytes", "path-bytes", "claude-plugin-registry"].includes(source.hashMode) && source.format === undefined && source.fields === undefined && (source.hashMode === "bytes" || source.sha256 !== null));
43301
+ 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));
43302
+ if (source.hashMode === "claude-settings-v1")
43303
+ requireBound(agent === "claude" && value.agent === "claude" && value.method === "reviewed" && !/[\x00-\x1f\x7f]/.test(source.path) && isAbsolute3(source.path) && resolve5(source.path) === source.path && basename3(source.path) === "settings.json");
43304
+ if (source.hashMode === "claude-marketplace-registry")
43305
+ requireBound(agent === "claude" && value.agent === "claude" && value.method === "reviewed" && !/[\x00-\x1f\x7f]/.test(source.path) && isAbsolute3(source.path) && resolve5(source.path) === source.path && basename3(source.path) === "known_marketplaces.json");
43116
43306
  if (source.hashMode === "claude-plugin-registry") {
43117
43307
  requireBound(agent === "claude");
43118
43308
  const managed = array(source.managedPlugins, 64);
@@ -50265,7 +50455,7 @@ var init_dist = __esm(() => {
50265
50455
  });
50266
50456
 
50267
50457
  // src/lib/agent-hermes.ts
50268
- import { dirname as dirname5, isAbsolute as isAbsolute3, join as join17, resolve as resolve5 } from "path";
50458
+ import { dirname as dirname5, isAbsolute as isAbsolute4, join as join17, resolve as resolve6 } from "path";
50269
50459
  import { lstatSync as lstatSync6, readFileSync as readFileSync10, opendirSync } from "fs";
50270
50460
  function object2(value) {
50271
50461
  return Boolean(value && typeof value === "object" && (Object.getPrototypeOf(value) === Object.prototype || Object.getPrototypeOf(value) === null));
@@ -50301,7 +50491,7 @@ function quoted(value) {
50301
50491
  return `'${value.replace(/'/g, `'\\''`)}'`;
50302
50492
  }
50303
50493
  function hermesHookDefinitions(supervisor) {
50304
- if (!isAbsolute3(supervisor.runtime) || !isAbsolute3(supervisor.path))
50494
+ if (!isAbsolute4(supervisor.runtime) || !isAbsolute4(supervisor.path))
50305
50495
  throw new Error("Expected absolute Hermes supervisor paths");
50306
50496
  const entry = (event) => ({ command: `${quoted(supervisor.runtime)} ${quoted(supervisor.path)} --event ${event}`, timeout: 15, ...event === "pre_tool_call" ? { fail_closed: true } : {} });
50307
50497
  return { pre_llm_call: entry("pre_llm_call"), pre_tool_call: entry("pre_tool_call") };
@@ -50337,7 +50527,7 @@ function assertHermesEnvironment(home) {
50337
50527
  throw new Error(`NATIVE_SKILL_DRIFT: Hermes ${variable} requires a dedicated discovery adapter; unset it before using this adapter`);
50338
50528
  }
50339
50529
  const selected = process.env.HERMES_HOME?.trim();
50340
- if (selected && (!isAbsolute3(selected) || resolve5(selected) !== join17(resolve5(home), ".hermes")))
50530
+ if (selected && (!isAbsolute4(selected) || resolve6(selected) !== join17(resolve6(home), ".hermes")))
50341
50531
  throw new Error("NATIVE_SKILL_DRIFT: custom Hermes homes/profiles require their own reviewed bridge");
50342
50532
  if (process.env.HERMES_ENABLE_PROJECT_PLUGINS?.trim() && !["0", "false", "no", "off"].includes(process.env.HERMES_ENABLE_PROJECT_PLUGINS.trim().toLowerCase()))
50343
50533
  throw new Error("NATIVE_SKILL_DRIFT: Hermes project plugins require a dedicated discovery review");
@@ -50360,7 +50550,7 @@ function assertHermesProtection(home, config, command, profile, supervisor) {
50360
50550
  assertHermesEnvironment(home);
50361
50551
  if (read(join17(home, ".hermes", HERMES_OPT_OUT)) === null)
50362
50552
  throw new Error("NATIVE_SKILL_DRIFT: Hermes bundled skill reseeding is not disabled; run skills hook install");
50363
- if (!supervisor || !isAbsolute3(supervisor.path) || supervisor.runtime !== process.execPath || read(supervisor.path) !== renderHermesSupervisor(command, profile))
50553
+ if (!supervisor || !isAbsolute4(supervisor.path) || supervisor.runtime !== process.execPath || read(supervisor.path) !== renderHermesSupervisor(command, profile))
50364
50554
  throw new Error("NATIVE_SKILL_DRIFT: Hermes owned supervisor changed; run skills hook install");
50365
50555
  const raw = read(join17(home, ".hermes/shell-hooks-allowlist.json"));
50366
50556
  let trust;
@@ -50386,7 +50576,7 @@ function assertHermesProtection(home, config, command, profile, supervisor) {
50386
50576
  }
50387
50577
  function assertNoHermesLegacyShadow(root) {
50388
50578
  let entries = 0;
50389
- for (let cursor = resolve5(root);; cursor = dirname5(cursor)) {
50579
+ for (let cursor = resolve6(root);; cursor = dirname5(cursor)) {
50390
50580
  if (lstatSync6(cursor, { throwIfNoEntry: false })?.isSymbolicLink())
50391
50581
  throw new Error("NATIVE_SKILL_DRIFT: symlink Hermes legacy discovery root");
50392
50582
  if (dirname5(cursor) === cursor)
@@ -50490,13 +50680,13 @@ var init_agent_hermes = __esm(() => {
50490
50680
  // src/lib/agent-discovery-directories.ts
50491
50681
  import { createHash as createHash5 } from "crypto";
50492
50682
  import { lstatSync as lstatSync7, opendirSync as opendirSync2 } from "fs";
50493
- import { dirname as dirname6, isAbsolute as isAbsolute4, join as join18, resolve as resolve6 } from "path";
50683
+ import { dirname as dirname6, isAbsolute as isAbsolute5, join as join18, resolve as resolve7 } from "path";
50494
50684
  function need(value, message) {
50495
50685
  if (!value)
50496
50686
  throw new Error(message);
50497
50687
  }
50498
50688
  function safe(path) {
50499
- need(typeof path === "string" && path.length <= AGENT_POLICY_LIMITS.pathCharacters && isAbsolute4(path) && resolve6(path) === path && !path.includes("\x00"), "Expected a canonical absolute discovery directory path");
50689
+ need(typeof path === "string" && path.length <= AGENT_POLICY_LIMITS.pathCharacters && isAbsolute5(path) && resolve7(path) === path && !path.includes("\x00"), "Expected a canonical absolute discovery directory path");
50500
50690
  for (let cursor = path;; cursor = dirname6(cursor)) {
50501
50691
  need(!lstatSync7(cursor, { throwIfNoEntry: false })?.isSymbolicLink(), "Refusing symlink native discovery directory");
50502
50692
  if (dirname6(cursor) === cursor)
@@ -50564,12 +50754,12 @@ var init_agent_discovery_directories = __esm(() => {
50564
50754
  // src/lib/agent-discovery-bytes.ts
50565
50755
  import { createHash as createHash6 } from "crypto";
50566
50756
  import { closeSync as closeSync3, constants as constants4, fstatSync as fstatSync3, lstatSync as lstatSync8, openSync as openSync3, readSync as readSync3 } from "fs";
50567
- import { dirname as dirname7, isAbsolute as isAbsolute5, resolve as resolve7 } from "path";
50757
+ import { dirname as dirname7, isAbsolute as isAbsolute6, resolve as resolve8 } from "path";
50568
50758
  function discoveryByteBudget() {
50569
50759
  return { remaining: AGENT_POLICY_LIMITS.discoveryRawTotalBytes };
50570
50760
  }
50571
50761
  function safe2(path) {
50572
- if (typeof path !== "string" || !isAbsolute5(path) || path !== resolve7(path) || path.length > AGENT_POLICY_LIMITS.pathCharacters || path.includes("\x00"))
50762
+ if (typeof path !== "string" || !isAbsolute6(path) || path !== resolve8(path) || path.length > AGENT_POLICY_LIMITS.pathCharacters || path.includes("\x00"))
50573
50763
  throw new Error("Expected a canonical absolute raw discovery path");
50574
50764
  for (let cursor = path;; cursor = dirname7(cursor)) {
50575
50765
  if (lstatSync8(cursor, { throwIfNoEntry: false })?.isSymbolicLink())
@@ -50635,7 +50825,7 @@ var init_agent_discovery_bytes = __esm(() => {
50635
50825
  // src/lib/agent-discovery-path-bytes.ts
50636
50826
  import { createHash as createHash7 } from "crypto";
50637
50827
  import { lstatSync as lstatSync9, readlinkSync } from "fs";
50638
- import { dirname as dirname8, isAbsolute as isAbsolute6, join as join19, parse as parse2, resolve as resolve8, sep as sep3 } from "path";
50828
+ import { dirname as dirname8, isAbsolute as isAbsolute7, join as join19, parse as parse2, resolve as resolve9, sep as sep3 } from "path";
50639
50829
  function identity3(stat, mutable = false) {
50640
50830
  return {
50641
50831
  dev: String(stat.dev),
@@ -50647,7 +50837,7 @@ function identity3(stat, mutable = false) {
50647
50837
  };
50648
50838
  }
50649
50839
  function canonical(path) {
50650
- if (typeof path !== "string" || !isAbsolute6(path) || path !== resolve8(path) || path.length > AGENT_POLICY_LIMITS.pathCharacters || path.includes("\x00") || Buffer.from(path).toString("utf8") !== path)
50840
+ if (typeof path !== "string" || !isAbsolute7(path) || path !== resolve9(path) || path.length > AGENT_POLICY_LIMITS.pathCharacters || path.includes("\x00") || Buffer.from(path).toString("utf8") !== path)
50651
50841
  throw new Error("Expected a canonical absolute discovery path");
50652
50842
  }
50653
50843
  function trace(path) {
@@ -50696,11 +50886,11 @@ function trace(path) {
50696
50886
  if (!target || target.includes("\x00") || Buffer.byteLength(target) > AGENT_POLICY_LIMITS.pathCharacters || !after2.isSymbolicLink() || JSON.stringify(identity3(stat, true)) !== JSON.stringify(identity3(after2, true)))
50697
50887
  throw new Error("Discovery link changed during read");
50698
50888
  record2(candidate, { type: "link", target, ...identity3(stat, true) });
50699
- if (isAbsolute6(target)) {
50889
+ if (isAbsolute7(target)) {
50700
50890
  cursor = parse2(target).root;
50701
50891
  root();
50702
50892
  }
50703
- const remainder = isAbsolute6(target) ? target.slice(parse2(target).root.length) : target;
50893
+ const remainder = isAbsolute7(target) ? target.slice(parse2(target).root.length) : target;
50704
50894
  pending = [...remainder.split(sep3), ...pending];
50705
50895
  if (pending.length + steps > AGENT_POLICY_LIMITS.discoveryPathSteps)
50706
50896
  throw new Error("Discovery path step limit exceeded");
@@ -50756,12 +50946,12 @@ import { spawnSync } from "child_process";
50756
50946
  import { closeSync as closeSync22, fstatSync as fstatSync22, openSync as openSync22, readFileSync as readFileSync22 } from "fs";
50757
50947
  import { O_NOFOLLOW as O_NOFOLLOW2, O_NONBLOCK as O_NONBLOCK2, O_RDONLY as O_RDONLY2 } from "constants";
50758
50948
  import { hostname as osHostname } from "os";
50759
- import { isAbsolute as isAbsolute7, join as join22 } from "path";
50949
+ import { isAbsolute as isAbsolute8, join as join22 } from "path";
50760
50950
  import { createRequire } from "module";
50761
50951
  import { fileURLToPath as fileURLToPath2 } from "url";
50762
50952
  import { closeSync as closeSync4, fstatSync as fstatSync4, lstatSync as lstatSync10, openSync as openSync4, readFileSync as readFileSync11, realpathSync as realpathSync3, statSync as statSync7 } from "fs";
50763
50953
  import { O_NOFOLLOW, O_NONBLOCK, O_RDONLY } from "constants";
50764
- import { basename as basename3, dirname as dirname9, join as join20, relative as relative4, sep as sep4 } from "path";
50954
+ import { basename as basename4, dirname as dirname9, join as join20, relative as relative4, sep as sep4 } from "path";
50765
50955
  import { fileURLToPath, pathToFileURL } from "url";
50766
50956
  function envToken(name) {
50767
50957
  return name.toUpperCase().replace(/-/g, "_");
@@ -50866,7 +51056,7 @@ function entryPoint(directory) {
50866
51056
  function resolveInstalledSecrets(parentUrl) {
50867
51057
  let directory = dirname9(fileURLToPath(parentUrl));
50868
51058
  for (;; ) {
50869
- if (basename3(directory) !== "node_modules") {
51059
+ if (basename4(directory) !== "node_modules") {
50870
51060
  const candidate = join20(directory, "node_modules", PACKAGE);
50871
51061
  let absent = false;
50872
51062
  try {
@@ -50891,7 +51081,7 @@ function homeDir(env3) {
50891
51081
  }
50892
51082
  function absoluteOverride(env3, key) {
50893
51083
  const value = env3[key]?.trim();
50894
- return value && isAbsolute7(value) ? value : null;
51084
+ return value && isAbsolute8(value) ? value : null;
50895
51085
  }
50896
51086
  function hasnaHomeDir(env3) {
50897
51087
  const override = absoluteOverride(env3, HASNA_HOME_ENV_KEY);
@@ -51709,6 +51899,7 @@ __export(exports_fleet_credentials, {
51709
51899
  SKILLS_API_URL_ENV: () => SKILLS_API_URL_ENV,
51710
51900
  SKILLS_API_KEY_ENV_KEYS: () => SKILLS_API_KEY_ENV_KEYS,
51711
51901
  SKILLS_API_KEY_ENV: () => SKILLS_API_KEY_ENV,
51902
+ REDACTED_VAULT_REFERENCE: () => REDACTED_VAULT_REFERENCE,
51712
51903
  MissingSkillsFleetError: () => MissingSkillsFleetError
51713
51904
  });
51714
51905
  function isCredentialResolutionError(error) {
@@ -51717,10 +51908,15 @@ function isCredentialResolutionError(error) {
51717
51908
  function isSkillsFleetCredentialError(error) {
51718
51909
  return error instanceof SkillsFleetCredentialError || typeof error === "object" && error !== null && error.name === "SkillsFleetCredentialError";
51719
51910
  }
51720
- function asSkillsFleetCredentialError(error) {
51911
+ function redactVaultReference(message, vaultReference) {
51912
+ if (!vaultReference)
51913
+ return message;
51914
+ return message.split(vaultReference).join(REDACTED_VAULT_REFERENCE);
51915
+ }
51916
+ function asSkillsFleetCredentialError(error, vaultReference) {
51721
51917
  if (!isCredentialResolutionError(error))
51722
51918
  return null;
51723
- return new SkillsFleetCredentialError(error.message, "MISSING_API_CREDENTIAL");
51919
+ return new SkillsFleetCredentialError(redactVaultReference(error.message, vaultReference), "MISSING_API_CREDENTIAL");
51724
51920
  }
51725
51921
  function normalizeSkillsApiOrigin(apiUrl) {
51726
51922
  const url = new URL(apiUrl);
@@ -51907,7 +52103,7 @@ async function resolveSkillsConnection(env3 = process.env, options = {}) {
51907
52103
  try {
51908
52104
  completed = await completePointerCredential(SKILLS_APP, pointer, env3);
51909
52105
  } catch (error) {
51910
- const translated = asSkillsFleetCredentialError(error);
52106
+ const translated = asSkillsFleetCredentialError(error, pointer.pointerVaultKey);
51911
52107
  if (translated)
51912
52108
  throw translated;
51913
52109
  throw error;
@@ -51963,7 +52159,7 @@ function requireSkillsFleet(action = "This command", env3 = process.env, options
51963
52159
  return fleet;
51964
52160
  throw new MissingSkillsFleetError(action);
51965
52161
  }
51966
- var SKILLS_APP = "skills", ENV_KEYS, SKILLS_API_URL_ENV_KEYS, SKILLS_API_KEY_ENV_KEYS, SKILLS_API_URL_ENV, SKILLS_API_KEY_ENV, SkillsFleetCredentialError, localNoticePrinted = false, MissingSkillsFleetError;
52162
+ var SKILLS_APP = "skills", ENV_KEYS, SKILLS_API_URL_ENV_KEYS, SKILLS_API_KEY_ENV_KEYS, SKILLS_API_URL_ENV, SKILLS_API_KEY_ENV, SkillsFleetCredentialError, REDACTED_VAULT_REFERENCE = "[redacted vault reference]", localNoticePrinted = false, MissingSkillsFleetError;
51967
52163
  var init_fleet_credentials = __esm(() => {
51968
52164
  init_transport();
51969
52165
  init_instance_credentials();
@@ -52909,11 +53105,18 @@ async function syncSelectionProfile(profileId, options = {}) {
52909
53105
  return { profile, receipt, changed, downloaded, stationReported };
52910
53106
  }
52911
53107
  async function resolveSelectionContext(profileId, options = {}) {
52912
- const session = options.sessionId ? readSkillSession(options.sessionId, options) : null;
52913
- const parentSession = !session && options.parentSessionId ? readSkillSession(options.parentSessionId, options) : null;
53108
+ const sessionState = options.sessionId ? readSkillSessionSnapshotIfExists(options.sessionId, options) : null;
53109
+ const session = sessionState?.receipt ?? null;
53110
+ const parentState = !session && options.parentSessionId ? readSkillSessionSnapshotIfExists(options.parentSessionId, options) : null;
53111
+ if (!session && options.parentSessionId && !parentState) {
53112
+ throw new SkillSelectionError("SESSION_PARENT_NOT_FOUND", "A child Skills session requires an existing parent receipt so its inherited pin can be bound exactly.");
53113
+ }
53114
+ const parentSession = parentState?.receipt ?? null;
53115
+ const sessionSnapshot = sessionState ? skillSessionSnapshotBinding(sessionState) : null;
53116
+ const parentSnapshot = parentState ? skillSessionSnapshotBinding(parentState) : undefined;
52914
53117
  const project = options.projectDir ? readProjectSelection(options.projectDir) : null;
52915
53118
  if (session && session.profile.profileId !== profileId || parentSession && parentSession.profile.profileId !== profileId || project && project.profile.profileId !== profileId) {
52916
- throw new SkillSelectionError("PROFILE_LOCK_MISMATCH", "The session or project is pinned to a different Skills profile. Select that profile or explicitly sync the new selection.");
53119
+ throw new SkillSelectionError("PROFILE_LOCK_MISMATCH", "The session or project is pinned to a different Skills profile. Select the pinned profile, or review skills sessions reconcile for an intentional session change and explicit project sync for a project change.");
52917
53120
  }
52918
53121
  if (options.cached) {
52919
53122
  const receipt2 = session ?? parentSession ?? project ?? readSelectionProfile(profileId, options);
@@ -52921,7 +53124,7 @@ async function resolveSelectionContext(profileId, options = {}) {
52921
53124
  throw new SkillSelectionError("CACHED_PROFILE_MISSING", "No verified Skills profile is cached; authenticate and sync it first.");
52922
53125
  assertFreshCachedProfile(receipt2, options);
52923
53126
  assertBinding(receipt2.profile, options);
52924
- return { receipt: receipt2, session, inheritedLoaded: parentSession?.loaded };
53127
+ return { receipt: receipt2, session, sessionSnapshot, parentSnapshot, inheritedLoaded: parentSession?.loaded };
52925
53128
  }
52926
53129
  const client = options.client ?? await createProfileClient();
52927
53130
  const current = await client.resolveProfile(profileId);
@@ -52934,7 +53137,7 @@ async function resolveSelectionContext(profileId, options = {}) {
52934
53137
  throw new SkillSelectionError("PROFILE_IDENTITY_MISMATCH", "The pinned selection belongs to another Skills authority or workspace.");
52935
53138
  }
52936
53139
  const receipt = locked ?? { schemaVersion: 1, verifiedAt: new Date((options.now ?? Date.now)()).toISOString(), profile: current };
52937
- return { receipt, session, client, inheritedLoaded: parentSession?.loaded };
53140
+ return { receipt, session, sessionSnapshot, parentSnapshot, client, inheritedLoaded: parentSession?.loaded };
52938
53141
  }
52939
53142
  function assertBinding(profile, options) {
52940
53143
  if (options.authority !== undefined && profile.authority !== options.authority || options.workspaceId !== undefined && profile.workspaceId !== options.workspaceId) {
@@ -52973,7 +53176,7 @@ async function loadSelectedSkill(spec, profileId, options = {}) {
52973
53176
  sessionId: options.sessionId,
52974
53177
  loaded: [...new Set([...context.session?.loaded ?? [], selectionKey(selection)])]
52975
53178
  };
52976
- writeSelectionJson(sessionReceiptPath(options.sessionId, options), session);
53179
+ writeSkillSession(session, { current: context.sessionSnapshot, parent: context.parentSnapshot }, options);
52977
53180
  }
52978
53181
  return { content, selection, receipt };
52979
53182
  }
@@ -53214,8 +53417,8 @@ var init_plugin_projection = __esm(() => {
53214
53417
 
53215
53418
  // src/lib/plugin-projection-store.ts
53216
53419
  import { createHash as createHash10, randomUUID as randomUUID5 } from "crypto";
53217
- import { constants as constants7, closeSync as closeSync7, fchmodSync, fstatSync as fstatSync7, fsyncSync, linkSync, lstatSync as lstatSync13, mkdirSync as mkdirSync6, openSync as openSync7, opendirSync as opendirSync3, readSync as readSync5, renameSync as renameSync3, rmdirSync as rmdirSync2, rmSync as rmSync2, unlinkSync as unlinkSync3, writeSync as writeSync2 } from "fs";
53218
- import { dirname as dirname10, isAbsolute as isAbsolute8, join as join25, parse as parse4, resolve as resolve9 } from "path";
53420
+ import { constants as constants7, closeSync as closeSync7, fchmodSync, fstatSync as fstatSync7, fsyncSync as fsyncSync2, linkSync, lstatSync as lstatSync13, mkdirSync as mkdirSync6, openSync as openSync7, opendirSync as opendirSync3, readSync as readSync5, renameSync as renameSync3, rmdirSync as rmdirSync2, rmSync as rmSync2, unlinkSync as unlinkSync3, writeSync as writeSync2 } from "fs";
53421
+ import { dirname as dirname10, isAbsolute as isAbsolute9, join as join25, parse as parse4, resolve as resolve10 } from "path";
53219
53422
  function stat(path) {
53220
53423
  try {
53221
53424
  return lstatSync13(path, { bigint: true });
@@ -53226,7 +53429,7 @@ function stat(path) {
53226
53429
  }
53227
53430
  }
53228
53431
  function canonical2(path) {
53229
- pluginNeed(typeof path === "string" && path.length <= 8192 && isAbsolute8(path) && resolve9(path) === path && !/[\x00-\x1f\x7f]/.test(path), "Plugin storage paths must be canonical absolute paths");
53432
+ pluginNeed(typeof path === "string" && path.length <= 8192 && isAbsolute9(path) && resolve10(path) === path && !/[\x00-\x1f\x7f]/.test(path), "Plugin storage paths must be canonical absolute paths");
53230
53433
  }
53231
53434
  function owner(stats, system = false) {
53232
53435
  const current = uid();
@@ -53435,7 +53638,7 @@ function writeExclusive(path, bytes, mode) {
53435
53638
  pluginNeed(count > 0, "Plugin file write did not progress");
53436
53639
  offset += count;
53437
53640
  }
53438
- fsyncSync(fd);
53641
+ fsyncSync2(fd);
53439
53642
  } catch (error) {
53440
53643
  if (created) {
53441
53644
  same3(created, stat(path), true);
@@ -53608,7 +53811,7 @@ var init_selected_manifest = __esm(() => {
53608
53811
 
53609
53812
  // src/lib/plugin-admission.ts
53610
53813
  import { homedir as homedir3 } from "os";
53611
- import { isAbsolute as isAbsolute9, join as join26, resolve as resolve10 } from "path";
53814
+ import { isAbsolute as isAbsolute10, join as join26, resolve as resolve11 } from "path";
53612
53815
  function pluginAdmissionRoot() {
53613
53816
  return join26(homedir3(), ".hasna", "skills", "plugin-admission");
53614
53817
  }
@@ -53621,7 +53824,7 @@ function validatePluginTarget(value) {
53621
53824
  for (const registration of value.registrations) {
53622
53825
  pluginKeys(registration, ["scope", "projectPath"]);
53623
53826
  pluginNeed(registration.scope === "user" || registration.scope === "project", "Unsupported plugin registration scope");
53624
- pluginNeed(registration.scope === "user" ? registration.projectPath === null : typeof registration.projectPath === "string" && isAbsolute9(registration.projectPath) && resolve10(registration.projectPath) === registration.projectPath, "Plugin scope requires its exact project path");
53827
+ pluginNeed(registration.scope === "user" ? registration.projectPath === null : typeof registration.projectPath === "string" && isAbsolute10(registration.projectPath) && resolve11(registration.projectPath) === registration.projectPath, "Plugin scope requires its exact project path");
53625
53828
  const key = JSON.stringify([registration.scope, registration.projectPath]);
53626
53829
  pluginNeed(!scopes.has(key), "Duplicate plugin registration scope");
53627
53830
  scopes.add(key);
@@ -53629,7 +53832,7 @@ function validatePluginTarget(value) {
53629
53832
  for (const key of ["native", "resolver"]) {
53630
53833
  pluginKeys(value[key], key === "native" ? ["version", "executable", "digest"] : ["executable", "digest"]);
53631
53834
  pluginText(value[key].executable);
53632
- pluginNeed(isAbsolute9(value[key].executable) && resolve10(value[key].executable) === value[key].executable, "Plugin executable must have a canonical absolute path");
53835
+ pluginNeed(isAbsolute10(value[key].executable) && resolve11(value[key].executable) === value[key].executable, "Plugin executable must have a canonical absolute path");
53633
53836
  pluginDigest(value[key].digest);
53634
53837
  }
53635
53838
  pluginNeed(["2.1.274", "2.1.276"].includes(value.native.version), "Plugin admission requires a certified Claude command-source runtime (2.1.274 or 2.1.276)");
@@ -53779,7 +53982,7 @@ function pluginResolverCommand(binding) {
53779
53982
  }
53780
53983
  function root(options) {
53781
53984
  const path = options.storeRoot ?? pluginAdmissionRoot();
53782
- pluginNeed(isAbsolute9(path) && resolve10(path) === path, "Invalid plugin admission store root");
53985
+ pluginNeed(isAbsolute10(path) && resolve11(path) === path, "Invalid plugin admission store root");
53783
53986
  return path;
53784
53987
  }
53785
53988
  function pluginBindingPath(storeRoot, id) {
@@ -53987,7 +54190,7 @@ var init_plugin_admission = __esm(() => {
53987
54190
 
53988
54191
  // src/lib/plugin-discovery.ts
53989
54192
  import { closeSync as closeSync8, constants as constants8, fstatSync as fstatSync8, lstatSync as lstatSync14, openSync as openSync8, opendirSync as opendirSync4, readSync as readSync6 } from "fs";
53990
- import { basename as basename4, dirname as dirname11, isAbsolute as isAbsolute10, join as join27, resolve as resolve11 } from "path";
54193
+ import { basename as basename5, dirname as dirname11, isAbsolute as isAbsolute11, join as join27, resolve as resolve12 } from "path";
53991
54194
  function validateManagedPluginWitnesses(value) {
53992
54195
  pluginNeed(Array.isArray(value) && value.length > 0 && value.length <= PLUGIN_PROJECTION_LIMITS.registrations, "Invalid managed plugin witness collection");
53993
54196
  const seen = new Set;
@@ -53996,12 +54199,12 @@ function validateManagedPluginWitnesses(value) {
53996
54199
  pluginNeed(typeof item.bindingId === "string" && /^[a-f0-9]{64}$/.test(item.bindingId) && !seen.has(item.bindingId), "Invalid or duplicate managed plugin witness");
53997
54200
  seen.add(item.bindingId);
53998
54201
  pluginText(item.storeRoot);
53999
- pluginNeed(isAbsolute10(item.storeRoot) && resolve11(item.storeRoot) === item.storeRoot, "Invalid plugin receipt store path");
54202
+ pluginNeed(isAbsolute11(item.storeRoot) && resolve12(item.storeRoot) === item.storeRoot, "Invalid plugin receipt store path");
54000
54203
  }
54001
54204
  }
54002
54205
  function safe3(path) {
54003
54206
  pluginText(path);
54004
- pluginNeed(isAbsolute10(path) && resolve11(path) === path, "Invalid plugin registry path");
54207
+ pluginNeed(isAbsolute11(path) && resolve12(path) === path, "Invalid plugin registry path");
54005
54208
  for (let at2 = path;; at2 = dirname11(at2)) {
54006
54209
  pluginNeed(!lstatSync14(at2, { throwIfNoEntry: false })?.isSymbolicLink(), "Plugin registry path traverses a symlink");
54007
54210
  if (at2 === dirname11(at2))
@@ -54070,7 +54273,7 @@ function hashManagedPluginRegistry(path, managed) {
54070
54273
  pluginNeed(/^(?:[A-Za-z0-9][A-Za-z0-9._+-]*-)?[a-f0-9]{12}$/.test(row.version) && row.installPath === join27(cacheRoot, row.version), "Managed plugin cache path or version is outside its registration");
54071
54274
  const approval = (producer) => {
54072
54275
  pluginText(producer);
54073
- const digest = `sha256:${basename4(producer)}`;
54276
+ const digest = `sha256:${basename5(producer)}`;
54074
54277
  const receipt2 = readPluginAdmissionReceipt(witness.storeRoot, witness.bindingId, digest);
54075
54278
  pluginNeed(receipt2.materializedPath === producer, "Managed producer path is not an approved immutable projection");
54076
54279
  if (!verified.has(producer)) {
@@ -54133,10 +54336,403 @@ var init_plugin_discovery = __esm(() => {
54133
54336
  init_plugin_projection_store();
54134
54337
  });
54135
54338
 
54136
- // src/lib/agent-discovery.ts
54339
+ // src/lib/claude-marketplace-registry.ts
54137
54340
  import { createHash as createHash11 } from "crypto";
54138
- import { lstatSync as lstatSync15, readFileSync as readFileSync14, readdirSync as readdirSync9, realpathSync as realpathSync4 } from "fs";
54139
- import { dirname as dirname12, isAbsolute as isAbsolute11, join as join28, resolve as resolve12, sep as sep5 } from "path";
54341
+ import { closeSync as closeSync9, constants as constants9, fstatSync as fstatSync9, lstatSync as lstatSync15, openSync as openSync9, readSync as readSync7 } from "fs";
54342
+ import { basename as basename6, dirname as dirname12, isAbsolute as isAbsolute12, resolve as resolve13 } from "path";
54343
+ function need2(value, reason) {
54344
+ if (!value)
54345
+ throw new Error(`Claude marketplace registry ${reason}`);
54346
+ }
54347
+ function absolutePath(value) {
54348
+ need2(typeof value === "string" && value.length > 0 && value.length <= CLAUDE_MARKETPLACE_REGISTRY_LIMITS.pathCharacters && !/[\x00-\x1f\x7f]/.test(value) && isAbsolute12(value) && resolve13(value) === value, "requires a normalized absolute path");
54349
+ }
54350
+ function parents(path) {
54351
+ const result2 = [];
54352
+ for (let at2 = dirname12(path);; at2 = dirname12(at2)) {
54353
+ const stat2 = lstatSync15(at2, { bigint: true });
54354
+ need2(stat2.isDirectory() && !stat2.isSymbolicLink(), "path traverses a symlink or non-directory");
54355
+ result2.push([at2, stat2]);
54356
+ if (at2 === dirname12(at2))
54357
+ return result2;
54358
+ }
54359
+ }
54360
+ function readRegistry2(path, budget) {
54361
+ absolutePath(path);
54362
+ need2(basename6(path) === "known_marketplaces.json", "requires known_marketplaces.json");
54363
+ need2(Number.isSafeInteger(budget.remaining) && budget.remaining >= 0, "has an invalid byte budget");
54364
+ const ancestors2 = parents(path), initial2 = lstatSync15(path, { bigint: true });
54365
+ need2(initial2.isFile() && !initial2.isSymbolicLink() && initial2.size <= BigInt(CLAUDE_MARKETPLACE_REGISTRY_LIMITS.bytes), "is not a bounded regular file");
54366
+ need2(initial2.size <= BigInt(budget.remaining), "exceeds its aggregate byte limit");
54367
+ const fd = openSync9(path, constants9.O_RDONLY | constants9.O_NOFOLLOW | constants9.O_NONBLOCK);
54368
+ try {
54369
+ const opened = fstatSync9(fd, { bigint: true });
54370
+ need2(opened.isFile() && sameFile(initial2, opened), "changed during open");
54371
+ const bytes = Buffer.alloc(Number(opened.size) + 1);
54372
+ let length = 0;
54373
+ while (length < bytes.length) {
54374
+ const count = readSync7(fd, bytes, length, bytes.length - length, null);
54375
+ if (!count)
54376
+ break;
54377
+ length += count;
54378
+ }
54379
+ const after2 = fstatSync9(fd, { bigint: true }), current = lstatSync15(path, { bigint: true });
54380
+ need2(current.isFile() && sameFile(opened, after2) && sameFile(after2, current) && BigInt(length) === opened.size, "changed during read");
54381
+ for (const [ancestor, before2] of ancestors2) {
54382
+ const now3 = lstatSync15(ancestor, { bigint: true });
54383
+ need2(now3.isDirectory() && before2.dev === now3.dev && before2.ino === now3.ino && before2.mode === now3.mode, "parent changed during read");
54384
+ }
54385
+ budget.remaining -= length;
54386
+ try {
54387
+ return new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(bytes.subarray(0, length));
54388
+ } catch {
54389
+ throw new Error("Claude marketplace registry is not strict UTF-8");
54390
+ }
54391
+ } finally {
54392
+ closeSync9(fd);
54393
+ }
54394
+ }
54395
+ function parse5(text2) {
54396
+ let at2 = 0, nodes = 0;
54397
+ const numberPattern = /-?(?:0|[1-9][0-9]*)(?:\.[0-9]+)?(?:[eE][+-]?[0-9]+)?/y;
54398
+ const space = () => {
54399
+ while (at2 < text2.length && /[\x20\t\r\n]/.test(text2[at2]))
54400
+ at2++;
54401
+ };
54402
+ function string() {
54403
+ need2(text2[at2] === '"', "contains invalid JSON");
54404
+ const start = at2++;
54405
+ while (at2 < text2.length) {
54406
+ const character = text2[at2++];
54407
+ if (character === '"') {
54408
+ let value2;
54409
+ try {
54410
+ value2 = JSON.parse(text2.slice(start, at2));
54411
+ } catch {
54412
+ throw new Error("Claude marketplace registry contains invalid JSON string");
54413
+ }
54414
+ need2(value2.length <= CLAUDE_MARKETPLACE_REGISTRY_LIMITS.stringCharacters, "exceeds its string limit");
54415
+ return value2;
54416
+ }
54417
+ if (character === "\\")
54418
+ at2++;
54419
+ }
54420
+ throw new Error("Claude marketplace registry contains an unterminated JSON string");
54421
+ }
54422
+ function value(depth) {
54423
+ need2(depth <= CLAUDE_MARKETPLACE_REGISTRY_LIMITS.depth && ++nodes <= CLAUDE_MARKETPLACE_REGISTRY_LIMITS.nodes, "exceeds its nesting or node limit");
54424
+ space();
54425
+ const character = text2[at2];
54426
+ if (character === '"')
54427
+ return { kind: "string", value: string() };
54428
+ if (character === "{" || character === "[") {
54429
+ at2++;
54430
+ space();
54431
+ const object4 = character === "{", end = object4 ? "}" : "]", entries = [], items = [], keys2 = new Set;
54432
+ if (text2[at2] !== end)
54433
+ while (true) {
54434
+ if (object4) {
54435
+ space();
54436
+ const key = string();
54437
+ need2(!keys2.has(key), "contains a duplicate JSON key");
54438
+ keys2.add(key);
54439
+ space();
54440
+ need2(text2[at2++] === ":", "contains invalid JSON");
54441
+ entries.push([key, value(depth + 1)]);
54442
+ } else
54443
+ items.push(value(depth + 1));
54444
+ space();
54445
+ if (text2[at2] === end)
54446
+ break;
54447
+ need2(text2[at2++] === ",", "contains invalid JSON");
54448
+ }
54449
+ at2++;
54450
+ return object4 ? { kind: "object", entries } : { kind: "array", items };
54451
+ }
54452
+ for (const literal of ["true", "false", "null"])
54453
+ if (text2.startsWith(literal, at2)) {
54454
+ at2 += literal.length;
54455
+ return { kind: "literal", value: literal };
54456
+ }
54457
+ numberPattern.lastIndex = at2;
54458
+ const number = numberPattern.exec(text2);
54459
+ need2(number, "contains invalid JSON");
54460
+ at2 += number[0].length;
54461
+ return { kind: "number", value: number[0] };
54462
+ }
54463
+ const root2 = value(0);
54464
+ space();
54465
+ need2(at2 === text2.length && root2.kind === "object", "requires a JSON object without trailing content");
54466
+ need2(root2.entries.length <= CLAUDE_MARKETPLACE_REGISTRY_LIMITS.rows, "exceeds its marketplace row limit");
54467
+ return root2;
54468
+ }
54469
+ function exactKeys(value, keys2) {
54470
+ return value?.kind === "object" && value.entries.length === keys2.length && value.entries.every(([key]) => keys2.includes(key));
54471
+ }
54472
+ function textField(value) {
54473
+ need2(value?.kind === "string" && value.value.length > 0 && !/[\x00-\x1f\x7f]/.test(value.value), "contains an invalid recognized field");
54474
+ return value.value;
54475
+ }
54476
+ function normalizeRow(row) {
54477
+ if (!exactKeys(row, ["source", "installLocation", "lastUpdated"]))
54478
+ return;
54479
+ const source = field(row, "source");
54480
+ if (source?.kind !== "object")
54481
+ return;
54482
+ const type = field(source, "source");
54483
+ if (type?.kind !== "string" || !["github", "directory"].includes(type.value))
54484
+ return;
54485
+ const location = type.value === "github" ? "repo" : "path";
54486
+ if (!exactKeys(source, ["source", location]))
54487
+ return;
54488
+ const sourceLocation = textField(field(source, location));
54489
+ if (type.value === "directory")
54490
+ absolutePath(sourceLocation);
54491
+ absolutePath(textField(field(row, "installLocation")));
54492
+ const updated = textField(field(row, "lastUpdated"));
54493
+ need2(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/.test(updated), "contains an invalid recognized update timestamp");
54494
+ const millis = Date.parse(updated);
54495
+ need2(Number.isFinite(millis) && new Date(millis).toISOString() === updated, "contains an invalid recognized update timestamp");
54496
+ row.entries = row.entries.map(([key, value]) => [key, key === "lastUpdated" ? { kind: "validated-update-time" } : value]);
54497
+ }
54498
+ function captureClaudeMarketplaceRegistry(path, budget = { remaining: 256 * 1024 * 1024 }) {
54499
+ const value = parse5(readRegistry2(path, budget));
54500
+ for (const [, row] of value.entries)
54501
+ normalizeRow(row);
54502
+ const sha2562 = createHash11("sha256").update("hasna.skills.claude-marketplace-registry.v1\x00").update(JSON.stringify(value)).digest("hex");
54503
+ return { path, hashMode: "claude-marketplace-registry", sha256: sha2562 };
54504
+ }
54505
+ var CLAUDE_MARKETPLACE_REGISTRY_LIMITS, sameFile = (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, field = (object4, key) => object4.entries.find(([name]) => name === key)?.[1];
54506
+ var init_claude_marketplace_registry = __esm(() => {
54507
+ CLAUDE_MARKETPLACE_REGISTRY_LIMITS = Object.freeze({ bytes: 1024 * 1024, rows: 1024, depth: 32, nodes: 65536, stringCharacters: 16384, pathCharacters: 4096 });
54508
+ });
54509
+
54510
+ // src/lib/claude-settings-witness.ts
54511
+ import { createHash as createHash12 } from "crypto";
54512
+ import { closeSync as closeSync10, constants as constants10, fstatSync as fstatSync10, lstatSync as lstatSync16, openSync as openSync10, readSync as readSync8 } from "fs";
54513
+ import { basename as basename7, dirname as dirname13, isAbsolute as isAbsolute13, resolve as resolve14 } from "path";
54514
+ function need3(value, reason) {
54515
+ if (!value)
54516
+ throw new Error(`Claude settings witness ${reason}`);
54517
+ }
54518
+ function absolutePath2(value) {
54519
+ need3(typeof value === "string" && value.length > 0 && value.length <= CLAUDE_SETTINGS_WITNESS_LIMITS.pathCharacters && !/[\x00-\x1f\x7f]/.test(value) && isAbsolute13(value) && resolve14(value) === value, "requires a normalized absolute path");
54520
+ }
54521
+ function parents2(path) {
54522
+ const result2 = [];
54523
+ for (let at2 = dirname13(path);; at2 = dirname13(at2)) {
54524
+ const stat2 = lstatSync16(at2, { bigint: true });
54525
+ need3(stat2.isDirectory() && !stat2.isSymbolicLink(), "path traverses a symlink or non-directory");
54526
+ result2.push([at2, stat2]);
54527
+ if (at2 === dirname13(at2))
54528
+ return result2;
54529
+ }
54530
+ }
54531
+ function readSettings(path, budget) {
54532
+ absolutePath2(path);
54533
+ need3(basename7(path) === "settings.json", "requires settings.json");
54534
+ need3(Number.isSafeInteger(budget.remaining) && budget.remaining >= 0, "has an invalid byte budget");
54535
+ const ancestors2 = parents2(path), initial2 = lstatSync16(path, { bigint: true });
54536
+ need3(initial2.isFile() && !initial2.isSymbolicLink() && initial2.size <= BigInt(CLAUDE_SETTINGS_WITNESS_LIMITS.bytes), "is not a bounded regular file");
54537
+ need3(initial2.size <= BigInt(budget.remaining), "exceeds its aggregate byte limit");
54538
+ const fd = openSync10(path, constants10.O_RDONLY | constants10.O_NOFOLLOW | constants10.O_NONBLOCK);
54539
+ try {
54540
+ const opened = fstatSync10(fd, { bigint: true });
54541
+ need3(opened.isFile() && sameFile2(initial2, opened), "changed during open");
54542
+ const bytes = Buffer.alloc(Number(opened.size) + 1);
54543
+ let length = 0;
54544
+ while (length < bytes.length) {
54545
+ const count = readSync8(fd, bytes, length, bytes.length - length, null);
54546
+ if (!count)
54547
+ break;
54548
+ length += count;
54549
+ }
54550
+ const after2 = fstatSync10(fd, { bigint: true }), current = lstatSync16(path, { bigint: true });
54551
+ need3(current.isFile() && sameFile2(opened, after2) && sameFile2(after2, current) && BigInt(length) === opened.size, "changed during read");
54552
+ for (const [ancestor, before2] of ancestors2) {
54553
+ const now3 = lstatSync16(ancestor, { bigint: true });
54554
+ need3(now3.isDirectory() && before2.dev === now3.dev && before2.ino === now3.ino && before2.mode === now3.mode, "parent changed during read");
54555
+ }
54556
+ budget.remaining -= length;
54557
+ try {
54558
+ return new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(bytes.subarray(0, length));
54559
+ } catch {
54560
+ throw new Error("Claude settings witness is not strict UTF-8");
54561
+ }
54562
+ } finally {
54563
+ closeSync10(fd);
54564
+ }
54565
+ }
54566
+ function parse6(text2) {
54567
+ let at2 = 0, nodes = 0;
54568
+ const numberPattern = /-?(?:0|[1-9][0-9]*)(?:\.[0-9]+)?(?:[eE][+-]?[0-9]+)?/y;
54569
+ const space = () => {
54570
+ while (at2 < text2.length && /[\x20\t\r\n]/.test(text2[at2]))
54571
+ at2++;
54572
+ };
54573
+ function string() {
54574
+ need3(text2[at2] === '"', "contains invalid JSON");
54575
+ const start = at2++;
54576
+ while (at2 < text2.length) {
54577
+ const character = text2[at2++];
54578
+ if (character === '"') {
54579
+ let value2;
54580
+ try {
54581
+ value2 = JSON.parse(text2.slice(start, at2));
54582
+ } catch {
54583
+ throw new Error("Claude settings witness contains invalid JSON string");
54584
+ }
54585
+ need3(value2.length <= CLAUDE_SETTINGS_WITNESS_LIMITS.stringCharacters, "exceeds its string limit");
54586
+ return value2;
54587
+ }
54588
+ if (character === "\\")
54589
+ at2++;
54590
+ }
54591
+ throw new Error("Claude settings witness contains an unterminated JSON string");
54592
+ }
54593
+ function value(depth) {
54594
+ need3(depth <= CLAUDE_SETTINGS_WITNESS_LIMITS.depth && ++nodes <= CLAUDE_SETTINGS_WITNESS_LIMITS.nodes, "exceeds its nesting or node limit");
54595
+ space();
54596
+ const character = text2[at2];
54597
+ if (character === '"')
54598
+ return { kind: "string", value: string() };
54599
+ if (character === "{" || character === "[") {
54600
+ at2++;
54601
+ space();
54602
+ const object4 = character === "{", end = object4 ? "}" : "]", entries = [], items = [], keys2 = new Set;
54603
+ if (text2[at2] !== end)
54604
+ while (true) {
54605
+ if (object4) {
54606
+ space();
54607
+ const key = string();
54608
+ need3(!keys2.has(key), "contains a duplicate JSON key");
54609
+ keys2.add(key);
54610
+ space();
54611
+ need3(text2[at2++] === ":", "contains invalid JSON");
54612
+ entries.push([key, value(depth + 1)]);
54613
+ } else
54614
+ items.push(value(depth + 1));
54615
+ space();
54616
+ if (text2[at2] === end)
54617
+ break;
54618
+ need3(text2[at2++] === ",", "contains invalid JSON");
54619
+ }
54620
+ at2++;
54621
+ return object4 ? { kind: "object", entries } : { kind: "array", items };
54622
+ }
54623
+ for (const literal of ["true", "false", "null"])
54624
+ if (text2.startsWith(literal, at2)) {
54625
+ at2 += literal.length;
54626
+ return { kind: "literal", value: literal };
54627
+ }
54628
+ numberPattern.lastIndex = at2;
54629
+ const number = numberPattern.exec(text2);
54630
+ need3(number, "contains invalid JSON");
54631
+ at2 += number[0].length;
54632
+ return { kind: "number", value: number[0] };
54633
+ }
54634
+ const root2 = value(0);
54635
+ space();
54636
+ need3(at2 === text2.length && root2.kind === "object", "requires a JSON object without trailing content");
54637
+ need3(root2.entries.length <= CLAUDE_SETTINGS_WITNESS_LIMITS.rows, "exceeds its settings field limit");
54638
+ return root2;
54639
+ }
54640
+ function canonical3(value) {
54641
+ if (value.kind === "object")
54642
+ return { kind: "object", entries: value.entries.map(([key, child]) => [key, canonical3(child)]).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0) };
54643
+ if (value.kind === "array")
54644
+ return { kind: "array", items: value.items.map(canonical3) };
54645
+ return value;
54646
+ }
54647
+ function settingsDigest(text2) {
54648
+ const value = parse6(text2);
54649
+ value.entries = value.entries.filter(([key, child]) => {
54650
+ if (key === "model") {
54651
+ need3(child.kind === "string", "contains an invalid model selection");
54652
+ return !BUILTIN_MODEL_SELECTIONS.has(child.value);
54653
+ }
54654
+ if (BOOLEAN_PREFERENCES.has(key)) {
54655
+ need3(child.kind === "literal" && (child.value === "true" || child.value === "false"), "contains an invalid display preference");
54656
+ return false;
54657
+ }
54658
+ if (Object.hasOwn(ENUM_PREFERENCES, key)) {
54659
+ need3(child.kind === "string" && ENUM_PREFERENCES[key].includes(child.value), "contains an invalid display preference");
54660
+ return false;
54661
+ }
54662
+ return true;
54663
+ });
54664
+ return createHash12("sha256").update("hasna.skills.claude-settings.v1\x00").update(JSON.stringify(canonical3(value))).digest("hex");
54665
+ }
54666
+ function hashClaudeSettingsReplacement(text2, budget) {
54667
+ need3(typeof text2 === "string", "requires settings text");
54668
+ const bytes = Buffer.byteLength(text2);
54669
+ need3(bytes <= CLAUDE_SETTINGS_WITNESS_LIMITS.bytes && Number.isSafeInteger(budget.remaining) && budget.remaining >= bytes, "exceeds its byte limit");
54670
+ budget.remaining -= bytes;
54671
+ return settingsDigest(text2);
54672
+ }
54673
+ function captureClaudeSettings(path, budget = { remaining: 256 * 1024 * 1024 }) {
54674
+ return { path, hashMode: "claude-settings-v1", sha256: settingsDigest(readSettings(path, budget)) };
54675
+ }
54676
+ var CLAUDE_SETTINGS_WITNESS_LIMITS, 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, BOOLEAN_PREFERENCES, ENUM_PREFERENCES, BUILTIN_MODEL_SELECTIONS;
54677
+ var init_claude_settings_witness = __esm(() => {
54678
+ CLAUDE_SETTINGS_WITNESS_LIMITS = Object.freeze({ bytes: 1024 * 1024, rows: 1024, depth: 32, nodes: 65536, stringCharacters: 16384, pathCharacters: 4096 });
54679
+ BOOLEAN_PREFERENCES = new Set([
54680
+ "autoScrollEnabled",
54681
+ "axScreenReader",
54682
+ "emojiCompletionEnabled",
54683
+ "prefersReducedMotion",
54684
+ "showTurnDuration",
54685
+ "spinnerTipsEnabled",
54686
+ "syntaxHighlightingDisabled",
54687
+ "terminalProgressBarEnabled",
54688
+ "terminalTitleFromRename",
54689
+ "verbose",
54690
+ "wheelScrollAccelerationEnabled"
54691
+ ]);
54692
+ ENUM_PREFERENCES = Object.freeze({
54693
+ editorMode: ["normal", "vim"],
54694
+ tui: ["default", "fullscreen"],
54695
+ viewMode: ["default", "verbose", "focus"]
54696
+ });
54697
+ BUILTIN_MODEL_SELECTIONS = new Set([
54698
+ "default",
54699
+ "best",
54700
+ "fable",
54701
+ "fable[1m]",
54702
+ "sonnet",
54703
+ "sonnet[1m]",
54704
+ "opus",
54705
+ "opus[1m]",
54706
+ "haiku",
54707
+ "opusplan",
54708
+ "claude-fable-5-1",
54709
+ "claude-fable-5",
54710
+ "claude-fable-5[1m]",
54711
+ "claude-opus-5",
54712
+ "claude-sonnet-5",
54713
+ "claude-haiku-4-5-20251001",
54714
+ "claude-opus-4-6",
54715
+ "claude-sonnet-4-5",
54716
+ "claude-sonnet-4-5-20250929",
54717
+ "claude-opus-4-8",
54718
+ "claude-opus-4-8[1m]",
54719
+ "claude-opus-4-7",
54720
+ "claude-sonnet-4-6",
54721
+ "claude-opus-4-5-20251101",
54722
+ "claude-opus-4-5",
54723
+ "claude-haiku-4-5",
54724
+ "claude-fable-5-1[1m]",
54725
+ "claude-opus-5[1m]",
54726
+ "claude-opus-4-7[1m]",
54727
+ "claude-opus-4-6[1m]",
54728
+ "claude-sonnet-4-6[1m]"
54729
+ ]);
54730
+ });
54731
+
54732
+ // src/lib/agent-discovery.ts
54733
+ import { createHash as createHash13 } from "crypto";
54734
+ import { lstatSync as lstatSync17, readFileSync as readFileSync14, readdirSync as readdirSync9, realpathSync as realpathSync4 } from "fs";
54735
+ import { basename as basename8, dirname as dirname14, isAbsolute as isAbsolute14, join as join28, resolve as resolve15, sep as sep5 } from "path";
54140
54736
  function parseConfig(text2, path, toml = false) {
54141
54737
  try {
54142
54738
  const value = toml ? Bun.TOML.parse(text2) : JSON.parse(text2);
@@ -54148,12 +54744,12 @@ function parseConfig(text2, path, toml = false) {
54148
54744
  }
54149
54745
  }
54150
54746
  function safe4(path) {
54151
- if (!isAbsolute11(path) || path.includes("\x00"))
54747
+ if (!isAbsolute14(path) || path.includes("\x00"))
54152
54748
  throw new Error("Expected an absolute native discovery path");
54153
- for (let cursor = path;; cursor = dirname12(cursor)) {
54154
- if (lstatSync15(cursor, { throwIfNoEntry: false })?.isSymbolicLink())
54749
+ for (let cursor = path;; cursor = dirname14(cursor)) {
54750
+ if (lstatSync17(cursor, { throwIfNoEntry: false })?.isSymbolicLink())
54155
54751
  throw new Error(`Refusing symlink native discovery input: ${cursor}`);
54156
- if (dirname12(cursor) === cursor)
54752
+ if (dirname14(cursor) === cursor)
54157
54753
  break;
54158
54754
  }
54159
54755
  }
@@ -54161,7 +54757,7 @@ function read2(path, changes) {
54161
54757
  safe4(path);
54162
54758
  if (changes?.has(path))
54163
54759
  return changes.get(path);
54164
- const stat2 = lstatSync15(path, { throwIfNoEntry: false });
54760
+ const stat2 = lstatSync17(path, { throwIfNoEntry: false });
54165
54761
  if (!stat2)
54166
54762
  return null;
54167
54763
  if (!stat2.isFile() || stat2.size > 16 * 1024 * 1024)
@@ -54169,6 +54765,22 @@ function read2(path, changes) {
54169
54765
  return readFileSync14(path, "utf8");
54170
54766
  }
54171
54767
  function projected(source, changes, budget = discoveryByteBudget()) {
54768
+ if (source.hashMode === "claude-settings-v1") {
54769
+ if (source.format !== undefined || source.fields !== undefined || source.managedPlugins !== undefined || typeof source.sha256 !== "string" || !/^[a-f0-9]{64}$/.test(source.sha256))
54770
+ throw new Error("Claude settings witnesses require exact typed metadata");
54771
+ const current = captureClaudeSettings(source.path, budget).sha256;
54772
+ if (current !== source.sha256)
54773
+ throw new Error(`Native discovery input changed; run skills hook install with a fresh discovery review: ${source.path}`);
54774
+ return changes?.has(source.path) ? hashClaudeSettingsReplacement(changes.get(source.path), budget) : current;
54775
+ }
54776
+ if (source.hashMode === "claude-marketplace-registry") {
54777
+ 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))
54778
+ throw new Error("Claude marketplace witnesses require an exact reviewed registry without synthetic changes");
54779
+ const sha2562 = captureClaudeMarketplaceRegistry(source.path, budget).sha256;
54780
+ if (sha2562 !== source.sha256)
54781
+ throw new Error(`Native discovery input changed; run skills hook install with a fresh discovery review: ${source.path}`);
54782
+ return sha2562;
54783
+ }
54172
54784
  if (source.hashMode === "claude-plugin-registry") {
54173
54785
  if (source.format !== undefined || source.fields !== undefined || !source.managedPlugins || changes?.has(source.path))
54174
54786
  throw new Error("Managed plugin registry witnesses require verified native registrations");
@@ -54193,7 +54805,7 @@ function projected(source, changes, budget = discoveryByteBudget()) {
54193
54805
  const object4 = source.format === "yaml" ? parseHermesConfig(text2) : parseConfig(text2, source.path, source.format === "toml");
54194
54806
  if (!object4 || typeof object4 !== "object" || Array.isArray(object4))
54195
54807
  throw new Error("Expected native discovery configuration object");
54196
- return digest(JSON.stringify(Object.fromEntries((source.fields ?? []).map((field) => [field, object4[field] ?? null]))));
54808
+ return digest(JSON.stringify(Object.fromEntries((source.fields ?? []).map((field2) => [field2, object4[field2] ?? null]))));
54197
54809
  }
54198
54810
  function verifyAgentDiscovery(binding) {
54199
54811
  if (!binding || !Array.isArray(binding.sources) || !Array.isArray(binding.roots) || binding.sources.length > AGENT_POLICY_LIMITS.discoverySources || binding.roots.length > AGENT_POLICY_LIMITS.discoveryRoots)
@@ -54204,9 +54816,10 @@ function verifyAgentDiscovery(binding) {
54204
54816
  verifyDiscoveryDirectories(binding.directories);
54205
54817
  const budget = discoveryByteBudget();
54206
54818
  for (const source of binding.sources) {
54819
+ assertMarketplaceBinding(binding, source);
54207
54820
  if (source.hashMode === "claude-plugin-registry" && binding.agent !== "claude")
54208
54821
  throw new Error("Managed Claude registry witnesses cannot apply to another agent");
54209
- if (source.format !== undefined && (!["json", "toml", "yaml"].includes(source.format) || !Array.isArray(source.fields) || !source.fields.length || source.fields.length > 64 || source.fields.some((field) => typeof field !== "string" || !field)))
54822
+ if (source.format !== undefined && (!["json", "toml", "yaml"].includes(source.format) || !Array.isArray(source.fields) || !source.fields.length || source.fields.length > 64 || source.fields.some((field2) => typeof field2 !== "string" || !field2)))
54210
54823
  throw new Error("Invalid native discovery projection");
54211
54824
  if (source.sha256 !== null && !/^[a-f0-9]{64}$/.test(source.sha256))
54212
54825
  throw new Error("Invalid native discovery digest");
@@ -54216,13 +54829,22 @@ function verifyAgentDiscovery(binding) {
54216
54829
  for (const root2 of binding.roots)
54217
54830
  safe4(root2);
54218
54831
  }
54832
+ function assertMarketplaceBinding(binding, source) {
54833
+ if (source.hashMode === "claude-settings-v1" && (binding.agent !== "claude" || binding.method !== "reviewed" || basename8(source.path) !== "settings.json"))
54834
+ throw new Error("Claude settings witnesses require explicit reviewed Claude configuration");
54835
+ if (source.hashMode === "claude-marketplace-registry" && (binding.agent !== "claude" || binding.method !== "reviewed"))
54836
+ throw new Error("Claude marketplace witnesses require explicit reviewed Claude discovery");
54837
+ }
54219
54838
  function rebindAgentDiscovery(binding, changes) {
54220
54839
  const budget = discoveryByteBudget();
54221
- return { ...binding, sources: binding.sources.map((source) => ({ ...source, sha256: projected(source, changes, budget) })) };
54840
+ return { ...binding, sources: binding.sources.map((source) => {
54841
+ assertMarketplaceBinding(binding, source);
54842
+ return { ...source, sha256: projected(source, changes, budget) };
54843
+ }) };
54222
54844
  }
54223
- function assertProjectDiscovery(agent, directories, home, canonical3 = resolve12, reviewed) {
54845
+ function assertProjectDiscovery(agent, directories, home, canonical4 = resolve15, reviewed) {
54224
54846
  for (const directory of directories) {
54225
- const isHome = resolve12(directory) === resolve12(home);
54847
+ const isHome = resolve15(directory) === resolve15(home);
54226
54848
  if (agent === "hermes") {
54227
54849
  assertHermesEnvironment(home);
54228
54850
  continue;
@@ -54231,7 +54853,7 @@ function assertProjectDiscovery(agent, directories, home, canonical3 = resolve12
54231
54853
  continue;
54232
54854
  const paths = agent === "claude" ? [...isHome ? [] : [".claude/settings.json"], ".claude/settings.local.json"] : agent === "codex" ? [".codex/config.toml"] : agent === "gemini" ? [".gemini/settings.json"] : agent === "opencode" ? ["opencode.json", "opencode.jsonc", ".opencode/opencode.json", ".opencode/opencode.jsonc"] : [".cursor/hooks.json"];
54233
54855
  for (const suffix of paths) {
54234
- const path = canonical3(join28(directory, suffix)), raw = read2(path);
54856
+ const path = canonical4(join28(directory, suffix)), raw = read2(path);
54235
54857
  if (raw === null)
54236
54858
  continue;
54237
54859
  if (suffix.endsWith(".jsonc"))
@@ -54244,25 +54866,25 @@ function assertProjectDiscovery(agent, directories, home, canonical3 = resolve12
54244
54866
  const managed = reviewed.sources.flatMap((source) => source.hashMode === "claude-plugin-registry" ? source.managedPlugins ?? [] : []);
54245
54867
  if (exact && projected(exact) === exact.sha256 && managed.length) {
54246
54868
  const bindings = managed.map((item) => readPluginBinding(item.storeRoot, item.bindingId));
54247
- admittedPlugins = Object.entries(config.enabledPlugins).every(([id, enabled]) => typeof enabled === "boolean" && bindings.some((binding) => binding.target.pluginId === id && binding.target.registrations.some((scope) => scope.scope === "project" && scope.projectPath === canonical3(directory))));
54869
+ admittedPlugins = Object.entries(config.enabledPlugins).every(([id, enabled]) => typeof enabled === "boolean" && bindings.some((binding) => binding.target.pluginId === id && binding.target.registrations.some((scope) => scope.scope === "project" && scope.projectPath === canonical4(directory))));
54248
54870
  }
54249
54871
  }
54250
54872
  if (keys2.some((key) => config[key] !== undefined && !(key === "enabledPlugins" && admittedPlugins)) || config.disableAllHooks === true || config.disableBundledSkills === false || config.hooksConfig?.enabled === false || config.permission?.skill !== undefined || config.permissions?.deny?.some((rule) => typeof rule === "string" && /^Skill(?:\(|$)/.test(rule)))
54251
54873
  throw new Error(`NATIVE_SKILL_DRIFT: higher-precedence project skill or hook configuration requires review: ${path}`);
54252
54874
  }
54253
54875
  if (agent === "claude") {
54254
- const commands = canonical3(join28(directory, ".claude/commands"));
54876
+ const commands = canonical4(join28(directory, ".claude/commands"));
54255
54877
  safe4(commands);
54256
- if (lstatSync15(commands, { throwIfNoEntry: false })?.isDirectory() && readdirSync9(commands).length)
54878
+ if (lstatSync17(commands, { throwIfNoEntry: false })?.isDirectory() && readdirSync9(commands).length)
54257
54879
  throw new Error("NATIVE_SKILL_DRIFT: legacy project command discovery requires a dedicated format adapter");
54258
54880
  }
54259
54881
  }
54260
54882
  }
54261
54883
  function resolveAgentDiscovery(options) {
54262
- const canonical3 = options.canonical ?? resolve12, home = resolve12(options.home), agent = options.agent;
54884
+ const canonical4 = options.canonical ?? resolve15, home = resolve15(options.home), agent = options.agent;
54263
54885
  const sources = [], roots = new Set, builtinNames = [];
54264
54886
  const witness = (path, format, fields) => {
54265
- const source = { path: canonical3(path), sha256: null, ...format ? { format, fields } : {} };
54887
+ const source = { path: canonical4(path), sha256: null, ...format ? { format, fields } : {} };
54266
54888
  source.sha256 = projected(source);
54267
54889
  sources.push(source);
54268
54890
  return read2(source.path);
@@ -54290,7 +54912,7 @@ function resolveAgentDiscovery(options) {
54290
54912
  continue;
54291
54913
  if (normalized.startsWith("~") && normalized !== "~" && !normalized.startsWith("~/"))
54292
54914
  unresolved("user-specific tilde expansion requires a separate discovery adapter");
54293
- const path = normalized === "~" ? home : normalized.startsWith("~/") ? join28(home, normalized.slice(2)) : resolve12(home, ".hermes", normalized);
54915
+ const path = normalized === "~" ? home : normalized.startsWith("~/") ? join28(home, normalized.slice(2)) : resolve15(home, ".hermes", normalized);
54294
54916
  safe4(path);
54295
54917
  roots.add(path);
54296
54918
  }
@@ -54299,21 +54921,21 @@ function resolveAgentDiscovery(options) {
54299
54921
  const executable = Bun.which("gemini");
54300
54922
  if (executable) {
54301
54923
  let packageRoot;
54302
- for (let directory = dirname12(realpathSync4(executable)), depth = 0;depth < 8; directory = dirname12(directory), depth++) {
54924
+ for (let directory = dirname14(realpathSync4(executable)), depth = 0;depth < 8; directory = dirname14(directory), depth++) {
54303
54925
  const path = join28(directory, "package.json"), raw = read2(path);
54304
54926
  if (raw !== null && parseConfig(raw, path).name === "@google/gemini-cli") {
54305
54927
  packageRoot = directory;
54306
54928
  witness(path);
54307
54929
  break;
54308
54930
  }
54309
- if (dirname12(directory) === directory)
54931
+ if (dirname14(directory) === directory)
54310
54932
  break;
54311
54933
  }
54312
54934
  if (!packageRoot)
54313
54935
  unresolved("installed Gemini package layout is not recognized");
54314
54936
  const builtinRoot = join28(packageRoot, "bundle/builtin");
54315
54937
  safe4(builtinRoot);
54316
- if (!lstatSync15(builtinRoot, { throwIfNoEntry: false })?.isDirectory())
54938
+ if (!lstatSync17(builtinRoot, { throwIfNoEntry: false })?.isDirectory())
54317
54939
  unresolved("installed Gemini builtin root is missing");
54318
54940
  for (const name of readdirSync9(builtinRoot).sort()) {
54319
54941
  const text2 = witness(join28(builtinRoot, name, "SKILL.md"));
@@ -54334,12 +54956,14 @@ function resolveAgentDiscovery(options) {
54334
54956
  if (review.sources.some((source) => source.format !== undefined || source.fields !== undefined))
54335
54957
  throw new Error("Explicit discovery reviews require full source-file hashes");
54336
54958
  verifyAgentDiscovery(supplied);
54337
- if (!review.sources.some((source) => source.path === canonical3(configPath)))
54959
+ if (review.sources.some((source) => source.hashMode === "claude-settings-v1" && source.path !== canonical4(configPath)))
54960
+ throw new Error("Semantic settings witnesses must name the configured Claude configuration source");
54961
+ if (!review.sources.some((source) => source.path === canonical4(configPath)))
54338
54962
  throw new Error("Discovery review must include the agent configuration source");
54339
54963
  return { ...supplied, roots: [...new Set([...roots, ...supplied.roots])].sort(), sources: [...sources, ...review.sources], ...agent === "gemini" ? { builtinNames } : {} };
54340
54964
  }
54341
54965
  function plugin(root2) {
54342
- root2 = canonical3(root2);
54966
+ root2 = canonical4(root2);
54343
54967
  safe4(root2);
54344
54968
  const manifestPath = join28(root2, agent === "claude" ? ".claude-plugin/plugin.json" : ".codex-plugin/plugin.json");
54345
54969
  const raw = witness(manifestPath);
@@ -54351,7 +54975,7 @@ function resolveAgentDiscovery(options) {
54351
54975
  unresolved("plugin hooks require a separate no-skill-injection review");
54352
54976
  const commands = join28(root2, "commands");
54353
54977
  safe4(commands);
54354
- if (agent === "claude" && (manifest.commands !== undefined || lstatSync15(commands, { throwIfNoEntry: false })?.isDirectory() && readdirSync9(commands).length))
54978
+ if (agent === "claude" && (manifest.commands !== undefined || lstatSync17(commands, { throwIfNoEntry: false })?.isDirectory() && readdirSync9(commands).length))
54355
54979
  unresolved("legacy command discovery requires retirement or a dedicated format adapter");
54356
54980
  const rootSkill = witness(join28(root2, "SKILL.md"));
54357
54981
  if (rootSkill !== null)
@@ -54362,18 +54986,18 @@ function resolveAgentDiscovery(options) {
54362
54986
  if (agent === "claude")
54363
54987
  roots.add(join28(root2, "skills"));
54364
54988
  for (const value of declared) {
54365
- const path = resolve12(root2, value);
54989
+ const path = resolve15(root2, value);
54366
54990
  if (path !== root2 && !path.startsWith(root2 + sep5))
54367
54991
  unresolved("plugin skill path escapes its root");
54368
- roots.add(path.endsWith(`${sep5}SKILL.md`) ? dirname12(path) : path);
54992
+ roots.add(path.endsWith(`${sep5}SKILL.md`) ? dirname14(path) : path);
54369
54993
  }
54370
54994
  }
54371
54995
  if (agent === "claude") {
54372
54996
  const registrations = witness(join28(home, ".claude/plugins/installed_plugins.json"));
54373
54997
  const installed = registrations === null ? {} : parseConfig(registrations, join28(home, ".claude/plugins/installed_plugins.json")).plugins;
54374
- const commands = canonical3(join28(home, ".claude/commands"));
54998
+ const commands = canonical4(join28(home, ".claude/commands"));
54375
54999
  safe4(commands);
54376
- if (lstatSync15(commands, { throwIfNoEntry: false })?.isDirectory() && readdirSync9(commands).length)
55000
+ if (lstatSync17(commands, { throwIfNoEntry: false })?.isDirectory() && readdirSync9(commands).length)
54377
55001
  unresolved("legacy home command discovery requires a dedicated format adapter");
54378
55002
  for (const [id, enabled] of Object.entries(config.enabledPlugins ?? {})) {
54379
55003
  if (enabled === false)
@@ -54393,7 +55017,7 @@ function resolveAgentDiscovery(options) {
54393
55017
  unresolved("unsupported plugin enablement");
54394
55018
  const split2 = id.lastIndexOf("@"), name = id.slice(0, split2), marketplace = id.slice(split2 + 1);
54395
55019
  const market = config.marketplaces?.[marketplace] ?? (marketplace === "personal" ? { source_type: "local", source: home } : undefined);
54396
- if (split2 < 1 || market?.source_type !== "local" || typeof market.source !== "string" || !isAbsolute11(market.source))
55020
+ if (split2 < 1 || market?.source_type !== "local" || typeof market.source !== "string" || !isAbsolute14(market.source))
54397
55021
  unresolved("enabled plugin marketplace is not an explicit local source");
54398
55022
  const catalogText = witness(join28(market.source, ".agents/plugins/marketplace.json"));
54399
55023
  if (catalogText === null)
@@ -54401,7 +55025,7 @@ function resolveAgentDiscovery(options) {
54401
55025
  const catalog = parseConfig(catalogText, join28(market.source, ".agents/plugins/marketplace.json")), matches2 = Array.isArray(catalog.plugins) ? catalog.plugins.filter((item) => item.name === name) : [];
54402
55026
  if (matches2.length !== 1 || matches2[0]?.source?.source !== "local" || typeof matches2[0]?.source?.path !== "string")
54403
55027
  unresolved("plugin catalog source is missing or ambiguous");
54404
- plugin(resolve12(market.source, matches2[0].source.path));
55028
+ plugin(resolve15(market.source, matches2[0].source.path));
54405
55029
  }
54406
55030
  } else if (agent === "opencode") {
54407
55031
  if (witness(join28(home, ".config/opencode/opencode.jsonc")) !== null || witness(join28(home, ".config/opencode/config.json")) !== null)
@@ -54409,18 +55033,18 @@ function resolveAgentDiscovery(options) {
54409
55033
  if ((config.plugin?.length ?? 0) > 0 || config.skills?.urls?.length)
54410
55034
  unresolved("external plugin or remote skill source");
54411
55035
  for (const path of config.skills?.paths ?? []) {
54412
- if (typeof path !== "string" || !isAbsolute11(path))
55036
+ if (typeof path !== "string" || !isAbsolute14(path))
54413
55037
  unresolved("relative or malformed added skill root");
54414
55038
  roots.add(path);
54415
55039
  }
54416
55040
  const localPlugins = join28(home, ".config/opencode/plugins");
54417
55041
  safe4(localPlugins);
54418
- if (lstatSync15(localPlugins, { throwIfNoEntry: false }) && readdirSync9(localPlugins).some((name) => name !== "skills-cli.js"))
55042
+ if (lstatSync17(localPlugins, { throwIfNoEntry: false }) && readdirSync9(localPlugins).some((name) => name !== "skills-cli.js"))
54419
55043
  unresolved("additional local plugin hooks require review");
54420
55044
  } else if (agent === "hermes") {
54421
55045
  for (const directory of [join28(home, ".hermes/plugins"), join28(home, ".hermes/hermes-agent")]) {
54422
55046
  safe4(directory);
54423
- if (lstatSync15(directory, { throwIfNoEntry: false }))
55047
+ if (lstatSync17(directory, { throwIfNoEntry: false }))
54424
55048
  unresolved("installed runtime/plugin discovery requires reviewed source bindings");
54425
55049
  }
54426
55050
  if (Bun.which("hermes") || Object.keys(config.plugins ?? {}).length)
@@ -54430,11 +55054,11 @@ function resolveAgentDiscovery(options) {
54430
55054
  unresolved("custom extension or skill paths");
54431
55055
  const directory = join28(home, ".gemini/extensions");
54432
55056
  safe4(directory);
54433
- if (lstatSync15(directory, { throwIfNoEntry: false }))
55057
+ if (lstatSync17(directory, { throwIfNoEntry: false }))
54434
55058
  for (const name of readdirSync9(directory)) {
54435
55059
  const root2 = join28(directory, name);
54436
55060
  safe4(root2);
54437
- if (!lstatSync15(root2)?.isDirectory())
55061
+ if (!lstatSync17(root2)?.isDirectory())
54438
55062
  continue;
54439
55063
  const raw = witness(join28(root2, "gemini-extension.json"));
54440
55064
  if (raw === null)
@@ -54445,9 +55069,9 @@ function resolveAgentDiscovery(options) {
54445
55069
  roots.add(join28(root2, "skills"));
54446
55070
  }
54447
55071
  }
54448
- return { agent, roots: [...roots].sort(), sources, method: "automatic", ...agent === "gemini" ? { builtinNames } : {}, ...agent === "hermes" ? { directories: captureDiscoveryDirectories([join28(home, ".hermes/plugins"), join28(home, ".hermes/hermes-agent")].map((path) => canonical3(path))) } : {} };
55072
+ return { agent, roots: [...roots].sort(), sources, method: "automatic", ...agent === "gemini" ? { builtinNames } : {}, ...agent === "hermes" ? { directories: captureDiscoveryDirectories([join28(home, ".hermes/plugins"), join28(home, ".hermes/hermes-agent")].map((path) => canonical4(path))) } : {} };
54449
55073
  }
54450
- var digest = (text2) => createHash11("sha256").update(text2).digest("hex");
55074
+ var digest = (text2) => createHash13("sha256").update(text2).digest("hex");
54451
55075
  var init_agent_discovery = __esm(() => {
54452
55076
  init_agent_policy_limits();
54453
55077
  init_agent_hermes();
@@ -54456,6 +55080,8 @@ var init_agent_discovery = __esm(() => {
54456
55080
  init_agent_discovery_path_bytes();
54457
55081
  init_plugin_discovery();
54458
55082
  init_plugin_admission();
55083
+ init_claude_marketplace_registry();
55084
+ init_claude_settings_witness();
54459
55085
  init_agent_discovery_directories();
54460
55086
  });
54461
55087
 
@@ -54540,7 +55166,7 @@ var init_agent_adapters = __esm(() => {
54540
55166
  });
54541
55167
 
54542
55168
  // src/lib/agent-codex.ts
54543
- import { isDeepStrictEqual as isDeepStrictEqual2 } from "util";
55169
+ import { isDeepStrictEqual as isDeepStrictEqual3 } from "util";
54544
55170
  function assertCodexPathConfigEditable(text2) {
54545
55171
  const before2 = Bun.TOML.parse(text2);
54546
55172
  if (before2.skills?.config === undefined)
@@ -54549,7 +55175,7 @@ function assertCodexPathConfigEditable(text2) {
54549
55175
  delete expected.skills.config;
54550
55176
  try {
54551
55177
  const withoutSections = Bun.TOML.parse(text2.replace(CODEX_SKILL_CONFIG_SECTIONS, ""));
54552
- if (isDeepStrictEqual2(withoutSections, expected))
55178
+ if (isDeepStrictEqual3(withoutSections, expected))
54553
55179
  return;
54554
55180
  } catch {}
54555
55181
  throw new Error("Codex skill path controls require ordinary [[skills.config]] TOML tables; preserve and convert inline or dotted config arrays before running skills hook install");
@@ -54587,7 +55213,7 @@ function disableCodexBundledSkills(text2) {
54587
55213
  const candidates = new Set;
54588
55214
  const consider = (candidate2) => {
54589
55215
  try {
54590
- if (isDeepStrictEqual2(Bun.TOML.parse(candidate2), expected))
55216
+ if (isDeepStrictEqual3(Bun.TOML.parse(candidate2), expected))
54591
55217
  candidates.add(candidate2);
54592
55218
  } catch {}
54593
55219
  };
@@ -54617,16 +55243,16 @@ var init_agent_codex = __esm(() => {
54617
55243
  });
54618
55244
 
54619
55245
  // src/lib/agent-integration.ts
54620
- import { createHash as createHash12, randomUUID as randomUUID6 } from "crypto";
54621
- import { existsSync as existsSync15, lstatSync as lstatSync16, statSync as statSync8, mkdirSync as mkdirSync7, readFileSync as readFileSync15, 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 openSync9, closeSync as closeSync9, fsyncSync as fsyncSync2, fstatSync as fstatSync9, readSync as readSync7, constants as constants9, linkSync as linkSync2 } from "fs";
54622
- import { dirname as dirname13, join as join29, resolve as resolve13, relative as relative5, isAbsolute as isAbsolute12, sep as sep6 } from "path";
55246
+ import { createHash as createHash14, randomUUID as randomUUID6 } from "crypto";
55247
+ import { existsSync as existsSync15, lstatSync as lstatSync18, statSync as statSync8, mkdirSync as mkdirSync7, readFileSync as readFileSync15, 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 constants11, linkSync as linkSync2 } from "fs";
55248
+ import { dirname as dirname15, join as join29, resolve as resolve16, relative as relative5, isAbsolute as isAbsolute15, sep as sep6 } from "path";
54623
55249
  import { homedir as homedir4 } from "os";
54624
55250
  function assertSafePath(path) {
54625
- let cursor = resolve13(path);
55251
+ let cursor = resolve16(path);
54626
55252
  while (true) {
54627
- if (lstatSync16(cursor, { throwIfNoEntry: false })?.isSymbolicLink())
55253
+ if (lstatSync18(cursor, { throwIfNoEntry: false })?.isSymbolicLink())
54628
55254
  throw new Error(`Refusing symlink path: ${cursor}`);
54629
- const parent = dirname13(cursor);
55255
+ const parent = dirname15(cursor);
54630
55256
  if (parent === cursor)
54631
55257
  return;
54632
55258
  cursor = parent;
@@ -54635,16 +55261,16 @@ function assertSafePath(path) {
54635
55261
  function readRootAlias(home, agent) {
54636
55262
  assertSafePath(home);
54637
55263
  const realHome = realpathSync5(home), alias = join29(realHome, `.${agent}`);
54638
- const stat2 = lstatSync16(alias, { throwIfNoEntry: false, bigint: true });
55264
+ const stat2 = lstatSync18(alias, { throwIfNoEntry: false, bigint: true });
54639
55265
  if (!stat2?.isSymbolicLink())
54640
55266
  throw new Error(`Agent root alias changed after planning: ${alias}`);
54641
- const link2 = readlinkSync2(alias), targetPath = resolve13(dirname13(alias), link2);
55267
+ const link2 = readlinkSync2(alias), targetPath = resolve16(dirname15(alias), link2);
54642
55268
  assertSafePath(targetPath);
54643
- const targetStat = lstatSync16(targetPath, { throwIfNoEntry: false });
55269
+ const targetStat = lstatSync18(targetPath, { throwIfNoEntry: false });
54644
55270
  if (!targetStat?.isDirectory())
54645
55271
  throw new Error(`Agent root alias must target an existing directory: ${alias}`);
54646
55272
  const target = realpathSync5(targetPath), inside = relative5(realHome, target);
54647
- if (!inside || inside === ".." || inside.startsWith(`..${sep6}`) || isAbsolute12(inside))
55273
+ if (!inside || inside === ".." || inside.startsWith(`..${sep6}`) || isAbsolute15(inside))
54648
55274
  throw new Error(`Agent root alias target must be inside the real home: ${alias}`);
54649
55275
  return { agent, home: realHome, alias, target, link: link2, aliasIdentity: `${stat2.dev}:${stat2.ino}:${stat2.ctimeNs}`, targetIdentity: `${targetStat.dev}:${targetStat.ino}` };
54650
55276
  }
@@ -54653,14 +55279,14 @@ function rootAliases(home, allowed = false) {
54653
55279
  return [];
54654
55280
  const result2 = [];
54655
55281
  for (const agent of ["claude", "codex"])
54656
- if (lstatSync16(join29(home, `.${agent}`), { throwIfNoEntry: false })?.isSymbolicLink())
55282
+ if (lstatSync18(join29(home, `.${agent}`), { throwIfNoEntry: false })?.isSymbolicLink())
54657
55283
  result2.push(readRootAlias(home, agent));
54658
55284
  if (result2.some((item, index) => result2.slice(index + 1).some((other) => item.target === other.target || item.target.startsWith(other.target + sep6) || other.target.startsWith(item.target + sep6))))
54659
55285
  throw new Error("Agent root alias targets must not overlap");
54660
55286
  return result2;
54661
55287
  }
54662
55288
  function canonicalAgentPath(path, aliases) {
54663
- const absolute = resolve13(path), binding = aliases.find((item) => absolute === item.alias || absolute.startsWith(item.alias + sep6));
55289
+ const absolute = resolve16(path), binding = aliases.find((item) => absolute === item.alias || absolute.startsWith(item.alias + sep6));
54664
55290
  return binding ? join29(binding.target, relative5(binding.alias, absolute)) : absolute;
54665
55291
  }
54666
55292
  function recheckRootAliases(aliases) {
@@ -54674,35 +55300,35 @@ function recheckRootAliases(aliases) {
54674
55300
  }
54675
55301
  function readNativeBytes(path, maximum = 64 * 1024 * 1024) {
54676
55302
  assertSafePath(path);
54677
- const before2 = lstatSync16(path);
55303
+ const before2 = lstatSync18(path);
54678
55304
  if (!before2.isFile() || before2.size > maximum)
54679
55305
  throw new Error("Unsupported or oversized native skill file");
54680
- const descriptor = openSync9(path, constants9.O_RDONLY | constants9.O_NOFOLLOW | constants9.O_NONBLOCK);
55306
+ const descriptor = openSync11(path, constants11.O_RDONLY | constants11.O_NOFOLLOW | constants11.O_NONBLOCK);
54681
55307
  try {
54682
- const opened = fstatSync9(descriptor);
55308
+ const opened = fstatSync11(descriptor);
54683
55309
  if (!opened.isFile() || opened.dev !== before2.dev || opened.ino !== before2.ino || opened.size !== before2.size)
54684
55310
  throw new Error("Native skill file changed while reading");
54685
55311
  const bytes = Buffer.allocUnsafe(before2.size + 1);
54686
55312
  let length = 0;
54687
55313
  while (length < bytes.length) {
54688
- const count = readSync7(descriptor, bytes, length, bytes.length - length, null);
55314
+ const count = readSync9(descriptor, bytes, length, bytes.length - length, null);
54689
55315
  if (!count)
54690
55316
  break;
54691
55317
  length += count;
54692
55318
  }
54693
- const after2 = fstatSync9(descriptor);
55319
+ const after2 = fstatSync11(descriptor);
54694
55320
  if (length !== before2.size || after2.size !== before2.size || after2.mtimeMs !== opened.mtimeMs || after2.ctimeMs !== opened.ctimeMs)
54695
55321
  throw new Error("Native skill file changed while reading");
54696
55322
  return bytes.subarray(0, length);
54697
55323
  } finally {
54698
- closeSync9(descriptor);
55324
+ closeSync11(descriptor);
54699
55325
  }
54700
55326
  }
54701
55327
  function treeHash(root2) {
54702
- const hash2 = createHash12("sha256");
55328
+ const hash2 = createHash14("sha256");
54703
55329
  let bytes = 0, files = 0;
54704
55330
  function visit2(path) {
54705
- const stat2 = lstatSync16(path);
55331
+ const stat2 = lstatSync18(path);
54706
55332
  if (stat2.isSymbolicLink())
54707
55333
  throw new Error(`Refusing symlink in skill: ${path}`);
54708
55334
  const rel = relative5(root2, path);
@@ -54728,11 +55354,11 @@ function treeHash(root2) {
54728
55354
  function projectAncestorDirectories(projects) {
54729
55355
  const directories = new Set;
54730
55356
  for (const project of projects) {
54731
- for (let path = resolve13(project), depth = 0;; depth++) {
55357
+ for (let path = resolve16(project), depth = 0;; depth++) {
54732
55358
  if (depth >= 100)
54733
55359
  throw new Error("NATIVE_SKILL_DRIFT: project ancestor discovery limit exceeded");
54734
55360
  directories.add(path);
54735
- const parent = dirname13(path);
55361
+ const parent = dirname15(path);
54736
55362
  if (parent === path)
54737
55363
  break;
54738
55364
  path = parent;
@@ -54759,10 +55385,10 @@ function inventoryNativeSkills(home = homedir4(), options = {}) {
54759
55385
  throw new Error("Native skill discovery metadata limit exceeded");
54760
55386
  }
54761
55387
  function emptySiblingCacheAlias(path, parent) {
54762
- const link2 = readlinkSync2(path), target = resolve13(parent, link2);
54763
- if (dirname13(target) !== parent || (isAbsolute12(link2) ? link2 !== target : dirname13(link2) !== "."))
55388
+ const link2 = readlinkSync2(path), target = resolve16(parent, link2);
55389
+ if (dirname15(target) !== parent || (isAbsolute15(link2) ? link2 !== target : dirname15(link2) !== "."))
54764
55390
  return false;
54765
- if (!lstatSync16(target, { throwIfNoEntry: false })?.isDirectory())
55391
+ if (!lstatSync18(target, { throwIfNoEntry: false })?.isDirectory())
54766
55392
  return false;
54767
55393
  const scan = cacheScans.get(target);
54768
55394
  return Boolean(scan?.complete && !scan.hasSkills && scan.entries <= maxAliasProofEntries);
@@ -54774,7 +55400,7 @@ function inventoryNativeSkills(home = homedir4(), options = {}) {
54774
55400
  assertSafePath(path);
54775
55401
  if (!existsSync15(path))
54776
55402
  return scan;
54777
- const stat2 = lstatSync16(path);
55403
+ const stat2 = lstatSync18(path);
54778
55404
  if (stat2.isFile())
54779
55405
  return scan;
54780
55406
  if (!stat2.isDirectory())
@@ -54793,7 +55419,7 @@ function inventoryNativeSkills(home = homedir4(), options = {}) {
54793
55419
  }
54794
55420
  const bridge = !vendor && isOwnedCliBridge(path, bridgePaths);
54795
55421
  const rootAlias = aliases.find((item) => path === item.target || path.startsWith(item.target + sep6));
54796
- entries.push({ agent, path, hash: treeHash(path), managed, vendor, ...agent === "codex" && path.startsWith(canonicalAgentPath(join29(home, ".codex", "skills", ".system"), aliases) + sep6) ? { system: true } : {}, ...bridge ? { bridge: true, bridgeHome: resolve13(home) } : {}, ...rootAlias ? { rootAlias } : {} });
55422
+ entries.push({ agent, path, hash: treeHash(path), managed, vendor, ...agent === "codex" && path.startsWith(canonicalAgentPath(join29(home, ".codex", "skills", ".system"), aliases) + sep6) ? { system: true } : {}, ...bridge ? { bridge: true, bridgeHome: resolve16(home) } : {}, ...rootAlias ? { rootAlias } : {} });
54797
55423
  return scan;
54798
55424
  }
54799
55425
  if (depth > (vendor ? 32 : 3))
@@ -54820,7 +55446,7 @@ function inventoryNativeSkills(home = homedir4(), options = {}) {
54820
55446
  if (isVendor && !options.includeVendor)
54821
55447
  continue;
54822
55448
  const child = join29(path, name);
54823
- if (isVendor && lstatSync16(child, { throwIfNoEntry: false })?.isSymbolicLink()) {
55449
+ if (isVendor && lstatSync18(child, { throwIfNoEntry: false })?.isSymbolicLink()) {
54824
55450
  const target = statSync8(child, { throwIfNoEntry: false });
54825
55451
  if (target?.isFile() || pluginCache && target?.isDirectory() && emptySiblingCacheAlias(child, path)) {
54826
55452
  scan.entries++;
@@ -54942,7 +55568,7 @@ function configureHooks(config, agent, command, profileId, nativeReady) {
54942
55568
  function disableCodexSkills(text2, skills, aliases, bridgePath) {
54943
55569
  const bundled = disableCodexBundledSkills(text2);
54944
55570
  let result2 = bundled;
54945
- const bridgeSelector = (entry) => typeof entry.name === "string" && entry.name.trim() === CLI_BRIDGE_NAME || typeof entry.path === "string" && [resolve13(bridgePath), resolve13(join29(bridgePath, "SKILL.md"))].includes(canonicalAgentPath(entry.path, aliases));
55571
+ const bridgeSelector = (entry) => typeof entry.name === "string" && entry.name.trim() === CLI_BRIDGE_NAME || typeof entry.path === "string" && [resolve16(bridgePath), resolve16(join29(bridgePath, "SKILL.md"))].includes(canonicalAgentPath(entry.path, aliases));
54946
55572
  const previousConfig = Bun.TOML.parse(bundled).skills?.config;
54947
55573
  if (previousConfig !== undefined && (!Array.isArray(previousConfig) || previousConfig.some((entry) => !entry || typeof entry !== "object" || entry.path !== undefined && entry.name !== undefined)))
54948
55574
  throw new Error("Codex skill controls require one path or name selector per [[skills.config]] entry; review ambiguous entries before running skills hook install");
@@ -54954,7 +55580,7 @@ function disableCodexSkills(text2, skills, aliases, bridgePath) {
54954
55580
  result2 = result2.replace(CODEX_SKILL_CONFIG_SECTIONS, (section) => {
54955
55581
  const parsed = Bun.TOML.parse(section);
54956
55582
  const declared = parsed.skills?.config?.[0];
54957
- if (!declared || !(skill.enabled && bridgeSelector(declared)) && !(typeof declared.path === "string" && [resolve13(path), resolve13(skill.path)].includes(canonicalAgentPath(declared.path, aliases))))
55583
+ if (!declared || !(skill.enabled && bridgeSelector(declared)) && !(typeof declared.path === "string" && [resolve16(path), resolve16(skill.path)].includes(canonicalAgentPath(declared.path, aliases))))
54958
55584
  return section;
54959
55585
  found = true;
54960
55586
  return /^\s*enabled\s*=/m.test(section) ? section.replace(/^\s*enabled\s*=.*$/m, `enabled = ${skill.enabled}`) : `${section.trimEnd()}
@@ -54984,9 +55610,9 @@ function planAgentIntegration(options) {
54984
55610
  throw new Error("Invalid existing Skills bridge policy");
54985
55611
  if (policy.bridge?.agents !== undefined && (!Array.isArray(policy.bridge.agents) || policy.bridge.agents.some((agent) => !INTEGRATION_AGENTS.includes(agent))))
54986
55612
  throw new Error("Invalid existing bridge agent inventory");
54987
- for (const field of ["commands", "profiles"])
54988
- if (policy.bridge?.[field] !== undefined && (!policy.bridge[field] || typeof policy.bridge[field] !== "object" || Array.isArray(policy.bridge[field]) || Object.entries(policy.bridge[field]).some(([key, value]) => !INTEGRATION_AGENTS.includes(key) || typeof value !== "string" || !value || value.includes("\x00"))))
54989
- throw new Error(`Invalid existing bridge ${field} binding`);
55613
+ for (const field2 of ["commands", "profiles"])
55614
+ if (policy.bridge?.[field2] !== undefined && (!policy.bridge[field2] || typeof policy.bridge[field2] !== "object" || Array.isArray(policy.bridge[field2]) || Object.entries(policy.bridge[field2]).some(([key, value]) => !INTEGRATION_AGENTS.includes(key) || typeof value !== "string" || !value || value.includes("\x00"))))
55615
+ throw new Error(`Invalid existing bridge ${field2} binding`);
54990
55616
  const priorAgents = policy.bridge?.agents ?? [];
54991
55617
  const profileId = options.profileId ?? policy.profileId ?? "default";
54992
55618
  const validateProfile = (value) => {
@@ -55072,7 +55698,7 @@ function planAgentIntegration(options) {
55072
55698
  version: CLI_BRIDGE_VERSION,
55073
55699
  digest: CLI_BRIDGE_DIGEST,
55074
55700
  agents: [...new Set([...priorAgents, ...options.agents])].sort(),
55075
- home: resolve13(home),
55701
+ home: resolve16(home),
55076
55702
  includeVendor: true,
55077
55703
  ...options.agents.includes("hermes") ? { supervisors: { ...policy.bridge?.supervisors, hermes: { path: join29(dataDir3, "agent-hooks", "hermes.js"), runtime: process.execPath, sha256: sha(renderHermesSupervisor(bindings.get("hermes").command, bindings.get("hermes").profileId)) } } } : {},
55078
55704
  commands: { ...policy.bridge?.commands, ...Object.fromEntries([...bindings].map(([agent, binding]) => [agent, binding.command])) },
@@ -55089,7 +55715,7 @@ function planAgentIntegration(options) {
55089
55715
  }
55090
55716
  function atomicWrite2(path, content) {
55091
55717
  assertSafePath(path);
55092
- mkdirSync7(dirname13(path), { recursive: true, mode: 448 });
55718
+ mkdirSync7(dirname15(path), { recursive: true, mode: 448 });
55093
55719
  const temporary = `${path}.skills-${randomUUID6()}`;
55094
55720
  try {
55095
55721
  writeFileSync5(temporary, content, { mode: 384, flag: "wx" });
@@ -55102,10 +55728,10 @@ function atomicWrite2(path, content) {
55102
55728
  function applyAgentIntegration(plan) {
55103
55729
  const policyPath = join29(plan.dataDir, "agent-policy.json");
55104
55730
  assertSafePath(policyPath);
55105
- const currentText = (path) => resolve13(path) === resolve13(policyPath) ? readManagedSkillPolicySnapshot(plan.dataDir)?.text ?? null : readOptional(path);
55731
+ const currentText = (path) => resolve16(path) === resolve16(policyPath) ? readManagedSkillPolicySnapshot(plan.dataDir)?.text ?? null : readOptional(path);
55106
55732
  readManagedSkillPolicySnapshot(plan.dataDir);
55107
55733
  for (const change of plan.changes)
55108
- if (resolve13(change.path) === resolve13(policyPath))
55734
+ if (resolve16(change.path) === resolve16(policyPath))
55109
55735
  parseManagedSkillPolicy(change.after);
55110
55736
  const aliases = plan.rootAliases ?? [];
55111
55737
  recheckRootAliases(aliases);
@@ -55135,7 +55761,7 @@ function applyAgentIntegration(plan) {
55135
55761
  recheckRootAliases(aliases);
55136
55762
  if (currentText(change.path) !== change.before)
55137
55763
  throw new Error(`Configuration changed after planning: ${change.path}`);
55138
- for (let directory = dirname13(change.path);!existsSync15(directory); directory = dirname13(directory))
55764
+ for (let directory = dirname15(change.path);!existsSync15(directory); directory = dirname15(directory))
55139
55765
  createdDirectories.add(directory);
55140
55766
  const after2 = change.after;
55141
55767
  atomicWrite2(change.path, after2);
@@ -55175,11 +55801,11 @@ function applyAgentIntegration(plan) {
55175
55801
  }
55176
55802
  function syncArchiveDirectory(path) {
55177
55803
  assertSafePath(path);
55178
- const descriptor = openSync9(path, constants9.O_RDONLY | constants9.O_DIRECTORY | constants9.O_NOFOLLOW | constants9.O_NONBLOCK);
55804
+ const descriptor = openSync11(path, constants11.O_RDONLY | constants11.O_DIRECTORY | constants11.O_NOFOLLOW | constants11.O_NONBLOCK);
55179
55805
  try {
55180
- fsyncSync2(descriptor);
55806
+ fsyncSync3(descriptor);
55181
55807
  } finally {
55182
- closeSync9(descriptor);
55808
+ closeSync11(descriptor);
55183
55809
  }
55184
55810
  }
55185
55811
  function writeArchiveJournal(path, value) {
@@ -55187,18 +55813,18 @@ function writeArchiveJournal(path, value) {
55187
55813
  const temporary = `${path}.skills-${randomUUID6()}`;
55188
55814
  let descriptor;
55189
55815
  try {
55190
- descriptor = openSync9(temporary, constants9.O_WRONLY | constants9.O_CREAT | constants9.O_EXCL | constants9.O_NOFOLLOW, 384);
55816
+ descriptor = openSync11(temporary, constants11.O_WRONLY | constants11.O_CREAT | constants11.O_EXCL | constants11.O_NOFOLLOW, 384);
55191
55817
  writeFileSync5(descriptor, `${JSON.stringify(value)}
55192
55818
  `);
55193
- fsyncSync2(descriptor);
55194
- closeSync9(descriptor);
55819
+ fsyncSync3(descriptor);
55820
+ closeSync11(descriptor);
55195
55821
  descriptor = undefined;
55196
55822
  renameSync4(temporary, path);
55197
- syncArchiveDirectory(dirname13(path));
55823
+ syncArchiveDirectory(dirname15(path));
55198
55824
  } finally {
55199
55825
  if (descriptor !== undefined)
55200
- closeSync9(descriptor);
55201
- if (lstatSync16(temporary, { throwIfNoEntry: false }))
55826
+ closeSync11(descriptor);
55827
+ if (lstatSync18(temporary, { throwIfNoEntry: false }))
55202
55828
  unlinkSync4(temporary);
55203
55829
  }
55204
55830
  }
@@ -55231,7 +55857,7 @@ function archiveNativeSkills(inventory, options) {
55231
55857
  const moved = [];
55232
55858
  const verifyArchive = (entry) => {
55233
55859
  assertSafePath(entry.archive);
55234
- const stat2 = lstatSync16(entry.archive);
55860
+ const stat2 = lstatSync18(entry.archive);
55235
55861
  if (entry.discoveryOnly ? !stat2.isFile() : !stat2.isDirectory())
55236
55862
  throw new Error("Archive type changed");
55237
55863
  if ((entry.discoveryOnly ? sha(readNativeBytes(entry.archive)) : treeHash(entry.archive)) !== entry.hash)
@@ -55239,14 +55865,14 @@ function archiveNativeSkills(inventory, options) {
55239
55865
  };
55240
55866
  assertSafePath(archiveRoot);
55241
55867
  const created = [];
55242
- for (let path = archiveRoot;!existsSync15(path); path = dirname13(path))
55868
+ for (let path = archiveRoot;!existsSync15(path); path = dirname15(path))
55243
55869
  created.push(path);
55244
55870
  mkdirSync7(archiveRoot, { recursive: true, mode: 448 });
55245
55871
  try {
55246
55872
  for (const directory of created)
55247
55873
  syncArchiveDirectory(directory);
55248
55874
  if (created.length)
55249
- syncArchiveDirectory(dirname13(created.at(-1)));
55875
+ syncArchiveDirectory(dirname15(created.at(-1)));
55250
55876
  writeArchiveJournal(receiptPath, journal);
55251
55877
  for (const [index, entry] of selected.entries()) {
55252
55878
  recheckRootAliases(aliases);
@@ -55258,7 +55884,7 @@ function archiveNativeSkills(inventory, options) {
55258
55884
  writeArchiveJournal(receiptPath, journal);
55259
55885
  renameSync4(move.source, move.archive);
55260
55886
  moved.push(move);
55261
- syncArchiveDirectory(dirname13(move.source));
55887
+ syncArchiveDirectory(dirname15(move.source));
55262
55888
  syncArchiveDirectory(archiveRoot);
55263
55889
  verifyArchive(move);
55264
55890
  move.status = "archived";
@@ -55279,7 +55905,7 @@ function archiveNativeSkills(inventory, options) {
55279
55905
  recheckRootAliases(aliases);
55280
55906
  assertSafePath(entry.source);
55281
55907
  assertSafePath(entry.archive);
55282
- if (lstatSync16(entry.source, { throwIfNoEntry: false })) {
55908
+ if (lstatSync18(entry.source, { throwIfNoEntry: false })) {
55283
55909
  entry.status = "recovery-required";
55284
55910
  entry.conflict = "source-occupied";
55285
55911
  continue;
@@ -55293,10 +55919,10 @@ function archiveNativeSkills(inventory, options) {
55293
55919
  }
55294
55920
  if (entry.discoveryOnly) {
55295
55921
  linkSync2(entry.archive, entry.source);
55296
- syncArchiveDirectory(dirname13(entry.source));
55922
+ syncArchiveDirectory(dirname15(entry.source));
55297
55923
  unlinkSync4(entry.archive);
55298
55924
  } else {
55299
- if (lstatSync16(entry.source, { throwIfNoEntry: false })) {
55925
+ if (lstatSync18(entry.source, { throwIfNoEntry: false })) {
55300
55926
  entry.status = "recovery-required";
55301
55927
  entry.conflict = "source-occupied";
55302
55928
  continue;
@@ -55304,7 +55930,7 @@ function archiveNativeSkills(inventory, options) {
55304
55930
  renameSync4(entry.archive, entry.source);
55305
55931
  }
55306
55932
  entry.status = "restored";
55307
- syncArchiveDirectory(dirname13(entry.source));
55933
+ syncArchiveDirectory(dirname15(entry.source));
55308
55934
  syncArchiveDirectory(archiveRoot);
55309
55935
  } catch {
55310
55936
  entry.status = "recovery-required";
@@ -55324,7 +55950,7 @@ function archiveNativeSkills(inventory, options) {
55324
55950
  return { entries: entries.map(({ status, conflict, ...entry }) => entry), receiptPath, ...aliases.length ? { rootAliases: aliases } : {} };
55325
55951
  }
55326
55952
  function assertManagedAgentBridge(agent, options = {}) {
55327
- const home = resolve13(options.home ?? homedir4()), dataDir3 = options.dataDir ?? getDataDirReadOnly();
55953
+ const home = resolve16(options.home ?? homedir4()), dataDir3 = options.dataDir ?? getDataDirReadOnly();
55328
55954
  assertSafePath(join29(dataDir3, "agent-policy.json"));
55329
55955
  const snapshot = readManagedSkillPolicySnapshot(dataDir3);
55330
55956
  if (!snapshot)
@@ -55447,7 +56073,7 @@ function assertNativeExportAllowed(dataDir3 = getDataDirReadOnly()) {
55447
56073
  if (requiresCliSkillLoading(dataDir3))
55448
56074
  throw new Error("NATIVE_SKILL_EXPORT_DISABLED: this station loads skills through the Skills CLI; use skills sync --selection-profile <id>");
55449
56075
  }
55450
- var sha = (data) => createHash12("sha256").update(data).digest("hex"), HOOK_EVENTS, ROOTS, SKILLS_LOADING_POLICY = "Skills loading policy: discover skills with `skills list` or `skills search`, and read selected instructions with `skills load <slug>`. Use `skills sync` to refresh the shared profile. The only native skill is the owned skills-cli bridge. Create and edit payload skills in the Skills authoring workspace; do not copy payload instructions into native discovery folders. Context loading does not authorize execution; use `skills run` only when the task calls for running a skill.";
56076
+ var sha = (data) => createHash14("sha256").update(data).digest("hex"), HOOK_EVENTS, ROOTS, SKILLS_LOADING_POLICY = "Skills loading policy: discover skills with `skills list` or `skills search`, and read selected instructions with `skills load <slug>`. Use `skills sync` to refresh the shared profile. The only native skill is the owned skills-cli bridge. Create and edit payload skills in the Skills authoring workspace; do not copy payload instructions into native discovery folders. Context loading does not authorize execution; use `skills run` only when the task calls for running a skill.";
55451
56077
  var init_agent_integration = __esm(() => {
55452
56078
  init_config();
55453
56079
  init_managed_policy();
@@ -55615,7 +56241,7 @@ var init_home_migration = __esm(() => {
55615
56241
  import {
55616
56242
  cpSync as cpSync2,
55617
56243
  existsSync as existsSync17,
55618
- lstatSync as lstatSync17,
56244
+ lstatSync as lstatSync19,
55619
56245
  mkdirSync as mkdirSync9,
55620
56246
  mkdtempSync as mkdtempSync2,
55621
56247
  readFileSync as readFileSync16,
@@ -55626,14 +56252,14 @@ import {
55626
56252
  writeFileSync as writeFileSync7
55627
56253
  } from "fs";
55628
56254
  import { homedir as homedir5 } from "os";
55629
- import { basename as basename5, dirname as dirname14, join as join31 } from "path";
56255
+ import { basename as basename9, dirname as dirname16, join as join31 } from "path";
55630
56256
  function isSkillsOwnershipMarker(marker) {
55631
56257
  return typeof marker === "object" && marker !== null && Object.hasOwn(marker, "managedBy") && marker.managedBy === SYNC_MARKER_MANAGED_BY;
55632
56258
  }
55633
56259
  function hasSkillsOwnershipMarker(dir) {
55634
56260
  const path = join31(dir, SYNC_MARKER_FILE);
55635
56261
  try {
55636
- if (!lstatSync17(path).isFile())
56262
+ if (!lstatSync19(path).isFile())
55637
56263
  return false;
55638
56264
  const marker = JSON.parse(readFileSync16(path, "utf8"));
55639
56265
  return isSkillsOwnershipMarker(marker);
@@ -55858,9 +56484,9 @@ function writeManagedSkillDir(dir, skillMd, options) {
55858
56484
  const action = dirExists ? "update" : "create";
55859
56485
  if (options.dryRun)
55860
56486
  return { action, path: skillMdPath };
55861
- const parentDir = dirname14(dir);
56487
+ const parentDir = dirname16(dir);
55862
56488
  mkdirSync9(parentDir, { recursive: true });
55863
- const transactionDir = mkdtempSync2(join31(parentDir, `.hasna-skills-write-${basename5(dir)}-`));
56489
+ const transactionDir = mkdtempSync2(join31(parentDir, `.hasna-skills-write-${basename9(dir)}-`));
55864
56490
  const candidateDir = join31(transactionDir, "candidate");
55865
56491
  const backupDir = join31(transactionDir, "backup");
55866
56492
  const candidateSkillMdPath = join31(candidateDir, "SKILL.md");
@@ -57710,7 +58336,7 @@ var _parse = (_Err) => {
57710
58336
  return result2.value;
57711
58337
  };
57712
58338
  return fn;
57713
- }, parse5, _parseAsync = (_Err) => {
58339
+ }, parse7, _parseAsync = (_Err) => {
57714
58340
  const fn = async (schema, value, _ctx, params) => {
57715
58341
  const ctx = _ctx ? { ..._ctx, async: true } : { async: true };
57716
58342
  let result2 = schema._zod.run({ value, issues: [] }, ctx);
@@ -57755,16 +58381,16 @@ var _parse = (_Err) => {
57755
58381
  result2 = await result2;
57756
58382
  return result2.issues.length === 0;
57757
58383
  }, _encode = (_Err) => {
57758
- const parse6 = _parse(_Err);
58384
+ const parse8 = _parse(_Err);
57759
58385
  const fn = (schema, value, _ctx, _params) => {
57760
58386
  const ctx = _ctx ? { ..._ctx, direction: "backward" } : { direction: "backward" };
57761
- return parse6(schema, value, ctx, finalizeParams(fn, _params));
58387
+ return parse8(schema, value, ctx, finalizeParams(fn, _params));
57762
58388
  };
57763
58389
  return fn;
57764
58390
  }, encode, _decode = (_Err) => {
57765
- const parse6 = _parse(_Err);
58391
+ const parse8 = _parse(_Err);
57766
58392
  const fn = (schema, value, _ctx, _params) => {
57767
- return parse6(schema, value, _ctx, finalizeParams(fn, _params));
58393
+ return parse8(schema, value, _ctx, finalizeParams(fn, _params));
57768
58394
  };
57769
58395
  return fn;
57770
58396
  }, decode, _encodeAsync = (_Err) => {
@@ -57795,7 +58421,7 @@ var init_parse = __esm(() => {
57795
58421
  init_core();
57796
58422
  init_errors();
57797
58423
  init_util();
57798
- parse5 = /* @__PURE__ */ _parse($ZodRealError);
58424
+ parse7 = /* @__PURE__ */ _parse($ZodRealError);
57799
58425
  parseAsync = /* @__PURE__ */ _parseAsync($ZodRealError);
57800
58426
  safeParse = /* @__PURE__ */ _safeParse($ZodRealError);
57801
58427
  safeParseAsync = /* @__PURE__ */ _safeParseAsync($ZodRealError);
@@ -59758,14 +60384,14 @@ var init_schemas = __esm(() => {
59758
60384
  const shape = zod.def.shape;
59759
60385
  const propValues = {};
59760
60386
  for (const key in shape) {
59761
- const field = shape[key]._zod;
59762
- if (field.values) {
60387
+ const field2 = shape[key]._zod;
60388
+ if (field2.values) {
59763
60389
  if (!Object.prototype.hasOwnProperty.call(propValues, key)) {
59764
60390
  assignProp(propValues, key, new Set);
59765
60391
  }
59766
- for (const v of field.values)
60392
+ for (const v of field2.values)
59767
60393
  propValues[key].add(v);
59768
- if (field.optin !== undefined)
60394
+ if (field2.optin !== undefined)
59769
60395
  propValues[key].add(undefined);
59770
60396
  }
59771
60397
  }
@@ -60720,10 +61346,10 @@ var init_schemas = __esm(() => {
60720
61346
  throw new Error("implement() must be called with a function");
60721
61347
  }
60722
61348
  return Object.defineProperty(function(...args) {
60723
- const parsedArgs = inst._def.input ? parse5(inst._def.input, args) : args;
61349
+ const parsedArgs = inst._def.input ? parse7(inst._def.input, args) : args;
60724
61350
  const result2 = Reflect.apply(func, this, parsedArgs);
60725
61351
  if (inst._def.output) {
60726
- return parse5(inst._def.output, result2);
61352
+ return parse7(inst._def.output, result2);
60727
61353
  }
60728
61354
  return result2;
60729
61355
  }, "_zod", { value: inst._zod, enumerable: false });
@@ -72040,11 +72666,11 @@ var formatMap, stringProcessor = (schema, ctx, _json, _params) => {
72040
72666
  }
72041
72667
  const allKeys = new Set(Object.keys(shape));
72042
72668
  const requiredKeys = new Set([...allKeys].filter((key) => {
72043
- const field = def.shape[key];
72669
+ const field2 = def.shape[key];
72044
72670
  if (ctx.io === "input") {
72045
- return inputOptin(field) === undefined;
72671
+ return inputOptin(field2) === undefined;
72046
72672
  } else {
72047
- return field._zod.optout === undefined;
72673
+ return field2._zod.optout === undefined;
72048
72674
  }
72049
72675
  }));
72050
72676
  if (requiredKeys.size > 0) {
@@ -72424,7 +73050,7 @@ __export(exports_core2, {
72424
73050
  prettifyError: () => prettifyError,
72425
73051
  parseURLObject: () => parseURLObject,
72426
73052
  parseAsync: () => parseAsync,
72427
- parse: () => parse5,
73053
+ parse: () => parse7,
72428
73054
  meta: () => meta,
72429
73055
  mergeValues: () => mergeValues,
72430
73056
  memoizer: () => memoizer,
@@ -72814,12 +73440,12 @@ var init_errors2 = __esm(() => {
72814
73440
  });
72815
73441
 
72816
73442
  // node_modules/zod/v4/classic/parse.js
72817
- var parse7, parseAsync2, safeParse2, safeParseAsync2, encode2, decode2, encodeAsync2, decodeAsync2, safeEncode2, safeDecode2, safeEncodeAsync2, safeDecodeAsync2;
73443
+ var parse9, parseAsync2, safeParse2, safeParseAsync2, encode2, decode2, encodeAsync2, decodeAsync2, safeEncode2, safeDecode2, safeEncodeAsync2, safeDecodeAsync2;
72818
73444
  var init_parse2 = __esm(() => {
72819
73445
  init_core2();
72820
73446
  init_errors2();
72821
73447
  init_core2();
72822
- parse7 = /* @__PURE__ */ _parse(ZodRealError);
73448
+ parse9 = /* @__PURE__ */ _parse(ZodRealError);
72823
73449
  parseAsync2 = /* @__PURE__ */ _parseAsync(ZodRealError);
72824
73450
  safeParse2 = /* @__PURE__ */ _safeParse(ZodRealError);
72825
73451
  safeParseAsync2 = /* @__PURE__ */ _safeParseAsync(ZodRealError);
@@ -73620,7 +74246,7 @@ var init_schemas2 = __esm(() => {
73620
74246
  exports_util.own(this, "~standard", value);
73621
74247
  },
73622
74248
  parse: function _parse2(data, params) {
73623
- return parse7(this, data, params, { callee: _parse2 });
74249
+ return parse9(this, data, params, { callee: _parse2 });
73624
74250
  },
73625
74251
  parseAsync: async function _parseAsync2(data, params) {
73626
74252
  return await parseAsync2(this, data, params, { callee: _parseAsync2 });
@@ -75313,7 +75939,7 @@ __export(exports_external, {
75313
75939
  pipe: () => pipe,
75314
75940
  partialRecord: () => partialRecord,
75315
75941
  parseAsync: () => parseAsync2,
75316
- parse: () => parse7,
75942
+ parse: () => parse9,
75317
75943
  overwrite: () => _overwrite,
75318
75944
  output: () => output,
75319
75945
  optional: () => optional,
@@ -75794,7 +76420,7 @@ var init_v4 = __esm(() => {
75794
76420
  });
75795
76421
 
75796
76422
  // src/lib/canonical-json.ts
75797
- import { createHash as createHash13 } from "crypto";
76423
+ import { createHash as createHash15 } from "crypto";
75798
76424
  function canonicalJson2(value, maximumBytes = 2 * 1024 * 1024) {
75799
76425
  return canonicalJsonAtDepth(value, maximumBytes, 64);
75800
76426
  }
@@ -75838,7 +76464,7 @@ function canonicalJsonAtDepth(value, maximumBytes, maximumDepth) {
75838
76464
  return visit3(value, 0);
75839
76465
  }
75840
76466
  function canonicalJsonSha256(value, maximumBytes) {
75841
- return createHash13("sha256").update(canonicalJson2(value, maximumBytes)).digest("hex");
76467
+ return createHash15("sha256").update(canonicalJson2(value, maximumBytes)).digest("hex");
75842
76468
  }
75843
76469
  var init_canonical_json = () => {};
75844
76470
 
@@ -76592,13 +77218,13 @@ var init_remote_workspace_leave = __esm(() => {
76592
77218
 
76593
77219
  // src/lib/auth-store.ts
76594
77220
  import { chmodSync as chmodSync2, existsSync as existsSync20, mkdirSync as mkdirSync11, readFileSync as readFileSync19, renameSync as renameSync7, statSync as statSync11, unlinkSync as unlinkSync5, writeFileSync as writeFileSync9 } from "fs";
76595
- import { basename as basename6, dirname as dirname15, join as join34 } from "path";
77221
+ import { basename as basename10, dirname as dirname17, join as join34 } from "path";
76596
77222
  function getAuthFilePath(env3 = process.env) {
76597
77223
  return skillsCredentialFilePath(env3);
76598
77224
  }
76599
77225
  function getIdentityFilePath(env3 = process.env) {
76600
77226
  const file2 = skillsCredentialFilePath(env3);
76601
- return join34(dirname15(file2), basename6(file2).replace(/^credentials/, "identity") + ".json");
77227
+ return join34(dirname17(file2), basename10(file2).replace(/^credentials/, "identity") + ".json");
76602
77228
  }
76603
77229
  function getAuthIdentity(env3 = process.env) {
76604
77230
  return readIdentity(env3);
@@ -76614,10 +77240,10 @@ function readIdentity(env3 = process.env) {
76614
77240
  if (selected && normalizeSkillsApiOrigin(bound) !== selected)
76615
77241
  return {};
76616
77242
  const identity4 = {};
76617
- for (const field of ["email", "orgId", "orgSlug", "userId"]) {
76618
- const value = record6[field];
77243
+ for (const field2 of ["email", "orgId", "orgSlug", "userId"]) {
77244
+ const value = record6[field2];
76619
77245
  if (typeof value === "string" && value.length > 0)
76620
- identity4[field] = value;
77246
+ identity4[field2] = value;
76621
77247
  }
76622
77248
  return identity4;
76623
77249
  } catch {
@@ -76632,7 +77258,7 @@ function getAuthConfig(env3 = process.env, options = {}) {
76632
77258
  }
76633
77259
  function writeCredentialValues(values2, env3 = process.env) {
76634
77260
  const file2 = skillsCredentialFilePath(env3);
76635
- mkdirSync11(dirname15(file2), { recursive: true, mode: 448 });
77261
+ mkdirSync11(dirname17(file2), { recursive: true, mode: 448 });
76636
77262
  const lines = [];
76637
77263
  const written = new Set;
76638
77264
  if (existsSync20(file2)) {
@@ -76700,10 +77326,10 @@ function saveAuthConfig(config2, env3 = process.env, authenticatedOrigin) {
76700
77326
  const apiUrl = authenticatedOrigin ? normalizeSkillsApiOrigin(authenticatedOrigin) : resolveSkillsApiOrigin(env3)?.origin ?? defaultFleetGatewayBaseUrl("skills");
76701
77327
  const file2 = writeCredentialValues({ SKILLS_API_KEY: null, SKILLS_API_URL: null, [SKILLS_API_KEY_REF]: null, [SKILLS_API_KEY_ENV]: apiKey, [SKILLS_BOUND_API_URL]: apiUrl, [SKILLS_API_URL_ENV]: apiUrl }, env3);
76702
77328
  const identity4 = {};
76703
- for (const field of ["email", "orgId", "orgSlug", "userId"]) {
76704
- const value = config2[field];
77329
+ for (const field2 of ["email", "orgId", "orgSlug", "userId"]) {
77330
+ const value = config2[field2];
76705
77331
  if (typeof value === "string" && value.length > 0)
76706
- identity4[field] = value;
77332
+ identity4[field2] = value;
76707
77333
  }
76708
77334
  const identityFile = getIdentityFilePath(env3);
76709
77335
  if (Object.keys(identity4).length > 0) {
@@ -76896,15 +77522,44 @@ var init_remote_account = __esm(() => {
76896
77522
  };
76897
77523
  });
76898
77524
 
77525
+ // src/lib/remote-credit-checkout.ts
77526
+ function creditCheckoutRequestKey(value) {
77527
+ if (value === undefined)
77528
+ return crypto.randomUUID();
77529
+ if (typeof value !== "string" || !creditCheckoutKeyPattern.test(value))
77530
+ throw new Error("Checkout idempotency key must be 8-255 URL-safe characters");
77531
+ return value;
77532
+ }
77533
+ function creditCheckoutFailure(value, status, key) {
77534
+ if (!value || typeof value !== "object" || Array.isArray(value))
77535
+ return { code: "CREDIT_CHECKOUT_UNCONFIRMED" };
77536
+ const row = value;
77537
+ if (row.requestIdempotencyKey !== undefined && row.requestIdempotencyKey !== key)
77538
+ return { code: "CREDIT_CHECKOUT_UNCONFIRMED" };
77539
+ const code = status === 409 && row.error === "credit checkout in_progress" ? "CREDIT_CHECKOUT_IN_PROGRESS" : status === 409 && row.error === "credit checkout expired" && row.requestIdempotencyKey === key ? "CREDIT_CHECKOUT_EXPIRED" : status === 409 && row.error === "credit checkout fulfilled" && row.requestIdempotencyKey === key ? "CREDIT_CHECKOUT_FULFILLED" : "CREDIT_CHECKOUT_UNCONFIRMED";
77540
+ const delay2 = row.retryAfterSeconds;
77541
+ return { code, ...code === "CREDIT_CHECKOUT_IN_PROGRESS" || status === 503 && row.error === "credit checkout creation unresolved" ? typeof delay2 === "number" && Number.isSafeInteger(delay2) && delay2 > 0 && delay2 <= 3600 ? { retryAfterSeconds: delay2 } : {} : {} };
77542
+ }
77543
+ var creditCheckoutKeyPattern, creditCheckoutMessages;
77544
+ var init_remote_credit_checkout = __esm(() => {
77545
+ creditCheckoutKeyPattern = /^[A-Za-z0-9._:-]{8,255}$/;
77546
+ creditCheckoutMessages = {
77547
+ CREDIT_CHECKOUT_UNCONFIRMED: "Checkout creation could not be confirmed. Keep the request idempotency key, inspect billing, and use the same key for an explicit retry on the same server, account and pack. No automatic retry was made.",
77548
+ CREDIT_CHECKOUT_IN_PROGRESS: "This checkout is still being created. Wait before explicitly retrying the same server, account and pack with the same request idempotency key. No automatic retry was made.",
77549
+ CREDIT_CHECKOUT_EXPIRED: "This checkout has expired. Inspect billing before deliberately starting a new purchase with a new request idempotency key. Do not retry this checkout automatically.",
77550
+ CREDIT_CHECKOUT_FULFILLED: "This checkout is already fulfilled. Inspect the account balance; do not create another checkout to recover this purchase."
77551
+ };
77552
+ });
77553
+
76899
77554
  // src/lib/remote-profile.ts
76900
- function customerNamePatch(input2, field) {
76901
- if (!isRecord4(input2) || Object.keys(input2).length !== 1 || !Object.hasOwn(input2, field))
77555
+ function customerNamePatch(input2, field2) {
77556
+ if (!isRecord4(input2) || Object.keys(input2).length !== 1 || !Object.hasOwn(input2, field2))
76902
77557
  throw new Error("Provide only the requested name field.");
76903
- const value = input2[field];
77558
+ const value = input2[field2];
76904
77559
  if (typeof value !== "string" || /[\p{Cc}\p{Cs}\u2028\u2029]/u.test(value) || !value.trim() || [...value.trim()].length > 100) {
76905
77560
  throw new Error("Use a name of 1\u2013100 characters without control characters or newlines.");
76906
77561
  }
76907
- return { [field]: value.trim() };
77562
+ return { [field2]: value.trim() };
76908
77563
  }
76909
77564
  function isRecord4(value) {
76910
77565
  return !!value && typeof value === "object" && !Array.isArray(value);
@@ -76941,10 +77596,10 @@ async function readQuoteUnavailableCode(response) {
76941
77596
  let timer;
76942
77597
  let deadlineExceeded = false;
76943
77598
  const expired = Symbol("quote body deadline");
76944
- const deadline = new Promise((resolve14) => {
77599
+ const deadline = new Promise((resolve17) => {
76945
77600
  timer = setTimeout(() => {
76946
77601
  deadlineExceeded = true;
76947
- resolve14(expired);
77602
+ resolve17(expired);
76948
77603
  reader.cancel().catch(() => {});
76949
77604
  }, 1500);
76950
77605
  });
@@ -77059,6 +77714,7 @@ __export(exports_remote_client, {
77059
77714
  RemoteRouteUnsupportedError: () => RemoteRouteUnsupportedError,
77060
77715
  RemoteRequestError: () => RemoteRequestError,
77061
77716
  RemoteQuoteUnavailableError: () => RemoteQuoteUnavailableError,
77717
+ RemoteCreditCheckoutError: () => RemoteCreditCheckoutError,
77062
77718
  RemoteCapabilityUnavailableError: () => RemoteCapabilityUnavailableError
77063
77719
  });
77064
77720
 
@@ -77509,14 +78165,43 @@ class RemoteSkillsClient {
77509
78165
  async listCreditPacks() {
77510
78166
  return parseRemoteCreditPacks(await (await this.requestNewRoute("/api/v1/billing/credits")).json());
77511
78167
  }
77512
- async createCreditCheckout(packId) {
78168
+ async createCreditCheckout(packId, options = {}) {
78169
+ const requestIdempotencyKey = creditCheckoutRequestKey(options.idempotencyKey);
77513
78170
  const packs = await this.listCreditPacks();
77514
78171
  if (!packs.some((pack) => pack.id === packId))
77515
78172
  throw new Error("Choose a credit pack returned by skills credits packs");
77516
- return parseRemoteCheckout(await (await this.requestNewRoute("/api/v1/billing/credits", {
77517
- method: "POST",
77518
- body: JSON.stringify({ packId })
77519
- })).json());
78173
+ let response;
78174
+ try {
78175
+ response = await this.request("/api/v1/billing/credits", {
78176
+ method: "POST",
78177
+ body: JSON.stringify({ packId, idempotencyKey: requestIdempotencyKey })
78178
+ });
78179
+ } catch {
78180
+ throw new RemoteCreditCheckoutError("CREDIT_CHECKOUT_UNCONFIRMED", 0, requestIdempotencyKey);
78181
+ }
78182
+ if (response.status === 404 || response.status === 405) {
78183
+ response.body?.cancel().catch(() => {});
78184
+ throw new RemoteRouteUnsupportedError("/api/v1/billing/credits", response.status, this.apiUrl);
78185
+ }
78186
+ let value;
78187
+ try {
78188
+ value = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(await readBoundedResponse(response, 4096)));
78189
+ } catch {
78190
+ throw new RemoteCreditCheckoutError("CREDIT_CHECKOUT_UNCONFIRMED", response.status, requestIdempotencyKey);
78191
+ }
78192
+ if (!response.ok) {
78193
+ const failure = creditCheckoutFailure(value, response.status, requestIdempotencyKey);
78194
+ throw new RemoteCreditCheckoutError(failure.code, response.status, requestIdempotencyKey, failure.retryAfterSeconds);
78195
+ }
78196
+ try {
78197
+ const checkout = parseRemoteCheckout(value);
78198
+ const echo = value.requestIdempotencyKey;
78199
+ if (echo !== undefined && echo !== requestIdempotencyKey)
78200
+ throw new Error("checkout request key changed");
78201
+ return { ...checkout, requestIdempotencyKey };
78202
+ } catch {
78203
+ throw new RemoteCreditCheckoutError("CREDIT_CHECKOUT_UNCONFIRMED", response.status, requestIdempotencyKey);
78204
+ }
77520
78205
  }
77521
78206
  async getUsage() {
77522
78207
  return this.arrayResponse("/api/v1/billing/usage");
@@ -77749,13 +78434,13 @@ class RemoteSkillsClient {
77749
78434
  return normalizeUpdatedSincePage(await response.json());
77750
78435
  }
77751
78436
  }
77752
- function requireOptionalString(record7, field) {
77753
- if (record7[field] === undefined)
78437
+ function requireOptionalString(record7, field2) {
78438
+ if (record7[field2] === undefined)
77754
78439
  return;
77755
- if (typeof record7[field] !== "string") {
77756
- throw new Error(`Remote payload did not match the expected contract (${field} must be a string when present)`);
78440
+ if (typeof record7[field2] !== "string") {
78441
+ throw new Error(`Remote payload did not match the expected contract (${field2} must be a string when present)`);
77757
78442
  }
77758
- return record7[field];
78443
+ return record7[field2];
77759
78444
  }
77760
78445
  function isVersionRecord(value) {
77761
78446
  return value !== null && typeof value === "object" && !Array.isArray(value);
@@ -77886,7 +78571,7 @@ async function createRemoteSkillsClient(env3 = process.env) {
77886
78571
  function createRemoteSkillsClientReadOnly(env3 = process.env) {
77887
78572
  return createRemoteSkillsClient(env3);
77888
78573
  }
77889
- var RemoteRouteUnsupportedError, RemoteRequestError, RemoteQuoteUnavailableError, RemoteWorkspaceMemberError, RemoteWorkspaceSelectionError, RemoteCapabilityUnavailableError, INVALID_SKILL_VERSION_RESPONSE = "Remote skill version payload did not match the expected contract.";
78574
+ var RemoteRouteUnsupportedError, RemoteRequestError, RemoteCreditCheckoutError, RemoteQuoteUnavailableError, RemoteWorkspaceMemberError, RemoteWorkspaceSelectionError, RemoteCapabilityUnavailableError, INVALID_SKILL_VERSION_RESPONSE = "Remote skill version payload did not match the expected contract.";
77890
78575
  var init_remote_client = __esm(() => {
77891
78576
  init_remote_recurring();
77892
78577
  init_remote_invitations();
@@ -77898,6 +78583,7 @@ var init_remote_client = __esm(() => {
77898
78583
  init_fleet_credentials();
77899
78584
  init_remote_account();
77900
78585
  init_remote_files();
78586
+ init_remote_credit_checkout();
77901
78587
  init_remote_quote_errors();
77902
78588
  init_remote_permissions();
77903
78589
  RemoteRouteUnsupportedError = class RemoteRouteUnsupportedError extends Error {
@@ -77922,6 +78608,19 @@ var init_remote_client = __esm(() => {
77922
78608
  this.name = "RemoteRequestError";
77923
78609
  }
77924
78610
  };
78611
+ RemoteCreditCheckoutError = class RemoteCreditCheckoutError extends RemoteRequestError {
78612
+ code;
78613
+ requestIdempotencyKey;
78614
+ retryAfterSeconds;
78615
+ constructor(code, status, requestIdempotencyKey, retryAfterSeconds) {
78616
+ super("/api/v1/billing/credits", status);
78617
+ this.code = code;
78618
+ this.requestIdempotencyKey = requestIdempotencyKey;
78619
+ this.retryAfterSeconds = retryAfterSeconds;
78620
+ this.name = "RemoteCreditCheckoutError";
78621
+ this.message = creditCheckoutMessages[code];
78622
+ }
78623
+ };
77925
78624
  RemoteQuoteUnavailableError = class RemoteQuoteUnavailableError extends RemoteRequestError {
77926
78625
  code;
77927
78626
  constructor(path, code) {
@@ -77962,9 +78661,9 @@ var init_remote_client = __esm(() => {
77962
78661
  });
77963
78662
 
77964
78663
  // src/lib/revision.ts
77965
- import { createHash as createHash14 } from "crypto";
78664
+ import { createHash as createHash16 } from "crypto";
77966
78665
  function revisionIdOf(content) {
77967
- const canonical3 = JSON.stringify({
78666
+ const canonical4 = JSON.stringify({
77968
78667
  slug: content.slug,
77969
78668
  displayName: content.displayName,
77970
78669
  description: content.description,
@@ -77977,7 +78676,7 @@ function revisionIdOf(content) {
77977
78676
  bundleSha256: content.bundleSha256 ?? null,
77978
78677
  bundleByteSize: content.bundleByteSize ?? null
77979
78678
  });
77980
- return createHash14("sha256").update(canonical3).digest("hex");
78679
+ return createHash16("sha256").update(canonical4).digest("hex");
77981
78680
  }
77982
78681
  var REVISION_ID_PATTERN;
77983
78682
  var init_revision = __esm(() => {
@@ -78007,7 +78706,7 @@ var init_skill_bundles = __esm(() => {
78007
78706
 
78008
78707
  // src/lib/pull.ts
78009
78708
  import { existsSync as existsSync21, mkdirSync as mkdirSync12, mkdtempSync as mkdtempSync3, readFileSync as readFileSync20, renameSync as renameSync8, rmSync as rmSync6, writeFileSync as writeFileSync10 } from "fs";
78010
- import { dirname as dirname16, join as join35 } from "path";
78709
+ import { dirname as dirname18, join as join35 } from "path";
78011
78710
  async function pullSkills(options = {}) {
78012
78711
  const client2 = options.client !== undefined ? options.client : await createRemoteSkillsClient();
78013
78712
  if (!client2) {
@@ -78311,7 +79010,7 @@ function installBundleAtomically(name, entries, options = {}, marker = {}) {
78311
79010
  try {
78312
79011
  for (const entry of entries) {
78313
79012
  const destination = join35(staging, entry.path);
78314
- mkdirSync12(dirname16(destination), { recursive: true });
79013
+ mkdirSync12(dirname18(destination), { recursive: true });
78315
79014
  writeFileSync10(destination, entry.bytes, { mode: entry.mode });
78316
79015
  }
78317
79016
  writePullMarker(staging, {
@@ -78426,8 +79125,8 @@ var init_pull = __esm(() => {
78426
79125
  });
78427
79126
 
78428
79127
  // src/lib/skill-context.ts
78429
- import { createHash as createHash15 } from "crypto";
78430
- import { resolve as resolve14 } from "path";
79128
+ import { createHash as createHash17 } from "crypto";
79129
+ import { resolve as resolve17 } from "path";
78431
79130
  function words2(value) {
78432
79131
  return new Set(value.toLowerCase().match(/[a-z0-9]+/g) ?? []);
78433
79132
  }
@@ -78462,7 +79161,7 @@ async function buildSkillContext(input2, options = {}) {
78462
79161
  const promptWords = words2(prompt);
78463
79162
  const promptNames = new Set(prompt.toLowerCase().match(/[a-z0-9]+(?:-[a-z0-9]+)*/g) ?? []);
78464
79163
  const loaded = new Set(resolved.session?.loaded ?? []);
78465
- const paths = [...input2.paths ?? [], ...input2.cwd ? [input2.cwd, resolve14(input2.cwd)] : []];
79164
+ const paths = [...input2.paths ?? [], ...input2.cwd ? [input2.cwd, resolve17(input2.cwd)] : []];
78466
79165
  const candidates = profile.selections.map((selection) => {
78467
79166
  const key = selectionKey(selection);
78468
79167
  if (input2.restore && loaded.has(key))
@@ -78515,7 +79214,7 @@ ${content}`;
78515
79214
  `);
78516
79215
  const receipt = {
78517
79216
  schemaVersion: 1,
78518
- id: createHash15("sha256").update(JSON.stringify({ profile: profile.profileRevision, sessionId, selections, omitted })).digest("hex"),
79217
+ id: createHash17("sha256").update(JSON.stringify({ profile: profile.profileRevision, sessionId, selections, omitted })).digest("hex"),
78519
79218
  profileId: profile.profileId,
78520
79219
  profileRevision: profile.profileRevision,
78521
79220
  authority: profile.authority,
@@ -78527,7 +79226,7 @@ ${content}`;
78527
79226
  selections
78528
79227
  };
78529
79228
  if (sessionId)
78530
- writeSelectionJson(sessionReceiptPath(sessionId, options), { ...resolved.receipt, sessionId, loaded: [...loaded] });
79229
+ writeSkillSession({ ...resolved.receipt, sessionId, loaded: [...loaded] }, { current: resolved.sessionSnapshot, parent: resolved.parentSnapshot }, options);
78531
79230
  return { context, selections, omitted, receipt };
78532
79231
  }
78533
79232
  var init_skill_context = __esm(() => {
@@ -78536,6 +79235,107 @@ var init_skill_context = __esm(() => {
78536
79235
  init_selected_document();
78537
79236
  });
78538
79237
 
79238
+ // src/lib/session-reconciliation.ts
79239
+ import { createHash as createHash18 } from "crypto";
79240
+ function exactTimestamp(value) {
79241
+ const parsed = value === undefined ? Number.NaN : Date.parse(value);
79242
+ if (!Number.isFinite(parsed) || new Date(parsed).toISOString() !== value) {
79243
+ throw new SkillSelectionError("SESSION_PLAN_WINDOW_INVALID", "The reviewed plan must include its exact canonical issuedAt and expiresAt timestamps.");
79244
+ }
79245
+ return parsed;
79246
+ }
79247
+ function assertPlanWindow(issuedAt, expiresAt, now3) {
79248
+ const issued = exactTimestamp(issuedAt), expires = exactTimestamp(expiresAt);
79249
+ if (expires - issued !== SESSION_RECONCILIATION_PLAN_TTL_MS) {
79250
+ throw new SkillSelectionError("SESSION_PLAN_WINDOW_INVALID", "A session reconciliation approval is valid for exactly five minutes and cannot be extended by the caller.");
79251
+ }
79252
+ if (now3 < issued || now3 >= expires) {
79253
+ throw new SkillSelectionError("SESSION_PLAN_EXPIRED", "The reviewed session reconciliation plan is not currently valid; inspect the receipt and prepare a new plan.");
79254
+ }
79255
+ }
79256
+ function inspectSkillSession(sessionId, options = {}) {
79257
+ const snapshot = readSkillSessionSnapshot(sessionId, options), { receipt } = snapshot;
79258
+ return {
79259
+ sessionId,
79260
+ path: snapshot.path,
79261
+ receiptSha256: snapshot.sha256,
79262
+ generation: snapshot.generation,
79263
+ verifiedAt: receipt.verifiedAt,
79264
+ authority: receipt.profile.authority,
79265
+ workspaceId: receipt.profile.workspaceId,
79266
+ profileId: receipt.profile.profileId,
79267
+ profileRevision: receipt.profile.profileRevision,
79268
+ selectionCount: receipt.profile.selections.length,
79269
+ loadedCount: receipt.loaded.length
79270
+ };
79271
+ }
79272
+ async function reconcileSkillSession(input2, options = {}) {
79273
+ if (![input2.fromProfile, input2.fromRevision, input2.selectionProfile, input2.profileRevision].every((value) => typeof value === "string" && value.trim()) || !/^[a-f0-9]{64}$/.test(input2.receiptSha256)) {
79274
+ throw new SkillSelectionError("INVALID_SESSION_RECONCILIATION", "Name the exact old receipt SHA256, old profile/revision and intended target profile/revision.");
79275
+ }
79276
+ if (input2.apply && (!input2.planDigest || !input2.planIssuedAt || !input2.planExpiresAt)) {
79277
+ throw new SkillSelectionError("SESSION_PLAN_REQUIRED", "Review the session reconciliation plan and provide its exact digest, issuedAt and expiresAt before applying it.");
79278
+ }
79279
+ if (!input2.apply && (input2.planDigest !== undefined || input2.planIssuedAt !== undefined || input2.planExpiresAt !== undefined)) {
79280
+ throw new SkillSelectionError("SESSION_PLAN_WINDOW_INVALID", "Plan timestamps are minted by the planner and may only be replayed with --apply.");
79281
+ }
79282
+ const now3 = (options.now ?? Date.now)();
79283
+ const issuedAt = input2.apply ? input2.planIssuedAt : new Date(now3).toISOString();
79284
+ const expiresAt = input2.apply ? input2.planExpiresAt : new Date(now3 + SESSION_RECONCILIATION_PLAN_TTL_MS).toISOString();
79285
+ if (input2.apply)
79286
+ assertPlanWindow(issuedAt, expiresAt, now3);
79287
+ const snapshot = readSkillSessionSnapshot(input2.sessionId, options), old = snapshot.receipt;
79288
+ if (snapshot.sha256 !== input2.receiptSha256 || old.profile.profileId !== input2.fromProfile || old.profile.profileRevision !== input2.fromRevision) {
79289
+ throw new SkillSelectionError("SESSION_RECEIPT_CHANGED", "The current session receipt does not match the reviewed old bytes, profile and revision.");
79290
+ }
79291
+ const client2 = options.client ?? await createProfileClient();
79292
+ const target = structuredClone(await client2.resolveProfile(input2.selectionProfile));
79293
+ validateResolvedProfile(target, client2.authority);
79294
+ if (target.profileId !== input2.selectionProfile || target.profileRevision !== input2.profileRevision) {
79295
+ throw new SkillSelectionError("SESSION_TARGET_CHANGED", "The API selection profile does not match the intended target revision; review the current selection before proceeding.");
79296
+ }
79297
+ if (old.profile.authority !== target.authority || old.profile.workspaceId !== target.workspaceId) {
79298
+ throw new SkillSelectionError("PROFILE_IDENTITY_MISMATCH", "A session reconciliation cannot change its Skills authority or workspace.");
79299
+ }
79300
+ const targetKeys = new Set(target.selections.map(selectionKey));
79301
+ const loaded = old.loaded.filter((key) => targetKeys.has(key));
79302
+ const replacementGeneration = nextSkillSessionGeneration(snapshot.generation);
79303
+ const plan = {
79304
+ schemaVersion: 1,
79305
+ issuedAt,
79306
+ expiresAt,
79307
+ sessionId: input2.sessionId,
79308
+ sessionPath: snapshot.path,
79309
+ before: { receiptSha256: snapshot.sha256, generation: snapshot.generation, profileId: old.profile.profileId, profileRevision: old.profile.profileRevision, selectionCount: old.profile.selections.length },
79310
+ target: { authority: target.authority, workspaceId: target.workspaceId, profileId: target.profileId, profileRevision: target.profileRevision, profileSha256: digest3(target), selectionCount: target.selections.length },
79311
+ replacementGeneration,
79312
+ retainedLoadedCount: loaded.length,
79313
+ retiredLoadedCount: old.loaded.length - loaded.length,
79314
+ scope: "Only this receipt; existing child sessions, project locks, shared profiles, hooks and running processes are unchanged."
79315
+ };
79316
+ const planDigest = digest3(plan);
79317
+ if (input2.planDigest !== undefined && input2.planDigest !== planDigest)
79318
+ throw new SkillSelectionError("SESSION_PLAN_CHANGED", "The session reconciliation plan differs from the reviewed plan.");
79319
+ if (!input2.apply)
79320
+ return { applied: false, plan, planDigest, archivePath: undefined, receiptPath: undefined, beforeSha256: snapshot.sha256, afterSha256: undefined };
79321
+ assertPlanWindow(issuedAt, expiresAt, (options.now ?? Date.now)());
79322
+ const replacement = {
79323
+ ...old,
79324
+ generation: replacementGeneration,
79325
+ verifiedAt: new Date((options.now ?? Date.now)()).toISOString(),
79326
+ profile: target,
79327
+ loaded
79328
+ };
79329
+ const result2 = replaceSkillSession(skillSessionSnapshotBinding(snapshot), replacement, { ...plan, planDigest }, options, () => assertPlanWindow(issuedAt, expiresAt, (options.now ?? Date.now)()));
79330
+ return { applied: true, plan, planDigest, ...result2 };
79331
+ }
79332
+ var SESSION_RECONCILIATION_PLAN_TTL_MS, digest3 = (value) => createHash18("sha256").update(JSON.stringify(value)).digest("hex");
79333
+ var init_session_reconciliation = __esm(() => {
79334
+ init_profile_client();
79335
+ init_selection_cache();
79336
+ SESSION_RECONCILIATION_PLAN_TTL_MS = 5 * 60 * 1000;
79337
+ });
79338
+
78539
79339
  // src/cli/commands/context.ts
78540
79340
  var exports_context = {};
78541
79341
  __export(exports_context, {
@@ -78545,7 +79345,7 @@ __export(exports_context, {
78545
79345
  parseSkillContextInput: () => parseSkillContextInput,
78546
79346
  contextResolverOptions: () => contextResolverOptions
78547
79347
  });
78548
- import { readSync as readSync8 } from "fs";
79348
+ import { readSync as readSync10 } from "fs";
78549
79349
  function selectedProfileId(explicit) {
78550
79350
  return explicit ?? process.env.HASNA_SKILLS_SELECTION_PROFILE ?? readManagedSkillPolicy()?.profileId ?? "default";
78551
79351
  }
@@ -78559,6 +79359,25 @@ function contextResolverOptions(options) {
78559
79359
  return { cached: true, authority };
78560
79360
  }
78561
79361
  function registerContextCommands(parent) {
79362
+ const sessions = parent.command("sessions").description("Inspect exact session pins and explicitly reconcile one reviewed receipt");
79363
+ sessions.command("show <id>").option("--json", "Return metadata as JSON", false).description("Inspect one session receipt without displaying payloads or changing its pin").action(async (id, options) => {
79364
+ try {
79365
+ const result2 = inspectSkillSession(id);
79366
+ await writeCliOutput(options.json ? JSON.stringify(result2) : `${JSON.stringify(id)}: ${result2.profileId} at ${result2.profileRevision}
79367
+ Receipt SHA256: ${result2.receiptSha256}`);
79368
+ } catch (error61) {
79369
+ reportContextError(error61, options.json);
79370
+ }
79371
+ });
79372
+ sessions.command("reconcile <id>").requiredOption("--from-profile <id>", "Expected current session profile").requiredOption("--from-revision <revision>", "Expected current session profile revision").requiredOption("--receipt-sha256 <sha256>", "Expected exact current receipt bytes").requiredOption("--selection-profile <id>", "Intended target selection profile").requiredOption("--profile-revision <revision>", "Expected current API target revision").option("--apply", "Archive the old receipt and atomically apply the reviewed plan", false).option("--plan-digest <sha256>", "Exact reviewed plan digest; required with --apply").option("--plan-issued-at <timestamp>", "Exact reviewed plan issuedAt; required with --apply").option("--plan-expires-at <timestamp>", "Exact reviewed plan expiresAt; required with --apply").option("--json", "Return the plan or application receipt as JSON", false).description("Plan an intentional migration of one session pin; ordinary hooks never migrate pins").action(async (id, options) => {
79373
+ try {
79374
+ const result2 = await reconcileSkillSession({ ...options, sessionId: id });
79375
+ await writeCliOutput(options.json ? JSON.stringify(result2) : result2.applied ? `Reconciled ${JSON.stringify(id)} to ${result2.plan.target.profileId} at ${result2.plan.target.profileRevision}.
79376
+ Preserved original receipt: ${result2.archivePath}` : `Planned one session reconciliation. Review --json output, then use --apply --plan-digest ${result2.planDigest} --plan-issued-at ${result2.plan.issuedAt} --plan-expires-at ${result2.plan.expiresAt}.`);
79377
+ } catch (error61) {
79378
+ reportContextError(error61, options.json);
79379
+ }
79380
+ });
78562
79381
  parent.command("load <skill>").description("Load an exact API-selected skill and return its version/digest receipt").option("--selection-profile <id>", "Selection profile (separate from the credential --profile)").option("--cached", "Use only an explicitly selected verified cache, at most 24 hours old", false).option("--session <id>", "Pin this load to a session").option("--file <path>", "Read an exact bundle file (default: SKILL.md, README.md, then CLAUDE.md)").option("--json", "Return content and provenance as JSON", false).action(async (skill, options) => {
78563
79382
  try {
78564
79383
  const result2 = await loadSelectedSkill(skill, selectedProfileId(options.selectionProfile), {
@@ -78604,7 +79423,7 @@ async function readContextStdin() {
78604
79423
  let size2 = 0;
78605
79424
  while (true) {
78606
79425
  const chunk2 = Buffer.allocUnsafe(8192);
78607
- const count = readSync8(0, chunk2, 0, chunk2.length, null);
79426
+ const count = readSync10(0, chunk2, 0, chunk2.length, null);
78608
79427
  if (count === 0)
78609
79428
  break;
78610
79429
  size2 += count;
@@ -78662,6 +79481,7 @@ var init_context = __esm(() => {
78662
79481
  init_selection_resolver();
78663
79482
  init_selection_cache();
78664
79483
  init_managed_policy();
79484
+ init_session_reconciliation();
78665
79485
  });
78666
79486
 
78667
79487
  // src/cli/commands/profile-sync.ts
@@ -79080,12 +79900,12 @@ function handleBrowseError(error61) {
79080
79900
  async function writeJson(value, space) {
79081
79901
  const text3 = `${JSON.stringify(value, null, space)}
79082
79902
  `;
79083
- await new Promise((resolve15, reject2) => {
79903
+ await new Promise((resolve18, reject2) => {
79084
79904
  process.stdout.write(text3, (error61) => {
79085
79905
  if (error61)
79086
79906
  reject2(error61);
79087
79907
  else
79088
- resolve15();
79908
+ resolve18();
79089
79909
  });
79090
79910
  });
79091
79911
  }
@@ -79617,7 +80437,7 @@ function handleDiff(name, options) {
79617
80437
  const sourcePath = getSkillPath(bare);
79618
80438
  const canonicalDir = join36(resolveCorpusRoot(), normalized);
79619
80439
  const canonicalSkillMd = join36(canonicalDir, "SKILL.md");
79620
- const canonical3 = {
80440
+ const canonical4 = {
79621
80441
  present: existsSync22(canonicalSkillMd),
79622
80442
  path: canonicalDir,
79623
80443
  ...existsSync22(canonicalSkillMd) ? { hash: hashSkillMarkdownFile(canonicalSkillMd) } : {},
@@ -79649,7 +80469,7 @@ function handleDiff(name, options) {
79649
80469
  stub = undefined;
79650
80470
  }
79651
80471
  }
79652
- const diverged = present && canonical3.present && managed && hash3 !== canonical3.hash;
80472
+ const diverged = present && canonical4.present && managed && hash3 !== canonical4.hash;
79653
80473
  homes.push({
79654
80474
  agent,
79655
80475
  path: dir,
@@ -79664,7 +80484,7 @@ function handleDiff(name, options) {
79664
80484
  if (options.json) {
79665
80485
  console.log(JSON.stringify({
79666
80486
  name: bare,
79667
- canonical: canonical3,
80487
+ canonical: canonical4,
79668
80488
  pinned,
79669
80489
  installedVersion,
79670
80490
  registryVersion,
@@ -79672,10 +80492,10 @@ function handleDiff(name, options) {
79672
80492
  homes
79673
80493
  }, null, 2));
79674
80494
  } else {
79675
- if (!canonical3.present) {
80495
+ if (!canonical4.present) {
79676
80496
  console.log(source_default.yellow(`${bare}: no canonical corpus entry`));
79677
80497
  } else {
79678
- console.log(source_default.dim(`${bare} canonical: ${canonical3.hash?.slice(0, 12)}\u2026`));
80498
+ console.log(source_default.dim(`${bare} canonical: ${canonical4.hash?.slice(0, 12)}\u2026`));
79679
80499
  }
79680
80500
  if (pinned) {
79681
80501
  console.log(upToDate ? source_default.green(`\u2713 pin is up to date (${installedVersion})`) : source_default.yellow(`pin metadata differs: ${installedVersion} \u2192 ${registryVersion}`));
@@ -79686,14 +80506,14 @@ function handleDiff(name, options) {
79686
80506
  } else if (!home.managed) {
79687
80507
  console.log(`${source_default.dim("\u2022")} ${home.agent}: ${source_default.yellow("unmarked (adoption candidate)")}`);
79688
80508
  } else if (home.diverged) {
79689
- const stubNote = home.stub === true ? " (home is a pointer stub; canonical holds content)" : canonical3.stub === true ? " (home holds content; canonical renders a pointer stub \u2014 sync refuses to replace it)" : "";
79690
- console.log(`${source_default.red("\u2717")} ${home.agent}: ${source_default.red("diverged")} ${source_default.dim(home.hash?.slice(0, 12))} \u2260 ${source_default.dim(canonical3.hash?.slice(0, 12))}${stubNote}`);
80509
+ const stubNote = home.stub === true ? " (home is a pointer stub; canonical holds content)" : canonical4.stub === true ? " (home holds content; canonical renders a pointer stub \u2014 sync refuses to replace it)" : "";
80510
+ console.log(`${source_default.red("\u2717")} ${home.agent}: ${source_default.red("diverged")} ${source_default.dim(home.hash?.slice(0, 12))} \u2260 ${source_default.dim(canonical4.hash?.slice(0, 12))}${stubNote}`);
79691
80511
  } else {
79692
80512
  console.log(`${source_default.green("\u2713")} ${home.agent}: ${source_default.green("matches canonical")}`);
79693
80513
  }
79694
80514
  }
79695
80515
  }
79696
- if (divergedHomes.length > 0 || homes.length > 0 && !canonical3.present)
80516
+ if (divergedHomes.length > 0 || homes.length > 0 && !canonical4.present)
79697
80517
  process.exitCode = 1;
79698
80518
  }
79699
80519
  var init_introspect = __esm(() => {
@@ -80429,7 +81249,7 @@ var init_init = __esm(() => {
80429
81249
  });
80430
81250
 
80431
81251
  // src/lib/home-adoption.ts
80432
- import { constants as constants10, closeSync as closeSync10, fstatSync as fstatSync10, lstatSync as lstatSync18, openSync as openSync10, readSync as readSync9, existsSync as existsSync24, mkdirSync as mkdirSync13, readdirSync as readdirSync13, readFileSync as readFileSync25, rmSync as rmSync7, statSync as statSync12, writeFileSync as writeFileSync12 } from "fs";
81252
+ import { constants as constants12, closeSync as closeSync12, fstatSync as fstatSync12, lstatSync as lstatSync20, openSync as openSync12, readSync as readSync11, existsSync as existsSync24, mkdirSync as mkdirSync13, readdirSync as readdirSync13, readFileSync as readFileSync25, rmSync as rmSync7, statSync as statSync12, writeFileSync as writeFileSync12 } from "fs";
80433
81253
  import { homedir as homedir7 } from "os";
80434
81254
  import { join as join38 } from "path";
80435
81255
  function indexCanonicalCorpus(corpusRoot) {
@@ -80584,25 +81404,25 @@ function adoptUnmarkedHomes(options = {}) {
80584
81404
  function pruneOwnership(dir) {
80585
81405
  let descriptor;
80586
81406
  try {
80587
- const directory = lstatSync18(dir);
81407
+ const directory = lstatSync20(dir);
80588
81408
  if (!directory.isDirectory())
80589
81409
  return;
80590
- const markerPath = join38(dir, SYNC_MARKER_FILE), markerPathBefore = lstatSync18(markerPath);
81410
+ const markerPath = join38(dir, SYNC_MARKER_FILE), markerPathBefore = lstatSync20(markerPath);
80591
81411
  if (!markerPathBefore.isFile())
80592
81412
  return;
80593
- descriptor = openSync10(markerPath, constants10.O_RDONLY | constants10.O_NOFOLLOW | constants10.O_NONBLOCK);
80594
- const before2 = fstatSync10(descriptor);
81413
+ descriptor = openSync12(markerPath, constants12.O_RDONLY | constants12.O_NOFOLLOW | constants12.O_NONBLOCK);
81414
+ const before2 = fstatSync12(descriptor);
80595
81415
  if (!before2.isFile() || before2.dev !== markerPathBefore.dev || before2.ino !== markerPathBefore.ino || before2.size !== markerPathBefore.size || before2.mtimeMs !== markerPathBefore.mtimeMs || before2.ctimeMs !== markerPathBefore.ctimeMs || before2.size < 1 || before2.size > 65536)
80596
81416
  return;
80597
81417
  const bytes = Buffer.alloc(before2.size + 1);
80598
81418
  let length = 0;
80599
81419
  while (length < bytes.length) {
80600
- const count = readSync9(descriptor, bytes, length, bytes.length - length, length);
81420
+ const count = readSync11(descriptor, bytes, length, bytes.length - length, length);
80601
81421
  if (!count)
80602
81422
  break;
80603
81423
  length += count;
80604
81424
  }
80605
- const after2 = fstatSync10(descriptor), current = lstatSync18(dir), markerPathAfter = lstatSync18(markerPath);
81425
+ const after2 = fstatSync12(descriptor), current = lstatSync20(dir), markerPathAfter = lstatSync20(markerPath);
80606
81426
  if (!markerPathAfter.isFile() || markerPathAfter.dev !== before2.dev || markerPathAfter.ino !== before2.ino || markerPathAfter.size !== before2.size || markerPathAfter.mtimeMs !== before2.mtimeMs || markerPathAfter.ctimeMs !== before2.ctimeMs || length !== before2.size || after2.size !== before2.size || after2.mtimeMs !== before2.mtimeMs || after2.ctimeMs !== before2.ctimeMs || !current.isDirectory() || current.dev !== directory.dev || current.ino !== directory.ino)
80607
81427
  return;
80608
81428
  const text3 = bytes.subarray(0, length).toString("utf8"), marker = JSON.parse(text3);
@@ -80613,7 +81433,7 @@ function pruneOwnership(dir) {
80613
81433
  return;
80614
81434
  } finally {
80615
81435
  if (descriptor !== undefined)
80616
- closeSync10(descriptor);
81436
+ closeSync12(descriptor);
80617
81437
  }
80618
81438
  }
80619
81439
  function pruneStrayHomes(options = {}) {
@@ -80798,7 +81618,7 @@ var init_home_census = __esm(() => {
80798
81618
  });
80799
81619
 
80800
81620
  // src/cli/env-assignment.ts
80801
- import { closeSync as closeSync11, constants as constants11, fstatSync as fstatSync11, ftruncateSync as ftruncateSync2, lstatSync as lstatSync19, openSync as openSync11, readFileSync as readFileSync27, writeSync as writeSync3 } from "fs";
81621
+ import { closeSync as closeSync13, constants as constants13, fstatSync as fstatSync13, ftruncateSync as ftruncateSync2, lstatSync as lstatSync21, openSync as openSync13, readFileSync as readFileSync27, writeSync as writeSync3 } from "fs";
80802
81622
  function serializeValue(value) {
80803
81623
  if (controls.test(value))
80804
81624
  throw new EnvAssignmentError("Environment values cannot contain control characters or newlines.");
@@ -80877,7 +81697,7 @@ function setEnvAssignment(path, assignment) {
80877
81697
  try {
80878
81698
  const previous = (() => {
80879
81699
  try {
80880
- return lstatSync19(path);
81700
+ return lstatSync21(path);
80881
81701
  } catch (error61) {
80882
81702
  if (error61.code === "ENOENT")
80883
81703
  return;
@@ -80886,8 +81706,8 @@ function setEnvAssignment(path, assignment) {
80886
81706
  })();
80887
81707
  if (previous && !previous.isFile())
80888
81708
  throw new EnvAssignmentError("The project .env must be a regular file, not a symlink or special file.");
80889
- descriptor = openSync11(path, previous ? constants11.O_RDWR | constants11.O_NOFOLLOW | constants11.O_NONBLOCK : constants11.O_WRONLY | constants11.O_CREAT | constants11.O_EXCL | constants11.O_NOFOLLOW, 384);
80890
- const opened = fstatSync11(descriptor);
81709
+ descriptor = openSync13(path, previous ? constants13.O_RDWR | constants13.O_NOFOLLOW | constants13.O_NONBLOCK : constants13.O_WRONLY | constants13.O_CREAT | constants13.O_EXCL | constants13.O_NOFOLLOW, 384);
81710
+ const opened = fstatSync13(descriptor);
80891
81711
  if (!opened.isFile() || previous && (opened.ino !== previous.ino || opened.dev !== previous.dev)) {
80892
81712
  throw new EnvAssignmentError("The project .env changed while opening it; retry with a regular file.");
80893
81713
  }
@@ -80914,7 +81734,7 @@ function setEnvAssignment(path, assignment) {
80914
81734
  throw new EnvAssignmentError("Cannot safely read or write the project .env file.");
80915
81735
  } finally {
80916
81736
  if (descriptor !== undefined)
80917
- closeSync11(descriptor);
81737
+ closeSync13(descriptor);
80918
81738
  }
80919
81739
  }
80920
81740
  var INVALID_LAYOUT = "Cannot safely update .env with multiline or unsupported assignments. Use single-line KEY=VALUE entries or edit the file manually.", controls, EnvAssignmentError;
@@ -81397,12 +82217,12 @@ function parseExecution(value) {
81397
82217
  ].includes(v.status) || typeof v.skill !== "string" || typeof v.version !== "string" || !Array.isArray(v.artifacts))
81398
82218
  throw Error("Unsupported cloud execution response");
81399
82219
  runId(v.id);
81400
- for (const field of [
82220
+ for (const field2 of [
81401
82221
  "bundleDigest",
81402
82222
  "inputDigest",
81403
82223
  "runtimeImageDigest"
81404
82224
  ])
81405
- if (typeof v[field] !== "string" || !/^(sha256:)?[a-f0-9]{64}$/.test(v[field]))
82225
+ if (typeof v[field2] !== "string" || !/^(sha256:)?[a-f0-9]{64}$/.test(v[field2]))
81406
82226
  throw Error("Invalid cloud execution integrity receipt");
81407
82227
  return v;
81408
82228
  }
@@ -81423,11 +82243,11 @@ var init_cloud_executions = __esm(() => {
81423
82243
  // node_modules/@hasna/secrets/dist/sdk.js
81424
82244
  import { isIP as isIP3 } from "net";
81425
82245
  import { spawnSync as spawnSync2 } from "child_process";
81426
- import { closeSync as closeSync12, fstatSync as fstatSync12, openSync as openSync12, readFileSync as readFileSync29 } from "fs";
82246
+ import { closeSync as closeSync14, fstatSync as fstatSync14, openSync as openSync14, readFileSync as readFileSync29 } from "fs";
81427
82247
  import { O_NOFOLLOW as O_NOFOLLOW3, O_NONBLOCK as O_NONBLOCK3, O_RDONLY as O_RDONLY3 } from "constants";
81428
82248
  import { createRequire as createRequire2 } from "module";
81429
82249
  import { hostname as osHostname2 } from "os";
81430
- import { isAbsolute as isAbsolute13, join as join41 } from "path";
82250
+ import { isAbsolute as isAbsolute16, join as join41 } from "path";
81431
82251
  import { createRequire as createRequire22 } from "module";
81432
82252
  function envToken2(name) {
81433
82253
  return name.toUpperCase().replace(/-/g, "_");
@@ -81451,7 +82271,7 @@ function homeDir2(env3) {
81451
82271
  }
81452
82272
  function absoluteOverride2(env3, key) {
81453
82273
  const value = env3[key]?.trim();
81454
- return value && isAbsolute13(value) ? value : null;
82274
+ return value && isAbsolute16(value) ? value : null;
81455
82275
  }
81456
82276
  function hasnaHomeDir2(env3) {
81457
82277
  const override = absoluteOverride2(env3, HASNA_HOME_ENV_KEY2);
@@ -81528,7 +82348,7 @@ function readAppConfigFile2(path) {
81528
82348
  };
81529
82349
  let fd = -1;
81530
82350
  try {
81531
- fd = openSync12(path, O_RDONLY3 | O_NOFOLLOW3 | O_NONBLOCK3);
82351
+ fd = openSync14(path, O_RDONLY3 | O_NOFOLLOW3 | O_NONBLOCK3);
81532
82352
  } catch (error61) {
81533
82353
  const code = error61.code;
81534
82354
  if (code === "ENOENT" || code === "ENOTDIR")
@@ -81538,7 +82358,7 @@ function readAppConfigFile2(path) {
81538
82358
  unsafe(`the path could not be opened (${code ?? "unknown error"})`);
81539
82359
  }
81540
82360
  try {
81541
- const before2 = fstatSync12(fd);
82361
+ const before2 = fstatSync14(fd);
81542
82362
  if (!before2.isFile())
81543
82363
  unsafe("the path is not a regular file");
81544
82364
  if (!configFileModeAllowed2(before2.mode)) {
@@ -81550,14 +82370,14 @@ function readAppConfigFile2(path) {
81550
82370
  if (before2.size > MAX_CREDENTIAL_FILE_BYTES2)
81551
82371
  unsafe("the file exceeds the size limit");
81552
82372
  const bytes = readFileSync29(fd);
81553
- const after2 = fstatSync12(fd);
82373
+ const after2 = fstatSync14(fd);
81554
82374
  if (!configFileReadsCoherent2(before2, after2)) {
81555
82375
  unsafe("the file changed while being read");
81556
82376
  }
81557
82377
  return parseEnvFile2(bytes.toString("utf8"));
81558
82378
  } finally {
81559
82379
  if (fd !== -1)
81560
- closeSync12(fd);
82380
+ closeSync14(fd);
81561
82381
  }
81562
82382
  }
81563
82383
  function readCredentialFile2(path, apiKeyKeys) {
@@ -82588,7 +83408,7 @@ function createSecretsClientFromEnv(env3 = process.env, overrides = {}) {
82588
83408
  });
82589
83409
  return new SecretsClient({ ...clientOverrides, baseUrl, apiKey });
82590
83410
  }
82591
- var __esm2 = (fn, res) => () => (fn && (res = fn(fn = 0)), res), CREDENTIAL_PROFILE_ENV_KEY2 = "HASNA_PROFILE", CredentialResolutionError2, CredentialFileUnsafeError2, HASNA_HOME_ENV_KEY2 = "HASNA_HOME", HASNA_CONFIG_HOME_ENV_KEY2 = "HASNA_CONFIG_HOME", KEYCHAIN_STATION_ENV_KEY2 = "HASNA_STATION", HASNA_HOME_DIR2 = ".hasna", CONFIG_SUBDIR2 = "config", CREDENTIALS_FILE2 = "credentials", KEYCHAIN_SECURITY_BIN2 = "/usr/bin/security", KEYCHAIN_SERVICE_PREFIX2 = "hasna.credentials", KEYCHAIN_ITEM_NOT_FOUND_STATUS2 = 44, KEYCHAIN_SPAWN_TIMEOUT_MS2 = 1e4, MAX_CREDENTIAL_FILE_BYTES2, SAFE_APP_SLUG2, SAFE_PROFILE2, ILLEGAL_IN_HEADER_VALUE2, VAULT_POINTER_SHAPE2, CREDENTIAL_SHAPED_KEY2, INSPECT_CUSTOM2, CREDENTIAL_SEAL2, CALLER_SUPPLIED_CREDENTIAL_PROVIDER_SOURCE = "caller-supplied CredentialProvider", AMBIENT_ENVIRONMENT2, SECRETS_PACKAGE_SPECIFIER, requireSecretsSdk2, DEFAULT_FLEET_GATEWAY_ORIGIN2 = "https://api.hasna.com", DEFAULT_AUTHORITY_SOURCE = "default", ASCII_CONTROL_PATTERN2, DNS_LABEL_PATTERN2, ClientTransportConfigurationError2, HasnaHttpError, DEFAULT_RETRY_STATUSES, IDEMPOTENT_METHODS2, AUTHORITY_OVERRIDE_HEADERS2, defaultSleep = (ms) => new Promise((resolve15) => setTimeout(resolve15, ms)), init_transport2, MAX_CREDENTIAL_FILE_BYTES22, INSPECT_CUSTOM22, CREDENTIAL_SEAL22, AMBIENT_ENVIRONMENT22, SECRETS_PACKAGE_SPECIFIER2, requireSecretsSdk22, IDEMPOTENT_METHODS22, AUTHORITY_OVERRIDE_HEADERS22, init_storage, PATHS_RESOLVER_APP_SLUG_RE3, SQLITE_SIDECAR_FILES, LEGACY_SERVICE_FILES, init_data_dir, SecretsTestIsolationError, TEST_ENTRYPOINT_RE, init_test_isolation, init_client, ApiError;
83411
+ var __esm2 = (fn, res) => () => (fn && (res = fn(fn = 0)), res), CREDENTIAL_PROFILE_ENV_KEY2 = "HASNA_PROFILE", CredentialResolutionError2, CredentialFileUnsafeError2, HASNA_HOME_ENV_KEY2 = "HASNA_HOME", HASNA_CONFIG_HOME_ENV_KEY2 = "HASNA_CONFIG_HOME", KEYCHAIN_STATION_ENV_KEY2 = "HASNA_STATION", HASNA_HOME_DIR2 = ".hasna", CONFIG_SUBDIR2 = "config", CREDENTIALS_FILE2 = "credentials", KEYCHAIN_SECURITY_BIN2 = "/usr/bin/security", KEYCHAIN_SERVICE_PREFIX2 = "hasna.credentials", KEYCHAIN_ITEM_NOT_FOUND_STATUS2 = 44, KEYCHAIN_SPAWN_TIMEOUT_MS2 = 1e4, MAX_CREDENTIAL_FILE_BYTES2, SAFE_APP_SLUG2, SAFE_PROFILE2, ILLEGAL_IN_HEADER_VALUE2, VAULT_POINTER_SHAPE2, CREDENTIAL_SHAPED_KEY2, INSPECT_CUSTOM2, CREDENTIAL_SEAL2, CALLER_SUPPLIED_CREDENTIAL_PROVIDER_SOURCE = "caller-supplied CredentialProvider", AMBIENT_ENVIRONMENT2, SECRETS_PACKAGE_SPECIFIER, requireSecretsSdk2, DEFAULT_FLEET_GATEWAY_ORIGIN2 = "https://api.hasna.com", DEFAULT_AUTHORITY_SOURCE = "default", ASCII_CONTROL_PATTERN2, DNS_LABEL_PATTERN2, ClientTransportConfigurationError2, HasnaHttpError, DEFAULT_RETRY_STATUSES, IDEMPOTENT_METHODS2, AUTHORITY_OVERRIDE_HEADERS2, defaultSleep = (ms) => new Promise((resolve18) => setTimeout(resolve18, ms)), init_transport2, MAX_CREDENTIAL_FILE_BYTES22, INSPECT_CUSTOM22, CREDENTIAL_SEAL22, AMBIENT_ENVIRONMENT22, SECRETS_PACKAGE_SPECIFIER2, requireSecretsSdk22, IDEMPOTENT_METHODS22, AUTHORITY_OVERRIDE_HEADERS22, init_storage, PATHS_RESOLVER_APP_SLUG_RE3, SQLITE_SIDECAR_FILES, LEGACY_SERVICE_FILES, init_data_dir, SecretsTestIsolationError, TEST_ENTRYPOINT_RE, init_test_isolation, init_client, ApiError;
82592
83412
  var init_sdk = __esm(() => {
82593
83413
  init_transport2 = __esm2(() => {
82594
83414
  CredentialResolutionError2 = class CredentialResolutionError3 extends Error {
@@ -82723,7 +83543,7 @@ var init_sdk = __esm(() => {
82723
83543
  });
82724
83544
 
82725
83545
  // src/lib/execution-secrets.ts
82726
- import { constants as constants12, closeSync as closeSync13, fstatSync as fstatSync13, openSync as openSync13, readSync as readSync10, realpathSync as realpathSync6 } from "fs";
83546
+ import { constants as constants14, closeSync as closeSync15, fstatSync as fstatSync15, openSync as openSync15, readSync as readSync12, realpathSync as realpathSync6 } from "fs";
82727
83547
  import { hostname as stationHostname } from "os";
82728
83548
  function selectedSecretBindingsTemplate(scope, names, createClient2 = createSecretsClientFromEnv) {
82729
83549
  let secretsAuthority;
@@ -82747,7 +83567,7 @@ function refuse(code, message) {
82747
83567
  function record7(value) {
82748
83568
  return !!value && typeof value === "object" && !Array.isArray(value);
82749
83569
  }
82750
- function exactKeys(value, keys2) {
83570
+ function exactKeys2(value, keys2) {
82751
83571
  return Object.keys(value).length === keys2.length && keys2.every((key) => Object.hasOwn(value, key));
82752
83572
  }
82753
83573
  function identifier2(value) {
@@ -82767,13 +83587,13 @@ function declaredSecretNames(value) {
82767
83587
  function readSelectedSecretBindings(path) {
82768
83588
  let fd;
82769
83589
  try {
82770
- fd = openSync13(path, constants12.O_RDONLY | constants12.O_NOFOLLOW | constants12.O_NONBLOCK);
82771
- const stat2 = fstatSync13(fd);
83590
+ fd = openSync15(path, constants14.O_RDONLY | constants14.O_NOFOLLOW | constants14.O_NONBLOCK);
83591
+ const stat2 = fstatSync15(fd);
82772
83592
  if (!stat2.isFile() || stat2.size > 65536)
82773
83593
  throw new Error;
82774
83594
  const bytes = Buffer.alloc(65537);
82775
83595
  let size2 = 0, count;
82776
- while ((count = readSync10(fd, bytes, size2, bytes.length - size2, null)) > 0) {
83596
+ while ((count = readSync12(fd, bytes, size2, bytes.length - size2, null)) > 0) {
82777
83597
  size2 += count;
82778
83598
  if (size2 > 65536)
82779
83599
  throw new Error;
@@ -82783,11 +83603,11 @@ function readSelectedSecretBindings(path) {
82783
83603
  return refuse("INVALID_SECRET_BINDINGS", "Secret bindings must be a regular JSON file of at most 64 KiB, containing reference names only.");
82784
83604
  } finally {
82785
83605
  if (fd !== undefined)
82786
- closeSync13(fd);
83606
+ closeSync15(fd);
82787
83607
  }
82788
83608
  }
82789
83609
  function validateSelectedSecretBindings(value, scope, names) {
82790
- if (!record7(value) || !exactKeys(value, ["schema", "selection", "consumer", "secretsAuthority", "bindings"]) || value.schema !== "hasna.skills-secret-bindings.v1" || !record7(value.selection) || !exactKeys(value.selection, ["authority", "workspaceId", "profileId", "profileRevision", "slug", "version", "bundleDigest"]) || !record7(value.consumer) || !exactKeys(value.consumer, ["stationId", "workspaceDirectory"]) || !record7(value.bindings)) {
83610
+ if (!record7(value) || !exactKeys2(value, ["schema", "selection", "consumer", "secretsAuthority", "bindings"]) || value.schema !== "hasna.skills-secret-bindings.v1" || !record7(value.selection) || !exactKeys2(value.selection, ["authority", "workspaceId", "profileId", "profileRevision", "slug", "version", "bundleDigest"]) || !record7(value.consumer) || !exactKeys2(value.consumer, ["stationId", "workspaceDirectory"]) || !record7(value.bindings)) {
82791
83611
  return refuse("INVALID_SECRET_BINDINGS", "Secret bindings do not match the hasna.skills-secret-bindings.v1 contract.");
82792
83612
  }
82793
83613
  for (const [key, expected] of Object.entries({ authority: scope.selection.authority, workspaceId: scope.selection.workspaceId, profileId: scope.profileId, profileRevision: scope.selection.profileRevision, slug: scope.selection.slug, version: scope.selection.version, bundleDigest: scope.selection.bundleDigest })) {
@@ -82812,7 +83632,7 @@ function validateSelectedSecretBindings(value, scope, names) {
82812
83632
  } catch {
82813
83633
  return refuse("INVALID_SECRET_BINDINGS", "Secret bindings require a canonical HTTPS Secrets /v1 authority (loopback HTTP is allowed).");
82814
83634
  }
82815
- if (!exactKeys(value.bindings, names) || Object.values(value.bindings).some((key) => !identifier2(key) || !/^[A-Za-z0-9][A-Za-z0-9._/-]*$/.test(key) || key.split("/").some((part) => !part || part === "." || part === ".."))) {
83635
+ if (!exactKeys2(value.bindings, names) || Object.values(value.bindings).some((key) => !identifier2(key) || !/^[A-Za-z0-9][A-Za-z0-9._/-]*$/.test(key) || key.split("/").some((part) => !part || part === "." || part === ".."))) {
82816
83636
  return refuse("INVALID_SECRET_BINDINGS", "Bind every declared environment name exactly once to a vault key; undeclared bindings and values are refused.");
82817
83637
  }
82818
83638
  return structuredClone(value);
@@ -82990,7 +83810,7 @@ var init_execution_grants = __esm(() => {
82990
83810
  });
82991
83811
 
82992
83812
  // src/lib/execution-grant-client.ts
82993
- import { isDeepStrictEqual as isDeepStrictEqual3 } from "util";
83813
+ import { isDeepStrictEqual as isDeepStrictEqual4 } from "util";
82994
83814
  function id(value) {
82995
83815
  if (!grantIdentifier(value))
82996
83816
  throw new Error("Invalid execution grant profile or revision identifier.");
@@ -83042,7 +83862,7 @@ async function saveExecutionGrantPolicy(profileId, grants, revision) {
83042
83862
  headers: revision === undefined ? { "If-None-Match": "*" } : { "If-Match": `"${revision}"` },
83043
83863
  body: JSON.stringify({ grants: snapshot })
83044
83864
  }));
83045
- if (policy.profileId !== profileId || policy.previousRevision !== (revision ?? null) || !isDeepStrictEqual3(policy.grants, snapshot)) {
83865
+ if (policy.profileId !== profileId || policy.previousRevision !== (revision ?? null) || !isDeepStrictEqual4(policy.grants, snapshot)) {
83046
83866
  throw new Error("The API did not preserve the reviewed execution grant policy; read it before retrying.");
83047
83867
  }
83048
83868
  return policy;
@@ -83053,7 +83873,7 @@ async function resolveExecutionGrant(input2) {
83053
83873
  if (!grantRecord(value) || Object.keys(value).length !== 3 || !grantIdentifier(value.policyRevision) || !grantIdentifier(value.grantId) || !grantRecord(value.bindings)) {
83054
83874
  throw new SkillSelectionError("INVALID_EXECUTION_GRANT", "The Skills API returned an invalid execution grant.");
83055
83875
  }
83056
- if (!isDeepStrictEqual3(value.bindings.selection, snapshot.selection) || !isDeepStrictEqual3(value.bindings.consumer, snapshot.consumer)) {
83876
+ if (!isDeepStrictEqual4(value.bindings.selection, snapshot.selection) || !isDeepStrictEqual4(value.bindings.consumer, snapshot.consumer)) {
83057
83877
  throw new SkillSelectionError("EXECUTION_GRANT_SCOPE_MISMATCH", "The Skills API returned a grant for a different selection or consumer.");
83058
83878
  }
83059
83879
  return value;
@@ -83072,10 +83892,10 @@ __export(exports_selected_run, {
83072
83892
  prepareSelectedSecretBindings: () => prepareSelectedSecretBindings,
83073
83893
  executeSelectedLocal: () => executeSelectedLocal
83074
83894
  });
83075
- import { createHash as createHash16 } from "crypto";
83895
+ import { createHash as createHash19 } from "crypto";
83076
83896
  import { spawn as spawn2 } from "child_process";
83077
83897
  import { mkdirSync as mkdirSync14, mkdtempSync as mkdtempSync4, writeFileSync as writeFileSync13, realpathSync as realpathSync7 } from "fs";
83078
- import { dirname as dirname17, join as join42, resolve as resolve15 } from "path";
83898
+ import { dirname as dirname19, join as join42, resolve as resolve18 } from "path";
83079
83899
  import { tmpdir, hostname as stationHostname2 } from "os";
83080
83900
  async function resolveSelectedRun(spec, profileId, options = {}) {
83081
83901
  const context = await resolveSelectionContext(profileId, options);
@@ -83164,11 +83984,11 @@ async function executeSelectedLocal(selected, options = {}) {
83164
83984
  throw new SkillSelectionError("INVALID_BUNDLE_PATH", "The execution bundle path exceeds its limit.");
83165
83985
  });
83166
83986
  const destination = join42(runDirectory, entry.path);
83167
- mkdirSync14(dirname17(destination), { recursive: true, mode: 448 });
83987
+ mkdirSync14(dirname19(destination), { recursive: true, mode: 448 });
83168
83988
  writeFileSync13(destination, entry.bytes, { flag: "wx", mode: entry.mode & 511 });
83169
83989
  }
83170
83990
  env3.SKILLS_INPUT_JSON = input2;
83171
- env3.SKILLS_WORKSPACE_DIR = resolve15(options.cwd ?? process.cwd());
83991
+ env3.SKILLS_WORKSPACE_DIR = resolve18(options.cwd ?? process.cwd());
83172
83992
  env3.SKILLS_RUN_DIR = runDirectory;
83173
83993
  if (runtime.version) {
83174
83994
  const version2 = await subprocess([executable, ...runtimeName === "bun" ? ["--no-env-file"] : [], "--version"], runDirectory, env3, "", Math.min(timeoutMs, 5000));
@@ -83198,7 +84018,7 @@ async function executeSelectedLocal(selected, options = {}) {
83198
84018
  selection: selection2,
83199
84019
  target: "local",
83200
84020
  runtime: runtimeName,
83201
- inputDigest: `sha256:${createHash16("sha256").update(input2).digest("hex")}`,
84021
+ inputDigest: `sha256:${createHash19("sha256").update(input2).digest("hex")}`,
83202
84022
  runDirectory,
83203
84023
  ...executionGrant ? { executionGrant } : {},
83204
84024
  ...bindings ? { secretBinding: { schema: bindings.schema, selection: bindings.selection, consumer: bindings.consumer, secretsAuthority: bindings.secretsAuthority, bindings: bindings.bindings } } : {},
@@ -87415,7 +88235,7 @@ var init_runs = __esm(() => {
87415
88235
  });
87416
88236
 
87417
88237
  // src/lib/run-state.ts
87418
- import { createHash as createHash17, randomBytes } from "crypto";
88238
+ import { createHash as createHash20, randomBytes } from "crypto";
87419
88239
  import { existsSync as existsSync27, mkdirSync as mkdirSync15, readFileSync as readFileSync30, readdirSync as readdirSync16, statSync as statSync15, writeFileSync as writeFileSync14 } from "fs";
87420
88240
  import { extname, join as join43, relative as relative6 } from "path";
87421
88241
  function createSkillRun(params, targetDir = process.cwd()) {
@@ -87552,7 +88372,7 @@ function collectRunArtifacts(context) {
87552
88372
  artifacts.push({
87553
88373
  path: toProjectRelative(context.targetDir, path),
87554
88374
  mime: mimeForPath(path),
87555
- sha256: createHash17("sha256").update(bytes).digest("hex"),
88375
+ sha256: createHash20("sha256").update(bytes).digest("hex"),
87556
88376
  sizeBytes: stat2.size
87557
88377
  });
87558
88378
  }
@@ -88555,12 +89375,12 @@ class StdioServerTransport {
88555
89375
  this.onclose?.();
88556
89376
  }
88557
89377
  send(message) {
88558
- return new Promise((resolve16) => {
89378
+ return new Promise((resolve19) => {
88559
89379
  const json2 = serializeMessage(message);
88560
89380
  if (this._stdout.write(json2)) {
88561
- resolve16();
89381
+ resolve19();
88562
89382
  } else {
88563
- this._stdout.once("drain", resolve16);
89383
+ this._stdout.once("drain", resolve19);
88564
89384
  }
88565
89385
  });
88566
89386
  }
@@ -88602,7 +89422,7 @@ var init_schemas3 = __esm(() => {
88602
89422
  own(this, "with", value);
88603
89423
  },
88604
89424
  parse(data, params) {
88605
- return parse5(this, data, params, { callee: this.parse });
89425
+ return parse7(this, data, params, { callee: this.parse });
88606
89426
  },
88607
89427
  parseAsync(data, params) {
88608
89428
  return parseAsync(this, data, params, { callee: this.parseAsync });
@@ -90746,7 +91566,7 @@ class Protocol {
90746
91566
  return;
90747
91567
  }
90748
91568
  const pollInterval = task2.pollInterval ?? this._options?.defaultTaskPollInterval ?? 1000;
90749
- await new Promise((resolve16) => setTimeout(resolve16, pollInterval));
91569
+ await new Promise((resolve19) => setTimeout(resolve19, pollInterval));
90750
91570
  options?.signal?.throwIfAborted();
90751
91571
  }
90752
91572
  } catch (error61) {
@@ -90758,7 +91578,7 @@ class Protocol {
90758
91578
  }
90759
91579
  request(request2, resultSchema, options) {
90760
91580
  const { relatedRequestId, resumptionToken, onresumptiontoken, task, relatedTask } = options ?? {};
90761
- return new Promise((resolve16, reject2) => {
91581
+ return new Promise((resolve19, reject2) => {
90762
91582
  const earlyReject = (error61) => {
90763
91583
  reject2(error61);
90764
91584
  };
@@ -90836,7 +91656,7 @@ class Protocol {
90836
91656
  if (!parseResult.success) {
90837
91657
  reject2(parseResult.error);
90838
91658
  } else {
90839
- resolve16(parseResult.data);
91659
+ resolve19(parseResult.data);
90840
91660
  }
90841
91661
  } catch (error61) {
90842
91662
  reject2(error61);
@@ -91027,12 +91847,12 @@ class Protocol {
91027
91847
  interval = task.pollInterval;
91028
91848
  }
91029
91849
  } catch {}
91030
- return new Promise((resolve16, reject2) => {
91850
+ return new Promise((resolve19, reject2) => {
91031
91851
  if (signal.aborted) {
91032
91852
  reject2(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
91033
91853
  return;
91034
91854
  }
91035
- const timeoutId = setTimeout(resolve16, interval);
91855
+ const timeoutId = setTimeout(resolve19, interval);
91036
91856
  signal.addEventListener("abort", () => {
91037
91857
  clearTimeout(timeoutId);
91038
91858
  reject2(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
@@ -91509,11 +92329,11 @@ var require_codegen = __commonJS((exports) => {
91509
92329
  const rhs = this.rhs === undefined ? "" : ` = ${this.rhs}`;
91510
92330
  return `${varKind} ${this.name}${rhs};` + _n;
91511
92331
  }
91512
- optimizeNames(names, constants13) {
92332
+ optimizeNames(names, constants15) {
91513
92333
  if (!names[this.name.str])
91514
92334
  return;
91515
92335
  if (this.rhs)
91516
- this.rhs = optimizeExpr(this.rhs, names, constants13);
92336
+ this.rhs = optimizeExpr(this.rhs, names, constants15);
91517
92337
  return this;
91518
92338
  }
91519
92339
  get names() {
@@ -91531,10 +92351,10 @@ var require_codegen = __commonJS((exports) => {
91531
92351
  render({ _n }) {
91532
92352
  return `${this.lhs} = ${this.rhs};` + _n;
91533
92353
  }
91534
- optimizeNames(names, constants13) {
92354
+ optimizeNames(names, constants15) {
91535
92355
  if (this.lhs instanceof code_1.Name && !names[this.lhs.str] && !this.sideEffects)
91536
92356
  return;
91537
- this.rhs = optimizeExpr(this.rhs, names, constants13);
92357
+ this.rhs = optimizeExpr(this.rhs, names, constants15);
91538
92358
  return this;
91539
92359
  }
91540
92360
  get names() {
@@ -91600,8 +92420,8 @@ var require_codegen = __commonJS((exports) => {
91600
92420
  optimizeNodes() {
91601
92421
  return `${this.code}` ? this : undefined;
91602
92422
  }
91603
- optimizeNames(names, constants13) {
91604
- this.code = optimizeExpr(this.code, names, constants13);
92423
+ optimizeNames(names, constants15) {
92424
+ this.code = optimizeExpr(this.code, names, constants15);
91605
92425
  return this;
91606
92426
  }
91607
92427
  get names() {
@@ -91631,12 +92451,12 @@ var require_codegen = __commonJS((exports) => {
91631
92451
  }
91632
92452
  return nodes.length > 0 ? this : undefined;
91633
92453
  }
91634
- optimizeNames(names, constants13) {
92454
+ optimizeNames(names, constants15) {
91635
92455
  const { nodes } = this;
91636
92456
  let i = nodes.length;
91637
92457
  while (i--) {
91638
92458
  const n2 = nodes[i];
91639
- if (n2.optimizeNames(names, constants13))
92459
+ if (n2.optimizeNames(names, constants15))
91640
92460
  continue;
91641
92461
  subtractNames(names, n2.names);
91642
92462
  nodes.splice(i, 1);
@@ -91693,12 +92513,12 @@ var require_codegen = __commonJS((exports) => {
91693
92513
  return;
91694
92514
  return this;
91695
92515
  }
91696
- optimizeNames(names, constants13) {
92516
+ optimizeNames(names, constants15) {
91697
92517
  var _a3;
91698
- this.else = (_a3 = this.else) === null || _a3 === undefined ? undefined : _a3.optimizeNames(names, constants13);
91699
- if (!(super.optimizeNames(names, constants13) || this.else))
92518
+ this.else = (_a3 = this.else) === null || _a3 === undefined ? undefined : _a3.optimizeNames(names, constants15);
92519
+ if (!(super.optimizeNames(names, constants15) || this.else))
91700
92520
  return;
91701
- this.condition = optimizeExpr(this.condition, names, constants13);
92521
+ this.condition = optimizeExpr(this.condition, names, constants15);
91702
92522
  return this;
91703
92523
  }
91704
92524
  get names() {
@@ -91723,10 +92543,10 @@ var require_codegen = __commonJS((exports) => {
91723
92543
  render(opts) {
91724
92544
  return `for(${this.iteration})` + super.render(opts);
91725
92545
  }
91726
- optimizeNames(names, constants13) {
91727
- if (!super.optimizeNames(names, constants13))
92546
+ optimizeNames(names, constants15) {
92547
+ if (!super.optimizeNames(names, constants15))
91728
92548
  return;
91729
- this.iteration = optimizeExpr(this.iteration, names, constants13);
92549
+ this.iteration = optimizeExpr(this.iteration, names, constants15);
91730
92550
  return this;
91731
92551
  }
91732
92552
  get names() {
@@ -91764,10 +92584,10 @@ var require_codegen = __commonJS((exports) => {
91764
92584
  render(opts) {
91765
92585
  return `for(${this.varKind} ${this.name} ${this.loop} ${this.iterable})` + super.render(opts);
91766
92586
  }
91767
- optimizeNames(names, constants13) {
91768
- if (!super.optimizeNames(names, constants13))
92587
+ optimizeNames(names, constants15) {
92588
+ if (!super.optimizeNames(names, constants15))
91769
92589
  return;
91770
- this.iterable = optimizeExpr(this.iterable, names, constants13);
92590
+ this.iterable = optimizeExpr(this.iterable, names, constants15);
91771
92591
  return this;
91772
92592
  }
91773
92593
  get names() {
@@ -91812,11 +92632,11 @@ var require_codegen = __commonJS((exports) => {
91812
92632
  (_b = this.finally) === null || _b === undefined || _b.optimizeNodes();
91813
92633
  return this;
91814
92634
  }
91815
- optimizeNames(names, constants13) {
92635
+ optimizeNames(names, constants15) {
91816
92636
  var _a3, _b;
91817
- super.optimizeNames(names, constants13);
91818
- (_a3 = this.catch) === null || _a3 === undefined || _a3.optimizeNames(names, constants13);
91819
- (_b = this.finally) === null || _b === undefined || _b.optimizeNames(names, constants13);
92637
+ super.optimizeNames(names, constants15);
92638
+ (_a3 = this.catch) === null || _a3 === undefined || _a3.optimizeNames(names, constants15);
92639
+ (_b = this.finally) === null || _b === undefined || _b.optimizeNames(names, constants15);
91820
92640
  return this;
91821
92641
  }
91822
92642
  get names() {
@@ -92090,7 +92910,7 @@ var require_codegen = __commonJS((exports) => {
92090
92910
  function addExprNames(names, from) {
92091
92911
  return from instanceof code_1._CodeOrName ? addNames(names, from.names) : names;
92092
92912
  }
92093
- function optimizeExpr(expr, names, constants13) {
92913
+ function optimizeExpr(expr, names, constants15) {
92094
92914
  if (expr instanceof code_1.Name)
92095
92915
  return replaceName(expr);
92096
92916
  if (!canOptimize(expr))
@@ -92105,14 +92925,14 @@ var require_codegen = __commonJS((exports) => {
92105
92925
  return items;
92106
92926
  }, []));
92107
92927
  function replaceName(n2) {
92108
- const c = constants13[n2.str];
92928
+ const c = constants15[n2.str];
92109
92929
  if (c === undefined || names[n2.str] !== 1)
92110
92930
  return n2;
92111
92931
  delete names[n2.str];
92112
92932
  return c;
92113
92933
  }
92114
92934
  function canOptimize(e2) {
92115
- return e2 instanceof code_1._Code && e2._items.some((c) => c instanceof code_1.Name && names[c.str] === 1 && constants13[c.str] !== undefined);
92935
+ return e2 instanceof code_1._Code && e2._items.some((c) => c instanceof code_1.Name && names[c.str] === 1 && constants15[c.str] !== undefined);
92116
92936
  }
92117
92937
  }
92118
92938
  function subtractNames(names, from) {
@@ -94017,7 +94837,7 @@ var require_compile = __commonJS((exports) => {
94017
94837
  const schOrFunc = root2.refs[ref];
94018
94838
  if (schOrFunc)
94019
94839
  return schOrFunc;
94020
- let _sch = resolve16.call(this, root2, ref);
94840
+ let _sch = resolve19.call(this, root2, ref);
94021
94841
  if (_sch === undefined) {
94022
94842
  const schema = (_a3 = root2.localRefs) === null || _a3 === undefined ? undefined : _a3[ref];
94023
94843
  const { schemaId } = this.opts;
@@ -94044,7 +94864,7 @@ var require_compile = __commonJS((exports) => {
94044
94864
  function sameSchemaEnv(s1, s2) {
94045
94865
  return s1.schema === s2.schema && s1.root === s2.root && s1.baseId === s2.baseId;
94046
94866
  }
94047
- function resolve16(root2, ref) {
94867
+ function resolve19(root2, ref) {
94048
94868
  let sch;
94049
94869
  while (typeof (sch = this.refs[ref]) == "string")
94050
94870
  ref = sch;
@@ -94842,11 +95662,11 @@ var require_fast_uri = __commonJS((exports, module) => {
94842
95662
  if (typeof uri === "string") {
94843
95663
  uri = normalizeString(uri, options);
94844
95664
  } else if (typeof uri === "object") {
94845
- uri = parse10(serialize(uri, options), options);
95665
+ uri = parse12(serialize(uri, options), options);
94846
95666
  }
94847
95667
  return uri;
94848
95668
  }
94849
- function resolve16(baseURI, relativeURI, options) {
95669
+ function resolve19(baseURI, relativeURI, options) {
94850
95670
  const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
94851
95671
  const {
94852
95672
  parsed: baseParsed,
@@ -94882,8 +95702,8 @@ var require_fast_uri = __commonJS((exports, module) => {
94882
95702
  function resolveComponent(base2, relative7, options, skipNormalization) {
94883
95703
  const target = {};
94884
95704
  if (!skipNormalization) {
94885
- base2 = parse10(serialize(base2, options), options);
94886
- relative7 = parse10(serialize(relative7, options), options);
95705
+ base2 = parse12(serialize(base2, options), options);
95706
+ relative7 = parse12(serialize(relative7, options), options);
94887
95707
  }
94888
95708
  options = options || {};
94889
95709
  if (!options.tolerant && relative7.scheme) {
@@ -95183,7 +96003,7 @@ var require_fast_uri = __commonJS((exports, module) => {
95183
96003
  }
95184
96004
  return { parsed, malformedAuthorityOrPort, malformedPercentEncoding, malformedSchemeSpecific, malformedHost, malformedScheme };
95185
96005
  }
95186
- function parse10(uri, opts) {
96006
+ function parse12(uri, opts) {
95187
96007
  return parseWithStatus(uri, opts).parsed;
95188
96008
  }
95189
96009
  function normalizeString(uri, opts) {
@@ -95216,11 +96036,11 @@ var require_fast_uri = __commonJS((exports, module) => {
95216
96036
  var fastUri = {
95217
96037
  SCHEMES,
95218
96038
  normalize: normalize3,
95219
- resolve: resolve16,
96039
+ resolve: resolve19,
95220
96040
  resolveComponent,
95221
96041
  equal,
95222
96042
  serialize,
95223
- parse: parse10
96043
+ parse: parse12
95224
96044
  };
95225
96045
  module.exports = fastUri;
95226
96046
  module.exports.default = fastUri;
@@ -99002,7 +99822,7 @@ class McpServer {
99002
99822
  let task = createTaskResult.task;
99003
99823
  const pollInterval = task.pollInterval ?? 5000;
99004
99824
  while (task.status !== "completed" && task.status !== "failed" && task.status !== "cancelled") {
99005
- await new Promise((resolve16) => setTimeout(resolve16, pollInterval));
99825
+ await new Promise((resolve19) => setTimeout(resolve19, pollInterval));
99006
99826
  const updatedTask = await extra.taskStore.getTask(taskId);
99007
99827
  if (!updatedTask) {
99008
99828
  throw new McpError(ErrorCode.InternalError, `Task ${taskId} not found during polling`);
@@ -99045,11 +99865,11 @@ class McpServer {
99045
99865
  return EMPTY_COMPLETION_RESULT;
99046
99866
  }
99047
99867
  const promptShape = getObjectShape(prompt.argsSchema);
99048
- const field = promptShape?.[request2.params.argument.name];
99049
- if (!isCompletable(field)) {
99868
+ const field2 = promptShape?.[request2.params.argument.name];
99869
+ if (!isCompletable(field2)) {
99050
99870
  return EMPTY_COMPLETION_RESULT;
99051
99871
  }
99052
- const completer = getCompleter(field);
99872
+ const completer = getCompleter(field2);
99053
99873
  if (!completer) {
99054
99874
  return EMPTY_COMPLETION_RESULT;
99055
99875
  }
@@ -99321,8 +100141,8 @@ class McpServer {
99321
100141
  };
99322
100142
  this._registeredPrompts[name] = registeredPrompt;
99323
100143
  if (argsSchema) {
99324
- const hasCompletable = Object.values(argsSchema).some((field) => {
99325
- const inner = field instanceof ZodOptional ? field._def?.innerType : field;
100144
+ const hasCompletable = Object.values(argsSchema).some((field2) => {
100145
+ const inner = field2 instanceof ZodOptional ? field2._def?.innerType : field2;
99326
100146
  return isCompletable(inner);
99327
100147
  });
99328
100148
  if (hasCompletable) {
@@ -99514,9 +100334,9 @@ function promptArgumentsFromSchema(schema) {
99514
100334
  const shape = getObjectShape(schema);
99515
100335
  if (!shape)
99516
100336
  return [];
99517
- return Object.entries(shape).map(([name, field]) => {
99518
- const description = getSchemaDescription(field);
99519
- const isOptional = isSchemaOptional(field);
100337
+ return Object.entries(shape).map(([name, field2]) => {
100338
+ const description = getSchemaDescription(field2);
100339
+ const isOptional = isSchemaOptional(field2);
99520
100340
  return {
99521
100341
  name,
99522
100342
  description,
@@ -99575,7 +100395,7 @@ var init_remote_customer_operations = __esm(() => {
99575
100395
  { name: "list_remote_skills", title: "List Remote Skills", parameter: null, mutates: false, invoke: (client2) => client2.listSkills() },
99576
100396
  { name: "get_billing_status", title: "Get Billing Status", parameter: null, mutates: false, invoke: (client2) => client2.getBillingStatus() },
99577
100397
  { name: "list_credit_packs", title: "List Credit Packs", parameter: null, mutates: false, invoke: (client2) => client2.listCreditPacks() },
99578
- { name: "create_credit_checkout", title: "Create Credit Checkout", parameter: "pack_id", mutates: true, invoke: (client2, value) => client2.createCreditCheckout(value) },
100398
+ { name: "create_credit_checkout", title: "Create Credit Checkout", parameter: "pack_id", mutates: true, invoke: (client2, value, options) => client2.createCreditCheckout(value, options) },
99579
100399
  { name: "get_billing_usage", title: "Get Billing Usage", parameter: null, mutates: false, invoke: (client2) => client2.getUsage() },
99580
100400
  { name: "list_invoices", title: "List Invoices", parameter: null, mutates: false, invoke: (client2) => client2.listInvoices() },
99581
100401
  { name: "create_billing_checkout", title: "Create Billing Checkout", parameter: null, mutates: true, invoke: (client2) => client2.createBillingCheckout() },
@@ -99689,7 +100509,7 @@ var init_remote_invitation_recovery = __esm(() => {
99689
100509
  });
99690
100510
 
99691
100511
  // src/lib/remote-private-publications.ts
99692
- import { createHash as createHash18 } from "crypto";
100512
+ import { createHash as createHash21 } from "crypto";
99693
100513
  function checkedPublicationDeclaration(value) {
99694
100514
  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)
99695
100515
  return bad();
@@ -99934,12 +100754,12 @@ class RemotePrivatePublicationsClient {
99934
100754
  previous = view;
99935
100755
  if (!["queued", "verifying"].includes(view.state) || Date.now() >= until)
99936
100756
  return view;
99937
- await new Promise((resolve16) => {
100757
+ await new Promise((resolve19) => {
99938
100758
  const timer = setTimeout(done, Math.min(1000, until - Date.now()));
99939
100759
  function done() {
99940
100760
  clearTimeout(timer);
99941
100761
  options.signal?.removeEventListener("abort", done);
99942
- resolve16();
100762
+ resolve19();
99943
100763
  }
99944
100764
  options.signal?.addEventListener("abort", done, { once: true });
99945
100765
  });
@@ -99950,7 +100770,7 @@ var PRIVATE_PUBLICATION_MAX_BYTES, failures2, PrivatePublicationError, bad = ()
99950
100770
  throw new PrivatePublicationError("INVALID_PUBLICATION_INPUT", "Invalid publication input or recovery data.");
99951
100771
  }, invalid5 = () => {
99952
100772
  throw new PrivatePublicationError("INVALID_PUBLICATION_RESPONSE", "The server returned an invalid publication result.");
99953
- }, publicationUuid = (v) => typeof v === "string" && /^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/.test(v), hash3 = (v) => typeof v === "string" && /^[a-f0-9]{64}$/.test(v), record10 = (v) => !!v && typeof v === "object" && !Array.isArray(v), exact = (v, keys3) => record10(v) && Object.keys(v).sort().join(",") === keys3.sort().join(","), date6 = (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)), publicationSha256 = (bytes) => createHash18("sha256").update(bytes).digest("hex");
100773
+ }, publicationUuid = (v) => typeof v === "string" && /^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/.test(v), hash3 = (v) => typeof v === "string" && /^[a-f0-9]{64}$/.test(v), record10 = (v) => !!v && typeof v === "object" && !Array.isArray(v), exact = (v, keys3) => record10(v) && Object.keys(v).sort().join(",") === keys3.sort().join(","), date6 = (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)), publicationSha256 = (bytes) => createHash21("sha256").update(bytes).digest("hex");
99954
100774
  var init_remote_private_publications = __esm(() => {
99955
100775
  init_fleet_credentials();
99956
100776
  init_remote_workspace_selection();
@@ -100227,11 +101047,11 @@ var init_remote_auth = __esm(() => {
100227
101047
  });
100228
101048
 
100229
101049
  // src/lib/workspace-profile.ts
100230
- import { constants as constants13, closeSync as closeSync14, fstatSync as fstatSync14, lstatSync as lstatSync20, mkdirSync as mkdirSync16, mkdtempSync as mkdtempSync5, openSync as openSync14, readFileSync as readFileSync31, renameSync as renameSync9, rmSync as rmSync8, writeFileSync as writeFileSync15 } from "fs";
100231
- import { dirname as dirname18, join as join44 } from "path";
101050
+ import { constants as constants15, closeSync as closeSync16, fstatSync as fstatSync16, lstatSync as lstatSync22, mkdirSync as mkdirSync16, mkdtempSync as mkdtempSync5, openSync as openSync16, readFileSync as readFileSync31, renameSync as renameSync9, rmSync as rmSync8, writeFileSync as writeFileSync15 } from "fs";
101051
+ import { dirname as dirname20, join as join44 } from "path";
100232
101052
  function stat2(path) {
100233
101053
  try {
100234
- return lstatSync20(path);
101054
+ return lstatSync22(path);
100235
101055
  } catch (error61) {
100236
101056
  if (error61.code === "ENOENT")
100237
101057
  return null;
@@ -100241,14 +101061,14 @@ function stat2(path) {
100241
101061
  function safeText(file2) {
100242
101062
  if (stat2(file2) === null)
100243
101063
  return null;
100244
- const fd = openSync14(file2, constants13.O_RDONLY | constants13.O_NOFOLLOW | constants13.O_NONBLOCK);
101064
+ const fd = openSync16(file2, constants15.O_RDONLY | constants15.O_NOFOLLOW | constants15.O_NONBLOCK);
100245
101065
  try {
100246
- const s = fstatSync14(fd);
101066
+ const s = fstatSync16(fd);
100247
101067
  if (!s.isFile() || s.size > 65536 || ![256, 384].includes(s.mode & 4095) || process.getuid && s.uid !== process.getuid())
100248
101068
  return fail2("The selected profile must use bounded owner-only regular files.");
100249
101069
  return readFileSync31(fd, "utf8");
100250
101070
  } finally {
100251
- closeSync14(fd);
101071
+ closeSync16(fd);
100252
101072
  }
100253
101073
  }
100254
101074
  function checkIdentityMetadata(file2, identity4) {
@@ -100313,18 +101133,18 @@ async function prepareWorkspaceEnrollment(membershipId, source = process.env) {
100313
101133
  `);
100314
101134
  if (Buffer.byteLength(credentialBody("x".repeat(8192)), "utf8") > 65536)
100315
101135
  return fail2("The selected profile has insufficient space for a bounded credential. Reduce its unrelated configuration before signing in.");
100316
- const parents = [];
100317
- for (let path = dirname18(file2);; path = dirname18(path)) {
101136
+ const parents3 = [];
101137
+ for (let path = dirname20(file2);; path = dirname20(path)) {
100318
101138
  const before2 = stat2(path);
100319
101139
  if (before2 && (!before2.isDirectory() || before2.isSymbolicLink()))
100320
101140
  return fail2("The profile directory must not be a symbolic link.");
100321
- parents.push([path, before2]);
100322
- if (path === dirname18(path))
101141
+ parents3.push([path, before2]);
101142
+ if (path === dirname20(path))
100323
101143
  break;
100324
101144
  }
100325
101145
  const unchanged2 = () => {
100326
101146
  unchangedFiles();
100327
- for (const [path, before2] of parents) {
101147
+ for (const [path, before2] of parents3) {
100328
101148
  const now3 = stat2(path);
100329
101149
  if (!before2 ? now3 !== null : !now3 || !now3.isDirectory() || before2.dev !== now3.dev || before2.ino !== now3.ino)
100330
101150
  changed();
@@ -100378,14 +101198,14 @@ async function prepareWorkspaceEnrollment(membershipId, source = process.env) {
100378
101198
  return fail2("The new profile exceeds the credential reader size limit.");
100379
101199
  const identity4 = JSON.stringify({ email: verified.user.email, userId: verified.user.id, orgId: verified.organization.id, orgSlug: verified.organization.slug, apiUrl: origin }, null, 2) + `
100380
101200
  `;
100381
- mkdirSync16(dirname18(file2), { recursive: true, mode: 448 });
100382
- const temp = mkdtempSync5(join44(dirname18(file2), ".workspace-login-"));
101201
+ mkdirSync16(dirname20(file2), { recursive: true, mode: 448 });
101202
+ const temp = mkdtempSync5(join44(dirname20(file2), ".workspace-login-"));
100383
101203
  let identityInstalled = false;
100384
101204
  try {
100385
101205
  writeFileSync15(join44(temp, "credentials"), body, { mode: 384, flag: "wx" });
100386
101206
  writeFileSync15(join44(temp, "identity"), identity4, { mode: 384, flag: "wx" });
100387
101207
  unchangedFiles();
100388
- for (const [path, before2] of parents) {
101208
+ for (const [path, before2] of parents3) {
100389
101209
  const now3 = stat2(path);
100390
101210
  if (!now3 || !now3.isDirectory() || now3.isSymbolicLink() || before2 && (before2.dev !== now3.dev || before2.ino !== now3.ino))
100391
101211
  changed();
@@ -100595,8 +101415,8 @@ var init_recurring_customer = __esm(() => {
100595
101415
  });
100596
101416
 
100597
101417
  // src/lib/recurring-recovery.ts
100598
- import { constants as constants14, closeSync as closeSync15, fsyncSync as fsyncSync3, fstatSync as fstatSync15, lstatSync as lstatSync21, mkdirSync as mkdirSync17, openSync as openSync15, readSync as readSync11, realpathSync as realpathSync8, renameSync as renameSync10, unlinkSync as unlinkSync6, writeFileSync as writeFileSync16 } from "fs";
100599
- import { dirname as dirname19, isAbsolute as isAbsolute14, join as join45, resolve as resolve16 } from "path";
101418
+ import { constants as constants16, closeSync as closeSync17, fsyncSync as fsyncSync4, fstatSync as fstatSync17, lstatSync as lstatSync23, mkdirSync as mkdirSync17, openSync as openSync17, readSync as readSync13, realpathSync as realpathSync8, renameSync as renameSync10, unlinkSync as unlinkSync6, writeFileSync as writeFileSync16 } from "fs";
101419
+ import { dirname as dirname21, isAbsolute as isAbsolute17, join as join45, resolve as resolve19 } from "path";
100600
101420
  import { randomUUID as randomUUID7 } from "crypto";
100601
101421
 
100602
101422
  class RecoveryOwner {
@@ -100604,14 +101424,14 @@ class RecoveryOwner {
100604
101424
  parents = [];
100605
101425
  constructor(directory) {
100606
101426
  this.directory = directory;
100607
- if (!isAbsolute14(directory) || resolve16(directory) !== directory || realpathSync8(directory) !== directory)
101427
+ if (!isAbsolute17(directory) || resolve19(directory) !== directory || realpathSync8(directory) !== directory)
100608
101428
  invalid6();
100609
- for (let path = directory;; path = dirname19(path)) {
100610
- const stat3 = lstatSync21(path);
101429
+ for (let path = directory;; path = dirname21(path)) {
101430
+ const stat3 = lstatSync23(path);
100611
101431
  if (!stat3.isDirectory() || stat3.isSymbolicLink())
100612
101432
  invalid6();
100613
101433
  this.parents.push({ path, dev: stat3.dev, ino: stat3.ino });
100614
- if (path === dirname19(path))
101434
+ if (path === dirname21(path))
100615
101435
  break;
100616
101436
  }
100617
101437
  this.assert();
@@ -100620,59 +101440,59 @@ class RecoveryOwner {
100620
101440
  if (realpathSync8(this.directory) !== this.directory)
100621
101441
  invalid6();
100622
101442
  for (const prior of this.parents) {
100623
- const now3 = lstatSync21(prior.path);
101443
+ const now3 = lstatSync23(prior.path);
100624
101444
  if (!now3.isDirectory() || now3.isSymbolicLink() || now3.dev !== prior.dev || now3.ino !== prior.ino)
100625
101445
  invalid6();
100626
101446
  }
100627
- const own2 = lstatSync21(this.directory);
101447
+ const own2 = lstatSync23(this.directory);
100628
101448
  if ((own2.mode & 511) !== 448 || (own2.mode & 3584) !== 0 || process.getuid && own2.uid !== process.getuid())
100629
101449
  invalid6();
100630
101450
  }
100631
101451
  read(name) {
100632
101452
  this.assert();
100633
- const fd = openSync15(join45(this.directory, name), constants14.O_RDONLY | constants14.O_NOFOLLOW | constants14.O_NONBLOCK);
101453
+ const fd = openSync17(join45(this.directory, name), constants16.O_RDONLY | constants16.O_NOFOLLOW | constants16.O_NONBLOCK);
100634
101454
  try {
100635
- const before2 = fstatSync15(fd);
101455
+ const before2 = fstatSync17(fd);
100636
101456
  if (!before2.isFile() || before2.nlink !== 1 || (before2.mode & 4095) !== 384 || before2.size < 1 || before2.size > 8192 || process.getuid && before2.uid !== process.getuid())
100637
101457
  invalid6();
100638
101458
  const bytes = Buffer.alloc(before2.size + 1);
100639
101459
  let size2 = 0;
100640
101460
  while (size2 < bytes.length) {
100641
- const n2 = readSync11(fd, bytes, size2, bytes.length - size2, size2);
101461
+ const n2 = readSync13(fd, bytes, size2, bytes.length - size2, size2);
100642
101462
  if (!n2)
100643
101463
  break;
100644
101464
  size2 += n2;
100645
101465
  }
100646
- const after2 = fstatSync15(fd), path = lstatSync21(join45(this.directory, name));
101466
+ const after2 = fstatSync17(fd), path = lstatSync23(join45(this.directory, name));
100647
101467
  if (size2 !== before2.size || after2.size !== before2.size || before2.mtimeMs !== after2.mtimeMs || before2.ctimeMs !== after2.ctimeMs || path.dev !== before2.dev || path.ino !== before2.ino || !path.isFile() || path.isSymbolicLink())
100648
101468
  invalid6();
100649
101469
  this.assert();
100650
101470
  return new TextDecoder("utf-8", { fatal: true }).decode(bytes.subarray(0, size2));
100651
101471
  } finally {
100652
- closeSync15(fd);
101472
+ closeSync17(fd);
100653
101473
  }
100654
101474
  }
100655
101475
  write(name, value) {
100656
101476
  this.assert();
100657
101477
  const bytes = canonicalJson2(value, 8192) + `
100658
101478
  `;
100659
- const fd = openSync15(join45(this.directory, name), constants14.O_WRONLY | constants14.O_CREAT | constants14.O_EXCL | constants14.O_NOFOLLOW, 384);
101479
+ const fd = openSync17(join45(this.directory, name), constants16.O_WRONLY | constants16.O_CREAT | constants16.O_EXCL | constants16.O_NOFOLLOW, 384);
100660
101480
  try {
100661
101481
  writeFileSync16(fd, bytes);
100662
- fsyncSync3(fd);
101482
+ fsyncSync4(fd);
100663
101483
  } finally {
100664
- closeSync15(fd);
101484
+ closeSync17(fd);
100665
101485
  }
100666
101486
  this.assert();
100667
101487
  this.sync();
100668
101488
  }
100669
101489
  sync() {
100670
101490
  this.assert();
100671
- const fd = openSync15(this.directory, constants14.O_RDONLY | constants14.O_NOFOLLOW);
101491
+ const fd = openSync17(this.directory, constants16.O_RDONLY | constants16.O_NOFOLLOW);
100672
101492
  try {
100673
- fsyncSync3(fd);
101493
+ fsyncSync4(fd);
100674
101494
  } finally {
100675
- closeSync15(fd);
101495
+ closeSync17(fd);
100676
101496
  }
100677
101497
  }
100678
101498
  saveState(state, expected) {
@@ -100690,20 +101510,20 @@ class RecoveryOwner {
100690
101510
  this.assert();
100691
101511
  let fd;
100692
101512
  try {
100693
- fd = openSync15(join45(this.directory, "operation.lock"), constants14.O_WRONLY | constants14.O_CREAT | constants14.O_EXCL | constants14.O_NOFOLLOW, 384);
101513
+ fd = openSync17(join45(this.directory, "operation.lock"), constants16.O_WRONLY | constants16.O_CREAT | constants16.O_EXCL | constants16.O_NOFOLLOW, 384);
100694
101514
  } catch {
100695
101515
  throw new RecurringCustomerError("RECURRING_RECOVERY_BUSY", "Recovery is locked. Confirm the original process has stopped before explicitly reconciling the retained lock; no request was retried.");
100696
101516
  }
100697
- const owner2 = fstatSync15(fd);
101517
+ const owner2 = fstatSync17(fd);
100698
101518
  try {
100699
101519
  writeFileSync16(fd, JSON.stringify({ pid: process.pid }));
100700
- fsyncSync3(fd);
101520
+ fsyncSync4(fd);
100701
101521
  this.sync();
100702
101522
  return await action();
100703
101523
  } finally {
100704
- closeSync15(fd);
101524
+ closeSync17(fd);
100705
101525
  this.assert();
100706
- const now3 = lstatSync21(join45(this.directory, "operation.lock"));
101526
+ const now3 = lstatSync23(join45(this.directory, "operation.lock"));
100707
101527
  if (owner2.dev !== now3.dev || owner2.ino !== now3.ino || !now3.isFile() || now3.isSymbolicLink())
100708
101528
  invalid6();
100709
101529
  unlinkSync6(join45(this.directory, "operation.lock"));
@@ -100739,7 +101559,7 @@ function base2(customer, organizationId) {
100739
101559
  };
100740
101560
  }
100741
101561
  function create3(directory, intent) {
100742
- if (!isAbsolute14(directory) || resolve16(directory) !== directory || realpathSync8(dirname19(directory)) !== dirname19(directory))
101562
+ if (!isAbsolute17(directory) || resolve19(directory) !== directory || realpathSync8(dirname21(directory)) !== dirname21(directory))
100743
101563
  invalid6();
100744
101564
  mkdirSync17(directory, { mode: 448 });
100745
101565
  const owner2 = new RecoveryOwner(directory), checked = intentSchema.parse(intent), intentSha256 = canonicalJsonSha256(checked);
@@ -100902,7 +101722,7 @@ var init_recurring_recovery = __esm(() => {
100902
101722
  });
100903
101723
 
100904
101724
  // src/lib/recurring-surface.ts
100905
- import { isAbsolute as isAbsolute15 } from "path";
101725
+ import { isAbsolute as isAbsolute18 } from "path";
100906
101726
  function recurringMcpSchema(action) {
100907
101727
  return action === "activate" ? recurringSurfaceSchemas.activate.extend({ code, confirm: exports_external.literal(true) }) : recurringSurfaceSchemas[action];
100908
101728
  }
@@ -101007,7 +101827,7 @@ var init_recurring_surface = __esm(() => {
101007
101827
  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}$/);
101008
101828
  context = { userId: uuid13.optional(), membershipId: uuid13.optional() };
101009
101829
  page2 = { limit: exports_external.number().int().min(1).max(100).optional(), cursor: exports_external.string().min(1).max(2048).optional() };
101010
- directory = exports_external.string().max(4096).refine(isAbsolute15, "Use an absolute recovery directory");
101830
+ directory = exports_external.string().max(4096).refine(isAbsolute18, "Use an absolute recovery directory");
101011
101831
  email4 = exports_external.string().trim().toLowerCase().email().max(254);
101012
101832
  code = exports_external.string().regex(/^\d{6}$/);
101013
101833
  recurringSurfaceSchemas = {
@@ -101976,11 +102796,11 @@ var init_mcp_contracts = __esm(() => {
101976
102796
  name: operation.name,
101977
102797
  title: operation.title,
101978
102798
  description: `${operation.title} on the configured server; unavailable capabilities fail explicitly.`,
101979
- params: operation.parameter ? [operation.parameter] : [],
102799
+ params: operation.parameter ? [operation.parameter, ...operation.name === "create_credit_checkout" ? ["idempotency_key?"] : []] : [],
101980
102800
  category: "execution",
101981
102801
  sideEffects: operation.mutates ? "local-process-or-remote-run" : "none",
101982
102802
  stable: true,
101983
- inputSchema: objectSchema(operation.parameter ? { [operation.parameter]: stringSchema("Server resource identifier.") } : {}, operation.parameter ? [operation.parameter] : []),
102803
+ inputSchema: objectSchema(operation.parameter ? { [operation.parameter]: stringSchema("Server resource identifier."), ...operation.name === "create_credit_checkout" ? { idempotency_key: { type: "string", pattern: "^[A-Za-z0-9._:-]{8,255}$", description: "Caller-owned key retained before submission; reuse only for explicit recovery of the same server/account/pack." } } : {} } : {}, operation.parameter ? [operation.parameter] : []),
101984
102804
  outputSchema: { oneOf: [objectSchema({}, [], "Server response.", true), { type: "array", items: objectSchema({}, [], "Server record.", true) }] }
101985
102805
  }));
101986
102806
  remoteCustomerContracts.push({
@@ -102913,14 +103733,14 @@ var init_operation_tools = __esm(() => {
102913
103733
 
102914
103734
  // src/lib/feedback.ts
102915
103735
  import { appendFileSync as appendFileSync2, existsSync as existsSync29, mkdirSync as mkdirSync18 } from "fs";
102916
- import { dirname as dirname20, join as join47 } from "path";
103736
+ import { dirname as dirname22, join as join47 } from "path";
102917
103737
  import { Database } from "bun:sqlite";
102918
103738
  function getFeedbackDbPath() {
102919
103739
  return join47(getDataDir(), "skills.db");
102920
103740
  }
102921
103741
  function getFeedbackDb() {
102922
103742
  const dbPath = getFeedbackDbPath();
102923
- const dir = dirname20(dbPath);
103743
+ const dir = dirname22(dbPath);
102924
103744
  if (!existsSync29(dir))
102925
103745
  mkdirSync18(dir, { recursive: true });
102926
103746
  const db = new Database(dbPath);
@@ -102949,7 +103769,7 @@ function saveFeedback(input2) {
102949
103769
  const category = input2.category ?? "general";
102950
103770
  if (isApiMode()) {
102951
103771
  const path = join47(getDataDir(), "feedback.jsonl");
102952
- const dir = dirname20(path);
103772
+ const dir = dirname22(path);
102953
103773
  if (!existsSync29(dir))
102954
103774
  mkdirSync18(dir, { recursive: true });
102955
103775
  appendFileSync2(path, JSON.stringify({ message, category, email: input2.email ?? null, agent: input2.agent ?? null, version: input2.version ?? null, createdAt: new Date().toISOString() }) + `
@@ -103427,7 +104247,7 @@ var init_schedule_tools = __esm(() => {
103427
104247
  });
103428
104248
 
103429
104249
  // src/lib/native-storage.ts
103430
- import { createHash as createHash19, createHmac as createHmac3 } from "crypto";
104250
+ import { createHash as createHash22, createHmac as createHmac3 } from "crypto";
103431
104251
  import {
103432
104252
  existsSync as existsSync31,
103433
104253
  mkdirSync as mkdirSync20,
@@ -103436,7 +104256,7 @@ import {
103436
104256
  statSync as statSync17,
103437
104257
  writeFileSync as writeFileSync18
103438
104258
  } from "fs";
103439
- import { dirname as dirname21, join as join49, normalize as normalize3, relative as relative7, sep as sep7 } from "path";
104259
+ import { dirname as dirname23, join as join49, normalize as normalize3, relative as relative7, sep as sep7 } from "path";
103440
104260
  function resolveSkillsNativeStorageConfig(env3 = process.env) {
103441
104261
  assertNoRetiredModeEnvVars(env3, {
103442
104262
  app: SKILLS_ENV_NAMESPACE,
@@ -103504,7 +104324,7 @@ function exportSkillsLocalSnapshot(targetDir = process.cwd(), options = {}) {
103504
104324
  files.push({
103505
104325
  path: relativePath,
103506
104326
  sizeBytes: bytes.byteLength,
103507
- sha256: createHash19("sha256").update(bytes).digest("hex"),
104327
+ sha256: createHash22("sha256").update(bytes).digest("hex"),
103508
104328
  ...options.includeFileContents ? { contentBase64: Buffer.from(bytes).toString("base64") } : {}
103509
104329
  });
103510
104330
  }
@@ -103796,20 +104616,20 @@ var init_private_publication_customer = __esm(() => {
103796
104616
  });
103797
104617
 
103798
104618
  // src/lib/private-publication-recovery.ts
103799
- import { constants as constants15, closeSync as closeSync16, fsyncSync as fsyncSync4, fstatSync as fstatSync16, lstatSync as lstatSync22, mkdirSync as mkdirSync21, openSync as openSync16, readSync as readSync12, realpathSync as realpathSync9, renameSync as renameSync11, unlinkSync as unlinkSync7, writeFileSync as writeFileSync19 } from "fs";
103800
- import { dirname as dirname22, isAbsolute as isAbsolute16, join as join50, resolve as resolve17 } from "path";
104619
+ import { constants as constants17, closeSync as closeSync18, fsyncSync as fsyncSync5, fstatSync as fstatSync18, lstatSync as lstatSync24, mkdirSync as mkdirSync21, openSync as openSync18, readSync as readSync14, realpathSync as realpathSync9, renameSync as renameSync11, unlinkSync as unlinkSync7, writeFileSync as writeFileSync19 } from "fs";
104620
+ import { dirname as dirname24, isAbsolute as isAbsolute19, join as join50, resolve as resolve20 } from "path";
103801
104621
  import { randomUUID as randomUUID8 } from "crypto";
103802
104622
  function safeDirectory(directory2) {
103803
- if (!isAbsolute16(directory2) || directory2 !== resolve17(directory2) || realpathSync9(directory2) !== directory2)
104623
+ if (!isAbsolute19(directory2) || directory2 !== resolve20(directory2) || realpathSync9(directory2) !== directory2)
103804
104624
  return fail3();
103805
- for (let path = directory2;; path = dirname22(path)) {
103806
- const stat3 = lstatSync22(path);
104625
+ for (let path = directory2;; path = dirname24(path)) {
104626
+ const stat3 = lstatSync24(path);
103807
104627
  if (!stat3.isDirectory() || stat3.isSymbolicLink())
103808
104628
  return fail3();
103809
- if (path === dirname22(path))
104629
+ if (path === dirname24(path))
103810
104630
  break;
103811
104631
  }
103812
- const own2 = lstatSync22(directory2);
104632
+ const own2 = lstatSync24(directory2);
103813
104633
  if ((own2.mode & 63) !== 0 || process.getuid && own2.uid !== process.getuid())
103814
104634
  return fail3();
103815
104635
  return { dev: own2.dev, ino: own2.ino };
@@ -103821,35 +104641,35 @@ function unchangedDirectory(directory2, identity4) {
103821
104641
  }
103822
104642
  function readOwned(directory2, name, max2) {
103823
104643
  const identity4 = safeDirectory(directory2), file2 = join50(directory2, name);
103824
- const fd = openSync16(file2, constants15.O_RDONLY | constants15.O_NOFOLLOW);
104644
+ const fd = openSync18(file2, constants17.O_RDONLY | constants17.O_NOFOLLOW);
103825
104645
  try {
103826
- const stat3 = fstatSync16(fd);
104646
+ const stat3 = fstatSync18(fd);
103827
104647
  if (!stat3.isFile() || stat3.nlink !== 1 || stat3.size > max2 || stat3.size < 1 || (stat3.mode & 63) !== 0 || process.getuid && stat3.uid !== process.getuid())
103828
104648
  return fail3();
103829
104649
  const buffer = Buffer.alloc(Math.min(max2, stat3.size) + 1);
103830
104650
  let length = 0;
103831
104651
  while (length < buffer.length) {
103832
- const count = readSync12(fd, buffer, length, buffer.length - length, length);
104652
+ const count = readSync14(fd, buffer, length, buffer.length - length, length);
103833
104653
  if (count === 0)
103834
104654
  break;
103835
104655
  length += count;
103836
104656
  }
103837
- const bytes = buffer.subarray(0, length), after2 = fstatSync16(fd);
104657
+ const bytes = buffer.subarray(0, length), after2 = fstatSync18(fd);
103838
104658
  unchangedDirectory(directory2, identity4);
103839
104659
  if (bytes.length !== stat3.size || stat3.size !== after2.size || stat3.mtimeMs !== after2.mtimeMs || stat3.ctimeMs !== after2.ctimeMs)
103840
104660
  return fail3();
103841
104661
  return bytes;
103842
104662
  } finally {
103843
- closeSync16(fd);
104663
+ closeSync18(fd);
103844
104664
  }
103845
104665
  }
103846
104666
  function writeOwned(directory2, name, bytes) {
103847
- const fd = openSync16(join50(directory2, name), constants15.O_WRONLY | constants15.O_CREAT | constants15.O_EXCL | constants15.O_NOFOLLOW, 384);
104667
+ const fd = openSync18(join50(directory2, name), constants17.O_WRONLY | constants17.O_CREAT | constants17.O_EXCL | constants17.O_NOFOLLOW, 384);
103848
104668
  try {
103849
104669
  writeFileSync19(fd, bytes);
103850
- fsyncSync4(fd);
104670
+ fsyncSync5(fd);
103851
104671
  } finally {
103852
- closeSync16(fd);
104672
+ closeSync18(fd);
103853
104673
  }
103854
104674
  }
103855
104675
  function save(directory2, value) {
@@ -103858,11 +104678,11 @@ function save(directory2, value) {
103858
104678
  `);
103859
104679
  unchangedDirectory(directory2, identity4);
103860
104680
  renameSync11(join50(directory2, temporary), join50(directory2, "receipt.json"));
103861
- const fd = openSync16(directory2, constants15.O_RDONLY | constants15.O_NOFOLLOW);
104681
+ const fd = openSync18(directory2, constants17.O_RDONLY | constants17.O_NOFOLLOW);
103862
104682
  try {
103863
- fsyncSync4(fd);
104683
+ fsyncSync5(fd);
103864
104684
  } finally {
103865
- closeSync16(fd);
104685
+ closeSync18(fd);
103866
104686
  }
103867
104687
  }
103868
104688
  function bind2(client2, receipt) {
@@ -103873,20 +104693,20 @@ async function locked(directory2, action) {
103873
104693
  const identity4 = safeDirectory(directory2), file2 = join50(directory2, "operation.lock");
103874
104694
  let fd;
103875
104695
  try {
103876
- fd = openSync16(file2, constants15.O_WRONLY | constants15.O_CREAT | constants15.O_EXCL | constants15.O_NOFOLLOW, 384);
104696
+ fd = openSync18(file2, constants17.O_WRONLY | constants17.O_CREAT | constants17.O_EXCL | constants17.O_NOFOLLOW, 384);
103877
104697
  } catch {
103878
104698
  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.");
103879
104699
  }
103880
- const lock = fstatSync16(fd);
104700
+ const lock = fstatSync18(fd);
103881
104701
  try {
103882
104702
  writeFileSync19(fd, JSON.stringify({ pid: process.pid }) + `
103883
104703
  `);
103884
- fsyncSync4(fd);
104704
+ fsyncSync5(fd);
103885
104705
  return await action();
103886
104706
  } finally {
103887
- closeSync16(fd);
104707
+ closeSync18(fd);
103888
104708
  unchangedDirectory(directory2, identity4);
103889
- const now3 = lstatSync22(file2);
104709
+ const now3 = lstatSync24(file2);
103890
104710
  if (now3.dev !== lock.dev || now3.ino !== lock.ino || !now3.isFile() || now3.isSymbolicLink())
103891
104711
  fail3();
103892
104712
  unlinkSync7(file2);
@@ -103938,15 +104758,15 @@ async function preparePrivatePublication(client2, sourceDirectory, recoveryDirec
103938
104758
  phase: "prepared",
103939
104759
  intent: null
103940
104760
  };
103941
- if (!isAbsolute16(recoveryDirectory) || resolve17(recoveryDirectory) !== recoveryDirectory || realpathSync9(dirname22(recoveryDirectory)) !== dirname22(recoveryDirectory))
104761
+ if (!isAbsolute19(recoveryDirectory) || resolve20(recoveryDirectory) !== recoveryDirectory || realpathSync9(dirname24(recoveryDirectory)) !== dirname24(recoveryDirectory))
103942
104762
  return fail3();
103943
104763
  mkdirSync21(recoveryDirectory, { mode: 448 });
103944
104764
  safeDirectory(recoveryDirectory);
103945
- const parent = openSync16(dirname22(recoveryDirectory), constants15.O_RDONLY | constants15.O_NOFOLLOW);
104765
+ const parent = openSync18(dirname24(recoveryDirectory), constants17.O_RDONLY | constants17.O_NOFOLLOW);
103946
104766
  try {
103947
- fsyncSync4(parent);
104767
+ fsyncSync5(parent);
103948
104768
  } finally {
103949
- closeSync16(parent);
104769
+ closeSync18(parent);
103950
104770
  }
103951
104771
  writeOwned(recoveryDirectory, "bundle.tgz", packed.bytes);
103952
104772
  save(recoveryDirectory, receipt);
@@ -104039,10 +104859,10 @@ var init_private_publication_recovery = __esm(() => {
104039
104859
  });
104040
104860
 
104041
104861
  // src/mcp/private-publication-tools.ts
104042
- import { isAbsolute as isAbsolute17 } from "path";
104862
+ import { isAbsolute as isAbsolute20 } from "path";
104043
104863
  function registerPrivatePublicationTools(server) {
104044
104864
  const uuid9 = exports_external.string().regex(/^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/);
104045
- const directory2 = exports_external.string().max(4096).refine(isAbsolute17, "Use an absolute local directory");
104865
+ const directory2 = exports_external.string().max(4096).refine(isAbsolute20, "Use an absolute local directory");
104046
104866
  const verification2 = { email: exports_external.string().email().max(254), code: exports_external.string().regex(/^\d{6}$/), userId: uuid9, membershipId: uuid9, recoveryDirectory: directory2 };
104047
104867
  const description = "Manage a private source publication using fresh workspace-bound verification and a host-local recovery directory. Publishing requires explicit UUID current-version comparison and upload consent. Resume reuses immutable saved bytes and intent; an uncertain PUT is finalized for server verification, never uploaded twice. Sessions and signed URLs are not returned or persisted. Private execution is unavailable. Host request history may contain the supplied verification code.";
104048
104868
  const handler = (action) => async (value) => {
@@ -104197,6 +105017,14 @@ function registerRemoteCustomerTools(server) {
104197
105017
  });
104198
105018
  }
104199
105019
  for (const operation of REMOTE_CUSTOMER_OPERATIONS) {
105020
+ if (operation.name === "create_credit_checkout") {
105021
+ server.registerTool(operation.name, {
105022
+ title: operation.title,
105023
+ description: "Create one external checkout link on the selected Skills server. Retain an idempotency_key before calling and reuse it only for explicit recovery on the same server, account and pack. No automatic retries; payment requires customer confirmation.",
105024
+ inputSchema: { pack_id: exports_external.string().min(1), idempotency_key: exports_external.string().regex(/^[A-Za-z0-9._:-]{8,255}$/).optional() }
105025
+ }, ({ pack_id, idempotency_key }) => callRemote((client2) => operation.invoke(client2, pack_id, { idempotencyKey: idempotency_key })));
105026
+ continue;
105027
+ }
104200
105028
  const inputSchema = {};
104201
105029
  if (operation.parameter)
104202
105030
  inputSchema[operation.parameter] = exports_external.string().min(1);
@@ -104273,6 +105101,15 @@ async function callRemote(action) {
104273
105101
  return mcpError("AUTH_REQUIRED", "Configure a Skills API and sign in with skills auth login");
104274
105102
  return mcpJson(await action(client2));
104275
105103
  } catch (error61) {
105104
+ if (error61 instanceof RemoteCreditCheckoutError) {
105105
+ return { ...mcpJson({
105106
+ code: error61.code,
105107
+ message: error61.message,
105108
+ status: error61.status,
105109
+ requestIdempotencyKey: error61.requestIdempotencyKey,
105110
+ ...error61.retryAfterSeconds === undefined ? {} : { retryAfterSeconds: error61.retryAfterSeconds }
105111
+ }), isError: true };
105112
+ }
104276
105113
  if (error61 instanceof RemoteCapabilityUnavailableError) {
104277
105114
  return { ...mcpJson({ code: error61.code, message: error61.message, status: error61.status }), isError: true };
104278
105115
  }
@@ -104385,7 +105222,7 @@ var init_mcp2 = __esm(() => {
104385
105222
  // src/cli/commands/runtime-mcp.ts
104386
105223
  import { existsSync as existsSync32, mkdirSync as mkdirSync22, readFileSync as readFileSync34, writeFileSync as writeFileSync20 } from "fs";
104387
105224
  import { homedir as homedir9 } from "os";
104388
- import { dirname as dirname23, join as join51 } from "path";
105225
+ import { dirname as dirname25, join as join51 } from "path";
104389
105226
  async function handleMcp(options) {
104390
105227
  if (options.register) {
104391
105228
  let agents;
@@ -104559,7 +105396,7 @@ function writeJsonObject(path, data) {
104559
105396
  `);
104560
105397
  }
104561
105398
  function writeTextFile(path, content) {
104562
- mkdirSync22(dirname23(path), { recursive: true });
105399
+ mkdirSync22(dirname25(path), { recursive: true });
104563
105400
  writeFileSync20(path, content.endsWith(`
104564
105401
  `) ? content : `${content}
104565
105402
  `);
@@ -104622,7 +105459,7 @@ function registerRemoteAccount(parent) {
104622
105459
  billing.command("portal").option("--json", "Output as JSON", false).description("Create an external customer billing portal link").action((options) => execute(options, (client2) => client2.createBillingPortal()));
104623
105460
  const credits = parent.command("credits").description("Inspect and purchase credits from the configured server");
104624
105461
  credits.command("packs").option("--json", "Output as JSON", false).action((options) => execute(options, (client2) => client2.listCreditPacks()));
104625
- credits.command("buy").argument("<pack-id>", "An ID returned by credits packs").option("--json", "Output as JSON", false).description("Create an external checkout link; payment is confirmed in the browser").action((packId, options) => execute(options, (client2) => client2.createCreditCheckout(packId)));
105462
+ credits.command("buy").argument("<pack-id>", "An ID returned by credits packs").option("--json", "Output as JSON", false).option("--idempotency-key <key>", "Retain and reuse this request key for explicit checkout recovery").description("Create an external checkout link; payment is confirmed in the browser. No automatic retries.").action((packId, options) => execute(options, (client2) => client2.createCreditCheckout(packId, { idempotencyKey: options.idempotencyKey })));
104626
105463
  }
104627
105464
  async function execute(options, action) {
104628
105465
  try {
@@ -104633,6 +105470,23 @@ async function execute(options, action) {
104633
105470
  console.log(JSON.stringify(result2, null, 2));
104634
105471
  } catch (error61) {
104635
105472
  const message = error61 instanceof Error ? error61.message : "The Skills server request failed";
105473
+ if (error61 instanceof RemoteCreditCheckoutError) {
105474
+ const result2 = {
105475
+ error: error61.message,
105476
+ code: error61.code,
105477
+ status: error61.status,
105478
+ requestIdempotencyKey: error61.requestIdempotencyKey,
105479
+ ...error61.retryAfterSeconds === undefined ? {} : { retryAfterSeconds: error61.retryAfterSeconds }
105480
+ };
105481
+ if (options.json)
105482
+ console.log(JSON.stringify(result2));
105483
+ else
105484
+ console.error(`${error61.message}
105485
+ Request key: ${error61.requestIdempotencyKey}` + (error61.code === "CREDIT_CHECKOUT_UNCONFIRMED" || error61.code === "CREDIT_CHECKOUT_IN_PROGRESS" ? `
105486
+ For explicit recovery, pass this key with --idempotency-key. Keep the same server, account and pack.` : ""));
105487
+ process.exitCode = 1;
105488
+ return;
105489
+ }
104636
105490
  if (options.json)
104637
105491
  console.log(JSON.stringify({
104638
105492
  error: message,
@@ -104652,9 +105506,9 @@ var exports_runtime = {};
104652
105506
  __export(exports_runtime, {
104653
105507
  registerRuntime: () => registerRuntime
104654
105508
  });
104655
- import { createHash as createHash20, randomUUID as randomUUID9 } from "crypto";
104656
- import { lstatSync as lstatSync23, mkdirSync as mkdirSync23, readFileSync as readFileSync35, realpathSync as realpathSync10, writeFileSync as writeFileSync21 } from "fs";
104657
- import { basename as basename7, isAbsolute as isAbsolute18, join as join52 } from "path";
105509
+ import { createHash as createHash23, randomUUID as randomUUID9 } from "crypto";
105510
+ import { lstatSync as lstatSync25, mkdirSync as mkdirSync23, readFileSync as readFileSync35, realpathSync as realpathSync10, writeFileSync as writeFileSync21 } from "fs";
105511
+ import { basename as basename11, isAbsolute as isAbsolute21, join as join52 } from "path";
104658
105512
  import { createInterface } from "readline";
104659
105513
  function registerRuntime(parent) {
104660
105514
  parent.command("run").argument("<skill>", "Skill name").argument("[args...]", "Arguments to pass to the skill; use -- to end Skills options").allowUnknownOption(true).passThroughOptions(true).option("--json", "Output result as JSON", false).option("--remote", "Run on the configured server, using its catalog and quote", false).option("--target <target>", "Execution target: local or cloud").option("--secret-bindings <path>", "Reviewed, exact-selection local execution vault bindings (JSON file)").option("--secret-bindings-template", "Print a scoped bindings template without resolving secrets or running the skill", false).option("--input <json>", "Structured cloud execution input").option("--skill-version <version>", "Exact selected skill version").option("--selection-profile <id>", "Selected Skills profile").option("--session <id>", "Pinned Skills session").option("--cached", "Use the explicit verified selected cache", false).option("--yes", "Approve the server's quoted credit cost for this run", false).option("--idempotency-key <key>", "Reuse this key when retrying the same remote submission").option("--file <path>", "Attach a local input file to a remote run (repeatable)", (value, prior) => [...prior, value], []).option("--wait", "Poll remote runs until a terminal status", false).option("--poll-interval-ms <ms>", "Remote polling interval in milliseconds", "1000").option("--poll-timeout-ms <ms>", "Maximum time to wait for a remote run", "300000").description("Run a skill directly").action(async (name, args2, options, command) => {
@@ -104684,7 +105538,7 @@ function registerRuntime(parent) {
104684
105538
  if (!expected)
104685
105539
  throw new Error("Cloud artifact not found");
104686
105540
  const bytes = await client2.download(id2, name);
104687
- if (bytes.length !== expected.byteSize || createHash20("sha256").update(bytes).digest("hex") !== expected.sha256)
105541
+ if (bytes.length !== expected.byteSize || createHash23("sha256").update(bytes).digest("hex") !== expected.sha256)
104688
105542
  throw new Error("Cloud artifact integrity verification failed");
104689
105543
  writeFileSync21(options.output, bytes, { flag: "wx", mode: 384 });
104690
105544
  console.log(JSON.stringify({ path: options.output, sha256: expected.sha256, byteSize: bytes.length }));
@@ -104772,7 +105626,7 @@ Updating ${name}...
104772
105626
  async function readUpdatedVersion(bunExecutable) {
104773
105627
  const output2 = await readUpdateCommand([bunExecutable, "pm", "bin", "-g"]);
104774
105628
  const globalBin = output2.replace(/\r?\n$/, "");
104775
- if (!globalBin || !isAbsolute18(globalBin) || /[\r\n\0]/.test(globalBin))
105629
+ if (!globalBin || !isAbsolute21(globalBin) || /[\r\n\0]/.test(globalBin))
104776
105630
  throw new Error("Update bin discovery failed");
104777
105631
  const installed = Bun.which("skills", { PATH: globalBin, cwd: globalBin });
104778
105632
  const selected = Bun.which("skills");
@@ -104908,14 +105762,14 @@ function requireHttpUrl(value) {
104908
105762
  }
104909
105763
  function promptLine(question) {
104910
105764
  const rl = createInterface({ input: process.stdin, output: process.stdout });
104911
- return new Promise((resolve18) => {
105765
+ return new Promise((resolve21) => {
104912
105766
  let settled = false;
104913
105767
  const finish = (answer) => {
104914
105768
  if (settled)
104915
105769
  return;
104916
105770
  settled = true;
104917
105771
  rl.close();
104918
- resolve18(answer);
105772
+ resolve21(answer);
104919
105773
  };
104920
105774
  rl.once("SIGINT", () => finish(null));
104921
105775
  rl.once("close", () => finish(null));
@@ -105092,10 +105946,10 @@ async function handleRun(name, args2, options, separatorBeforeSkill) {
105092
105946
  try {
105093
105947
  parsePollingOptions(options);
105094
105948
  inputFiles = (options.file ?? []).map((path) => {
105095
- const info = lstatSync23(path);
105949
+ const info = lstatSync25(path);
105096
105950
  if (!info.isFile() || info.size > 20 * 1024 * 1024)
105097
105951
  throw new Error("Input must be a regular file no larger than 20 MiB");
105098
- return { name: basename7(path), bytes: new Uint8Array(readFileSync35(path)) };
105952
+ return { name: basename11(path), bytes: new Uint8Array(readFileSync35(path)) };
105099
105953
  });
105100
105954
  describeRemoteFiles(inputFiles);
105101
105955
  client2 = new RemoteSkillsClient(routing.apiKey, routing.apiOrigin);
@@ -105522,7 +106376,7 @@ function ensureSafeExportParent(root2, relativePath) {
105522
106376
  if (part)
105523
106377
  parent = join52(parent, part);
105524
106378
  try {
105525
- if (!lstatSync23(parent).isDirectory() || lstatSync23(parent).isSymbolicLink())
106379
+ if (!lstatSync25(parent).isDirectory() || lstatSync25(parent).isSymbolicLink())
105526
106380
  throw new Error("Unsafe artifact directory");
105527
106381
  } catch (error61) {
105528
106382
  if (error61.code !== "ENOENT")
@@ -105560,7 +106414,7 @@ async function pollRemoteRun(client2, runId2, options) {
105560
106414
  const remaining = deadline - Date.now();
105561
106415
  if (remaining <= 0)
105562
106416
  break;
105563
- await new Promise((resolve18) => setTimeout(resolve18, Math.min(options.intervalMs, remaining)));
106417
+ await new Promise((resolve21) => setTimeout(resolve21, Math.min(options.intervalMs, remaining)));
105564
106418
  }
105565
106419
  return {
105566
106420
  run: current ?? { id: runId2, status: "queued" },
@@ -105752,7 +106606,7 @@ async function readCode() {
105752
106606
  function promptCode() {
105753
106607
  const { stdin, stderr: output2 } = process;
105754
106608
  const { isRaw: wasRaw, readableFlowing: wasFlowing } = stdin;
105755
- return new Promise((resolve18) => {
106609
+ return new Promise((resolve21) => {
105756
106610
  let value = "", settled = false;
105757
106611
  const finish = (answer) => {
105758
106612
  if (settled)
@@ -105769,7 +106623,7 @@ function promptCode() {
105769
106623
  `);
105770
106624
  if (answer === null)
105771
106625
  process.exitCode = 130;
105772
- resolve18(answer);
106626
+ resolve21(answer);
105773
106627
  };
105774
106628
  const cancel = () => finish(null);
105775
106629
  const keypress = (text3, key) => {
@@ -105814,37 +106668,37 @@ var exports_recurring = {};
105814
106668
  __export(exports_recurring, {
105815
106669
  registerRecurringCommands: () => registerRecurringCommands
105816
106670
  });
105817
- import { constants as constants16, closeSync as closeSync17, fstatSync as fstatSync17, lstatSync as lstatSync24, openSync as openSync17, readSync as readSync13 } from "fs";
106671
+ import { constants as constants18, closeSync as closeSync19, fstatSync as fstatSync19, lstatSync as lstatSync26, openSync as openSync19, readSync as readSync15 } from "fs";
105818
106672
  import { createInterface as createInterface2 } from "readline";
105819
106673
  function readRequest(path) {
105820
- const fd = openSync17(path, constants16.O_RDONLY | constants16.O_NOFOLLOW | constants16.O_NONBLOCK);
106674
+ const fd = openSync19(path, constants18.O_RDONLY | constants18.O_NOFOLLOW | constants18.O_NONBLOCK);
105821
106675
  try {
105822
- const before2 = fstatSync17(fd);
106676
+ const before2 = fstatSync19(fd);
105823
106677
  if (!before2.isFile() || before2.size > 1048576 || before2.size < 1)
105824
106678
  throw new RecurringInputError;
105825
106679
  const bytes = Buffer.alloc(before2.size + 1);
105826
106680
  let length = 0;
105827
106681
  while (length < bytes.length) {
105828
- const n2 = readSync13(fd, bytes, length, bytes.length - length, length);
106682
+ const n2 = readSync15(fd, bytes, length, bytes.length - length, length);
105829
106683
  if (!n2)
105830
106684
  break;
105831
106685
  length += n2;
105832
106686
  }
105833
- const after2 = fstatSync17(fd), current = lstatSync24(path);
106687
+ const after2 = fstatSync19(fd), current = lstatSync26(path);
105834
106688
  if (length !== before2.size || after2.size !== before2.size || before2.mtimeMs !== after2.mtimeMs || before2.ctimeMs !== after2.ctimeMs || current.dev !== before2.dev || current.ino !== before2.ino || !current.isFile() || current.isSymbolicLink())
105835
106689
  throw new RecurringInputError;
105836
106690
  return JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(bytes.subarray(0, length)));
105837
106691
  } catch {
105838
106692
  throw new RecurringInputError;
105839
106693
  } finally {
105840
- closeSync17(fd);
106694
+ closeSync19(fd);
105841
106695
  }
105842
106696
  }
105843
106697
  async function acceptAtTerminal(draft) {
105844
- await new Promise((resolve18, reject2) => process.stderr.write(`${jsonText(draft)}
106698
+ await new Promise((resolve21, reject2) => process.stderr.write(`${jsonText(draft)}
105845
106699
  This grants an additional recurring budget. Each occurrence reprices within the approved ceilings. Revocation prevents new authority; an already-authorized attempt may finish, and cancellation is separate.
105846
- `, (error61) => error61 ? reject2(error61) : resolve18()));
105847
- return new Promise((resolve18) => {
106700
+ `, (error61) => error61 ? reject2(error61) : resolve21()));
106701
+ return new Promise((resolve21) => {
105848
106702
  const rl = createInterface2({ input: process.stdin, output: process.stderr });
105849
106703
  let settled = false;
105850
106704
  const finish = (accepted) => {
@@ -105855,7 +106709,7 @@ This grants an additional recurring budget. Each occurrence reprices within the
105855
106709
  rl.close();
105856
106710
  if (!accepted)
105857
106711
  process.exitCode = 130;
105858
- resolve18(accepted);
106712
+ resolve21(accepted);
105859
106713
  };
105860
106714
  const timer = setTimeout(() => finish(false), 5 * 60 * 1000);
105861
106715
  rl.once("SIGINT", () => finish(false));
@@ -106263,7 +107117,7 @@ var init_portable_snapshot_filter = __esm(() => {
106263
107117
  });
106264
107118
 
106265
107119
  // src/lib/station-snapshot.ts
106266
- import { createHash as createHash21 } from "crypto";
107120
+ import { createHash as createHash24 } from "crypto";
106267
107121
  import {
106268
107122
  copyFileSync,
106269
107123
  mkdirSync as mkdirSync24,
@@ -106271,14 +107125,14 @@ import {
106271
107125
  statSync as statSync19,
106272
107126
  writeFileSync as writeFileSync22
106273
107127
  } from "fs";
106274
- import { dirname as dirname25, isAbsolute as isAbsolute19, relative as relative8, resolve as resolve18, sep as sep9 } from "path";
107128
+ import { dirname as dirname27, isAbsolute as isAbsolute22, relative as relative8, resolve as resolve21, sep as sep9 } from "path";
106275
107129
  function validateStationId(stationId) {
106276
107130
  if (!/^[a-z0-9-]+$/.test(stationId)) {
106277
107131
  throw new StationSnapshotError("INVALID_STATION", `station id must be a slug, got: ${stationId}`);
106278
107132
  }
106279
107133
  }
106280
107134
  function sha256File(filePath) {
106281
- return createHash21("sha256").update(readFileSync36(filePath)).digest("hex");
107135
+ return createHash24("sha256").update(readFileSync36(filePath)).digest("hex");
106282
107136
  }
106283
107137
  function scanHome(definition, homesRoot) {
106284
107138
  const homePath = homePathFor(definition, homesRoot);
@@ -106349,7 +107203,7 @@ function humanHomes(scanned) {
106349
107203
  }));
106350
107204
  }
106351
107205
  function writeStationSnapshot(options) {
106352
- const repoRoot = resolve18(options.repoRoot ?? process.cwd());
107206
+ const repoRoot = resolve21(options.repoRoot ?? process.cwd());
106353
107207
  const { scanned, plans, totalBytes } = planStationSnapshot(options);
106354
107208
  const manifestFiles = plans.map((plan) => ({
106355
107209
  relativePath: plan.source.relativePath,
@@ -106375,9 +107229,9 @@ function writeStationSnapshot(options) {
106375
107229
  const conflicts = [];
106376
107230
  const untouched = [];
106377
107231
  for (const plan of plans) {
106378
- const destination = resolve18(repoRoot, plan.destination);
107232
+ const destination = resolve21(repoRoot, plan.destination);
106379
107233
  const destinationRelative = relative8(repoRoot, destination);
106380
- if (destinationRelative.startsWith("..") || destinationRelative.startsWith(sep9) || isAbsolute19(destinationRelative)) {
107234
+ if (destinationRelative.startsWith("..") || destinationRelative.startsWith(sep9) || isAbsolute22(destinationRelative)) {
106381
107235
  throw new StationSnapshotError("DESTINATION_ESCAPE", `destination escapes repo root: ${plan.destination}`);
106382
107236
  }
106383
107237
  let existingDigest = null;
@@ -106398,8 +107252,8 @@ function writeStationSnapshot(options) {
106398
107252
  }
106399
107253
  let written = 0;
106400
107254
  for (const plan of untouched) {
106401
- const destination = resolve18(repoRoot, plan.destination);
106402
- mkdirSync24(dirname25(destination), { recursive: true });
107255
+ const destination = resolve21(repoRoot, plan.destination);
107256
+ mkdirSync24(dirname27(destination), { recursive: true });
106403
107257
  copyFileSync(plan.source.fullPath, destination);
106404
107258
  written += 1;
106405
107259
  }
@@ -106417,8 +107271,8 @@ function writeStationSnapshot(options) {
106417
107271
  },
106418
107272
  files: manifestFiles
106419
107273
  };
106420
- const manifestPath = resolve18(repoRoot, "resources", options.stationId, "skills", "sync-manifest.json");
106421
- mkdirSync24(dirname25(manifestPath), { recursive: true });
107274
+ const manifestPath = resolve21(repoRoot, "resources", options.stationId, "skills", "sync-manifest.json");
107275
+ mkdirSync24(dirname27(manifestPath), { recursive: true });
106422
107276
  writeFileSync22(manifestPath, `${JSON.stringify(manifest, null, 2)}
106423
107277
  `);
106424
107278
  return {
@@ -106852,10 +107706,10 @@ var init_create_sync_config = __esm(() => {
106852
107706
  // src/lib/codex-hook-rpc.ts
106853
107707
  import { execFile, spawn as spawn3 } from "child_process";
106854
107708
  import { realpathSync as realpathSync11, statSync as statSync20 } from "fs";
106855
- import { isAbsolute as isAbsolute20 } from "path";
107709
+ import { isAbsolute as isAbsolute23 } from "path";
106856
107710
  import { promisify } from "util";
106857
107711
  async function connectCodexHookRpc(options) {
106858
- const found = isAbsolute20(options.command) ? options.command : Bun.which(options.command, { PATH: process.env.PATH });
107712
+ const found = isAbsolute23(options.command) ? options.command : Bun.which(options.command, { PATH: process.env.PATH });
106859
107713
  if (!found)
106860
107714
  throw new Error("CODEX_HOOK_TRUST_NATIVE_UNAVAILABLE: install Codex or pass --codex-command");
106861
107715
  const binary = realpathSync11(found), stat3 = statSync20(binary);
@@ -106941,13 +107795,13 @@ async function connectCodexHookRpc(options) {
106941
107795
  request(method2, params) {
106942
107796
  if (stopped)
106943
107797
  return Promise.reject(new Error("CODEX_HOOK_TRUST_NATIVE_RPC_CLOSED"));
106944
- return new Promise((resolve19, reject2) => {
107798
+ return new Promise((resolve22, reject2) => {
106945
107799
  const id2 = nextId++;
106946
107800
  const timer = setTimeout(() => {
106947
107801
  fail4();
106948
107802
  child.kill();
106949
107803
  }, 20000);
106950
- pending.set(id2, { resolve: resolve19, reject: reject2, timer });
107804
+ pending.set(id2, { resolve: resolve22, reject: reject2, timer });
106951
107805
  child.stdin.write(JSON.stringify({ id: id2, method: method2, params }) + `
106952
107806
  `);
106953
107807
  });
@@ -106957,14 +107811,14 @@ async function connectCodexHookRpc(options) {
106957
107811
  child.stdin.end();
106958
107812
  if (child.exitCode !== null || child.signalCode !== null)
106959
107813
  return;
106960
- await new Promise((resolve19) => {
107814
+ await new Promise((resolve22) => {
106961
107815
  const timer = setTimeout(() => {
106962
107816
  child.kill();
106963
- resolve19();
107817
+ resolve22();
106964
107818
  }, 1000);
106965
107819
  child.once("exit", () => {
106966
107820
  clearTimeout(timer);
106967
- resolve19();
107821
+ resolve22();
106968
107822
  });
106969
107823
  });
106970
107824
  }
@@ -106985,7 +107839,7 @@ var init_codex_hook_rpc = __esm(() => {
106985
107839
  });
106986
107840
 
106987
107841
  // src/lib/codex-hook-trust-layout.ts
106988
- import { isDeepStrictEqual as isDeepStrictEqual4 } from "util";
107842
+ import { isDeepStrictEqual as isDeepStrictEqual5 } from "util";
106989
107843
  function codexTrustTextWitness(text3, keys3) {
106990
107844
  const parsed = Bun.TOML.parse(text3), wanted = new Set(keys3);
106991
107845
  const headers = [...text3.matchAll(/^[ \t]*(\[[^\r\n]+\])[ \t]*(#[^\r\n]*)?(?:\r?\n|$)/gm)];
@@ -107032,11 +107886,11 @@ function codexTrustTextWitness(text3, keys3) {
107032
107886
  comments.push(line);
107033
107887
  continue;
107034
107888
  }
107035
- const field = /^[ \t]*(?:enabled|trusted_hash)[ \t]*=[ \t]*(?:true|false|"(?:[^"\\]|\\.)*"|'[^']*')[ \t]*(#[^\r\n]*)?$/.exec(line);
107036
- if (!field)
107889
+ const field2 = /^[ \t]*(?:enabled|trusted_hash)[ \t]*=[ \t]*(?:true|false|"(?:[^"\\]|\\.)*"|'[^']*')[ \t]*(#[^\r\n]*)?$/.exec(line);
107890
+ if (!field2)
107037
107891
  throw fail4();
107038
- if (field[1])
107039
- comments.push(field[1]);
107892
+ if (field2[1])
107893
+ comments.push(field2[1]);
107040
107894
  }
107041
107895
  replacements2.push({ start, end, comments: comments.join(`
107042
107896
  `) + `
@@ -107050,7 +107904,7 @@ function codexTrustTextWitness(text3, keys3) {
107050
107904
  if (expected.hooks)
107051
107905
  delete expected.hooks.state;
107052
107906
  try {
107053
- if (!isDeepStrictEqual4(prune(Bun.TOML.parse(noState)), prune(expected)))
107907
+ if (!isDeepStrictEqual5(prune(Bun.TOML.parse(noState)), prune(expected)))
107054
107908
  throw fail4();
107055
107909
  } catch {
107056
107910
  throw fail4();
@@ -107071,59 +107925,59 @@ var fail4 = () => new Error('CODEX_HOOK_TRUST_UNSUPPORTED_LAYOUT: preserve and c
107071
107925
  var init_codex_hook_trust_layout = () => {};
107072
107926
 
107073
107927
  // src/lib/codex-hook-trust-files.ts
107074
- import { closeSync as closeSync18, constants as constants17, fstatSync as fstatSync18, fsyncSync as fsyncSync5, lstatSync as lstatSync25, openSync as openSync18, readSync as readSync14, writeFileSync as writeFileSync23 } from "fs";
107075
- import { createHash as createHash22 } from "crypto";
107076
- import { dirname as dirname26 } from "path";
107077
- function need2(value, code2) {
107928
+ import { closeSync as closeSync20, constants as constants19, fstatSync as fstatSync20, fsyncSync as fsyncSync6, lstatSync as lstatSync27, openSync as openSync20, readSync as readSync16, writeFileSync as writeFileSync23 } from "fs";
107929
+ import { createHash as createHash25 } from "crypto";
107930
+ import { dirname as dirname28 } from "path";
107931
+ function need4(value, code2) {
107078
107932
  if (!value)
107079
107933
  throw new Error(`CODEX_HOOK_TRUST_${code2}`);
107080
107934
  }
107081
107935
  function safeParents(file2) {
107082
- for (let p = dirname26(file2);; p = dirname26(p)) {
107083
- const s = lstatSync25(p);
107084
- need2(s.isDirectory() && !s.isSymbolicLink(), "UNSAFE_PARENT");
107085
- need2((s.mode & 18) === 0 || s.uid === 0 && (s.mode & 512) !== 0, "UNSAFE_PARENT");
107086
- if (dirname26(p) === p)
107936
+ for (let p = dirname28(file2);; p = dirname28(p)) {
107937
+ const s = lstatSync27(p);
107938
+ need4(s.isDirectory() && !s.isSymbolicLink(), "UNSAFE_PARENT");
107939
+ need4((s.mode & 18) === 0 || s.uid === 0 && (s.mode & 512) !== 0, "UNSAFE_PARENT");
107940
+ if (dirname28(p) === p)
107087
107941
  break;
107088
107942
  }
107089
107943
  }
107090
107944
  function snapshot(file2, privateFile = false, options = {}) {
107091
107945
  const readOnlyPackage = options.readOnlyPackage === true && !privateFile;
107092
107946
  safeParents(file2);
107093
- const initial2 = lstatSync25(file2, { bigint: true });
107094
- need2(initial2.isFile() && initial2.uid === BigInt(process.getuid()) && (initial2.nlink === 1n || readOnlyPackage && initial2.nlink > 1n) && (initial2.mode & 0o022n) === 0n && (!privateFile || (initial2.mode & 0o777n) === 0o600n), "UNSAFE_FILE");
107095
- need2(initial2.size <= 8n * 1024n * 1024n, "FILE_BOUND");
107096
- const fd = openSync18(file2, constants17.O_RDONLY | constants17.O_NOFOLLOW | constants17.O_NONBLOCK);
107947
+ const initial2 = lstatSync27(file2, { bigint: true });
107948
+ need4(initial2.isFile() && initial2.uid === BigInt(process.getuid()) && (initial2.nlink === 1n || readOnlyPackage && initial2.nlink > 1n) && (initial2.mode & 0o022n) === 0n && (!privateFile || (initial2.mode & 0o777n) === 0o600n), "UNSAFE_FILE");
107949
+ need4(initial2.size <= 8n * 1024n * 1024n, "FILE_BOUND");
107950
+ const fd = openSync20(file2, constants19.O_RDONLY | constants19.O_NOFOLLOW | constants19.O_NONBLOCK);
107097
107951
  try {
107098
- const before2 = fstatSync18(fd, { bigint: true });
107099
- need2(sameStat(initial2, before2), "INPUT_CHANGED");
107952
+ const before2 = fstatSync20(fd, { bigint: true });
107953
+ need4(sameStat(initial2, before2), "INPUT_CHANGED");
107100
107954
  const bytes = Buffer.alloc(Number(before2.size) + 1);
107101
107955
  let length = 0;
107102
107956
  while (length < bytes.length) {
107103
- const n2 = readSync14(fd, bytes, length, bytes.length - length, null);
107957
+ const n2 = readSync16(fd, bytes, length, bytes.length - length, null);
107104
107958
  if (!n2)
107105
107959
  break;
107106
107960
  length += n2;
107107
107961
  }
107108
- need2(length === Number(before2.size) && sameStat(before2, fstatSync18(fd, { bigint: true })) && sameStat(before2, lstatSync25(file2, { bigint: true })), "INPUT_CHANGED");
107962
+ need4(length === Number(before2.size) && sameStat(before2, fstatSync20(fd, { bigint: true })) && sameStat(before2, lstatSync27(file2, { bigint: true })), "INPUT_CHANGED");
107109
107963
  const content = bytes.subarray(0, length), text3 = new TextDecoder("utf-8", { fatal: true }).decode(content);
107110
- return { file: file2, privateFile, readOnlyPackage, text: text3, bytes: content, stat: before2, sha256: createHash22("sha256").update(content).digest("hex") };
107964
+ return { file: file2, privateFile, readOnlyPackage, text: text3, bytes: content, stat: before2, sha256: createHash25("sha256").update(content).digest("hex") };
107111
107965
  } finally {
107112
- closeSync18(fd);
107966
+ closeSync20(fd);
107113
107967
  }
107114
107968
  }
107115
107969
  function unchanged2(before2) {
107116
107970
  const after2 = snapshot(before2.file, before2.privateFile, before2.readOnlyPackage ? { readOnlyPackage: true } : {});
107117
- need2(sameStat(before2.stat, after2.stat) && after2.sha256 === before2.sha256, "INPUT_CHANGED");
107971
+ need4(sameStat(before2.stat, after2.stat) && after2.sha256 === before2.sha256, "INPUT_CHANGED");
107118
107972
  }
107119
107973
  function save2(file2, content) {
107120
107974
  safeParents(file2);
107121
- const fd = openSync18(file2, constants17.O_WRONLY | constants17.O_CREAT | constants17.O_EXCL | constants17.O_NOFOLLOW, 384);
107975
+ const fd = openSync20(file2, constants19.O_WRONLY | constants19.O_CREAT | constants19.O_EXCL | constants19.O_NOFOLLOW, 384);
107122
107976
  try {
107123
107977
  writeFileSync23(fd, content);
107124
- fsyncSync5(fd);
107978
+ fsyncSync6(fd);
107125
107979
  } finally {
107126
- closeSync18(fd);
107980
+ closeSync20(fd);
107127
107981
  }
107128
107982
  }
107129
107983
  var sameStat = (a, b) => ["dev", "ino", "uid", "nlink", "mode", "size", "mtimeNs", "ctimeNs"].every((key) => a[key] === b[key]);
@@ -107131,26 +107985,26 @@ var init_codex_hook_trust_files = () => {};
107131
107985
 
107132
107986
  // src/lib/codex-hook-trust-identity.ts
107133
107987
  import { realpathSync as realpathSync12 } from "fs";
107134
- import { dirname as dirname27, isAbsolute as isAbsolute21, join as join55 } from "path";
107988
+ import { dirname as dirname29, isAbsolute as isAbsolute24, join as join55 } from "path";
107135
107989
  function bindSkillsCli(command, reviewed) {
107136
107990
  const normal = Bun.which("skills", { PATH: process.env.PATH });
107137
- need2(normal, "SKILLS_COMMAND_UNAVAILABLE");
107991
+ need4(normal, "SKILLS_COMMAND_UNAVAILABLE");
107138
107992
  const resolved = realpathSync12(normal);
107139
- const bound = isAbsolute21(command) ? command : command === "skills" ? normal : undefined;
107140
- need2(bound && realpathSync12(bound) === resolved, "SKILLS_COMMAND_MISMATCH");
107993
+ const bound = isAbsolute24(command) ? command : command === "skills" ? normal : undefined;
107994
+ need4(bound && realpathSync12(bound) === resolved, "SKILLS_COMMAND_MISMATCH");
107141
107995
  const entrypoint = reviewed?.path ?? process.argv[1];
107142
- need2(entrypoint && realpathSync12(entrypoint) === resolved, "SKILLS_ENTRYPOINT_MISMATCH");
107996
+ need4(entrypoint && realpathSync12(entrypoint) === resolved, "SKILLS_ENTRYPOINT_MISMATCH");
107143
107997
  const cli = snapshot(resolved, false, { readOnlyPackage: true });
107144
- const manifest = snapshot(join55(dirname27(dirname27(resolved)), "package.json"), false, { readOnlyPackage: true });
107998
+ const manifest = snapshot(join55(dirname29(dirname29(resolved)), "package.json"), false, { readOnlyPackage: true });
107145
107999
  const pkg = JSON.parse(manifest.text);
107146
- need2(pkg.name === "@hasna/skills" && /^\d+\.\d+\.\d+$/.test(pkg.version) && pkg.bin?.skills === "bin/index.js" && resolved === join55(dirname27(manifest.file), "bin/index.js"), "SKILLS_PACKAGE_MISMATCH");
108000
+ need4(pkg.name === "@hasna/skills" && /^\d+\.\d+\.\d+$/.test(pkg.version) && pkg.bin?.skills === "bin/index.js" && resolved === join55(dirname29(manifest.file), "bin/index.js"), "SKILLS_PACKAGE_MISMATCH");
107147
108001
  if (reviewed)
107148
- need2(/^[a-f0-9]{64}$/.test(reviewed.sha256) && reviewed.sha256 === cli.sha256 && reviewed.version === pkg.version, "SKILLS_RELEASE_MISMATCH");
107149
- need2((cli.stat.mode & 0o100n) !== 0n, "SKILLS_COMMAND_NOT_EXECUTABLE");
108002
+ need4(/^[a-f0-9]{64}$/.test(reviewed.sha256) && reviewed.sha256 === cli.sha256 && reviewed.version === pkg.version, "SKILLS_RELEASE_MISMATCH");
108003
+ need4((cli.stat.mode & 0o100n) !== 0n, "SKILLS_COMMAND_NOT_EXECUTABLE");
107150
108004
  return {
107151
108005
  receipt: { path: resolved, version: pkg.version, sha256: cli.sha256, manifestSha256: manifest.sha256 },
107152
108006
  recheck() {
107153
- need2(Bun.which("skills", { PATH: process.env.PATH }) === normal && realpathSync12(normal) === resolved && realpathSync12(bound) === resolved && realpathSync12(entrypoint) === resolved, "SKILLS_COMMAND_CHANGED");
108007
+ need4(Bun.which("skills", { PATH: process.env.PATH }) === normal && realpathSync12(normal) === resolved && realpathSync12(bound) === resolved && realpathSync12(entrypoint) === resolved, "SKILLS_COMMAND_CHANGED");
107154
108008
  unchanged2(cli);
107155
108009
  unchanged2(manifest);
107156
108010
  }
@@ -107161,15 +108015,15 @@ var init_codex_hook_trust_identity = __esm(() => {
107161
108015
  });
107162
108016
 
107163
108017
  // src/lib/agent-codex-trust.ts
107164
- import { lstatSync as lstatSync26, mkdirSync as mkdirSync25, readdirSync as readdirSync20 } from "fs";
107165
- import { createHash as createHash23, randomUUID as randomUUID10 } from "crypto";
107166
- import { join as join56, resolve as resolve19 } from "path";
108018
+ import { lstatSync as lstatSync28, mkdirSync as mkdirSync25, readdirSync as readdirSync20 } from "fs";
108019
+ import { createHash as createHash26, randomUUID as randomUUID10 } from "crypto";
108020
+ import { join as join56, resolve as resolve22 } from "path";
107167
108021
  import { homedir as homedir11 } from "os";
107168
- import { isDeepStrictEqual as isDeepStrictEqual5 } from "util";
108022
+ import { isDeepStrictEqual as isDeepStrictEqual6 } from "util";
107169
108023
  async function enrollCodexNativeHooks(options = {}, connect = connectCodexHookRpc) {
107170
108024
  let rpc, journal;
107171
108025
  try {
107172
- const home = resolve19(options.home ?? homedir11()), dataDir3 = resolve19(options.dataDir ?? getDataDirReadOnly());
108026
+ const home = resolve22(options.home ?? homedir11()), dataDir3 = resolve22(options.dataDir ?? getDataDirReadOnly());
107173
108027
  assertManagedAgentBridge("codex", { home, dataDir: dataDir3, projectDir: home });
107174
108028
  const policyFile = snapshot(join56(dataDir3, "agent-policy.json"), true), policy = parseManagedSkillPolicy(policyFile.text);
107175
108029
  const binding = policy.bridge, alias = binding.rootAliases?.find((item) => item.agent === "codex");
@@ -107180,35 +108034,35 @@ async function enrollCodexNativeHooks(options = {}, connect = connectCodexHookRp
107180
108034
  for (const [event, [nativeEvent, label]] of Object.entries(eventNames)) {
107181
108035
  const command = renderAgentHookCommand(binding.commands.codex, "codex", binding.profiles.codex, event);
107182
108036
  const groups = declarations[event];
107183
- need2(Array.isArray(groups), "DECLARATION_CHANGED");
108037
+ need4(Array.isArray(groups), "DECLARATION_CHANGED");
107184
108038
  const matches2 = groups.flatMap((group, gi) => (group.hooks ?? []).flatMap((entry, hi) => entry.command === command ? [{ group, entry, gi, hi }] : []));
107185
- need2(matches2.length === 1 && isDeepStrictEqual5(matches2[0].group, { hooks: [{ type: "command", command, timeout: 15 }] }), "DECLARATION_CHANGED");
108039
+ need4(matches2.length === 1 && isDeepStrictEqual6(matches2[0].group, { hooks: [{ type: "command", command, timeout: 15 }] }), "DECLARATION_CHANGED");
107186
108040
  expected.push({ event: nativeEvent, key: `${join56(home, ".codex/hooks.json")}:${label}:${matches2[0].gi}:${matches2[0].hi}`, command });
107187
108041
  }
107188
108042
  codexTrustTextWitness(configFile.text, expected.map((h) => h.key));
107189
108043
  rpc = await connect({ command: options.codexCommand ?? "codex", home, codexHome });
107190
- need2(SUPPORTED_CODEX_HOOK_VERSIONS.includes(rpc.version), "NATIVE_UNSUPPORTED_VERSION");
108044
+ need4(SUPPORTED_CODEX_HOOK_VERSIONS.includes(rpc.version), "NATIVE_UNSUPPORTED_VERSION");
107191
108045
  const list2 = async () => {
107192
108046
  const response = await rpc.request("hooks/list", { cwds: [home] });
107193
- need2(Array.isArray(response?.data) && response.data.length === 1 && response.data[0].cwd === home && Array.isArray(response.data[0].hooks) && response.data[0].hooks.length <= 1e4 && !response.data[0].errors?.length && !response.data[0].warnings?.length, "NATIVE_DISCOVERY_REFUSED");
108047
+ need4(Array.isArray(response?.data) && response.data.length === 1 && response.data[0].cwd === home && Array.isArray(response.data[0].hooks) && response.data[0].hooks.length <= 1e4 && !response.data[0].errors?.length && !response.data[0].warnings?.length, "NATIVE_DISCOVERY_REFUSED");
107194
108048
  return response.data[0].hooks;
107195
108049
  };
107196
108050
  const admit = (hooks) => expected.map((wanted) => {
107197
108051
  const canonicalKey = wanted.key.replace(join56(home, ".codex/hooks.json"), hooksPath);
107198
108052
  const matches2 = hooks.filter((h2) => h2.key === wanted.key || h2.key === canonicalKey);
107199
- need2(matches2.length === 1, "AMBIGUOUS_IDENTITY");
108053
+ need4(matches2.length === 1, "AMBIGUOUS_IDENTITY");
107200
108054
  const h = matches2[0];
107201
- need2(h.eventName === wanted.event && h.handlerType === "command" && h.command === wanted.command && h.matcher === null && h.timeoutSec === 15 && h.async === false && h.statusMessage === null && h.additionalContextLimit === null && [hooksPath, join56(home, ".codex/hooks.json")].includes(h.sourcePath) && h.source === "user" && h.pluginId === null && h.isManaged === false && /^sha256:[a-f0-9]{64}$/.test(h.currentHash) && typeof h.enabled === "boolean", "NATIVE_IDENTITY_CHANGED");
107202
- need2(hooks.filter((other) => other.command === wanted.command).length === 1, "AMBIGUOUS_IDENTITY");
107203
- need2(["trusted", "untrusted", "modified"].includes(h.trustStatus), "UNKNOWN_TRUST_STATUS");
108055
+ need4(h.eventName === wanted.event && h.handlerType === "command" && h.command === wanted.command && h.matcher === null && h.timeoutSec === 15 && h.async === false && h.statusMessage === null && h.additionalContextLimit === null && [hooksPath, join56(home, ".codex/hooks.json")].includes(h.sourcePath) && h.source === "user" && h.pluginId === null && h.isManaged === false && /^sha256:[a-f0-9]{64}$/.test(h.currentHash) && typeof h.enabled === "boolean", "NATIVE_IDENTITY_CHANGED");
108056
+ need4(hooks.filter((other) => other.command === wanted.command).length === 1, "AMBIGUOUS_IDENTITY");
108057
+ need4(["trusted", "untrusted", "modified"].includes(h.trustStatus), "UNKNOWN_TRUST_STATUS");
107204
108058
  return { key: h.key, event: wanted.event, command: wanted.command, handlerType: h.handlerType, timeoutSec: h.timeoutSec, sourcePath: h.sourcePath, currentHash: h.currentHash, enabled: h.enabled, trustStatus: h.trustStatus };
107205
108059
  });
107206
108060
  const discovered = await list2(), admitted = admit(discovered);
107207
108061
  const config2 = await rpc.request("config/read", { includeLayers: true, cwd: home });
107208
108062
  const layers = config2?.layers?.filter((layer) => layer.name?.type === "user" && layer.name.file === configPath && !layer.name.profile);
107209
- need2(layers?.length === 1 && /^sha256:[a-f0-9]{64}$/.test(layers[0].version) && !layers[0].disabledReason && isDeepStrictEqual5(layers[0].config, original), "NATIVE_CONFIG_MISMATCH");
107210
- need2(config2.config && config2.config.features?.hooks !== false, "NATIVE_HOOKS_DISABLED");
107211
- need2(config2.layers.slice(0, config2.layers.indexOf(layers[0])).every((layer) => layer.config?.hooks === undefined && layer.config?.features?.hooks === undefined), "NATIVE_CONFIG_OVERRIDDEN");
108063
+ need4(layers?.length === 1 && /^sha256:[a-f0-9]{64}$/.test(layers[0].version) && !layers[0].disabledReason && isDeepStrictEqual6(layers[0].config, original), "NATIVE_CONFIG_MISMATCH");
108064
+ need4(config2.config && config2.config.features?.hooks !== false, "NATIVE_HOOKS_DISABLED");
108065
+ need4(config2.layers.slice(0, config2.layers.indexOf(layers[0])).every((layer) => layer.config?.hooks === undefined && layer.config?.features?.hooks === undefined), "NATIVE_CONFIG_OVERRIDDEN");
107212
108066
  const keys3 = admitted.map((h) => h.key), planned = admitted.filter((h) => !h.enabled || h.trustStatus !== "trusted");
107213
108067
  const preservationText = codexTrustTextWitness(configFile.text, keys3);
107214
108068
  const checkInputs = () => {
@@ -107219,19 +108073,19 @@ async function enrollCodexNativeHooks(options = {}, connect = connectCodexHookRp
107219
108073
  unchanged2(configFile);
107220
108074
  };
107221
108075
  checkInputs();
107222
- const planDigest = createHash23("sha256").update(json2({ version: 1, home, configPath, configSha256: configFile.sha256, configVersion: layers[0].version, policySha256: policyFile.sha256, hooksSha256: hooksFile.sha256, skillsCli: skillsCli.receipt, nativeVersion: rpc.version, declarations: expected, admitted })).digest("hex");
108076
+ const planDigest = createHash26("sha256").update(json2({ version: 1, home, configPath, configSha256: configFile.sha256, configVersion: layers[0].version, policySha256: policyFile.sha256, hooksSha256: hooksFile.sha256, skillsCli: skillsCli.receipt, nativeVersion: rpc.version, declarations: expected, admitted })).digest("hex");
107223
108077
  const baseReceipt = { planDigest, skillsCli: skillsCli.receipt, nativeVersion: rpc.version, ownedNativeProcessId: rpc.processId, agent: "codex", applied: false, planned, nativeEligible: planned.length === 0, transport: "owned-stdio-process", existingSessionsReloaded: false, nativeExecutionVerified: false };
107224
108078
  if (options.apply)
107225
- need2(options.reviewedPlanDigest === planDigest, "PLAN_CHANGED: run the dry-run again and pass its reviewed --plan-digest with --apply");
108079
+ need4(options.reviewedPlanDigest === planDigest, "PLAN_CHANGED: run the dry-run again and pass its reviewed --plan-digest with --apply");
107226
108080
  const parent = join56(dataDir3, "native-hook-trust");
107227
- const st = lstatSync26(parent, { throwIfNoEntry: false });
108081
+ const st = lstatSync28(parent, { throwIfNoEntry: false });
107228
108082
  if (st) {
107229
- need2(st.isDirectory() && !st.isSymbolicLink() && st.uid === process.getuid() && (st.mode & 511) === 448, "UNSAFE_JOURNAL");
108083
+ need4(st.isDirectory() && !st.isSymbolicLink() && st.uid === process.getuid() && (st.mode & 511) === 448, "UNSAFE_JOURNAL");
107230
108084
  const priorJournals = readdirSync20(parent);
107231
- need2(priorJournals.length < 1000, "JOURNAL_BOUND");
108085
+ need4(priorJournals.length < 1000, "JOURNAL_BOUND");
107232
108086
  for (const name of priorJournals) {
107233
- need2(/^[a-f0-9-]{36}$/.test(name), "UNSAFE_JOURNAL");
107234
- need2(lstatSync26(join56(parent, name, "receipt.json"), { throwIfNoEntry: false })?.isFile(), "RECONCILE_REQUIRED: inspect the incomplete private journal before applying again");
108087
+ need4(/^[a-f0-9-]{36}$/.test(name), "UNSAFE_JOURNAL");
108088
+ need4(lstatSync28(join56(parent, name, "receipt.json"), { throwIfNoEntry: false })?.isFile(), "RECONCILE_REQUIRED: inspect the incomplete private journal before applying again");
107235
108089
  }
107236
108090
  }
107237
108091
  if (!options.apply || !planned.length)
@@ -107244,7 +108098,7 @@ async function enrollCodexNativeHooks(options = {}, connect = connectCodexHookRp
107244
108098
  save2(join56(journal, "hooks.before.json"), hooksFile.bytes);
107245
108099
  save2(join56(journal, "policy.before.json"), policyFile.bytes);
107246
108100
  save2(join56(journal, "intent.json"), json2({ version: 1, planDigest, skillsCli: skillsCli.receipt, nativeVersion: rpc.version, configPath, beforeSha256: configFile.sha256, hooksSha256: hooksFile.sha256, policySha256: policyFile.sha256, expectedVersion: layers[0].version, hooks: planned }));
107247
- need2(isDeepStrictEqual5(admit(await list2()), admitted), "NATIVE_DISCOVERY_CHANGED");
108101
+ need4(isDeepStrictEqual6(admit(await list2()), admitted), "NATIVE_DISCOVERY_CHANGED");
107248
108102
  checkInputs();
107249
108103
  let result2;
107250
108104
  try {
@@ -107252,19 +108106,19 @@ async function enrollCodexNativeHooks(options = {}, connect = connectCodexHookRp
107252
108106
  } catch {
107253
108107
  throw new Error("CODEX_HOOK_TRUST_NATIVE_WRITE_FAILED: reconcile the private journal before retrying");
107254
108108
  }
107255
- need2(result2?.status === "ok" && result2.filePath === configPath && /^sha256:[a-f0-9]{64}$/.test(result2.version), "NATIVE_WRITE_OVERRIDDEN");
108109
+ need4(result2?.status === "ok" && result2.filePath === configPath && /^sha256:[a-f0-9]{64}$/.test(result2.version), "NATIVE_WRITE_OVERRIDDEN");
107256
108110
  const after2 = snapshot(configPath, true), expectedConfig = structuredClone(original);
107257
108111
  expectedConfig.hooks ??= {};
107258
108112
  expectedConfig.hooks.state ??= {};
107259
108113
  for (const h of planned)
107260
108114
  expectedConfig.hooks.state[h.key] = { ...expectedConfig.hooks.state[h.key], enabled: true, trusted_hash: h.currentHash };
107261
- need2(isDeepStrictEqual5(structure(after2.text), expectedConfig) && codexTrustTextWitness(after2.text, keys3) === preservationText, "PRESERVATION_FAILED");
108115
+ need4(isDeepStrictEqual6(structure(after2.text), expectedConfig) && codexTrustTextWitness(after2.text, keys3) === preservationText, "PRESERVATION_FAILED");
107262
108116
  unchanged2(policyFile);
107263
108117
  unchanged2(hooksFile);
107264
108118
  assertManagedAgentBridge("codex", { home, dataDir: dataDir3, projectDir: home });
107265
108119
  const current = await list2(), confirmed = admit(current);
107266
- need2(confirmed.every((h) => h.enabled && h.trustStatus === "trusted") && isDeepStrictEqual5(confirmed.map((h) => [h.key, h.currentHash]), admitted.map((h) => [h.key, h.currentHash])), "NATIVE_NOT_ELIGIBLE");
107267
- need2(isDeepStrictEqual5(current.filter((h) => !keys3.includes(h.key)), discovered.filter((h) => !keys3.includes(h.key))), "UNRELATED_HOOK_CHANGED");
108120
+ need4(confirmed.every((h) => h.enabled && h.trustStatus === "trusted") && isDeepStrictEqual6(confirmed.map((h) => [h.key, h.currentHash]), admitted.map((h) => [h.key, h.currentHash])), "NATIVE_NOT_ELIGIBLE");
108121
+ need4(isDeepStrictEqual6(current.filter((h) => !keys3.includes(h.key)), discovered.filter((h) => !keys3.includes(h.key))), "UNRELATED_HOOK_CHANGED");
107268
108122
  unchanged2(after2);
107269
108123
  unchanged2(hooksFile);
107270
108124
  unchanged2(policyFile);
@@ -107298,39 +108152,142 @@ var init_agent_codex_trust = __esm(() => {
107298
108152
  eventNames = { UserPromptSubmit: ["userPromptSubmit", "user_prompt_submit"], SessionStart: ["sessionStart", "session_start"], SubagentStart: ["subagentStart", "subagent_start"] };
107299
108153
  });
107300
108154
 
108155
+ // src/lib/hook-diagnostics.ts
108156
+ function hookChildError(stdout, stage) {
108157
+ let code2;
108158
+ if (stdout.length <= 16 * 1024) {
108159
+ try {
108160
+ code2 = JSON.parse(stdout)?.error?.code;
108161
+ } catch {}
108162
+ }
108163
+ return new HookDiagnosticError(typeof code2 === "string" && CONTEXT_ERROR_CODES.has(code2) ? code2 : "SKILLS_CONTEXT_FAILED", stage);
108164
+ }
108165
+ function hookFailureReason(error61, profileId) {
108166
+ const owned = error61 instanceof HookDiagnosticError;
108167
+ const code2 = owned && (CONTEXT_ERROR_CODES.has(error61.code) || ["SKILLS_HOOK_TIMEOUT", "SKILLS_HOOK_INVALID_RESPONSE"].includes(error61.code)) ? error61.code : "SKILLS_HOOK_FAILED";
108168
+ const profile = typeof profileId === "string" && /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/.test(profileId) && !profileId.includes("..") ? profileId : undefined;
108169
+ const identity4 = [profile ? `profile=${profile}` : undefined, owned ? `stage=${error61.stage}` : undefined].filter(Boolean).join(", ");
108170
+ const prefix = `Skills context is unavailable [${code2}]${identity4 ? ` (${identity4})` : ""}.`;
108171
+ if (code2 === "PROFILE_LOCK_MISMATCH") {
108172
+ return `${prefix} This session or project is pinned to a different profile. Inspect the session with skills sessions show <session-id> --json; review skills sessions reconcile for an intentional session change, or explicit project sync for a project change. Sync alone does not change that pin.`;
108173
+ }
108174
+ if (code2.startsWith("SESSION_")) {
108175
+ return `${prefix} Inspect the session with skills sessions show <session-id> --json and review its parent or concurrent writer before retrying. Do not remove or rewrite its receipt to bypass this refusal.`;
108176
+ }
108177
+ if (["PROFILE_IDENTITY_MISMATCH", "BUNDLE_DIGEST_MISMATCH", "BUNDLE_IDENTITY_MISMATCH", "INVALID_RECEIPT", "INVALID_CACHE_FILE", "UNSAFE_CACHE_PATH"].includes(code2)) {
108178
+ return `${prefix} Verify the selected authority and receipt integrity before repairing the profile; do not bypass verification or substitute another cache.`;
108179
+ }
108180
+ const selected = profile ?? "<id>";
108181
+ return `${prefix} Run skills sync --selection-profile ${selected} --json, then diagnose with skills context --stdin --json --cached --selection-profile ${selected} using the same hook session and working-directory fields. Do not include credentials in diagnostic input.`;
108182
+ }
108183
+ var CONTEXT_ERROR_CODES, HookDiagnosticError;
108184
+ var init_hook_diagnostics = __esm(() => {
108185
+ CONTEXT_ERROR_CODES = new Set([
108186
+ "SKILLS_CONTEXT_FAILED",
108187
+ "PROFILE_LOCK_MISMATCH",
108188
+ "PROFILE_IDENTITY_MISMATCH",
108189
+ "PROFILE_APPLIED_REPORT_FAILED",
108190
+ "CACHED_AUTHORITY_REQUIRED",
108191
+ "CACHED_PROFILE_EXPIRED",
108192
+ "CACHED_PROFILE_MISSING",
108193
+ "CACHED_BUNDLE_MISSING",
108194
+ "INVALID_CONTEXT_INPUT",
108195
+ "CONTEXT_INPUT_TOO_LARGE",
108196
+ "INVALID_CONTEXT_BUDGET",
108197
+ "INVALID_SELECTION",
108198
+ "INVALID_SELECTION_ALIASES",
108199
+ "INVALID_RECEIPT",
108200
+ "INVALID_CACHE_FILE",
108201
+ "UNSAFE_CACHE_PATH",
108202
+ "RECEIPT_TOO_LARGE",
108203
+ "BUNDLE_DIGEST_MISMATCH",
108204
+ "BUNDLE_IDENTITY_MISMATCH",
108205
+ "BUNDLE_UNAVAILABLE",
108206
+ "BUNDLE_TOO_LARGE",
108207
+ "SKILL_NOT_SELECTED",
108208
+ "INVALID_SESSION",
108209
+ "SESSION_PARENT_NOT_FOUND",
108210
+ "SESSION_NOT_FOUND",
108211
+ "SESSION_GENERATION_CHANGED",
108212
+ "SESSION_GENERATION_EXHAUSTED",
108213
+ "SESSION_PARENT_CHANGED",
108214
+ "SESSION_RECEIPT_CHANGED",
108215
+ "SESSION_RECONCILIATION_INCOMPLETE",
108216
+ "SESSION_WRITE_LOCKED",
108217
+ "SESSION_WRITE_LOCK_CHANGED"
108218
+ ]);
108219
+ HookDiagnosticError = class HookDiagnosticError extends Error {
108220
+ code;
108221
+ stage;
108222
+ constructor(code2, stage) {
108223
+ super("Skills hook operation failed");
108224
+ this.code = code2;
108225
+ this.stage = stage;
108226
+ }
108227
+ };
108228
+ });
108229
+
107301
108230
  // src/cli/commands/agent-integration.ts
107302
108231
  var exports_agent_integration = {};
107303
108232
  __export(exports_agent_integration, {
107304
108233
  registerAgentIntegration: () => registerAgentIntegration
107305
108234
  });
107306
108235
  import { readFileSync as readFileSync37 } from "fs";
107307
- import { isAbsolute as isAbsolute22 } from "path";
108236
+ import { isAbsolute as isAbsolute25 } from "path";
108237
+ function pinnedHookProfile(input3, configuredProfile) {
108238
+ try {
108239
+ const parsed = parseSkillContextInput(JSON.stringify(input3));
108240
+ if (!parsed.sessionId)
108241
+ return configuredProfile;
108242
+ const sessionId = parsed.agentId ? `${parsed.sessionId}:${parsed.agentId}` : parsed.sessionId;
108243
+ const session = readSkillSessionSnapshotIfExists(sessionId);
108244
+ const parent = !session && parsed.agentId ? readSkillSessionSnapshotIfExists(parsed.sessionId) : null;
108245
+ return session?.receipt.profile.profileId ?? parent?.receipt.profile.profileId ?? configuredProfile;
108246
+ } catch (error61) {
108247
+ if (error61 instanceof SkillSelectionError)
108248
+ throw new HookDiagnosticError(error61.code, "context");
108249
+ throw error61;
108250
+ }
108251
+ }
107308
108252
  async function contextForHook(input3, profileId, cached2, deadline) {
107309
108253
  const remaining = deadline - Date.now();
107310
108254
  if (remaining <= 0)
107311
- throw new Error("Skills hook deadline exceeded");
108255
+ throw new HookDiagnosticError("SKILLS_HOOK_TIMEOUT", "context");
107312
108256
  const args2 = [process.execPath, process.argv[1], "context", "--stdin", "--json", "--selection-profile", profileId];
107313
108257
  if (cached2)
107314
108258
  args2.push("--cached");
107315
108259
  const child = Bun.spawn(args2, { stdin: new Blob([JSON.stringify(input3)]), stdout: "pipe", stderr: "pipe", env: { ...process.env, NO_COLOR: "1" } });
107316
- const timer = setTimeout(() => child.kill("SIGKILL"), Math.min(6500, remaining));
108260
+ let timedOut = false;
108261
+ const timer = setTimeout(() => {
108262
+ timedOut = true;
108263
+ child.kill("SIGKILL");
108264
+ }, Math.min(6500, remaining));
107317
108265
  let result2;
107318
108266
  let status;
108267
+ let output2;
107319
108268
  try {
107320
108269
  const [stdout, , exitCode] = await Promise.all([new Response(child.stdout).text(), new Response(child.stderr).text(), child.exited]);
108270
+ if (timedOut)
108271
+ throw new HookDiagnosticError("SKILLS_HOOK_TIMEOUT", "context");
107321
108272
  status = exitCode;
107322
- result2 = JSON.parse(stdout);
108273
+ output2 = stdout;
107323
108274
  } finally {
107324
108275
  clearTimeout(timer);
107325
108276
  }
107326
108277
  if (status !== 0) {
107327
- if (cached2 && RECOVERABLE_CONTEXT_CACHE_ERRORS.has(result2?.error?.code)) {
108278
+ const failure = hookChildError(output2, "context");
108279
+ if (cached2 && RECOVERABLE_CONTEXT_CACHE_ERRORS.has(failure.code)) {
107328
108280
  return contextForHook(input3, profileId, false, deadline);
107329
108281
  }
107330
- throw new Error("Skills context could not be resolved");
108282
+ throw failure;
108283
+ }
108284
+ try {
108285
+ result2 = JSON.parse(output2);
108286
+ } catch {
108287
+ throw new HookDiagnosticError("SKILLS_HOOK_INVALID_RESPONSE", "context");
107331
108288
  }
107332
108289
  if (typeof result2?.context !== "string")
107333
- throw new Error("Invalid Skills context response");
108290
+ throw new HookDiagnosticError("SKILLS_HOOK_INVALID_RESPONSE", "context");
107334
108291
  return result2;
107335
108292
  }
107336
108293
  function agents(value) {
@@ -107377,6 +108334,7 @@ function registerAgentIntegration(parent) {
107377
108334
  hook.command("user-prompt").requiredOption("--agent <agent>", `Native payload/output adapter: ${INTEGRATION_AGENTS.join(", ")}`).option("--event <event>", "Native lifecycle event supplied by the installed adapter").option("--selection-profile <id>", "Selection profile to load").description("Read native lifecycle JSON on stdin and return selected context").action(async (options) => {
107378
108335
  const deadline = Date.now() + 12000;
107379
108336
  let event = options.agent === "hermes" && options.event === "pre_tool_call" ? "pre_tool_call" : "UserPromptSubmit";
108337
+ let selectionProfile;
107380
108338
  try {
107381
108339
  if (agents(options.agent).length !== 1)
107382
108340
  throw new Error("A hook invocation requires one agent");
@@ -107393,18 +108351,18 @@ function registerAgentIntegration(parent) {
107393
108351
  input3.hook_event_name = event;
107394
108352
  const projects = [process.cwd()];
107395
108353
  if (input3.cwd !== undefined) {
107396
- if (typeof input3.cwd !== "string" || !isAbsolute22(input3.cwd) || input3.cwd.includes("\x00"))
108354
+ if (typeof input3.cwd !== "string" || !isAbsolute25(input3.cwd) || input3.cwd.includes("\x00"))
107397
108355
  throw new Error("Invalid native hook working directory");
107398
108356
  projects.push(input3.cwd);
107399
108357
  }
107400
108358
  if (options.agent === "cursor") {
107401
- if (!Array.isArray(input3.workspace_roots) || input3.workspace_roots.length > 32 || input3.workspace_roots.some((path) => typeof path !== "string" || !isAbsolute22(path) || path.includes("\x00")))
108359
+ if (!Array.isArray(input3.workspace_roots) || input3.workspace_roots.length > 32 || input3.workspace_roots.some((path) => typeof path !== "string" || !isAbsolute25(path) || path.includes("\x00")))
107402
108360
  throw new Error("Invalid Cursor workspace roots");
107403
108361
  projects.push(...input3.workspace_roots);
107404
108362
  input3.cwd ??= input3.workspace_roots[0] ?? process.cwd();
107405
108363
  input3.session_id ??= input3.conversation_id;
107406
108364
  }
107407
- const selectionProfile = selectedProfileId(options.selectionProfile);
108365
+ selectionProfile = selectedProfileId(options.selectionProfile);
107408
108366
  if (options.agent === "hermes" && event === "pre_tool_call") {
107409
108367
  assertManagedAgentBridge("hermes", { projectDirs: projects, profileId: selectionProfile });
107410
108368
  assertHermesTool(input3);
@@ -107426,17 +108384,24 @@ function registerAgentIntegration(parent) {
107426
108384
  if (event === "SessionStart") {
107427
108385
  const remaining = deadline - Date.now();
107428
108386
  if (remaining <= 0)
107429
- throw new Error("Skills hook deadline exceeded");
108387
+ throw new HookDiagnosticError("SKILLS_HOOK_TIMEOUT", "sync");
107430
108388
  const refresh = Bun.spawn([process.execPath, process.argv[1], "sync", "--selection-profile", selectionProfile, "--json"], { stdin: "ignore", stdout: "pipe", stderr: "pipe", env: { ...process.env, NO_COLOR: "1" } });
107431
- const timer = setTimeout(() => refresh.kill("SIGKILL"), Math.min(6500, remaining));
108389
+ let timedOut = false;
108390
+ const timer = setTimeout(() => {
108391
+ timedOut = true;
108392
+ refresh.kill("SIGKILL");
108393
+ }, Math.min(6500, remaining));
107432
108394
  try {
107433
- const [, , status] = await Promise.all([new Response(refresh.stdout).text(), new Response(refresh.stderr).text(), refresh.exited]);
108395
+ const [stdout, , status] = await Promise.all([new Response(refresh.stdout).text(), new Response(refresh.stderr).text(), refresh.exited]);
108396
+ if (timedOut)
108397
+ throw new HookDiagnosticError("SKILLS_HOOK_TIMEOUT", "sync");
107434
108398
  if (status !== 0)
107435
- throw new Error("Session profile refresh failed");
108399
+ throw hookChildError(stdout, "sync");
107436
108400
  } finally {
107437
108401
  clearTimeout(timer);
107438
108402
  }
107439
108403
  }
108404
+ selectionProfile = pinnedHookProfile(input3, selectionProfile);
107440
108405
  const result2 = await contextForHook(input3, selectionProfile, true, deadline);
107441
108406
  const output2 = hookContextOutput(event, result2);
107442
108407
  if (options.agent === "hermes") {
@@ -107449,7 +108414,7 @@ function registerAgentIntegration(parent) {
107449
108414
  await writeCliOutput(JSON.stringify(output2));
107450
108415
  }
107451
108416
  } catch (error61) {
107452
- const reason = error61 instanceof Error && error61.message.startsWith("NATIVE_SKILL_DRIFT:") ? error61.message : "Skills context is unavailable. Run skills sync --selection-profile <id> and skills context --stdin --json to diagnose the selected profile.";
108417
+ const reason = error61 instanceof Error && error61.message.startsWith("NATIVE_SKILL_DRIFT:") ? error61.message : hookFailureReason(error61, selectionProfile);
107453
108418
  if (options.agent === "hermes") {
107454
108419
  await writeCliOutput(JSON.stringify(event === "pre_tool_call" ? { action: "block", message: reason } : { context: `Required Skills context is unavailable. ${reason} Do not substitute native skill payloads; stop and repair the bridge before task actions.` }));
107455
108420
  } else if (options.agent === "claude" && event === "PreToolUse")
@@ -107489,6 +108454,8 @@ var init_agent_integration2 = __esm(() => {
107489
108454
  init_agent_adapters();
107490
108455
  init_agent_integration();
107491
108456
  init_agent_codex_trust();
108457
+ init_hook_diagnostics();
108458
+ init_selection_cache();
107492
108459
  RECOVERABLE_CONTEXT_CACHE_ERRORS = new Set(["CACHED_PROFILE_EXPIRED", "CACHED_PROFILE_MISSING", "CACHED_BUNDLE_MISSING"]);
107493
108460
  });
107494
108461
 
@@ -107627,17 +108594,17 @@ var exports_profiles = {};
107627
108594
  __export(exports_profiles, {
107628
108595
  registerProfiles: () => registerProfiles
107629
108596
  });
107630
- import { closeSync as closeSync19, constants as constants18, fstatSync as fstatSync19, openSync as openSync19, readSync as readSync15, writeFileSync as writeFileSync24 } from "fs";
108597
+ import { closeSync as closeSync21, constants as constants20, fstatSync as fstatSync21, openSync as openSync21, readSync as readSync17, writeFileSync as writeFileSync24 } from "fs";
107631
108598
  function readProfileInput(path) {
107632
- const fd = openSync19(path, constants18.O_RDONLY | constants18.O_NONBLOCK);
108599
+ const fd = openSync21(path, constants20.O_RDONLY | constants20.O_NONBLOCK);
107633
108600
  try {
107634
- const stat3 = fstatSync19(fd);
108601
+ const stat3 = fstatSync21(fd);
107635
108602
  if (!stat3.isFile() || stat3.size > MAX_PROFILE_DOCUMENT_BYTES)
107636
108603
  throw new Error("Profile input exceeds the size limit or is not a regular file");
107637
108604
  const bytes = Buffer.alloc(MAX_PROFILE_DOCUMENT_BYTES + 1);
107638
108605
  let size2 = 0;
107639
108606
  while (size2 < bytes.length) {
107640
- const read3 = readSync15(fd, bytes, size2, bytes.length - size2, null);
108607
+ const read3 = readSync17(fd, bytes, size2, bytes.length - size2, null);
107641
108608
  if (!read3)
107642
108609
  break;
107643
108610
  size2 += read3;
@@ -107646,7 +108613,7 @@ function readProfileInput(path) {
107646
108613
  throw new Error("Profile input exceeds the size limit");
107647
108614
  return new TextDecoder("utf-8", { fatal: true }).decode(bytes.subarray(0, size2));
107648
108615
  } finally {
107649
- closeSync19(fd);
108616
+ closeSync21(fd);
107650
108617
  }
107651
108618
  }
107652
108619
  function registerProfiles(parent) {
@@ -107697,23 +108664,23 @@ __export(exports_grants, {
107697
108664
  registerGrants: () => registerGrants
107698
108665
  });
107699
108666
  import {
107700
- constants as constants19,
107701
- closeSync as closeSync20,
107702
- fstatSync as fstatSync20,
107703
- openSync as openSync20,
107704
- readSync as readSync16,
108667
+ constants as constants21,
108668
+ closeSync as closeSync23,
108669
+ fstatSync as fstatSync23,
108670
+ openSync as openSync23,
108671
+ readSync as readSync18,
107705
108672
  writeFileSync as writeFileSync25
107706
108673
  } from "fs";
107707
108674
  function readInput(path) {
107708
- const fd = openSync20(path, constants19.O_RDONLY | constants19.O_NONBLOCK);
108675
+ const fd = openSync23(path, constants21.O_RDONLY | constants21.O_NONBLOCK);
107709
108676
  try {
107710
- const stat3 = fstatSync20(fd);
108677
+ const stat3 = fstatSync23(fd);
107711
108678
  if (!stat3.isFile() || stat3.size > MAX_EXECUTION_GRANT_BYTES)
107712
108679
  throw new Error("Grant input must be a regular file within the policy size limit.");
107713
108680
  const bytes = Buffer.alloc(MAX_EXECUTION_GRANT_BYTES + 1);
107714
108681
  let size2 = 0;
107715
108682
  while (size2 < bytes.length) {
107716
- const count = readSync16(fd, bytes, size2, bytes.length - size2, null);
108683
+ const count = readSync18(fd, bytes, size2, bytes.length - size2, null);
107717
108684
  if (!count)
107718
108685
  break;
107719
108686
  size2 += count;
@@ -107726,7 +108693,7 @@ function readInput(path) {
107726
108693
  throw new Error("Grant input must be a JSON document containing a grants array.");
107727
108694
  }
107728
108695
  } finally {
107729
- closeSync20(fd);
108696
+ closeSync23(fd);
107730
108697
  }
107731
108698
  }
107732
108699
  function registerGrants(parent) {
@@ -107762,7 +108729,7 @@ var init_grants = __esm(() => {
107762
108729
  });
107763
108730
 
107764
108731
  // src/lib/station-hydrate.ts
107765
- import { createHash as createHash24 } from "crypto";
108732
+ import { createHash as createHash27 } from "crypto";
107766
108733
  import {
107767
108734
  copyFileSync as copyFileSync2,
107768
108735
  mkdirSync as mkdirSync26,
@@ -107771,7 +108738,7 @@ import {
107771
108738
  statSync as statSync21,
107772
108739
  writeFileSync as writeFileSync26
107773
108740
  } from "fs";
107774
- import { dirname as dirname28, join as join57, resolve as resolve20, sep as sep10 } from "path";
108741
+ import { dirname as dirname30, join as join57, resolve as resolve23, sep as sep10 } from "path";
107775
108742
  function fail5(code2, message, detail = []) {
107776
108743
  throw new StationSnapshotError(code2, message, detail);
107777
108744
  }
@@ -107965,12 +108932,12 @@ function skillSha256(skill) {
107965
108932
  return sha256File(skill.files[0].winner.fullPath);
107966
108933
  }
107967
108934
  const joined = skill.files.map((file2) => sha256File(file2.winner.fullPath));
107968
- return createHash24("sha256").update(joined.sort().join(`
108935
+ return createHash27("sha256").update(joined.sort().join(`
107969
108936
  `)).digest("hex");
107970
108937
  }
107971
108938
  function writeStationHydration(options) {
107972
- const repoRoot = resolve20(options.repoRoot ?? process.cwd());
107973
- const cacheRoot = resolve20(options.cacheRoot ?? resolveCorpusRoot());
108939
+ const repoRoot = resolve23(options.repoRoot ?? process.cwd());
108940
+ const cacheRoot = resolve23(options.cacheRoot ?? resolveCorpusRoot());
107974
108941
  const plan = planStationHydration(options.stationId, repoRoot);
107975
108942
  const resultSkills = plan.winners.map((skill) => ({
107976
108943
  ident: skill.ident,
@@ -108004,13 +108971,13 @@ function writeStationHydration(options) {
108004
108971
  for (const skill of plan.winners) {
108005
108972
  for (const file2 of skill.files) {
108006
108973
  const destination = join57(cacheRoot, skill.ident, file2.withinIdent);
108007
- const digest3 = sha256File(file2.winner.fullPath);
108974
+ const digest4 = sha256File(file2.winner.fullPath);
108008
108975
  let existingDigest = null;
108009
108976
  try {
108010
108977
  existingDigest = sha256File(destination);
108011
108978
  } catch {}
108012
108979
  if (existingDigest !== null) {
108013
- if (existingDigest === digest3) {
108980
+ if (existingDigest === digest4) {
108014
108981
  continue;
108015
108982
  }
108016
108983
  conflicts.push(`existing destination differs from snapshot winner: ${destination}`);
@@ -108024,7 +108991,7 @@ function writeStationHydration(options) {
108024
108991
  }
108025
108992
  let written = 0;
108026
108993
  for (const entry of toWrite) {
108027
- mkdirSync26(dirname28(entry.destination), { recursive: true });
108994
+ mkdirSync26(dirname30(entry.destination), { recursive: true });
108028
108995
  copyFileSync2(entry.fullPath, entry.destination);
108029
108996
  written += 1;
108030
108997
  }
@@ -108045,8 +109012,8 @@ function writeStationHydration(options) {
108045
109012
  },
108046
109013
  skills: resultSkills
108047
109014
  };
108048
- const hydrationManifestPath = join57(dirname28(cacheRoot), `hydration-${options.stationId}.json`);
108049
- mkdirSync26(dirname28(hydrationManifestPath), { recursive: true });
109015
+ const hydrationManifestPath = join57(dirname30(cacheRoot), `hydration-${options.stationId}.json`);
109016
+ mkdirSync26(dirname30(hydrationManifestPath), { recursive: true });
108050
109017
  writeFileSync26(hydrationManifestPath, `${JSON.stringify(hydration, null, 2)}
108051
109018
  `);
108052
109019
  return {
@@ -108122,10 +109089,10 @@ var init_hydrate = __esm(() => {
108122
109089
  });
108123
109090
 
108124
109091
  // src/lib/prepare-skill.ts
108125
- import { createHash as createHash25, randomUUID as randomUUID11 } from "crypto";
108126
- import { chmodSync as chmodSync3, existsSync as existsSync34, lstatSync as lstatSync27, mkdirSync as mkdirSync27, mkdtempSync as mkdtempSync6, readFileSync as readFileSync39, readdirSync as readdirSync22, renameSync as renameSync12, rmSync as rmSync9, writeFileSync as writeFileSync27 } from "fs";
109092
+ import { createHash as createHash28, randomUUID as randomUUID11 } from "crypto";
109093
+ import { chmodSync as chmodSync3, existsSync as existsSync34, lstatSync as lstatSync29, mkdirSync as mkdirSync27, mkdtempSync as mkdtempSync6, readFileSync as readFileSync39, readdirSync as readdirSync22, renameSync as renameSync12, rmSync as rmSync9, writeFileSync as writeFileSync27 } from "fs";
108127
109094
  import { tmpdir as tmpdir2 } from "os";
108128
- import { dirname as dirname29, isAbsolute as isAbsolute23, join as join58, relative as relative9, resolve as resolve21, sep as sep11 } from "path";
109095
+ import { dirname as dirname31, isAbsolute as isAbsolute26, join as join58, relative as relative9, resolve as resolve24, sep as sep11 } from "path";
108129
109096
  function prepareSkill(name, options) {
108130
109097
  const normalized = normalizePortableSkillName(name);
108131
109098
  if (!new RegExp(SEMVER_PATTERN).test(options.version))
@@ -108170,7 +109137,7 @@ function prepareSkill(name, options) {
108170
109137
  mkdirSync27(join58(staging, directory2), { recursive: true });
108171
109138
  for (const file2 of before2.files) {
108172
109139
  const destination = join58(staging, file2.path);
108173
- mkdirSync27(dirname29(destination), { recursive: true });
109140
+ mkdirSync27(dirname31(destination), { recursive: true });
108174
109141
  writeFileSync27(destination, file2.bytes, { mode: file2.mode });
108175
109142
  }
108176
109143
  const stagedManifest = join58(staging, "skill.json");
@@ -108230,8 +109197,8 @@ function validateRuntimeEntrypoint(candidate2, root2) {
108230
109197
  const entry = candidate2.runtime.entrypoint;
108231
109198
  if (typeof entry !== "string")
108232
109199
  return;
108233
- const target = resolve21(root2, entry), rel = relative9(root2, target);
108234
- if (isAbsolute23(entry) || /^[a-zA-Z]:/.test(entry) || entry.includes("\\") || !rel || rel === ".." || rel.startsWith(`..${sep11}`) || isAbsolute23(rel) || !existsSync34(target) || !lstatSync27(target).isFile()) {
109200
+ const target = resolve24(root2, entry), rel = relative9(root2, target);
109201
+ if (isAbsolute26(entry) || /^[a-zA-Z]:/.test(entry) || entry.includes("\\") || !rel || rel === ".." || rel.startsWith(`..${sep11}`) || isAbsolute26(rel) || !existsSync34(target) || !lstatSync29(target).isFile()) {
108235
109202
  throw new Error("Executable runtime.entrypoint must name an existing regular file inside the skill directory.");
108236
109203
  }
108237
109204
  }
@@ -108239,31 +109206,31 @@ function isRecord6(value) {
108239
109206
  return typeof value === "object" && value !== null && !Array.isArray(value);
108240
109207
  }
108241
109208
  function validateRawCandidate(candidate2) {
108242
- for (const field of ["standard", "name", "description", "version"]) {
108243
- if (typeof candidate2[field] !== "string" || !candidate2[field].trim())
108244
- throw new Error(`skill.json ${field} is required.`);
109209
+ for (const field2 of ["standard", "name", "description", "version"]) {
109210
+ if (typeof candidate2[field2] !== "string" || !candidate2[field2].trim())
109211
+ throw new Error(`skill.json ${field2} is required.`);
108245
109212
  }
108246
- for (const field of ["displayName", "category"]) {
108247
- if (candidate2[field] !== undefined && (typeof candidate2[field] !== "string" || !candidate2[field].trim()))
108248
- throw new Error(`Invalid skill.json ${field}.`);
109213
+ for (const field2 of ["displayName", "category"]) {
109214
+ if (candidate2[field2] !== undefined && (typeof candidate2[field2] !== "string" || !candidate2[field2].trim()))
109215
+ throw new Error(`Invalid skill.json ${field2}.`);
108249
109216
  }
108250
109217
  if (candidate2.tags !== undefined && (!Array.isArray(candidate2.tags) || candidate2.tags.some((tag) => typeof tag !== "string" || !tag.trim())))
108251
109218
  throw new Error("Invalid skill.json tags.");
108252
109219
  const issues = validatePortableManifestContract(candidate2, { strict: true });
108253
109220
  if (issues.length)
108254
109221
  throw new Error(`Invalid skill.json: ${issues.map((issue2) => issue2.code).join(", ")}`);
108255
- for (const field of ["inputs", "commands"]) {
108256
- const items = candidate2[field];
109222
+ for (const field2 of ["inputs", "commands"]) {
109223
+ const items = candidate2[field2];
108257
109224
  if (items === undefined)
108258
109225
  continue;
108259
109226
  if (!Array.isArray(items))
108260
- throw new Error(`skill.json ${field} must be an array.`);
109227
+ throw new Error(`skill.json ${field2} must be an array.`);
108261
109228
  for (const item of items) {
108262
109229
  if (!isRecord6(item) || typeof item.name !== "string" || !item.name.trim())
108263
- throw new Error(`Invalid skill.json ${field} name.`);
108264
- if (field === "inputs" && (typeof item.type !== "string" || !item.type.trim() || item.required !== undefined && typeof item.required !== "boolean"))
109230
+ throw new Error(`Invalid skill.json ${field2} name.`);
109231
+ if (field2 === "inputs" && (typeof item.type !== "string" || !item.type.trim() || item.required !== undefined && typeof item.required !== "boolean"))
108265
109232
  throw new Error("Invalid skill.json input type or required flag.");
108266
- if (field === "commands") {
109233
+ if (field2 === "commands") {
108267
109234
  if (!/^[a-z0-9][a-z0-9._-]*$/.test(item.name))
108268
109235
  throw new Error("Invalid skill.json command name.");
108269
109236
  for (const target of ["entry", "command"])
@@ -108303,11 +109270,11 @@ function compareVersions(left, right) {
108303
109270
  return 0;
108304
109271
  }
108305
109272
  function snapshot2(root2) {
108306
- const rootStat = lstatSync27(root2);
109273
+ const rootStat = lstatSync29(root2);
108307
109274
  if (rootStat.isSymbolicLink() || !rootStat.isDirectory())
108308
109275
  throw new Error("Skill root must be a real directory, not a symlink.");
108309
109276
  const files = [], directories = [];
108310
- const hash4 = createHash25("sha256").update(`${rootStat.dev}:${rootStat.ino}\x00`);
109277
+ const hash4 = createHash28("sha256").update(`${rootStat.dev}:${rootStat.ino}\x00`);
108311
109278
  let count = 0, bytes = 0;
108312
109279
  const walk2 = (relative10) => {
108313
109280
  for (const name of readdirSync22(join58(root2, relative10)).sort()) {
@@ -108316,7 +109283,7 @@ function snapshot2(root2) {
108316
109283
  const path = relative10 ? `${relative10}/${name}` : name;
108317
109284
  if (++count > 20000)
108318
109285
  throw new Error("Skill exceeds the preparation entry limit (20000).");
108319
- const absolute = join58(root2, path), stat3 = lstatSync27(absolute);
109286
+ const absolute = join58(root2, path), stat3 = lstatSync29(absolute);
108320
109287
  if (stat3.isSymbolicLink())
108321
109288
  throw new Error(`Skill contains a symlink: ${path}. No files were changed.`);
108322
109289
  if (stat3.isDirectory() && name === "node_modules")
@@ -108731,7 +109698,7 @@ var init_schedule = __esm(() => {
108731
109698
 
108732
109699
  // src/lib/registry-sync.ts
108733
109700
  import { mkdirSync as mkdirSync28, writeFileSync as writeFileSync28 } from "fs";
108734
- import { dirname as dirname30, relative as relative10 } from "path";
109701
+ import { dirname as dirname32, relative as relative10 } from "path";
108735
109702
  function createRegistrySyncArtifact(options = {}) {
108736
109703
  const profile = options.profile ?? "all";
108737
109704
  const includeDocs = options.includeDocs ?? true;
@@ -108788,7 +109755,7 @@ function createRegistrySyncArtifact(options = {}) {
108788
109755
  };
108789
109756
  }
108790
109757
  function writeRegistrySyncArtifact(path, artifact) {
108791
- mkdirSync28(dirname30(path), { recursive: true });
109758
+ mkdirSync28(dirname32(path), { recursive: true });
108792
109759
  writeFileSync28(path, `${JSON.stringify(artifact, null, 2)}
108793
109760
  `);
108794
109761
  }
@@ -108821,12 +109788,12 @@ function registerRegistry(parent) {
108821
109788
  async function writeJson2(value, space) {
108822
109789
  const text3 = `${JSON.stringify(value, null, space)}
108823
109790
  `;
108824
- await new Promise((resolve22, reject2) => {
109791
+ await new Promise((resolve25, reject2) => {
108825
109792
  process.stdout.write(text3, (error61) => {
108826
109793
  if (error61)
108827
109794
  reject2(error61);
108828
109795
  else
108829
- resolve22();
109796
+ resolve25();
108830
109797
  });
108831
109798
  });
108832
109799
  }
@@ -109283,7 +110250,7 @@ var exports_private_publications = {};
109283
110250
  __export(exports_private_publications, {
109284
110251
  registerPrivatePublications: () => registerPrivatePublications
109285
110252
  });
109286
- import { resolve as resolve22 } from "path";
110253
+ import { resolve as resolve25 } from "path";
109287
110254
  function verifyOptions(options, action) {
109288
110255
  if (options.userId === undefined !== (options.membershipId === undefined) || options.userId !== undefined && (!publicationUuid(options.userId) || !publicationUuid(options.membershipId)))
109289
110256
  throw new PrivatePublicationError("PUBLICATION_CONTEXT_REQUIRED", "Provide both observed --user-id and --membership-id UUIDs.");
@@ -109328,9 +110295,9 @@ function registerPrivatePublications(parent) {
109328
110295
  if (code2 === null)
109329
110296
  return;
109330
110297
  const context2 = options.userId ? { userId: options.userId, membershipId: options.membershipId } : undefined;
109331
- const client2 = await privatePublicationSession(options.email, code2, context2), directory2 = resolve22(options.recoveryDir);
110298
+ const client2 = await privatePublicationSession(options.email, code2, context2), directory2 = resolve25(options.recoveryDir);
109332
110299
  if (action === "publish")
109333
- await preparePrivatePublication(client2, resolve22(args2[0]), directory2, { skillId: options.skillId, expectedCurrentVersionId: options.expectedCurrentVersion ?? null, idempotencyKey: options.idempotencyKey });
110300
+ await preparePrivatePublication(client2, resolve25(args2[0]), directory2, { skillId: options.skillId, expectedCurrentVersionId: options.expectedCurrentVersion ?? null, idempotencyKey: options.idempotencyKey });
109334
110301
  const result2 = action === "publish" || action === "resume" ? await continuePrivatePublication(client2, directory2, { confirm: true, waitMs: Number(options.waitSeconds) * 1000 }) : await inspectPrivatePublication(client2, directory2, action === "cancel");
109335
110302
  print2(result2, options.json);
109336
110303
  } catch (error61) {
@@ -109431,7 +110398,7 @@ __export(exports_auth, {
109431
110398
  import { createInterface as createInterface3 } from "readline";
109432
110399
  function prompt(question) {
109433
110400
  const rl = createInterface3({ input: process.stdin, output: process.stdout });
109434
- return new Promise((resolve23) => {
110401
+ return new Promise((resolve26) => {
109435
110402
  let settled = false;
109436
110403
  const finish = (answer) => {
109437
110404
  if (settled)
@@ -109440,7 +110407,7 @@ function prompt(question) {
109440
110407
  rl.close();
109441
110408
  if (answer === null)
109442
110409
  process.exitCode = 130;
109443
- resolve23(answer);
110410
+ resolve26(answer);
109444
110411
  };
109445
110412
  rl.once("SIGINT", () => finish(null));
109446
110413
  rl.once("close", () => finish(null));
@@ -109548,7 +110515,7 @@ function printWhoami(payload) {
109548
110515
  console.log(source_default.dim("(offline \u2014 showing cached info)"));
109549
110516
  }
109550
110517
  function sleep(ms) {
109551
- return new Promise((resolve23) => setTimeout(resolve23, ms));
110518
+ return new Promise((resolve26) => setTimeout(resolve26, ms));
109552
110519
  }
109553
110520
  function browserCommand(url2) {
109554
110521
  if (process.platform === "darwin")
@@ -110050,7 +111017,7 @@ function promptInvitationProof(kind) {
110050
111017
  const label = kind === "token" ? "invitation token" : "recovery code";
110051
111018
  const character = kind === "token" ? /^[A-Za-z0-9_-]$/ : /^\d$/;
110052
111019
  const { stdin, stderr: output2 } = process, wasRaw = stdin.isRaw, wasFlowing = stdin.readableFlowing;
110053
- return new Promise((resolve23) => {
111020
+ return new Promise((resolve26) => {
110054
111021
  let value = "", settled = false, overflow = false;
110055
111022
  const finish = (answer) => {
110056
111023
  if (settled)
@@ -110067,7 +111034,7 @@ function promptInvitationProof(kind) {
110067
111034
  `);
110068
111035
  if (answer === null)
110069
111036
  process.exitCode = 130;
110070
- resolve23(answer);
111037
+ resolve26(answer);
110071
111038
  };
110072
111039
  const cancel = () => finish(null);
110073
111040
  const keypress = (text3, key) => {
@@ -110777,8 +111744,8 @@ async function currentRemoteDigest(client2, slug2) {
110777
111744
  }
110778
111745
  if (!body || typeof body !== "object")
110779
111746
  return;
110780
- const digest3 = body.bundleSha256;
110781
- return typeof digest3 === "string" && digest3 ? digest3 : undefined;
111747
+ const digest4 = body.bundleSha256;
111748
+ return typeof digest4 === "string" && digest4 ? digest4 : undefined;
110782
111749
  }
110783
111750
  async function reconcileRegistry(options = {}) {
110784
111751
  const conflict = options.conflict ?? "skip";