@hasna/skills 0.10.1 → 0.10.2

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.10.1",
36871
+ version: "0.10.2",
36872
36872
  description: "Skills library for AI coding agents",
36873
36873
  type: "module",
36874
36874
  bin: {
@@ -49704,7 +49704,9 @@ var init_skill_version = __esm(() => {
49704
49704
 
49705
49705
  // src/lib/selection-cache.ts
49706
49706
  import { createHash as createHash7, randomUUID as randomUUID3 } from "crypto";
49707
- import { closeSync as closeSync6, constants as constants4, fstatSync as fstatSync6, fsyncSync, lstatSync as lstatSync9, mkdirSync as mkdirSync3, openSync as openSync6, readSync as readSync3, renameSync, unlinkSync, writeFileSync as writeFileSync3 } from "fs";
49707
+ import { spawnSync as spawnSync2 } from "child_process";
49708
+ import { closeSync as closeSync6, constants as constants4, fstatSync as fstatSync6, fsyncSync, lstatSync as lstatSync9, mkdirSync as mkdirSync3, openSync as openSync6, readFileSync as readFileSync10, readlinkSync as readlinkSync2, readSync as readSync3, renameSync, unlinkSync, writeFileSync as writeFileSync3 } from "fs";
49709
+ import { hostname } from "os";
49708
49710
  import { dirname as dirname8, join as join16, parse as parse2, resolve as resolve8 } from "path";
49709
49711
  import { isDeepStrictEqual as isDeepStrictEqual2 } from "util";
49710
49712
  function selectionCacheRoot(options = {}) {
@@ -49986,6 +49988,201 @@ function readSkillSessionSnapshot(sessionId, options = {}) {
49986
49988
  function skillSessionSnapshotBinding(snapshot) {
49987
49989
  return { sessionId: snapshot.sessionId, generation: snapshot.generation, receiptSha256: snapshot.receiptSha256 };
49988
49990
  }
49991
+ function localBootId() {
49992
+ try {
49993
+ if (process.platform === "linux") {
49994
+ const value = readFileSync10("/proc/sys/kernel/random/boot_id", "utf8").trim();
49995
+ return /^[a-f0-9-]{36}$/i.test(value) ? value : null;
49996
+ }
49997
+ if (process.platform === "darwin") {
49998
+ const result2 = spawnSync2("/usr/sbin/sysctl", ["-n", "kern.boottime"], { encoding: "utf8", timeout: 3000, env: { LC_ALL: "C" } });
49999
+ if (result2.status !== 0 || result2.error)
50000
+ return null;
50001
+ const seconds = /\bsec\s*=\s*(\d+)\b/.exec(result2.stdout)?.[1];
50002
+ return seconds ? `darwin:${seconds}` : null;
50003
+ }
50004
+ } catch {}
50005
+ return null;
50006
+ }
50007
+ function processStart(pid) {
50008
+ if (!Number.isSafeInteger(pid) || pid <= 0)
50009
+ return { state: "unknown" };
50010
+ if (process.platform === "linux") {
50011
+ try {
50012
+ const stat = readFileSync10(`/proc/${pid}/stat`, "utf8");
50013
+ const close = stat.lastIndexOf(")");
50014
+ const start = close < 0 ? undefined : stat.slice(close + 2).trim().split(/\s+/)[19];
50015
+ return start && /^\d+$/.test(start) ? { state: "alive", start: `linux:${start}` } : { state: "unknown" };
50016
+ } catch (error) {
50017
+ return { state: error.code === "ENOENT" ? "absent" : "unknown" };
50018
+ }
50019
+ }
50020
+ if (process.platform === "darwin") {
50021
+ const result2 = spawnSync2("/bin/ps", ["-p", String(pid), "-o", "lstart="], { encoding: "utf8", timeout: 3000, env: { LC_ALL: "C" } });
50022
+ if (result2.error || result2.signal)
50023
+ return { state: "unknown" };
50024
+ const start = result2.stdout.trim();
50025
+ if (result2.status === 1 && !start && !result2.stderr.trim())
50026
+ return { state: "absent" };
50027
+ return result2.status === 0 && start ? { state: "alive", start: `darwin:${start}` } : { state: "unknown" };
50028
+ }
50029
+ return { state: "unknown" };
50030
+ }
50031
+ function localLockIdentity() {
50032
+ const bootId = localBootId(), owner = processStart(process.pid);
50033
+ if (!bootId || owner.state !== "alive")
50034
+ return null;
50035
+ let pidNamespace;
50036
+ if (process.platform === "linux") {
50037
+ try {
50038
+ pidNamespace = readlinkSync2("/proc/self/ns/pid");
50039
+ } catch {
50040
+ return null;
50041
+ }
50042
+ if (!/^pid:\[\d+\]$/.test(pidNamespace))
50043
+ return null;
50044
+ }
50045
+ return { host: hostname(), bootId, pidNamespace, processStart: owner.start };
50046
+ }
50047
+ function readSessionLock(sessionId, options) {
50048
+ const path = `${sessionReceiptPath(sessionId, options)}.write-lock`;
50049
+ const before2 = lstatSync9(path, { throwIfNoEntry: false });
50050
+ if (!before2)
50051
+ return null;
50052
+ if (!before2.isFile() || before2.nlink !== 1 || process.getuid && before2.uid !== process.getuid()) {
50053
+ throw new SkillSelectionError("SESSION_WRITE_LOCKED", "The session lock is not a private regular file; recovery requires review.");
50054
+ }
50055
+ const bytes = readRegularFile(path, SESSION_LOCK_MAX_BYTES);
50056
+ const after2 = lstatSync9(path, { throwIfNoEntry: false });
50057
+ if (!bytes || !after2?.isFile() || before2.dev !== after2.dev || before2.ino !== after2.ino || before2.mtimeMs !== after2.mtimeMs) {
50058
+ throw new SkillSelectionError("SESSION_WRITE_LOCKED", "The session lock changed during inspection; recovery requires review.");
50059
+ }
50060
+ let marker;
50061
+ try {
50062
+ marker = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(bytes));
50063
+ } catch {
50064
+ throw new SkillSelectionError("SESSION_WRITE_LOCKED", "The session lock is unreadable; recovery requires review.");
50065
+ }
50066
+ if (!marker || ![1, 2].includes(marker.schemaVersion) || marker.sessionId !== sessionId || !/^[a-f0-9-]{36}$/i.test(marker.operationId) || !Number.isSafeInteger(marker.pid) || marker.pid <= 0 || marker.schemaVersion === 2 && (!marker.host || !marker.bootId || !marker.processStart || process.platform === "linux" && !marker.pidNamespace)) {
50067
+ throw new SkillSelectionError("SESSION_WRITE_LOCKED", "The session lock has invalid ownership metadata; recovery requires review.");
50068
+ }
50069
+ return { path, bytes, marker, sha256: sha256Hex(bytes), dev: after2.dev, ino: after2.ino, mtimeMs: after2.mtimeMs };
50070
+ }
50071
+ function writerIsGone(lock, explicitLocalHost) {
50072
+ if (Date.now() - lock.mtimeMs < SESSION_LOCK_MIN_AGE_MS)
50073
+ return false;
50074
+ const owner = processStart(lock.marker.pid);
50075
+ if (owner.state === "unknown")
50076
+ return false;
50077
+ if (lock.marker.schemaVersion === 1)
50078
+ return explicitLocalHost && owner.state === "absent";
50079
+ const local = localLockIdentity();
50080
+ if (!local || lock.marker.host !== local.host || lock.marker.bootId !== local.bootId || lock.marker.pidNamespace !== local.pidNamespace)
50081
+ return false;
50082
+ return owner.state === "absent" || owner.state === "alive" && owner.start !== lock.marker.processStart;
50083
+ }
50084
+ function lockReviewDigest(lock, receipt) {
50085
+ return hash({
50086
+ sessionId: lock.marker.sessionId,
50087
+ lockSha256: lock.sha256,
50088
+ lockDev: lock.dev,
50089
+ lockIno: lock.ino,
50090
+ lockMtimeMs: lock.mtimeMs,
50091
+ receiptSha256: receipt?.sha256 ?? null,
50092
+ receiptGeneration: receipt?.generation ?? null
50093
+ });
50094
+ }
50095
+ function inspectSessionWriteLock(sessionId, options = {}) {
50096
+ const receipt = readSkillSessionSnapshotIfExists(sessionId, options), lock = readSessionLock(sessionId, options);
50097
+ if (!lock)
50098
+ throw new SkillSelectionError("SESSION_WRITE_LOCK_NOT_FOUND", "The session has no write lock to recover.");
50099
+ return {
50100
+ sessionId,
50101
+ schemaVersion: lock.marker.schemaVersion,
50102
+ pid: lock.marker.pid,
50103
+ lockSha256: lock.sha256,
50104
+ lockMtime: new Date(lock.mtimeMs).toISOString(),
50105
+ receiptSha256: receipt?.sha256 ?? null,
50106
+ receiptGeneration: receipt?.generation ?? null,
50107
+ reviewDigest: lockReviewDigest(lock, receipt),
50108
+ hostBound: lock.marker.schemaVersion === 2
50109
+ };
50110
+ }
50111
+ function archiveSessionLock(lock, receipt, explicitLocalHost) {
50112
+ const guardPath = `${lock.path}.recovery-guard`;
50113
+ let guardFd;
50114
+ try {
50115
+ guardFd = openSync6(guardPath, constants4.O_WRONLY | constants4.O_CREAT | constants4.O_EXCL | constants4.O_NOFOLLOW, 384);
50116
+ } catch (error) {
50117
+ if (error.code === "EEXIST")
50118
+ return null;
50119
+ throw error;
50120
+ }
50121
+ const guardStat = fstatSync6(guardFd);
50122
+ try {
50123
+ writeFileSync3(guardFd, `${JSON.stringify({ schemaVersion: 1, pid: process.pid, operationId: randomUUID3() })}
50124
+ `);
50125
+ fsyncSync(guardFd);
50126
+ const cacheOptions = { cacheDir: dirname8(dirname8(lock.path)) };
50127
+ const current = readSessionLock(lock.marker.sessionId, cacheOptions);
50128
+ if (!current || current.dev !== lock.dev || current.ino !== lock.ino || current.sha256 !== lock.sha256 || current.mtimeMs !== lock.mtimeMs || !writerIsGone(current, explicitLocalHost))
50129
+ return null;
50130
+ const currentReceipt = readSkillSessionSnapshotIfExists(lock.marker.sessionId, cacheOptions);
50131
+ if (currentReceipt?.sha256 !== receipt?.sha256 || currentReceipt?.generation !== receipt?.generation)
50132
+ return null;
50133
+ const directory = join16(dirname8(dirname8(lock.path)), "session-lock-recoveries", randomUUID3());
50134
+ const archivePath = join16(directory, "original.write-lock");
50135
+ const recordPath = join16(directory, "recovery.json");
50136
+ assertRegularPath(archivePath, true);
50137
+ archiveBytes(recordPath, Buffer.from(`${JSON.stringify({
50138
+ schemaVersion: 1,
50139
+ sessionId: lock.marker.sessionId,
50140
+ originalPath: lock.path,
50141
+ lockSha256: lock.sha256,
50142
+ lockMtime: new Date(lock.mtimeMs).toISOString(),
50143
+ lockPid: lock.marker.pid,
50144
+ receiptSha256: receipt?.sha256 ?? null,
50145
+ receiptGeneration: receipt?.generation ?? null,
50146
+ status: "prepared"
50147
+ })}
50148
+ `));
50149
+ syncDirectory(directory);
50150
+ syncDirectory(dirname8(directory));
50151
+ const finalLock = readSessionLock(lock.marker.sessionId, cacheOptions);
50152
+ if (!finalLock || finalLock.dev !== lock.dev || finalLock.ino !== lock.ino || finalLock.sha256 !== lock.sha256 || readSkillSessionSnapshotIfExists(lock.marker.sessionId, cacheOptions)?.sha256 !== receipt?.sha256)
50153
+ return null;
50154
+ let moved = false;
50155
+ try {
50156
+ renameSync(lock.path, archivePath);
50157
+ moved = true;
50158
+ syncDirectory(directory);
50159
+ syncDirectory(dirname8(lock.path));
50160
+ if (sha256Hex(readRegularFile(archivePath, SESSION_LOCK_MAX_BYTES)) !== lock.sha256) {
50161
+ throw new Error("Archived lock bytes changed");
50162
+ }
50163
+ } catch (error) {
50164
+ if (moved)
50165
+ throw new SkillSelectionError("SESSION_LOCK_RECOVERY_INCOMPLETE", "The lock moved, but durable recovery could not be confirmed; inspect the preserved recovery directory and session receipt.");
50166
+ throw error;
50167
+ }
50168
+ return archivePath;
50169
+ } finally {
50170
+ closeSync6(guardFd);
50171
+ const current = lstatSync9(guardPath, { throwIfNoEntry: false });
50172
+ if (current?.isFile() && current.dev === guardStat.dev && current.ino === guardStat.ino)
50173
+ unlinkSync(guardPath);
50174
+ }
50175
+ }
50176
+ function recoverSessionWriteLock(sessionId, reviewDigest, options = {}) {
50177
+ const receipt = readSkillSessionSnapshotIfExists(sessionId, options), lock = readSessionLock(sessionId, options);
50178
+ if (!lock || lockReviewDigest(lock, receipt) !== reviewDigest) {
50179
+ throw new SkillSelectionError("SESSION_LOCK_REVIEW_CHANGED", "The lock or receipt changed after review; inspect the session lock again.");
50180
+ }
50181
+ const archivePath = archiveSessionLock(lock, receipt, true);
50182
+ if (!archivePath)
50183
+ throw new SkillSelectionError("SESSION_WRITE_LOCKED", "The lock is live, too recent, or changed during recovery; leave it in place and inspect again.");
50184
+ return archivePath;
50185
+ }
49989
50186
  function withSessionWriteLocks(sessionIds, options, action) {
49990
50187
  const operationId = randomUUID3();
49991
50188
  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);
@@ -50005,13 +50202,30 @@ function withSessionWriteLocks(sessionIds, options, action) {
50005
50202
  try {
50006
50203
  fd = openSync6(lock.path, constants4.O_WRONLY | constants4.O_CREAT | constants4.O_EXCL | constants4.O_NOFOLLOW, 384);
50007
50204
  } catch (error) {
50008
- if (error.code === "EEXIST")
50009
- 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.");
50010
- throw error;
50205
+ if (error.code !== "EEXIST")
50206
+ throw error;
50207
+ try {
50208
+ const stale = readSessionLock(lock.sessionId, options);
50209
+ const receipt = stale && readSkillSessionSnapshotIfExists(lock.sessionId, options);
50210
+ if (stale?.marker.schemaVersion === 2 && writerIsGone(stale, false)) {
50211
+ archiveSessionLock(stale, receipt, false);
50212
+ }
50213
+ } catch (recoveryError) {
50214
+ if (recoveryError instanceof SkillSelectionError && recoveryError.code === "SESSION_LOCK_RECOVERY_INCOMPLETE")
50215
+ throw recoveryError;
50216
+ }
50217
+ try {
50218
+ fd = openSync6(lock.path, constants4.O_WRONLY | constants4.O_CREAT | constants4.O_EXCL | constants4.O_NOFOLLOW, 384);
50219
+ } catch (retryError) {
50220
+ if (retryError.code === "EEXIST")
50221
+ throw new SkillSelectionError("SESSION_WRITE_LOCKED", "Another Skills process owns a required session write lock; retry after it completes. A surviving legacy lock requires explicit recovery review.");
50222
+ throw retryError;
50223
+ }
50011
50224
  }
50012
50225
  const stat = fstatSync6(fd);
50013
50226
  owned.push({ path: lock.path, fd, dev: stat.dev, ino: stat.ino });
50014
- writeFileSync3(fd, `${JSON.stringify({ schemaVersion: 1, operationId, sessionId: lock.sessionId, pid: process.pid })}
50227
+ const identity4 = localLockIdentity();
50228
+ writeFileSync3(fd, `${JSON.stringify({ schemaVersion: identity4 ? 2 : 1, operationId, sessionId: lock.sessionId, pid: process.pid, ...identity4 })}
50015
50229
  `);
50016
50230
  }
50017
50231
  return action(assertOwned);
@@ -50128,7 +50342,7 @@ function replaceSkillSession(expected, replacement, plan, options = {}, beforeCo
50128
50342
  return { archivePath, receiptPath, beforeSha256: before2.sha256, afterSha256 };
50129
50343
  });
50130
50344
  }
50131
- var SkillSelectionError, MAX_CACHED_PROFILE_AGE_MS, SELECTION_LOCK_FILE = "selection.lock.json";
50345
+ var SkillSelectionError, MAX_CACHED_PROFILE_AGE_MS, SELECTION_LOCK_FILE = "selection.lock.json", SESSION_LOCK_MAX_BYTES = 4096, SESSION_LOCK_MIN_AGE_MS = 30000;
50132
50346
  var init_selection_cache = __esm(() => {
50133
50347
  init_config();
50134
50348
  init_skill_bundle();
@@ -50186,7 +50400,7 @@ function capturePreparationProcess(child, platform2 = process.platform, signalGr
50186
50400
  }
50187
50401
 
50188
50402
  // src/lib/dependency-preparation.ts
50189
- import { constants as constants5, closeSync as closeSync7, fstatSync as fstatSync7, lstatSync as lstatSync10, mkdirSync as mkdirSync4, openSync as openSync7, readFileSync as readFileSync10, readdirSync as readdirSync5, rmdirSync, unlinkSync as unlinkSync2, ftruncateSync, writeSync } from "fs";
50403
+ import { constants as constants5, closeSync as closeSync7, fstatSync as fstatSync7, lstatSync as lstatSync10, mkdirSync as mkdirSync4, openSync as openSync7, readFileSync as readFileSync11, readdirSync as readdirSync5, rmdirSync, unlinkSync as unlinkSync2, ftruncateSync, writeSync } from "fs";
50190
50404
  import { join as join17 } from "path";
50191
50405
  function hasDependencyPreparationMarker(skillPath) {
50192
50406
  try {
@@ -50216,7 +50430,7 @@ function claimPreparation(skillPath) {
50216
50430
  return;
50217
50431
  if (!lstatSync10(state).isFile() || lstatSync10(state).isSymbolicLink() || lstatSync10(state).size > 1024)
50218
50432
  return;
50219
- const previous = JSON.parse(readFileSync10(state, "utf8"));
50433
+ const previous = JSON.parse(readFileSync11(state, "utf8"));
50220
50434
  if (previous.version !== 1 || previous.status !== "failed" || Object.keys(previous).length !== 2)
50221
50435
  return;
50222
50436
  }
@@ -50436,7 +50650,7 @@ var init_managed_policy = __esm(() => {
50436
50650
 
50437
50651
  // src/lib/agent-bridge.ts
50438
50652
  import { createHash as createHash8 } from "crypto";
50439
- import { lstatSync as lstatSync12, readFileSync as readFileSync11, readdirSync as readdirSync6 } from "fs";
50653
+ import { lstatSync as lstatSync12, readFileSync as readFileSync12, readdirSync as readdirSync6 } from "fs";
50440
50654
  import { join as join19 } from "path";
50441
50655
  function isOwnedCliBridge(path, expectedPaths) {
50442
50656
  if (!expectedPaths.includes(path))
@@ -50448,7 +50662,7 @@ function isOwnedCliBridge(path, expectedPaths) {
50448
50662
  return false;
50449
50663
  return Object.entries(CLI_BRIDGE_FILES).every(([name, content]) => {
50450
50664
  const file = join19(path, name), stat = lstatSync12(file);
50451
- return stat.isFile() && !stat.isSymbolicLink() && stat.size === Buffer.byteLength(content) && readFileSync11(file, "utf8") === content;
50665
+ return stat.isFile() && !stat.isSymbolicLink() && stat.size === Buffer.byteLength(content) && readFileSync12(file, "utf8") === content;
50452
50666
  });
50453
50667
  } catch {
50454
50668
  return false;
@@ -50822,7 +51036,7 @@ var init_claude_settings_witness = __esm(() => {
50822
51036
 
50823
51037
  // src/lib/agent-integration.ts
50824
51038
  import { createHash as createHash10, randomUUID as randomUUID5 } from "crypto";
50825
- import { existsSync as existsSync12, lstatSync as lstatSync14, statSync as statSync7, mkdirSync as mkdirSync5, readFileSync as readFileSync12, readdirSync as readdirSync7, opendirSync as opendirSync3, readlinkSync as readlinkSync2, realpathSync as realpathSync3, renameSync as renameSync2, rmdirSync as rmdirSync2, writeFileSync as writeFileSync4, unlinkSync as unlinkSync3, chmodSync, openSync as openSync10, closeSync as closeSync10, fsyncSync as fsyncSync2, fstatSync as fstatSync10, readSync as readSync6, constants as constants8, linkSync } from "fs";
51039
+ import { existsSync as existsSync12, lstatSync as lstatSync14, statSync as statSync7, mkdirSync as mkdirSync5, readFileSync as readFileSync13, readdirSync as readdirSync7, opendirSync as opendirSync3, readlinkSync as readlinkSync3, realpathSync as realpathSync3, renameSync as renameSync2, rmdirSync as rmdirSync2, writeFileSync as writeFileSync4, unlinkSync as unlinkSync3, chmodSync, openSync as openSync10, closeSync as closeSync10, fsyncSync as fsyncSync2, fstatSync as fstatSync10, readSync as readSync6, constants as constants8, linkSync } from "fs";
50826
51040
  import { dirname as dirname10, join as join20, resolve as resolve10, relative as relative4, isAbsolute as isAbsolute9, sep as sep4 } from "path";
50827
51041
  import { homedir as homedir3 } from "os";
50828
51042
  function assertSafePath(path) {
@@ -50842,7 +51056,7 @@ function readRootAlias(home, agent) {
50842
51056
  const stat = lstatSync14(alias, { throwIfNoEntry: false, bigint: true });
50843
51057
  if (!stat?.isSymbolicLink())
50844
51058
  throw new Error(`Agent root alias changed after planning: ${alias}`);
50845
- const link2 = readlinkSync2(alias), targetPath = resolve10(dirname10(alias), link2);
51059
+ const link2 = readlinkSync3(alias), targetPath = resolve10(dirname10(alias), link2);
50846
51060
  assertSafePath(targetPath);
50847
51061
  const targetStat = lstatSync14(targetPath, { throwIfNoEntry: false });
50848
51062
  if (!targetStat?.isDirectory())
@@ -51042,7 +51256,7 @@ function inventoryNativeSkills(home = homedir3(), options = {}) {
51042
51256
  throw new Error("Native skill discovery metadata limit exceeded");
51043
51257
  }
51044
51258
  function emptySiblingCacheAlias(path, parent) {
51045
- const link2 = readlinkSync2(path), target = resolve10(parent, link2);
51259
+ const link2 = readlinkSync3(path), target = resolve10(parent, link2);
51046
51260
  if (dirname10(target) !== parent || (isAbsolute9(link2) ? link2 !== target : dirname10(link2) !== "."))
51047
51261
  return false;
51048
51262
  if (!lstatSync14(target, { throwIfNoEntry: false })?.isDirectory())
@@ -51071,7 +51285,7 @@ function inventoryNativeSkills(home = homedir3(), options = {}) {
51071
51285
  const marker = join20(path, ".hasna-skills.json");
51072
51286
  if (existsSync12(marker)) {
51073
51287
  try {
51074
- managed = JSON.parse(readFileSync12(marker, "utf8")).managedBy === "@hasna/skills";
51288
+ managed = JSON.parse(readFileSync13(marker, "utf8")).managedBy === "@hasna/skills";
51075
51289
  } catch {}
51076
51290
  }
51077
51291
  const bridge = !vendor && isOwnedCliBridge(path, bridgePaths);
@@ -51144,7 +51358,7 @@ function inventoryNativeSkills(home = homedir3(), options = {}) {
51144
51358
  }
51145
51359
  function readOptional(path) {
51146
51360
  assertSafePath(path);
51147
- return existsSync12(path) ? readFileSync12(path, "utf8") : null;
51361
+ return existsSync12(path) ? readFileSync13(path, "utf8") : null;
51148
51362
  }
51149
51363
  function jsonObject(text2, path) {
51150
51364
  if (text2 === null)
@@ -51945,7 +52159,7 @@ import {
51945
52159
  lstatSync as lstatSync15,
51946
52160
  mkdirSync as mkdirSync7,
51947
52161
  mkdtempSync,
51948
- readFileSync as readFileSync13,
52162
+ readFileSync as readFileSync14,
51949
52163
  readdirSync as readdirSync9,
51950
52164
  renameSync as renameSync4,
51951
52165
  rmSync as rmSync2,
@@ -51962,7 +52176,7 @@ function hasSkillsOwnershipMarker(dir) {
51962
52176
  try {
51963
52177
  if (!lstatSync15(path).isFile())
51964
52178
  return false;
51965
- const marker = JSON.parse(readFileSync13(path, "utf8"));
52179
+ const marker = JSON.parse(readFileSync14(path, "utf8"));
51966
52180
  return isSkillsOwnershipMarker(marker);
51967
52181
  } catch {
51968
52182
  return false;
@@ -52170,7 +52384,7 @@ function writeManagedSkillDir(dir, skillMd, options) {
52170
52384
  if (dirExists && managed && hasSkillMd && !options.force && isPointerSkillMd(skillMd)) {
52171
52385
  let existingIsStub = false;
52172
52386
  try {
52173
- existingIsStub = isPointerSkillMd(readFileSync13(skillMdPath, "utf-8"));
52387
+ existingIsStub = isPointerSkillMd(readFileSync14(skillMdPath, "utf-8"));
52174
52388
  } catch {
52175
52389
  existingIsStub = false;
52176
52390
  }
@@ -52243,7 +52457,7 @@ function sourceSkillMd(skillPath, name, description, kind, preferBundledDocs = f
52243
52457
  if (kind === undefined || kind === "instruction" || preferBundledDocs) {
52244
52458
  const skillMdPath = join23(skillPath, "SKILL.md");
52245
52459
  if (existsSync14(skillMdPath))
52246
- return readFileSync13(skillMdPath, "utf-8");
52460
+ return readFileSync14(skillMdPath, "utf-8");
52247
52461
  }
52248
52462
  return pointerSkillMd(name, description);
52249
52463
  }
@@ -52293,7 +52507,7 @@ var init_skill_aliases = __esm(() => {
52293
52507
  });
52294
52508
 
52295
52509
  // src/lib/project-state.ts
52296
- import { existsSync as existsSync15, mkdirSync as mkdirSync8, readFileSync as readFileSync14, writeFileSync as writeFileSync7 } from "fs";
52510
+ import { existsSync as existsSync15, mkdirSync as mkdirSync8, readFileSync as readFileSync15, writeFileSync as writeFileSync7 } from "fs";
52297
52511
  import { join as join25 } from "path";
52298
52512
  function getProjectStateDir(targetDir = process.cwd()) {
52299
52513
  return join25(targetDir, SKILLS_PROJECT_DIR);
@@ -52306,7 +52520,7 @@ function loadProjectConfig(targetDir = process.cwd()) {
52306
52520
  if (!existsSync15(path))
52307
52521
  return null;
52308
52522
  try {
52309
- return normalizeProjectConfig(JSON.parse(readFileSync14(path, "utf-8")));
52523
+ return normalizeProjectConfig(JSON.parse(readFileSync15(path, "utf-8")));
52310
52524
  } catch {
52311
52525
  return null;
52312
52526
  }
@@ -52460,7 +52674,7 @@ __export(exports_installer, {
52460
52674
  AGENT_TARGETS: () => AGENT_TARGETS,
52461
52675
  AGENT_LABELS: () => AGENT_LABELS
52462
52676
  });
52463
- import { existsSync as existsSync16, readFileSync as readFileSync15, rmSync as rmSync3 } from "fs";
52677
+ import { existsSync as existsSync16, readFileSync as readFileSync16, rmSync as rmSync3 } from "fs";
52464
52678
  import { join as join26 } from "path";
52465
52679
  import { homedir as homedir5 } from "os";
52466
52680
  function getSkillPath(name) {
@@ -52559,7 +52773,7 @@ function createLocalSkillManifest(name, generateSkillMd) {
52559
52773
  let skillMd = "";
52560
52774
  const skillMdPath = join26(sourcePath, "SKILL.md");
52561
52775
  if (existsSync16(skillMdPath)) {
52562
- skillMd = readFileSync15(skillMdPath, "utf-8");
52776
+ skillMd = readFileSync16(skillMdPath, "utf-8");
52563
52777
  } else if (generateSkillMd) {
52564
52778
  skillMd = generateSkillMd(name) ?? "";
52565
52779
  } else {
@@ -52686,7 +52900,7 @@ function resolveAgentSkillMd(name, generateSkillMd) {
52686
52900
  const sourcePath = getSkillPath(name);
52687
52901
  const skillMdPath = join26(sourcePath, "SKILL.md");
52688
52902
  if (existsSync16(skillMdPath))
52689
- return readFileSync15(skillMdPath, "utf-8");
52903
+ return readFileSync16(skillMdPath, "utf-8");
52690
52904
  if (generateSkillMd)
52691
52905
  return generateSkillMd(name);
52692
52906
  return generateMinimalSkillMd(name);
@@ -52742,14 +52956,14 @@ function readBundledSkillVersion(name) {
52742
52956
  if (!existsSync16(pkgPath))
52743
52957
  return "unknown";
52744
52958
  try {
52745
- const pkg = JSON.parse(readFileSync15(pkgPath, "utf-8"));
52959
+ const pkg = JSON.parse(readFileSync16(pkgPath, "utf-8"));
52746
52960
  return pkg.version || "unknown";
52747
52961
  } catch {
52748
52962
  return "unknown";
52749
52963
  }
52750
52964
  }
52751
52965
  function readFileIfExists(path) {
52752
- return existsSync16(path) ? readFileSync15(path, "utf-8") : null;
52966
+ return existsSync16(path) ? readFileSync16(path, "utf-8") : null;
52753
52967
  }
52754
52968
  function loadProjectConfigCompat(targetDir) {
52755
52969
  return loadProjectConfig(targetDir);
@@ -52824,7 +53038,7 @@ __export(exports_skillinfo, {
52824
53038
  generateEnvExample: () => generateEnvExample,
52825
53039
  detectProjectSkills: () => detectProjectSkills
52826
53040
  });
52827
- import { existsSync as existsSync17, readFileSync as readFileSync16 } from "fs";
53041
+ import { existsSync as existsSync17, readFileSync as readFileSync17 } from "fs";
52828
53042
  import { join as join27 } from "path";
52829
53043
  function isInstructionSkillDir(skillPath, meta) {
52830
53044
  if (meta?.kind === "instruction")
@@ -52833,7 +53047,7 @@ function isInstructionSkillDir(skillPath, meta) {
52833
53047
  if (!existsSync17(skillMdPath))
52834
53048
  return false;
52835
53049
  try {
52836
- return parseSkillFrontmatter(readFileSync16(skillMdPath, "utf-8"))?.kind === "instruction";
53050
+ return parseSkillFrontmatter(readFileSync17(skillMdPath, "utf-8"))?.kind === "instruction";
52837
53051
  } catch {
52838
53052
  return false;
52839
53053
  }
@@ -52868,7 +53082,7 @@ function getSkillRequirements(name) {
52868
53082
  const meta = getSkill(name);
52869
53083
  let dependencies = {};
52870
53084
  try {
52871
- dependencies = JSON.parse(readFileSync16(join27(skillPath, "package.json"), "utf8")).dependencies || {};
53085
+ dependencies = JSON.parse(readFileSync17(join27(skillPath, "package.json"), "utf8")).dependencies || {};
52872
53086
  } catch {}
52873
53087
  return getSkillRequirementsFromContent(name, texts, dependencies, meta);
52874
53088
  }
@@ -52957,7 +53171,7 @@ async function runSkill(name, args, options = {}) {
52957
53171
  }
52958
53172
  let entryPoint2;
52959
53173
  try {
52960
- const pkg = JSON.parse(readFileSync16(pkgPath, "utf-8"));
53174
+ const pkg = JSON.parse(readFileSync17(pkgPath, "utf-8"));
52961
53175
  if (pkg.bin) {
52962
53176
  const binValues = Object.values(pkg.bin);
52963
53177
  entryPoint2 = binValues[0];
@@ -53002,7 +53216,7 @@ async function runSkill(name, args, options = {}) {
53002
53216
  function detectProjectSkills(cwd2 = process.cwd()) {
53003
53217
  let pkg;
53004
53218
  try {
53005
- pkg = JSON.parse(readFileSync16(join27(cwd2, "package.json"), "utf8"));
53219
+ pkg = JSON.parse(readFileSync17(join27(cwd2, "package.json"), "utf8"));
53006
53220
  } catch {
53007
53221
  return { detected: [], recommended: [] };
53008
53222
  }
@@ -53088,7 +53302,7 @@ function generateSkillMd(name) {
53088
53302
  const pkgPath = join27(skillPath, "package.json");
53089
53303
  if (existsSync17(pkgPath)) {
53090
53304
  try {
53091
- const pkg = JSON.parse(readFileSync16(pkgPath, "utf-8"));
53305
+ const pkg = JSON.parse(readFileSync17(pkgPath, "utf-8"));
53092
53306
  if (pkg.bin) {
53093
53307
  const binKeys = Object.keys(pkg.bin);
53094
53308
  if (binKeys.length > 0)
@@ -53162,7 +53376,7 @@ function extractEnvVars(text2) {
53162
53376
  function readIfExists(path) {
53163
53377
  try {
53164
53378
  if (existsSync17(path)) {
53165
- return readFileSync16(path, "utf-8");
53379
+ return readFileSync17(path, "utf-8");
53166
53380
  }
53167
53381
  } catch {}
53168
53382
  return null;
@@ -55007,7 +55221,7 @@ var init_codex_hook_discovery_recovery = __esm(() => {
55007
55221
 
55008
55222
  // src/lib/agent-discovery.ts
55009
55223
  import { createHash as createHash16 } from "crypto";
55010
- import { lstatSync as lstatSync20, readFileSync as readFileSync17, readdirSync as readdirSync10, realpathSync as realpathSync4 } from "fs";
55224
+ import { lstatSync as lstatSync20, readFileSync as readFileSync18, readdirSync as readdirSync10, realpathSync as realpathSync4 } from "fs";
55011
55225
  import { basename as basename8, dirname as dirname16, isAbsolute as isAbsolute15, join as join31, resolve as resolve15, sep as sep5 } from "path";
55012
55226
  import { isDeepStrictEqual as isDeepStrictEqual7 } from "util";
55013
55227
  function parseConfig(text3, path, toml = false) {
@@ -55039,7 +55253,7 @@ function read2(path, changes) {
55039
55253
  return null;
55040
55254
  if (!stat2.isFile() || stat2.size > 16 * 1024 * 1024)
55041
55255
  throw new Error(`Unsupported or oversized native discovery input: ${path}`);
55042
- return readFileSync17(path, "utf8");
55256
+ return readFileSync18(path, "utf8");
55043
55257
  }
55044
55258
  function projected(source, changes, budget = discoveryByteBudget()) {
55045
55259
  if (source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || source.hashMode === "claude-settings-v3") {
@@ -56087,7 +56301,7 @@ __export(exports_registry, {
56087
56301
  CATEGORIES: () => CATEGORIES,
56088
56302
  BASIC_SKILL_NAMES: () => BASIC_SKILL_NAMES
56089
56303
  });
56090
- import { existsSync as existsSync19, readFileSync as readFileSync18, readdirSync as readdirSync12 } from "fs";
56304
+ import { existsSync as existsSync19, readFileSync as readFileSync19, readdirSync as readdirSync12 } from "fs";
56091
56305
  import { join as join34 } from "path";
56092
56306
  function isBasicSkillName(name) {
56093
56307
  return BASIC_SKILL_NAMES.includes(name);
@@ -56137,7 +56351,7 @@ function discoverSkillsInDir(dir, source = "custom") {
56137
56351
  continue;
56138
56352
  let content;
56139
56353
  try {
56140
- content = readFileSync18(skillMdPath, "utf-8");
56354
+ content = readFileSync19(skillMdPath, "utf-8");
56141
56355
  } catch {
56142
56356
  continue;
56143
56357
  }
@@ -56174,7 +56388,7 @@ function findExtensionSkillPath(name) {
56174
56388
  continue;
56175
56389
  let content;
56176
56390
  try {
56177
- content = readFileSync18(skillMdPath, "utf-8");
56391
+ content = readFileSync19(skillMdPath, "utf-8");
56178
56392
  } catch {
56179
56393
  continue;
56180
56394
  }
@@ -57886,7 +58100,7 @@ var require_cli_spinners = __commonJS((exports, module) => {
57886
58100
  });
57887
58101
 
57888
58102
  // src/lib/auth-store.ts
57889
- import { chmodSync as chmodSync2, existsSync as existsSync20, mkdirSync as mkdirSync11, readFileSync as readFileSync19, renameSync as renameSync7, statSync as statSync11, unlinkSync as unlinkSync5, writeFileSync as writeFileSync10 } from "fs";
58103
+ import { chmodSync as chmodSync2, existsSync as existsSync20, mkdirSync as mkdirSync11, readFileSync as readFileSync20, renameSync as renameSync7, statSync as statSync11, unlinkSync as unlinkSync5, writeFileSync as writeFileSync10 } from "fs";
57890
58104
  import { basename as basename11, dirname as dirname19, join as join35 } from "path";
57891
58105
  function getAuthFilePath(env3 = process.env) {
57892
58106
  return skillsCredentialFilePath(env3);
@@ -57900,7 +58114,7 @@ function getAuthIdentity(env3 = process.env) {
57900
58114
  }
57901
58115
  function readIdentity(env3 = process.env) {
57902
58116
  try {
57903
- const parsed = JSON.parse(readFileSync19(getIdentityFilePath(env3), "utf-8"));
58117
+ const parsed = JSON.parse(readFileSync20(getIdentityFilePath(env3), "utf-8"));
57904
58118
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
57905
58119
  return {};
57906
58120
  const record2 = parsed;
@@ -57931,7 +58145,7 @@ function writeCredentialValues(values2, env3 = process.env) {
57931
58145
  const lines = [];
57932
58146
  const written = new Set;
57933
58147
  if (existsSync20(file)) {
57934
- for (const raw of readFileSync19(file, "utf-8").split(/\r?\n/)) {
58148
+ for (const raw of readFileSync20(file, "utf-8").split(/\r?\n/)) {
57935
58149
  const match = /^\s*(?:export\s+)?([A-Za-z_][A-Za-z0-9_]*)\s*=/.exec(raw);
57936
58150
  const key = match?.[1];
57937
58151
  if (key && key in values2) {
@@ -57969,7 +58183,7 @@ function readCredentialValue(key, env3 = process.env) {
57969
58183
  if (!existsSync20(file))
57970
58184
  return null;
57971
58185
  try {
57972
- for (const raw of readFileSync19(file, "utf-8").split(/\r?\n/)) {
58186
+ for (const raw of readFileSync20(file, "utf-8").split(/\r?\n/)) {
57973
58187
  const match = new RegExp(`^\\s*(?:export\\s+)?${key}\\s*=\\s*(.*)$`).exec(raw);
57974
58188
  if (!match)
57975
58189
  continue;
@@ -57987,7 +58201,7 @@ function readCredentialValue(key, env3 = process.env) {
57987
58201
  }
57988
58202
  function readIdentityRecord(env3 = process.env) {
57989
58203
  try {
57990
- const parsed = JSON.parse(readFileSync19(getIdentityFilePath(env3), "utf-8"));
58204
+ const parsed = JSON.parse(readFileSync20(getIdentityFilePath(env3), "utf-8"));
57991
58205
  return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
57992
58206
  } catch {
57993
58207
  return null;
@@ -60276,7 +60490,7 @@ __export(exports_regexes, {
60276
60490
  idnEmail: () => idnEmail,
60277
60491
  httpProtocol: () => httpProtocol,
60278
60492
  html5Email: () => html5Email,
60279
- hostname: () => hostname,
60493
+ hostname: () => hostname2,
60280
60494
  hex: () => hex,
60281
60495
  guid: () => guid,
60282
60496
  extendedDuration: () => extendedDuration,
@@ -60336,7 +60550,7 @@ var cuid, cuid2, ulid, xid, ksuid, nanoid, duration, extendedDuration, guid, uui
60336
60550
  }, uuid42, uuid6, uuid7, email2, html5Email, rfc5322Email, unicodeEmail, idnEmail, browserEmail, _emoji = `^[\\p{Extended_Pictographic}\\p{Emoji_Component}]+$`, ipv4, ipv6, mac = (delimiter) => {
60337
60551
  const escapedDelim = escapeRegex(delimiter ?? ":");
60338
60552
  return new RegExp(`^(?:[0-9A-F]{2}${escapedDelim}){5}[0-9A-F]{2}$|^(?:[0-9a-f]{2}${escapedDelim}){5}[0-9a-f]{2}$`);
60339
- }, cidrv4, cidrv6, base64, base64url, hostname, domain, httpProtocol, e164, creditCard, dateSource = `(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))`, date2, string = (params) => {
60553
+ }, cidrv4, cidrv6, base64, base64url, hostname2, domain, httpProtocol, e164, creditCard, dateSource = `(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))`, date2, string = (params) => {
60340
60554
  const regex2 = params ? `[\\s\\S]{${params?.minimum ?? 0},${params?.maximum ?? ""}}` : `[\\s\\S]*`;
60341
60555
  return new RegExp(`^${regex2}$`);
60342
60556
  }, bigint, integer, number, boolean, _null, _undefined, lowercase, uppercase, hex, md5_hex, md5_base64, md5_base64url, sha1_hex, sha1_base64, sha1_base64url, sha256_hex, sha256_base64, sha256_base64url, sha384_hex, sha384_base64, sha384_base64url, sha512_hex, sha512_base64, sha512_base64url;
@@ -60366,7 +60580,7 @@ var init_regexes = __esm(() => {
60366
60580
  cidrv6 = /^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:))\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])$/;
60367
60581
  base64 = /^$|^(?:[0-9a-zA-Z+/]{4})*(?:(?:[0-9a-zA-Z+/]{2}==)|(?:[0-9a-zA-Z+/]{3}=))?$/;
60368
60582
  base64url = /^[A-Za-z0-9_-]*$/;
60369
- hostname = /^(?=.{1,253}\.?$)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[-0-9a-zA-Z]{0,61}[0-9a-zA-Z])?)*\.?$/;
60583
+ hostname2 = /^(?=.{1,253}\.?$)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[-0-9a-zA-Z]{0,61}[0-9a-zA-Z])?)*\.?$/;
60370
60584
  domain = /^(?=.{1,253}$)([a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,63}$/;
60371
60585
  httpProtocol = /^https?$/;
60372
60586
  e164 = /^\+[1-9]\d{6,14}$/;
@@ -61018,9 +61232,9 @@ function parseURLObject(trimmed, def) {
61018
61232
  function stripTabAndNewline(value) {
61019
61233
  return value.replace(asciiTabOrNewline, "");
61020
61234
  }
61021
- function urlHostnameOk(url, hostname2) {
61022
- hostname2.lastIndex = 0;
61023
- return hostname2.test(url.hostname);
61235
+ function urlHostnameOk(url, hostname3) {
61236
+ hostname3.lastIndex = 0;
61237
+ return hostname3.test(url.hostname);
61024
61238
  }
61025
61239
  function urlProtocolOk(url, protocol) {
61026
61240
  protocol.lastIndex = 0;
@@ -75322,7 +75536,7 @@ __export(exports_schemas2, {
75322
75536
  int: () => int,
75323
75537
  instanceof: () => _instanceof,
75324
75538
  httpUrl: () => httpUrl,
75325
- hostname: () => hostname2,
75539
+ hostname: () => hostname3,
75326
75540
  hex: () => hex2,
75327
75541
  hash: () => hash4,
75328
75542
  guid: () => guid2,
@@ -75524,7 +75738,7 @@ function jwt(params) {
75524
75738
  function stringFormat(format, fnOrRegex, _params = {}) {
75525
75739
  return _stringFormat(ZodCustomStringFormat, format, fnOrRegex, _params);
75526
75740
  }
75527
- function hostname2(_params) {
75741
+ function hostname3(_params) {
75528
75742
  return _stringFormat(ZodCustomStringFormat, "hostname", exports_regexes.hostname, _params);
75529
75743
  }
75530
75744
  function hex2(_params) {
@@ -77788,7 +78002,7 @@ __export(exports_external, {
77788
78002
  input: () => input,
77789
78003
  includes: () => _includes,
77790
78004
  httpUrl: () => httpUrl,
77791
- hostname: () => hostname2,
78005
+ hostname: () => hostname3,
77792
78006
  hex: () => hex2,
77793
78007
  hash: () => hash4,
77794
78008
  guid: () => guid2,
@@ -79916,7 +80130,7 @@ var init_remote_auth = __esm(() => {
79916
80130
 
79917
80131
  // src/lib/sign-in.ts
79918
80132
  import { createHash as createHash19 } from "crypto";
79919
- import { chmodSync as chmodSync3, mkdirSync as mkdirSync12, readFileSync as readFileSync20, readdirSync as readdirSync13, renameSync as renameSync8, unlinkSync as unlinkSync6, writeFileSync as writeFileSync11 } from "fs";
80133
+ import { chmodSync as chmodSync3, mkdirSync as mkdirSync12, readFileSync as readFileSync21, readdirSync as readdirSync13, renameSync as renameSync8, unlinkSync as unlinkSync6, writeFileSync as writeFileSync11 } from "fs";
79920
80134
  import { basename as basename12, dirname as dirname20, join as join36 } from "path";
79921
80135
  function isRecord6(value) {
79922
80136
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
@@ -80092,7 +80306,7 @@ function loadPendingDeviceSignIn(origin, env3 = process.env, now3 = Date.now())
80092
80306
  let parsed;
80093
80307
  try {
80094
80308
  path = pendingDeviceSignInPath(origin, env3);
80095
- parsed = JSON.parse(readFileSync20(path, "utf8"));
80309
+ parsed = JSON.parse(readFileSync21(path, "utf8"));
80096
80310
  } catch {
80097
80311
  return null;
80098
80312
  }
@@ -80137,7 +80351,7 @@ function pendingDeviceSignInOrigins(env3 = process.env, now3 = Date.now()) {
80137
80351
  if (!entry.startsWith(`${location.stem}-`) || !/-[0-9a-f]{16}\.json$/.test(entry))
80138
80352
  continue;
80139
80353
  try {
80140
- const parsed = JSON.parse(readFileSync20(join36(location.dir, entry), "utf8"));
80354
+ const parsed = JSON.parse(readFileSync21(join36(location.dir, entry), "utf8"));
80141
80355
  if (isRecord6(parsed) && typeof parsed.origin === "string" && Number(parsed.expiresAt) > now3 && pendingDeviceSignInPath(parsed.origin, env3) === join36(location.dir, entry))
80142
80356
  origins.push(parsed.origin);
80143
80357
  } catch {}
@@ -80811,7 +81025,7 @@ var init_skill_bundles = __esm(() => {
80811
81025
  });
80812
81026
 
80813
81027
  // src/lib/pull.ts
80814
- import { existsSync as existsSync21, mkdirSync as mkdirSync13, mkdtempSync as mkdtempSync3, readFileSync as readFileSync21, renameSync as renameSync9, rmSync as rmSync6, writeFileSync as writeFileSync12 } from "fs";
81028
+ import { existsSync as existsSync21, mkdirSync as mkdirSync13, mkdtempSync as mkdtempSync3, readFileSync as readFileSync23, renameSync as renameSync9, rmSync as rmSync6, writeFileSync as writeFileSync12 } from "fs";
80815
81029
  import { dirname as dirname21, join as join37 } from "path";
80816
81030
  async function pullSkills(options = {}) {
80817
81031
  const client2 = options.client !== undefined ? options.client : await createRemoteSkillsClient();
@@ -80973,7 +81187,7 @@ function reconcileTombstone(slug2, corpusOptions) {
80973
81187
  }
80974
81188
  function readPullMarker(dir) {
80975
81189
  try {
80976
- return JSON.parse(readFileSync21(join37(dir, PULL_MARKER_FILE), "utf-8"));
81190
+ return JSON.parse(readFileSync23(join37(dir, PULL_MARKER_FILE), "utf-8"));
80977
81191
  } catch {
80978
81192
  return null;
80979
81193
  }
@@ -81475,6 +81689,24 @@ Receipt SHA256: ${result2.receiptSha256}`);
81475
81689
  reportContextError(error61, options.json);
81476
81690
  }
81477
81691
  });
81692
+ sessions.command("recover-lock <id>").option("--apply", "Archive the exact reviewed stale lock", false).option("--review-digest <sha256>", "Exact digest returned by the lock review; required with --apply").option("--confirm-local-host", "Confirm this PID-only legacy lock was created on this host", false).option("--json", "Return lock metadata or recovery result as JSON", false).description("Review a stale session write lock, then archive it without changing the receipt").action(async (id, options) => {
81693
+ try {
81694
+ if (!options.apply) {
81695
+ const result2 = inspectSessionWriteLock(id);
81696
+ await writeCliOutput(options.json ? JSON.stringify(result2) : `Lock for ${JSON.stringify(id)}: PID ${result2.pid}, schema ${result2.schemaVersion}, modified ${result2.lockMtime}.
81697
+ Receipt SHA256: ${result2.receiptSha256}
81698
+ Review digest: ${result2.reviewDigest}`);
81699
+ return;
81700
+ }
81701
+ if (!options.reviewDigest || !/^[a-f0-9]{64}$/.test(options.reviewDigest) || !options.confirmLocalHost) {
81702
+ throw new SkillSelectionError("SESSION_LOCK_REVIEW_REQUIRED", "Apply requires the exact review digest and --confirm-local-host after verifying this lock belongs to this host.");
81703
+ }
81704
+ const archivePath = recoverSessionWriteLock(id, options.reviewDigest);
81705
+ await writeCliOutput(options.json ? JSON.stringify({ sessionId: id, recovered: true, archivePath }) : `Archived the stale lock at ${archivePath}. The session receipt was not changed.`);
81706
+ } catch (error61) {
81707
+ reportContextError(error61, options.json);
81708
+ }
81709
+ });
81478
81710
  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) => {
81479
81711
  try {
81480
81712
  const result2 = await reconcileSkillSession({ ...options, sessionId: id });
@@ -81592,13 +81824,13 @@ var init_context = __esm(() => {
81592
81824
  });
81593
81825
 
81594
81826
  // src/cli/commands/profile-sync.ts
81595
- import { hostname as hostname3 } from "os";
81827
+ import { hostname as hostname4 } from "os";
81596
81828
  async function handleProfileSync(options, dependencies = {}) {
81597
81829
  try {
81598
81830
  const result2 = await syncSelectionProfile(selectedProfileId(options.selectionProfile ?? options.profile), {
81599
81831
  ...dependencies,
81600
81832
  projectDir: options.project ? process.cwd() : dependencies.projectDir,
81601
- stationId: options.stationReport === false ? undefined : options.station ?? dependencies.stationId ?? process.env.HASNA_STATION ?? hostname3(),
81833
+ stationId: options.stationReport === false ? undefined : options.station ?? dependencies.stationId ?? process.env.HASNA_STATION ?? hostname4(),
81602
81834
  check: options.check ?? dependencies.check
81603
81835
  });
81604
81836
  if (options.json)
@@ -82326,7 +82558,7 @@ var exports_introspect = {};
82326
82558
  __export(exports_introspect, {
82327
82559
  registerIntrospect: () => registerIntrospect
82328
82560
  });
82329
- import { existsSync as existsSync22, readFileSync as readFileSync23 } from "fs";
82561
+ import { existsSync as existsSync22, readFileSync as readFileSync25 } from "fs";
82330
82562
  import { join as join38 } from "path";
82331
82563
  import { execSync } from "child_process";
82332
82564
  function registerIntrospect(parent) {
@@ -82548,7 +82780,7 @@ function handleDiff(name, options) {
82548
82780
  present: existsSync22(canonicalSkillMd),
82549
82781
  path: canonicalDir,
82550
82782
  ...existsSync22(canonicalSkillMd) ? { hash: hashSkillMarkdownFile(canonicalSkillMd) } : {},
82551
- ...existsSync22(canonicalSkillMd) ? { stub: isPointerSkillMd(readFileSync23(canonicalSkillMd, "utf-8")) } : {}
82783
+ ...existsSync22(canonicalSkillMd) ? { stub: isPointerSkillMd(readFileSync25(canonicalSkillMd, "utf-8")) } : {}
82552
82784
  };
82553
82785
  const pinned = getInstalledSkills().includes(bare);
82554
82786
  const installMeta = getInstallMeta();
@@ -82557,7 +82789,7 @@ function handleDiff(name, options) {
82557
82789
  let registryVersion = "unknown";
82558
82790
  if (existsSync22(registryPkgPath)) {
82559
82791
  try {
82560
- registryVersion = JSON.parse(readFileSync23(registryPkgPath, "utf-8")).version || "unknown";
82792
+ registryVersion = JSON.parse(readFileSync25(registryPkgPath, "utf-8")).version || "unknown";
82561
82793
  } catch {}
82562
82794
  }
82563
82795
  const upToDate = installedVersion === registryVersion;
@@ -82571,7 +82803,7 @@ function handleDiff(name, options) {
82571
82803
  let stub;
82572
82804
  if (present && existsSync22(skillMdPath)) {
82573
82805
  try {
82574
- stub = isPointerSkillMd(readFileSync23(skillMdPath, "utf-8"));
82806
+ stub = isPointerSkillMd(readFileSync25(skillMdPath, "utf-8"));
82575
82807
  } catch {
82576
82808
  stub = undefined;
82577
82809
  }
@@ -83109,7 +83341,7 @@ var exports_init = {};
83109
83341
  __export(exports_init, {
83110
83342
  registerSetup: () => registerSetup
83111
83343
  });
83112
- import { existsSync as existsSync23, readFileSync as readFileSync25, writeFileSync as writeFileSync13, appendFileSync } from "fs";
83344
+ import { existsSync as existsSync23, readFileSync as readFileSync26, writeFileSync as writeFileSync13, appendFileSync } from "fs";
83113
83345
  import { join as join39 } from "path";
83114
83346
  function registerSetup(parent) {
83115
83347
  parent.command("init").option("--json", "Output as JSON", false).option("--for <agent>", "Detect project type and show MCP registration guidance for agent").option("--scope <scope>", "Deprecated; agent skill-folder installs are disabled", "global").description("Initialize project for pinned skills (.env.example, .gitignore)").action((options) => handleInit(options));
@@ -83204,7 +83436,7 @@ Use: skills render`));
83204
83436
  console.log(source_default.dim(" No environment variables detected across pinned skills"));
83205
83437
  const gitignorePath = join39(cwd2, ".gitignore");
83206
83438
  const gitignoreEntries = [".skills/runs/", ".skills/exports/", ".skills/tmp/"];
83207
- let gitignoreContent = existsSync23(gitignorePath) ? readFileSync25(gitignorePath, "utf-8") : "";
83439
+ let gitignoreContent = existsSync23(gitignorePath) ? readFileSync26(gitignorePath, "utf-8") : "";
83208
83440
  let gitignoreUpdated = false;
83209
83441
  const missingEntries = gitignoreEntries.filter((entry) => !gitignoreContent.includes(entry));
83210
83442
  if (missingEntries.length > 0) {
@@ -83259,7 +83491,7 @@ async function handleImport(file2, options) {
83259
83491
  process.exitCode = 1;
83260
83492
  return;
83261
83493
  }
83262
- raw = readFileSync25(file2, "utf-8");
83494
+ raw = readFileSync26(file2, "utf-8");
83263
83495
  }
83264
83496
  } catch (err) {
83265
83497
  const error61 = `Failed to read file: ${err.message}`;
@@ -83356,7 +83588,7 @@ var init_init = __esm(() => {
83356
83588
  });
83357
83589
 
83358
83590
  // src/lib/home-adoption.ts
83359
- import { constants as constants13, closeSync as closeSync15, fstatSync as fstatSync15, lstatSync as lstatSync22, openSync as openSync15, readSync as readSync12, existsSync as existsSync24, mkdirSync as mkdirSync14, readdirSync as readdirSync14, readFileSync as readFileSync26, rmSync as rmSync7, statSync as statSync12, writeFileSync as writeFileSync14 } from "fs";
83591
+ import { constants as constants13, closeSync as closeSync15, fstatSync as fstatSync15, lstatSync as lstatSync22, openSync as openSync15, readSync as readSync12, existsSync as existsSync24, mkdirSync as mkdirSync14, readdirSync as readdirSync14, readFileSync as readFileSync27, rmSync as rmSync7, statSync as statSync12, writeFileSync as writeFileSync14 } from "fs";
83360
83592
  import { homedir as homedir8 } from "os";
83361
83593
  import { join as join40 } from "path";
83362
83594
  function indexCanonicalCorpus(corpusRoot) {
@@ -83460,7 +83692,7 @@ function appendConflictsLedger(appDir, conflicts) {
83460
83692
  let ledger = { version: 1, entries: [] };
83461
83693
  if (existsSync24(ledgerPath)) {
83462
83694
  try {
83463
- const parsed = JSON.parse(readFileSync26(ledgerPath, "utf-8"));
83695
+ const parsed = JSON.parse(readFileSync27(ledgerPath, "utf-8"));
83464
83696
  if (parsed && typeof parsed === "object" && Array.isArray(parsed.entries)) {
83465
83697
  ledger = parsed;
83466
83698
  }
@@ -83609,7 +83841,7 @@ var init_home_adoption = __esm(() => {
83609
83841
  });
83610
83842
 
83611
83843
  // src/lib/home-census.ts
83612
- import { existsSync as existsSync25, readFileSync as readFileSync27, readdirSync as readdirSync15, statSync as statSync13 } from "fs";
83844
+ import { existsSync as existsSync25, readFileSync as readFileSync28, readdirSync as readdirSync15, statSync as statSync13 } from "fs";
83613
83845
  import { homedir as homedir9 } from "os";
83614
83846
  import { join as join41 } from "path";
83615
83847
  function sortEntries(entries) {
@@ -83680,14 +83912,14 @@ function censusHomeDrift(options = {}) {
83680
83912
  if (homeHash !== canonicalHash) {
83681
83913
  let homeStub;
83682
83914
  try {
83683
- homeStub = isPointerSkillMd(readFileSync27(skillMdPath, "utf-8"));
83915
+ homeStub = isPointerSkillMd(readFileSync28(skillMdPath, "utf-8"));
83684
83916
  } catch {
83685
83917
  homeStub = undefined;
83686
83918
  }
83687
83919
  let canonicalStub;
83688
83920
  const canonicalSkillMd = join41(corpusRoot, skill, "SKILL.md");
83689
83921
  try {
83690
- canonicalStub = isPointerSkillMd(readFileSync27(canonicalSkillMd, "utf-8"));
83922
+ canonicalStub = isPointerSkillMd(readFileSync28(canonicalSkillMd, "utf-8"));
83691
83923
  } catch {
83692
83924
  canonicalStub = undefined;
83693
83925
  }
@@ -83725,7 +83957,7 @@ var init_home_census = __esm(() => {
83725
83957
  });
83726
83958
 
83727
83959
  // src/cli/env-assignment.ts
83728
- import { closeSync as closeSync16, constants as constants14, fstatSync as fstatSync16, ftruncateSync as ftruncateSync2, lstatSync as lstatSync23, openSync as openSync16, readFileSync as readFileSync28, writeSync as writeSync3 } from "fs";
83960
+ import { closeSync as closeSync16, constants as constants14, fstatSync as fstatSync16, ftruncateSync as ftruncateSync2, lstatSync as lstatSync23, openSync as openSync16, readFileSync as readFileSync29, writeSync as writeSync3 } from "fs";
83729
83961
  function serializeValue(value) {
83730
83962
  if (controls.test(value))
83731
83963
  throw new EnvAssignmentError("Environment values cannot contain control characters or newlines.");
@@ -83820,7 +84052,7 @@ function setEnvAssignment(path, assignment) {
83820
84052
  }
83821
84053
  let prepared = initial2;
83822
84054
  if (previous) {
83823
- const original = readFileSync28(descriptor), text4 = original.toString("utf8");
84055
+ const original = readFileSync29(descriptor), text4 = original.toString("utf8");
83824
84056
  if (!Buffer.from(text4, "utf8").equals(original))
83825
84057
  throw new EnvAssignmentError(INVALID_LAYOUT);
83826
84058
  prepared = prepareEnvAssignment(assignment, text4);
@@ -83907,7 +84139,7 @@ var exports_diagnostic = {};
83907
84139
  __export(exports_diagnostic, {
83908
84140
  registerDiagnostic: () => registerDiagnostic
83909
84141
  });
83910
- import { existsSync as existsSync26, readFileSync as readFileSync29, readdirSync as readdirSync16, statSync as statSync14 } from "fs";
84142
+ import { existsSync as existsSync26, readFileSync as readFileSync30, readdirSync as readdirSync16, statSync as statSync14 } from "fs";
83911
84143
  import { join as join42 } from "path";
83912
84144
  import { execSync as execSync2 } from "child_process";
83913
84145
  function registerDiagnostic(parent) {
@@ -84148,7 +84380,7 @@ function handleOutdated(options) {
84148
84380
  let registryVersion = "unknown";
84149
84381
  if (existsSync26(registryPkgPath))
84150
84382
  try {
84151
- registryVersion = JSON.parse(readFileSync29(registryPkgPath, "utf-8")).version || "unknown";
84383
+ registryVersion = JSON.parse(readFileSync30(registryPkgPath, "utf-8")).version || "unknown";
84152
84384
  } catch {}
84153
84385
  if (installedVersion !== registryVersion)
84154
84386
  pins.push({ skill: name, installedVersion, registryVersion });
@@ -84358,8 +84590,8 @@ var init_cloud_executions = __esm(() => {
84358
84590
 
84359
84591
  // node_modules/@hasna/secrets/dist/sdk.js
84360
84592
  import { isIP as isIP3 } from "net";
84361
- import { spawnSync as spawnSync2 } from "child_process";
84362
- import { closeSync as closeSync17, fstatSync as fstatSync17, openSync as openSync17, readFileSync as readFileSync30 } from "fs";
84593
+ import { spawnSync as spawnSync3 } from "child_process";
84594
+ import { closeSync as closeSync17, fstatSync as fstatSync17, openSync as openSync17, readFileSync as readFileSync31 } from "fs";
84363
84595
  import { O_NOFOLLOW as O_NOFOLLOW3, O_NONBLOCK as O_NONBLOCK3, O_RDONLY as O_RDONLY3 } from "constants";
84364
84596
  import { createRequire as createRequire2 } from "module";
84365
84597
  import { hostname as osHostname2 } from "os";
@@ -84485,7 +84717,7 @@ function readAppConfigFile2(path) {
84485
84717
  unsafe("the file is not owned by the current user");
84486
84718
  if (before2.size > MAX_CREDENTIAL_FILE_BYTES2)
84487
84719
  unsafe("the file exceeds the size limit");
84488
- const bytes = readFileSync30(fd);
84720
+ const bytes = readFileSync31(fd);
84489
84721
  const after2 = fstatSync17(fd);
84490
84722
  if (!configFileReadsCoherent2(before2, after2)) {
84491
84723
  unsafe("the file changed while being read");
@@ -84633,7 +84865,7 @@ function isAmbientEnvironment2(env3) {
84633
84865
  return env3 === process.env || env3[AMBIENT_ENVIRONMENT2] === true;
84634
84866
  }
84635
84867
  function defaultKeychainRunner2(argv) {
84636
- const result2 = spawnSync2(KEYCHAIN_SECURITY_BIN2, [...argv], {
84868
+ const result2 = spawnSync3(KEYCHAIN_SECURITY_BIN2, [...argv], {
84637
84869
  encoding: "utf8",
84638
84870
  stdio: ["ignore", "pipe", "pipe"],
84639
84871
  timeout: KEYCHAIN_SPAWN_TIMEOUT_MS2
@@ -90352,7 +90584,7 @@ var init_runs = __esm(() => {
90352
90584
 
90353
90585
  // src/lib/run-state.ts
90354
90586
  import { createHash as createHash24, randomBytes } from "crypto";
90355
- import { existsSync as existsSync27, mkdirSync as mkdirSync16, readFileSync as readFileSync31, readdirSync as readdirSync17, statSync as statSync15, writeFileSync as writeFileSync16 } from "fs";
90587
+ import { existsSync as existsSync27, mkdirSync as mkdirSync16, readFileSync as readFileSync32, readdirSync as readdirSync17, statSync as statSync15, writeFileSync as writeFileSync16 } from "fs";
90356
90588
  import { extname, join as join45, relative as relative6 } from "path";
90357
90589
  function createSkillRun(params, targetDir = process.cwd()) {
90358
90590
  const now3 = new Date;
@@ -90424,7 +90656,7 @@ function appendRunEvent(context, event, data = {}) {
90424
90656
  const line = JSON.stringify({ ts: new Date().toISOString(), event, ...data }) + `
90425
90657
  `;
90426
90658
  const path = join45(context.runDir, "events.ndjson");
90427
- const previous = existsSync27(path) ? readFileSync31(path, "utf-8") : "";
90659
+ const previous = existsSync27(path) ? readFileSync32(path, "utf-8") : "";
90428
90660
  writeFileSync16(path, previous + line);
90429
90661
  }
90430
90662
  function listSkillRuns(targetDir = process.cwd(), limit = 50) {
@@ -90484,7 +90716,7 @@ function collectRunArtifacts(context) {
90484
90716
  const artifacts = [];
90485
90717
  for (const path of walkFiles(context.exportDir)) {
90486
90718
  const stat2 = statSync15(path);
90487
- const bytes = readFileSync31(path);
90719
+ const bytes = readFileSync32(path);
90488
90720
  artifacts.push({
90489
90721
  path: toProjectRelative(context.targetDir, path),
90490
90722
  mime: mimeForPath(path),
@@ -90499,7 +90731,7 @@ function readRunRecord(runDir) {
90499
90731
  if (!existsSync27(path))
90500
90732
  return null;
90501
90733
  try {
90502
- return JSON.parse(readFileSync31(path, "utf-8"));
90734
+ return JSON.parse(readFileSync32(path, "utf-8"));
90503
90735
  } catch {
90504
90736
  return null;
90505
90737
  }
@@ -102524,7 +102756,7 @@ var init_remote_customer_operations = __esm(() => {
102524
102756
  });
102525
102757
 
102526
102758
  // src/lib/workspace-profile.ts
102527
- import { constants as constants16, closeSync as closeSync19, fstatSync as fstatSync19, lstatSync as lstatSync24, mkdirSync as mkdirSync17, mkdtempSync as mkdtempSync5, openSync as openSync19, readFileSync as readFileSync32, renameSync as renameSync10, rmSync as rmSync8, writeFileSync as writeFileSync17 } from "fs";
102759
+ import { constants as constants16, closeSync as closeSync19, fstatSync as fstatSync19, lstatSync as lstatSync24, mkdirSync as mkdirSync17, mkdtempSync as mkdtempSync5, openSync as openSync19, readFileSync as readFileSync33, renameSync as renameSync10, rmSync as rmSync8, writeFileSync as writeFileSync17 } from "fs";
102528
102760
  import { dirname as dirname23, join as join46 } from "path";
102529
102761
  function stat2(path) {
102530
102762
  try {
@@ -102543,7 +102775,7 @@ function safeText(file2) {
102543
102775
  const s = fstatSync19(fd);
102544
102776
  if (!s.isFile() || s.size > 65536 || ![256, 384].includes(s.mode & 4095) || process.getuid && s.uid !== process.getuid())
102545
102777
  return fail3("The selected profile must use bounded owner-only regular files.");
102546
- return readFileSync32(fd, "utf8");
102778
+ return readFileSync33(fd, "utf8");
102547
102779
  } finally {
102548
102780
  closeSync19(fd);
102549
102781
  }
@@ -105421,7 +105653,7 @@ var init_resource_meta_tools = __esm(() => {
105421
105653
  });
105422
105654
 
105423
105655
  // src/lib/scheduler.ts
105424
- import { existsSync as existsSync30, readFileSync as readFileSync33, writeFileSync as writeFileSync19, mkdirSync as mkdirSync20 } from "fs";
105656
+ import { existsSync as existsSync30, readFileSync as readFileSync34, writeFileSync as writeFileSync19, mkdirSync as mkdirSync20 } from "fs";
105425
105657
  import { join as join50 } from "path";
105426
105658
  function getSchedulesPath(targetDir = process.cwd()) {
105427
105659
  return join50(targetDir, ".skills", "schedules.json");
@@ -105430,7 +105662,7 @@ function loadSchedules(targetDir = process.cwd()) {
105430
105662
  const path = getSchedulesPath(targetDir);
105431
105663
  if (existsSync30(path)) {
105432
105664
  try {
105433
- return JSON.parse(readFileSync33(path, "utf-8"));
105665
+ return JSON.parse(readFileSync34(path, "utf-8"));
105434
105666
  } catch {}
105435
105667
  }
105436
105668
  return { version: 1, schedules: [] };
@@ -105740,7 +105972,7 @@ import { createHash as createHash25, createHmac as createHmac3 } from "crypto";
105740
105972
  import {
105741
105973
  existsSync as existsSync31,
105742
105974
  mkdirSync as mkdirSync21,
105743
- readFileSync as readFileSync34,
105975
+ readFileSync as readFileSync35,
105744
105976
  readdirSync as readdirSync19,
105745
105977
  statSync as statSync17,
105746
105978
  writeFileSync as writeFileSync20
@@ -105808,7 +106040,7 @@ function exportSkillsLocalSnapshot(targetDir = process.cwd(), options = {}) {
105808
106040
  const files = [];
105809
106041
  if (existsSync31(projectStateDir)) {
105810
106042
  for (const filePath of walkFiles2(projectStateDir)) {
105811
- const bytes = readFileSync34(filePath);
106043
+ const bytes = readFileSync35(filePath);
105812
106044
  const relativePath = toPosix(relative7(targetDir, filePath));
105813
106045
  files.push({
105814
106046
  path: relativePath,
@@ -106713,7 +106945,7 @@ var exports_runtime_mcp = {};
106713
106945
  __export(exports_runtime_mcp, {
106714
106946
  handleMcp: () => handleMcp
106715
106947
  });
106716
- import { existsSync as existsSync32, mkdirSync as mkdirSync23, readFileSync as readFileSync35, writeFileSync as writeFileSync22 } from "fs";
106948
+ import { existsSync as existsSync32, mkdirSync as mkdirSync23, readFileSync as readFileSync36, writeFileSync as writeFileSync22 } from "fs";
106717
106949
  import { homedir as homedir10 } from "os";
106718
106950
  import { dirname as dirname28, join as join53 } from "path";
106719
106951
  async function handleMcp(options) {
@@ -106824,7 +107056,7 @@ function registerCodexMcp(command) {
106824
107056
  const config2 = `[mcp_servers.${MCP_SERVER_NAME}]
106825
107057
  command = ${JSON.stringify(command)}`;
106826
107058
  try {
106827
- const current = existsSync32(path) ? readFileSync35(path, "utf-8") : "";
107059
+ const current = existsSync32(path) ? readFileSync36(path, "utf-8") : "";
106828
107060
  writeTextFile(path, upsertTomlSection(current, `[mcp_servers.${MCP_SERVER_NAME}]`, `command = ${JSON.stringify(command)}`));
106829
107061
  return { agent: "codex", success: true, path, config: config2 };
106830
107062
  } catch (err) {
@@ -106876,7 +107108,7 @@ function registerJsonMcpServer(agent, path, containerKey, server2) {
106876
107108
  function readJsonObject2(path) {
106877
107109
  if (!existsSync32(path))
106878
107110
  return {};
106879
- const raw = readFileSync35(path, "utf-8").trim();
107111
+ const raw = readFileSync36(path, "utf-8").trim();
106880
107112
  if (!raw)
106881
107113
  return {};
106882
107114
  const parsed = JSON.parse(raw);
@@ -107000,7 +107232,7 @@ __export(exports_runtime, {
107000
107232
  registerRuntime: () => registerRuntime
107001
107233
  });
107002
107234
  import { createHash as createHash26, randomUUID as randomUUID9 } from "crypto";
107003
- import { lstatSync as lstatSync27, mkdirSync as mkdirSync24, readFileSync as readFileSync36, realpathSync as realpathSync11, writeFileSync as writeFileSync23 } from "fs";
107235
+ import { lstatSync as lstatSync27, mkdirSync as mkdirSync24, readFileSync as readFileSync37, realpathSync as realpathSync11, writeFileSync as writeFileSync23 } from "fs";
107004
107236
  import { basename as basename13, isAbsolute as isAbsolute22, join as join54 } from "path";
107005
107237
  import { createInterface } from "readline";
107006
107238
  function registerRuntime(parent) {
@@ -107453,7 +107685,7 @@ async function handleRun(name, args2, options, separatorBeforeSkill) {
107453
107685
  const info = lstatSync27(path);
107454
107686
  if (!info.isFile() || info.size > 20 * 1024 * 1024)
107455
107687
  throw new Error("Input must be a regular file no larger than 20 MiB");
107456
- return { name: basename13(path), bytes: new Uint8Array(readFileSync36(path)) };
107688
+ return { name: basename13(path), bytes: new Uint8Array(readFileSync37(path)) };
107457
107689
  });
107458
107690
  describeRemoteFiles(inputFiles);
107459
107691
  client2 = new RemoteSkillsClient(routing.apiKey, routing.apiOrigin);
@@ -108625,7 +108857,7 @@ import { createHash as createHash27 } from "crypto";
108625
108857
  import {
108626
108858
  copyFileSync,
108627
108859
  mkdirSync as mkdirSync25,
108628
- readFileSync as readFileSync37,
108860
+ readFileSync as readFileSync38,
108629
108861
  statSync as statSync19,
108630
108862
  writeFileSync as writeFileSync24
108631
108863
  } from "fs";
@@ -108636,7 +108868,7 @@ function validateStationId(stationId) {
108636
108868
  }
108637
108869
  }
108638
108870
  function sha256File(filePath) {
108639
- return createHash27("sha256").update(readFileSync37(filePath)).digest("hex");
108871
+ return createHash27("sha256").update(readFileSync38(filePath)).digest("hex");
108640
108872
  }
108641
108873
  function scanHome(definition, homesRoot) {
108642
108874
  const homePath = homePathFor(definition, homesRoot);
@@ -109465,7 +109697,7 @@ var init_codex_hook_policy_recovery = __esm(() => {
109465
109697
  });
109466
109698
 
109467
109699
  // src/lib/agent-codex-trust.ts
109468
- import { lstatSync as lstatSync29, mkdirSync as mkdirSync26, readdirSync as readdirSync21, readFileSync as readFileSync38, realpathSync as realpathSync14, statSync as statSync21 } from "fs";
109700
+ import { lstatSync as lstatSync29, mkdirSync as mkdirSync26, readdirSync as readdirSync21, readFileSync as readFileSync39, realpathSync as realpathSync14, statSync as statSync21 } from "fs";
109469
109701
  import { createHash as createHash28, randomUUID as randomUUID10 } from "crypto";
109470
109702
  import { execFileSync } from "child_process";
109471
109703
  import { dirname as dirname32, isAbsolute as isAbsolute26, join as join58, resolve as resolve23 } from "path";
@@ -109475,13 +109707,13 @@ function verifyReleaseArtifact(proof, skillsCli) {
109475
109707
  need4(isAbsolute26(proof.packageTarPath) && !proof.packageTarPath.includes("\x00"), "RECONCILE_RELEASE_PROVENANCE_PATH");
109476
109708
  const tarPath = realpathSync14(proof.packageTarPath);
109477
109709
  need4(statSync21(tarPath).isFile(), "RECONCILE_RELEASE_PROVENANCE_PATH");
109478
- const tarBytes = readFileSync38(tarPath);
109710
+ const tarBytes = readFileSync39(tarPath);
109479
109711
  need4(tarBytes.byteLength === proof.packageTarBytes && createHash28("sha256").update(tarBytes).digest("hex") === proof.packageTarSha256, "RECONCILE_RELEASE_ARTIFACT_CHANGED");
109480
109712
  const packageRoot = dirname32(dirname32(realpathSync14(skillsCli.receipt.path)));
109481
- const manifest = readFileSync38(join58(packageRoot, "package.json"));
109713
+ const manifest = readFileSync39(join58(packageRoot, "package.json"));
109482
109714
  need4(createHash28("sha256").update(manifest).digest("hex") === skillsCli.receipt.manifestSha256 && skillsCli.receipt.manifestSha256 === proof.manifestSha256, "RECONCILE_RELEASE_MANIFEST_CHANGED");
109483
- need4(createHash28("sha256").update(readFileSync38(skillsCli.receipt.path)).digest("hex") === proof.executableSha256 && skillsCli.receipt.sha256 === proof.executableSha256, "RECONCILE_RELEASE_EXECUTABLE_CHANGED");
109484
- const members2 = [["package/package.json", manifest], ["package/bin/index.js", readFileSync38(skillsCli.receipt.path)]];
109715
+ need4(createHash28("sha256").update(readFileSync39(skillsCli.receipt.path)).digest("hex") === proof.executableSha256 && skillsCli.receipt.sha256 === proof.executableSha256, "RECONCILE_RELEASE_EXECUTABLE_CHANGED");
109716
+ const members2 = [["package/package.json", manifest], ["package/bin/index.js", readFileSync39(skillsCli.receipt.path)]];
109485
109717
  for (const [member, expected] of members2) {
109486
109718
  let actual;
109487
109719
  try {
@@ -109882,7 +110114,8 @@ var init_hook_diagnostics = __esm(() => {
109882
110114
  "SESSION_RECEIPT_CHANGED",
109883
110115
  "SESSION_RECONCILIATION_INCOMPLETE",
109884
110116
  "SESSION_WRITE_LOCKED",
109885
- "SESSION_WRITE_LOCK_CHANGED"
110117
+ "SESSION_WRITE_LOCK_CHANGED",
110118
+ "SESSION_LOCK_RECOVERY_INCOMPLETE"
109886
110119
  ]);
109887
110120
  HookDiagnosticError = class HookDiagnosticError extends Error {
109888
110121
  code;
@@ -109900,7 +110133,7 @@ var exports_agent_integration = {};
109900
110133
  __export(exports_agent_integration, {
109901
110134
  registerAgentIntegration: () => registerAgentIntegration
109902
110135
  });
109903
- import { readFileSync as readFileSync39 } from "fs";
110136
+ import { readFileSync as readFileSync40 } from "fs";
109904
110137
  import { isAbsolute as isAbsolute27 } from "path";
109905
110138
  function pinnedHookProfile(input3, configuredProfile) {
109906
110139
  try {
@@ -109978,7 +110211,7 @@ function registerAgentIntegration(parent) {
109978
110211
  });
109979
110212
  hook.command("install").option("--agent <agent>", `Agent to configure: ${INTEGRATION_AGENTS.join(", ")}, all`, "all").option("--command <path>", "Skills executable used by the hook (preserves existing binding; new agents use skills)").option("--selection-profile <id>", "Selection profile (preserves existing binding; new agents use default)").option("--include-vendor", "Retained for compatibility; vendor system skills are always inventoried and disabled", false).option("--discovery-inputs <file>", "Advanced reviewed active plugin roots and source hashes for unsupported registrations").option("--allow-root-aliases", "Allow home .claude/.codex aliases to existing directories within this home", false).option("--apply", "Apply the plan, preserving prior configuration in private backups", false).option("--json", "Output a receipt as JSON", false).description("Plan or install one Skills CLI bridge plus native prompt hooks").action(async (options) => {
109980
110213
  try {
109981
- const discoveryInputs = options.discoveryInputs ? JSON.parse(readFileSync39(options.discoveryInputs, "utf8")) : undefined;
110214
+ const discoveryInputs = options.discoveryInputs ? JSON.parse(readFileSync40(options.discoveryInputs, "utf8")) : undefined;
109982
110215
  const plan = planAgentIntegration({ agents: agents(options.agent), command: options.command, profileId: options.selectionProfile, includeVendor: options.includeVendor, discoveryInputs, allowRootAliases: options.allowRootAliases });
109983
110216
  const result2 = options.apply ? applyAgentIntegration(plan) : { changed: [], backups: [] };
109984
110217
  const receipt = { applied: options.apply, planned: plan.changes.map((change) => change.path), ...result2, rootAliases: plan.rootAliases ?? [], discovery: plan.discoveryAfter, nativeSkills: plan.nativeSkills.map((entry) => ({ agent: entry.agent, path: entry.path, managed: entry.managed, vendor: entry.vendor, system: entry.system === true, bridge: entry.bridge === true })), requiresNativeRetirement: plan.nativeSkills.some((entry) => !entry.bridge && !entry.system) };
@@ -110036,7 +110269,7 @@ function registerAgentIntegration(parent) {
110036
110269
  try {
110037
110270
  if (agents(options.agent).length !== 1)
110038
110271
  throw new Error("A hook invocation requires one agent");
110039
- const inputText = readFileSync39(0, "utf8");
110272
+ const inputText = readFileSync40(0, "utf8");
110040
110273
  if (inputText.length > 1024 * 1024)
110041
110274
  throw new Error("Hook input is too large");
110042
110275
  let input3 = JSON.parse(inputText);
@@ -110132,7 +110365,7 @@ function registerAgentIntegration(parent) {
110132
110365
  const migrate = parent.command("migrate").description("Preserve and retire native agent skill copies");
110133
110366
  migrate.command("native").option("--project <directory>", "Also inventory a project and its ancestors (the current directory and its ancestors are always included)").option("--include-unmanaged", "Archive user-authored skills as well as Skills-managed copies", false).option("--include-vendor", "Retire vendor SKILL.md discovery files while preserving plugin scripts and assets", false).option("--target-manifest <file>", "Reviewed exact native migration target manifest").option("--discovery-inputs <file>", "Advanced reviewed active plugin roots and source hashes").option("--allow-root-aliases", "Allow home .claude/.codex aliases to existing directories within this home", false).option("--apply", "Move selected skills to private archives outside agent discovery roots", false).option("--json", "Output inventory and archive receipt as JSON", false).description("Inventory native skill copies; preserve complete directories before retiring them").action(async (options) => {
110134
110367
  try {
110135
- const discoveryInputs = options.discoveryInputs ? JSON.parse(readFileSync39(options.discoveryInputs, "utf8")) : undefined;
110368
+ const discoveryInputs = options.discoveryInputs ? JSON.parse(readFileSync40(options.discoveryInputs, "utf8")) : undefined;
110136
110369
  if (options.targetManifest && (options.includeUnmanaged || options.includeVendor))
110137
110370
  throw new Error("--target-manifest cannot be combined with broad native migration selectors");
110138
110371
  const targetManifest = options.targetManifest ? readNativeMigrationTargetManifest(options.targetManifest) : undefined;
@@ -110439,7 +110672,7 @@ import {
110439
110672
  copyFileSync as copyFileSync2,
110440
110673
  mkdirSync as mkdirSync27,
110441
110674
  readdirSync as readdirSync22,
110442
- readFileSync as readFileSync40,
110675
+ readFileSync as readFileSync41,
110443
110676
  statSync as statSync22,
110444
110677
  writeFileSync as writeFileSync27
110445
110678
  } from "fs";
@@ -110455,7 +110688,7 @@ function readSnapshotManifest(repoRoot, stationId) {
110455
110688
  const manifestPath = join59(snapshotRoot, "sync-manifest.json");
110456
110689
  let manifest;
110457
110690
  try {
110458
- manifest = JSON.parse(readFileSync40(manifestPath, "utf8"));
110691
+ manifest = JSON.parse(readFileSync41(manifestPath, "utf8"));
110459
110692
  } catch (error61) {
110460
110693
  fail5("MANIFEST_UNREADABLE", `cannot read snapshot manifest: ${manifestPath}: ${error61.message}`);
110461
110694
  }
@@ -110591,7 +110824,7 @@ function planStationHydration(stationId, repoRoot) {
110591
110824
  for (const copy of copies) {
110592
110825
  let isStub = false;
110593
110826
  try {
110594
- isStub = isPointerSkillMd(readFileSync40(copy.fullPath, "utf8"));
110827
+ isStub = isPointerSkillMd(readFileSync41(copy.fullPath, "utf8"));
110595
110828
  } catch {
110596
110829
  isStub = false;
110597
110830
  }
@@ -110795,7 +111028,7 @@ var init_hydrate = __esm(() => {
110795
111028
 
110796
111029
  // src/lib/prepare-skill.ts
110797
111030
  import { createHash as createHash30, randomUUID as randomUUID11 } from "crypto";
110798
- import { chmodSync as chmodSync4, existsSync as existsSync34, lstatSync as lstatSync30, mkdirSync as mkdirSync28, mkdtempSync as mkdtempSync6, readFileSync as readFileSync41, readdirSync as readdirSync23, renameSync as renameSync13, rmSync as rmSync9, writeFileSync as writeFileSync28 } from "fs";
111031
+ import { chmodSync as chmodSync4, existsSync as existsSync34, lstatSync as lstatSync30, mkdirSync as mkdirSync28, mkdtempSync as mkdtempSync6, readFileSync as readFileSync42, readdirSync as readdirSync23, renameSync as renameSync13, rmSync as rmSync9, writeFileSync as writeFileSync28 } from "fs";
110799
111032
  import { tmpdir as tmpdir2 } from "os";
110800
111033
  import { dirname as dirname34, isAbsolute as isAbsolute28, join as join60, relative as relative9, resolve as resolve25, sep as sep12 } from "path";
110801
111034
  function prepareSkill(name, options) {
@@ -111015,7 +111248,7 @@ function snapshot2(root2) {
111015
111248
  bytes += stat3.size;
111016
111249
  if (bytes > 50000000)
111017
111250
  throw new Error("Skill exceeds the preparation size limit (50000000 bytes).");
111018
- const content = readFileSync41(absolute);
111251
+ const content = readFileSync42(absolute);
111019
111252
  if (content.length !== stat3.size)
111020
111253
  throw new Error("Skill changed during preparation.");
111021
111254
  files.push({ path, bytes: content, mode: stat3.mode & 511 });
@@ -111697,8 +111930,8 @@ __export(exports_publish, {
111697
111930
  PushSkillError: () => PushSkillError
111698
111931
  });
111699
111932
  import { execFileSync as execFileSync2 } from "child_process";
111700
- import { existsSync as existsSync35, readFileSync as readFileSync42 } from "fs";
111701
- import { hostname as hostname4 } from "os";
111933
+ import { existsSync as existsSync35, readFileSync as readFileSync43 } from "fs";
111934
+ import { hostname as hostname5 } from "os";
111702
111935
  import { join as join61 } from "path";
111703
111936
  function registerPublish(parent) {
111704
111937
  parent.command("push").argument("<name>", "Name of a skill in the local corpus (~/.hasna/skills/installed or the migrated ~/.hasna/skills/skills)").option("--version <version>", "Override the version recorded on the instance").option("--force-new-version", "If name@version already exists with different content, publish as the next patch version", false).option("--dry-run", "Pack and validate without uploading", false).option("--json", "Output result as JSON", false).description("Publish a local skill to the configured skills instance").action(async (name, options) => {
@@ -111752,7 +111985,7 @@ async function pushSkill(name, options = {}) {
111752
111985
  await verifyPackedCanonicalHash(skill.name, packed);
111753
111986
  const versionManifest = buildVersionManifest(skill.path, packed);
111754
111987
  const skillMdPath = join61(skill.path, "SKILL.md");
111755
- const skillMd = existsSync35(skillMdPath) ? readFileSync42(skillMdPath, "utf-8") : undefined;
111988
+ const skillMd = existsSync35(skillMdPath) ? readFileSync43(skillMdPath, "utf-8") : undefined;
111756
111989
  const base3 = {
111757
111990
  slug: skill.name,
111758
111991
  path: skill.path,
@@ -111882,7 +112115,7 @@ function buildVersionManifest(skillDir, packed) {
111882
112115
  unpackedByteSize: packed.unpackedByteSize,
111883
112116
  bundleSha256: packed.sha256,
111884
112117
  provenance: {
111885
- machine: hostname4(),
112118
+ machine: hostname5(),
111886
112119
  agent: process.env.SKILLS_AGENT_ID ?? process.env.HASNA_AGENT_ID ?? process.env.AGENT_ID ?? null,
111887
112120
  cliVersion: package_default.version,
111888
112121
  gitRemote: sanitizeGitRemote(gitValue(skillDir, ["remote", "get-url", "origin"])),
@@ -113471,7 +113704,7 @@ var init_storage2 = __esm(() => {
113471
113704
  });
113472
113705
 
113473
113706
  // src/lib/registry-reconcile.ts
113474
- import { existsSync as existsSync36, readFileSync as readFileSync43, statSync as statSync23, writeFileSync as writeFileSync30 } from "fs";
113707
+ import { existsSync as existsSync36, readFileSync as readFileSync44, statSync as statSync23, writeFileSync as writeFileSync30 } from "fs";
113475
113708
  import { join as join62 } from "path";
113476
113709
  function isDirectory2(path) {
113477
113710
  try {
@@ -113491,7 +113724,7 @@ function readBaseline(skillDir) {
113491
113724
  if (!existsSync36(markerPath))
113492
113725
  return;
113493
113726
  try {
113494
- const marker = JSON.parse(readFileSync43(markerPath, "utf-8"));
113727
+ const marker = JSON.parse(readFileSync44(markerPath, "utf-8"));
113495
113728
  if (!isSkillsOwnershipMarker(marker))
113496
113729
  return;
113497
113730
  return {
@@ -113507,7 +113740,7 @@ function readCursor(root2) {
113507
113740
  if (!existsSync36(path))
113508
113741
  return { runCount: 0 };
113509
113742
  try {
113510
- const cursor2 = JSON.parse(readFileSync43(path, "utf-8"));
113743
+ const cursor2 = JSON.parse(readFileSync44(path, "utf-8"));
113511
113744
  return { runCount: typeof cursor2.runCount === "number" ? cursor2.runCount : 0 };
113512
113745
  } catch {
113513
113746
  return { runCount: 0 };