@hasna/skills 0.10.0 → 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/dist/index.js CHANGED
@@ -6988,7 +6988,7 @@ var require_public_api = __commonJS((exports) => {
6988
6988
  });
6989
6989
 
6990
6990
  // src/lib/registry.ts
6991
- import { existsSync as existsSync14, readFileSync as readFileSync17, readdirSync as readdirSync11 } from "fs";
6991
+ import { existsSync as existsSync14, readFileSync as readFileSync18, readdirSync as readdirSync11 } from "fs";
6992
6992
  import { join as join29 } from "path";
6993
6993
 
6994
6994
  // src/lib/config.ts
@@ -9091,7 +9091,7 @@ function assertAgentPolicyCollections(policy) {
9091
9091
 
9092
9092
  // src/lib/agent-discovery.ts
9093
9093
  import { createHash as createHash16 } from "crypto";
9094
- import { lstatSync as lstatSync20, readFileSync as readFileSync16, readdirSync as readdirSync9, realpathSync as realpathSync4 } from "fs";
9094
+ import { lstatSync as lstatSync20, readFileSync as readFileSync17, readdirSync as readdirSync9, realpathSync as realpathSync4 } from "fs";
9095
9095
  import { basename as basename8, dirname as dirname16, isAbsolute as isAbsolute14, join as join26, resolve as resolve14, sep as sep5 } from "path";
9096
9096
  import { isDeepStrictEqual as isDeepStrictEqual3 } from "util";
9097
9097
 
@@ -9611,7 +9611,7 @@ import { isAbsolute as isAbsolute11, join as join23, resolve as resolve11 } from
9611
9611
  // package.json
9612
9612
  var package_default = {
9613
9613
  name: "@hasna/skills",
9614
- version: "0.10.0",
9614
+ version: "0.10.2",
9615
9615
  description: "Skills library for AI coding agents",
9616
9616
  type: "module",
9617
9617
  bin: {
@@ -10569,9 +10569,17 @@ var AUTHORITY_OVERRIDE_HEADERS = new Set([
10569
10569
 
10570
10570
  // src/lib/instance-credentials.ts
10571
10571
  import { closeSync as closeSync5, constants as constants2, fstatSync as fstatSync5, lstatSync as lstatSync8, openSync as openSync5, readSync as readSync2 } from "fs";
10572
+
10573
+ // src/lib/cli-credential-profile.ts
10574
+ var cliCredentialProfile;
10575
+ function selectedCliSkillsCredentialProfile() {
10576
+ return cliCredentialProfile;
10577
+ }
10578
+
10579
+ // src/lib/instance-credentials.ts
10572
10580
  var SKILLS_BOUND_API_URL = "HASNA_SKILLS_BOUND_API_URL";
10573
10581
  function selectedSkillsProfile(env, explicit) {
10574
- const selected = explicit ?? env.HASNA_PROFILE;
10582
+ const selected = explicit ?? selectedCliSkillsCredentialProfile() ?? env.HASNA_PROFILE;
10575
10583
  if (selected === undefined)
10576
10584
  return null;
10577
10585
  const profile = selected.trim();
@@ -10819,11 +10827,13 @@ function snapshotSkillsEnvironment(env) {
10819
10827
  return Object.freeze(snapshot);
10820
10828
  }
10821
10829
  function snapshotSkillsOptions(env, options) {
10830
+ const profile = options.credentials?.profile ?? selectedCliSkillsCredentialProfile();
10831
+ const credentials = profile === undefined ? options.credentials : { ...options.credentials, profile };
10822
10832
  if (env !== process.env)
10823
- return options;
10824
- return { ...options, credentials: { ...options.credentials, keychain: {
10825
- ...options.credentials?.keychain,
10826
- enabled: options.credentials?.keychain?.enabled ?? true
10833
+ return credentials === options.credentials ? options : { ...options, credentials };
10834
+ return { ...options, credentials: { ...credentials, keychain: {
10835
+ ...credentials?.keychain,
10836
+ enabled: credentials?.keychain?.enabled ?? true
10827
10837
  } } };
10828
10838
  }
10829
10839
  function resolveSkillsFleetOrThrow(env, options) {
@@ -10911,8 +10921,9 @@ async function resolveSkillsApiKey(env = process.env, options = {}) {
10911
10921
  }
10912
10922
  async function resolveSkillsConnection(env = process.env, options = {}) {
10913
10923
  const snapshotEnv = snapshotSkillsEnvironment(env);
10914
- const assertFilesUnchanged = selectsSkillsLocalMode(snapshotEnv) ? () => {} : captureSkillsCredentialFiles(skillsProfileCredentialFiles(snapshotEnv, options.credentials?.profile));
10915
- const fleet = resolveSkillsFleet(snapshotEnv, snapshotSkillsOptions(env, options));
10924
+ const resolvedOptions = snapshotSkillsOptions(env, options);
10925
+ const assertFilesUnchanged = selectsSkillsLocalMode(snapshotEnv) ? () => {} : captureSkillsCredentialFiles(skillsProfileCredentialFiles(snapshotEnv, resolvedOptions.credentials?.profile));
10926
+ const fleet = resolveSkillsFleet(snapshotEnv, resolvedOptions);
10916
10927
  if (fleet.mode === "local" && env === process.env)
10917
10928
  noticeLocalSkillsMode();
10918
10929
  if (fleet.mode !== "hosted")
@@ -11812,7 +11823,9 @@ function tarOctal(field) {
11812
11823
 
11813
11824
  // src/lib/selection-cache.ts
11814
11825
  import { createHash as createHash7, randomUUID } from "crypto";
11815
- import { closeSync as closeSync6, constants as constants3, fstatSync as fstatSync6, fsyncSync, lstatSync as lstatSync9, mkdirSync as mkdirSync3, openSync as openSync6, readSync as readSync3, renameSync, unlinkSync, writeFileSync as writeFileSync3 } from "fs";
11826
+ import { spawnSync as spawnSync2 } from "child_process";
11827
+ import { closeSync as closeSync6, constants as constants3, fstatSync as fstatSync6, fsyncSync, lstatSync as lstatSync9, mkdirSync as mkdirSync3, openSync as openSync6, readFileSync as readFileSync9, readlinkSync as readlinkSync2, readSync as readSync3, renameSync, unlinkSync, writeFileSync as writeFileSync3 } from "fs";
11828
+ import { hostname } from "os";
11816
11829
  import { dirname as dirname8, join as join12, parse as parse2, resolve as resolve7 } from "path";
11817
11830
  import { isDeepStrictEqual } from "util";
11818
11831
 
@@ -12113,6 +12126,166 @@ function readSkillSessionSnapshot(sessionId, options = {}) {
12113
12126
  function skillSessionSnapshotBinding(snapshot) {
12114
12127
  return { sessionId: snapshot.sessionId, generation: snapshot.generation, receiptSha256: snapshot.receiptSha256 };
12115
12128
  }
12129
+ var SESSION_LOCK_MAX_BYTES = 4096;
12130
+ var SESSION_LOCK_MIN_AGE_MS = 30000;
12131
+ function localBootId() {
12132
+ try {
12133
+ if (process.platform === "linux") {
12134
+ const value = readFileSync9("/proc/sys/kernel/random/boot_id", "utf8").trim();
12135
+ return /^[a-f0-9-]{36}$/i.test(value) ? value : null;
12136
+ }
12137
+ if (process.platform === "darwin") {
12138
+ const result = spawnSync2("/usr/sbin/sysctl", ["-n", "kern.boottime"], { encoding: "utf8", timeout: 3000, env: { LC_ALL: "C" } });
12139
+ if (result.status !== 0 || result.error)
12140
+ return null;
12141
+ const seconds = /\bsec\s*=\s*(\d+)\b/.exec(result.stdout)?.[1];
12142
+ return seconds ? `darwin:${seconds}` : null;
12143
+ }
12144
+ } catch {}
12145
+ return null;
12146
+ }
12147
+ function processStart(pid) {
12148
+ if (!Number.isSafeInteger(pid) || pid <= 0)
12149
+ return { state: "unknown" };
12150
+ if (process.platform === "linux") {
12151
+ try {
12152
+ const stat = readFileSync9(`/proc/${pid}/stat`, "utf8");
12153
+ const close = stat.lastIndexOf(")");
12154
+ const start = close < 0 ? undefined : stat.slice(close + 2).trim().split(/\s+/)[19];
12155
+ return start && /^\d+$/.test(start) ? { state: "alive", start: `linux:${start}` } : { state: "unknown" };
12156
+ } catch (error) {
12157
+ return { state: error.code === "ENOENT" ? "absent" : "unknown" };
12158
+ }
12159
+ }
12160
+ if (process.platform === "darwin") {
12161
+ const result = spawnSync2("/bin/ps", ["-p", String(pid), "-o", "lstart="], { encoding: "utf8", timeout: 3000, env: { LC_ALL: "C" } });
12162
+ if (result.error || result.signal)
12163
+ return { state: "unknown" };
12164
+ const start = result.stdout.trim();
12165
+ if (result.status === 1 && !start && !result.stderr.trim())
12166
+ return { state: "absent" };
12167
+ return result.status === 0 && start ? { state: "alive", start: `darwin:${start}` } : { state: "unknown" };
12168
+ }
12169
+ return { state: "unknown" };
12170
+ }
12171
+ function localLockIdentity() {
12172
+ const bootId = localBootId(), owner = processStart(process.pid);
12173
+ if (!bootId || owner.state !== "alive")
12174
+ return null;
12175
+ let pidNamespace;
12176
+ if (process.platform === "linux") {
12177
+ try {
12178
+ pidNamespace = readlinkSync2("/proc/self/ns/pid");
12179
+ } catch {
12180
+ return null;
12181
+ }
12182
+ if (!/^pid:\[\d+\]$/.test(pidNamespace))
12183
+ return null;
12184
+ }
12185
+ return { host: hostname(), bootId, pidNamespace, processStart: owner.start };
12186
+ }
12187
+ function readSessionLock(sessionId, options) {
12188
+ const path = `${sessionReceiptPath(sessionId, options)}.write-lock`;
12189
+ const before = lstatSync9(path, { throwIfNoEntry: false });
12190
+ if (!before)
12191
+ return null;
12192
+ if (!before.isFile() || before.nlink !== 1 || process.getuid && before.uid !== process.getuid()) {
12193
+ throw new SkillSelectionError("SESSION_WRITE_LOCKED", "The session lock is not a private regular file; recovery requires review.");
12194
+ }
12195
+ const bytes = readRegularFile(path, SESSION_LOCK_MAX_BYTES);
12196
+ const after = lstatSync9(path, { throwIfNoEntry: false });
12197
+ if (!bytes || !after?.isFile() || before.dev !== after.dev || before.ino !== after.ino || before.mtimeMs !== after.mtimeMs) {
12198
+ throw new SkillSelectionError("SESSION_WRITE_LOCKED", "The session lock changed during inspection; recovery requires review.");
12199
+ }
12200
+ let marker;
12201
+ try {
12202
+ marker = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(bytes));
12203
+ } catch {
12204
+ throw new SkillSelectionError("SESSION_WRITE_LOCKED", "The session lock is unreadable; recovery requires review.");
12205
+ }
12206
+ 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)) {
12207
+ throw new SkillSelectionError("SESSION_WRITE_LOCKED", "The session lock has invalid ownership metadata; recovery requires review.");
12208
+ }
12209
+ return { path, bytes, marker, sha256: sha256Hex(bytes), dev: after.dev, ino: after.ino, mtimeMs: after.mtimeMs };
12210
+ }
12211
+ function writerIsGone(lock, explicitLocalHost) {
12212
+ if (Date.now() - lock.mtimeMs < SESSION_LOCK_MIN_AGE_MS)
12213
+ return false;
12214
+ const owner = processStart(lock.marker.pid);
12215
+ if (owner.state === "unknown")
12216
+ return false;
12217
+ if (lock.marker.schemaVersion === 1)
12218
+ return explicitLocalHost && owner.state === "absent";
12219
+ const local = localLockIdentity();
12220
+ if (!local || lock.marker.host !== local.host || lock.marker.bootId !== local.bootId || lock.marker.pidNamespace !== local.pidNamespace)
12221
+ return false;
12222
+ return owner.state === "absent" || owner.state === "alive" && owner.start !== lock.marker.processStart;
12223
+ }
12224
+ function archiveSessionLock(lock, receipt, explicitLocalHost) {
12225
+ const guardPath = `${lock.path}.recovery-guard`;
12226
+ let guardFd;
12227
+ try {
12228
+ guardFd = openSync6(guardPath, constants3.O_WRONLY | constants3.O_CREAT | constants3.O_EXCL | constants3.O_NOFOLLOW, 384);
12229
+ } catch (error) {
12230
+ if (error.code === "EEXIST")
12231
+ return null;
12232
+ throw error;
12233
+ }
12234
+ const guardStat = fstatSync6(guardFd);
12235
+ try {
12236
+ writeFileSync3(guardFd, `${JSON.stringify({ schemaVersion: 1, pid: process.pid, operationId: randomUUID() })}
12237
+ `);
12238
+ fsyncSync(guardFd);
12239
+ const cacheOptions = { cacheDir: dirname8(dirname8(lock.path)) };
12240
+ const current = readSessionLock(lock.marker.sessionId, cacheOptions);
12241
+ if (!current || current.dev !== lock.dev || current.ino !== lock.ino || current.sha256 !== lock.sha256 || current.mtimeMs !== lock.mtimeMs || !writerIsGone(current, explicitLocalHost))
12242
+ return null;
12243
+ const currentReceipt = readSkillSessionSnapshotIfExists(lock.marker.sessionId, cacheOptions);
12244
+ if (currentReceipt?.sha256 !== receipt?.sha256 || currentReceipt?.generation !== receipt?.generation)
12245
+ return null;
12246
+ const directory = join12(dirname8(dirname8(lock.path)), "session-lock-recoveries", randomUUID());
12247
+ const archivePath = join12(directory, "original.write-lock");
12248
+ const recordPath = join12(directory, "recovery.json");
12249
+ assertRegularPath(archivePath, true);
12250
+ archiveBytes(recordPath, Buffer.from(`${JSON.stringify({
12251
+ schemaVersion: 1,
12252
+ sessionId: lock.marker.sessionId,
12253
+ originalPath: lock.path,
12254
+ lockSha256: lock.sha256,
12255
+ lockMtime: new Date(lock.mtimeMs).toISOString(),
12256
+ lockPid: lock.marker.pid,
12257
+ receiptSha256: receipt?.sha256 ?? null,
12258
+ receiptGeneration: receipt?.generation ?? null,
12259
+ status: "prepared"
12260
+ })}
12261
+ `));
12262
+ syncDirectory(directory);
12263
+ syncDirectory(dirname8(directory));
12264
+ const finalLock = readSessionLock(lock.marker.sessionId, cacheOptions);
12265
+ if (!finalLock || finalLock.dev !== lock.dev || finalLock.ino !== lock.ino || finalLock.sha256 !== lock.sha256 || readSkillSessionSnapshotIfExists(lock.marker.sessionId, cacheOptions)?.sha256 !== receipt?.sha256)
12266
+ return null;
12267
+ let moved = false;
12268
+ try {
12269
+ renameSync(lock.path, archivePath);
12270
+ moved = true;
12271
+ syncDirectory(directory);
12272
+ syncDirectory(dirname8(lock.path));
12273
+ if (sha256Hex(readRegularFile(archivePath, SESSION_LOCK_MAX_BYTES)) !== lock.sha256) {
12274
+ throw new Error("Archived lock bytes changed");
12275
+ }
12276
+ } catch (error) {
12277
+ if (moved)
12278
+ 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.");
12279
+ throw error;
12280
+ }
12281
+ return archivePath;
12282
+ } finally {
12283
+ closeSync6(guardFd);
12284
+ const current = lstatSync9(guardPath, { throwIfNoEntry: false });
12285
+ if (current?.isFile() && current.dev === guardStat.dev && current.ino === guardStat.ino)
12286
+ unlinkSync(guardPath);
12287
+ }
12288
+ }
12116
12289
  function withSessionWriteLocks(sessionIds, options, action) {
12117
12290
  const operationId = randomUUID();
12118
12291
  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);
@@ -12132,13 +12305,30 @@ function withSessionWriteLocks(sessionIds, options, action) {
12132
12305
  try {
12133
12306
  fd = openSync6(lock.path, constants3.O_WRONLY | constants3.O_CREAT | constants3.O_EXCL | constants3.O_NOFOLLOW, 384);
12134
12307
  } catch (error) {
12135
- if (error.code === "EEXIST")
12136
- 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.");
12137
- throw error;
12308
+ if (error.code !== "EEXIST")
12309
+ throw error;
12310
+ try {
12311
+ const stale = readSessionLock(lock.sessionId, options);
12312
+ const receipt = stale && readSkillSessionSnapshotIfExists(lock.sessionId, options);
12313
+ if (stale?.marker.schemaVersion === 2 && writerIsGone(stale, false)) {
12314
+ archiveSessionLock(stale, receipt, false);
12315
+ }
12316
+ } catch (recoveryError) {
12317
+ if (recoveryError instanceof SkillSelectionError && recoveryError.code === "SESSION_LOCK_RECOVERY_INCOMPLETE")
12318
+ throw recoveryError;
12319
+ }
12320
+ try {
12321
+ fd = openSync6(lock.path, constants3.O_WRONLY | constants3.O_CREAT | constants3.O_EXCL | constants3.O_NOFOLLOW, 384);
12322
+ } catch (retryError) {
12323
+ if (retryError.code === "EEXIST")
12324
+ 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.");
12325
+ throw retryError;
12326
+ }
12138
12327
  }
12139
12328
  const stat = fstatSync6(fd);
12140
12329
  owned.push({ path: lock.path, fd, dev: stat.dev, ino: stat.ino });
12141
- writeFileSync3(fd, `${JSON.stringify({ schemaVersion: 1, operationId, sessionId: lock.sessionId, pid: process.pid })}
12330
+ const identity3 = localLockIdentity();
12331
+ writeFileSync3(fd, `${JSON.stringify({ schemaVersion: identity3 ? 2 : 1, operationId, sessionId: lock.sessionId, pid: process.pid, ...identity3 })}
12142
12332
  `);
12143
12333
  }
12144
12334
  return action(assertOwned);
@@ -12257,7 +12447,7 @@ function replaceSkillSession(expected, replacement, plan, options = {}, beforeCo
12257
12447
  }
12258
12448
 
12259
12449
  // src/lib/dependency-preparation.ts
12260
- import { constants as constants4, closeSync as closeSync7, fstatSync as fstatSync7, lstatSync as lstatSync10, mkdirSync as mkdirSync4, openSync as openSync7, readFileSync as readFileSync9, readdirSync as readdirSync5, rmdirSync, unlinkSync as unlinkSync2, ftruncateSync, writeSync } from "fs";
12450
+ import { constants as constants4, 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";
12261
12451
  import { join as join13 } from "path";
12262
12452
 
12263
12453
  // src/lib/preparation-process.ts
@@ -12331,7 +12521,7 @@ function claimPreparation(skillPath) {
12331
12521
  return;
12332
12522
  if (!lstatSync10(state).isFile() || lstatSync10(state).isSymbolicLink() || lstatSync10(state).size > 1024)
12333
12523
  return;
12334
- const previous = JSON.parse(readFileSync9(state, "utf8"));
12524
+ const previous = JSON.parse(readFileSync10(state, "utf8"));
12335
12525
  if (previous.version !== 1 || previous.status !== "failed" || Object.keys(previous).length !== 2)
12336
12526
  return;
12337
12527
  }
@@ -12464,11 +12654,11 @@ async function prepareSkillDependencies(skillPath, env, timeoutMs = DEFAULT_PREP
12464
12654
  }
12465
12655
 
12466
12656
  // src/lib/skillinfo.ts
12467
- import { existsSync as existsSync12, readFileSync as readFileSync15 } from "fs";
12657
+ import { existsSync as existsSync12, readFileSync as readFileSync16 } from "fs";
12468
12658
  import { join as join20 } from "path";
12469
12659
 
12470
12660
  // src/lib/installer.ts
12471
- import { existsSync as existsSync11, readFileSync as readFileSync14, rmSync as rmSync2 } from "fs";
12661
+ import { existsSync as existsSync11, readFileSync as readFileSync15, rmSync as rmSync2 } from "fs";
12472
12662
  import { join as join19 } from "path";
12473
12663
  import { homedir as homedir4 } from "os";
12474
12664
 
@@ -12479,7 +12669,7 @@ import {
12479
12669
  lstatSync as lstatSync15,
12480
12670
  mkdirSync as mkdirSync6,
12481
12671
  mkdtempSync,
12482
- readFileSync as readFileSync12,
12672
+ readFileSync as readFileSync13,
12483
12673
  readdirSync as readdirSync8,
12484
12674
  renameSync as renameSync3,
12485
12675
  rmSync,
@@ -12491,7 +12681,7 @@ import { basename as basename5, dirname as dirname11, join as join17 } from "pat
12491
12681
 
12492
12682
  // src/lib/agent-integration.ts
12493
12683
  import { createHash as createHash10, randomUUID as randomUUID2 } from "crypto";
12494
- import { existsSync as existsSync8, lstatSync as lstatSync14, statSync as statSync7, mkdirSync as mkdirSync5, readFileSync as readFileSync11, 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 constants7, linkSync } from "fs";
12684
+ import { existsSync as existsSync8, lstatSync as lstatSync14, statSync as statSync7, mkdirSync as mkdirSync5, readFileSync as readFileSync12, 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 constants7, linkSync } from "fs";
12495
12685
  import { dirname as dirname10, join as join16, resolve as resolve9, relative as relative4, isAbsolute as isAbsolute9, sep as sep4 } from "path";
12496
12686
  import { homedir as homedir2 } from "os";
12497
12687
 
@@ -12577,7 +12767,7 @@ function requiresCliSkillLoading(dataDir2 = getDataDirReadOnly()) {
12577
12767
 
12578
12768
  // src/lib/agent-bridge.ts
12579
12769
  import { createHash as createHash8 } from "crypto";
12580
- import { lstatSync as lstatSync12, readFileSync as readFileSync10, readdirSync as readdirSync6 } from "fs";
12770
+ import { lstatSync as lstatSync12, readFileSync as readFileSync11, readdirSync as readdirSync6 } from "fs";
12581
12771
  import { join as join15 } from "path";
12582
12772
  var CLI_BRIDGE_NAME = "skills-cli";
12583
12773
  var CLI_BRIDGE_VERSION = 1;
@@ -12611,7 +12801,7 @@ function isOwnedCliBridge(path, expectedPaths) {
12611
12801
  return false;
12612
12802
  return Object.entries(CLI_BRIDGE_FILES).every(([name, content]) => {
12613
12803
  const file = join15(path, name), stat = lstatSync12(file);
12614
- return stat.isFile() && !stat.isSymbolicLink() && stat.size === Buffer.byteLength(content) && readFileSync10(file, "utf8") === content;
12804
+ return stat.isFile() && !stat.isSymbolicLink() && stat.size === Buffer.byteLength(content) && readFileSync11(file, "utf8") === content;
12615
12805
  });
12616
12806
  } catch {
12617
12807
  return false;
@@ -13011,7 +13201,7 @@ function readRootAlias(home, agent) {
13011
13201
  const stat = lstatSync14(alias, { throwIfNoEntry: false, bigint: true });
13012
13202
  if (!stat?.isSymbolicLink())
13013
13203
  throw new Error(`Agent root alias changed after planning: ${alias}`);
13014
- const link = readlinkSync2(alias), targetPath = resolve9(dirname10(alias), link);
13204
+ const link = readlinkSync3(alias), targetPath = resolve9(dirname10(alias), link);
13015
13205
  assertSafePath(targetPath);
13016
13206
  const targetStat = lstatSync14(targetPath, { throwIfNoEntry: false });
13017
13207
  if (!targetStat?.isDirectory())
@@ -13164,7 +13354,7 @@ function inventoryNativeSkills(home = homedir2(), options = {}) {
13164
13354
  throw new Error("Native skill discovery metadata limit exceeded");
13165
13355
  }
13166
13356
  function emptySiblingCacheAlias(path, parent) {
13167
- const link = readlinkSync2(path), target = resolve9(parent, link);
13357
+ const link = readlinkSync3(path), target = resolve9(parent, link);
13168
13358
  if (dirname10(target) !== parent || (isAbsolute9(link) ? link !== target : dirname10(link) !== "."))
13169
13359
  return false;
13170
13360
  if (!lstatSync14(target, { throwIfNoEntry: false })?.isDirectory())
@@ -13193,7 +13383,7 @@ function inventoryNativeSkills(home = homedir2(), options = {}) {
13193
13383
  const marker = join16(path, ".hasna-skills.json");
13194
13384
  if (existsSync8(marker)) {
13195
13385
  try {
13196
- managed = JSON.parse(readFileSync11(marker, "utf8")).managedBy === "@hasna/skills";
13386
+ managed = JSON.parse(readFileSync12(marker, "utf8")).managedBy === "@hasna/skills";
13197
13387
  } catch {}
13198
13388
  }
13199
13389
  const bridge = !vendor && isOwnedCliBridge(path, bridgePaths);
@@ -13266,7 +13456,7 @@ function inventoryNativeSkills(home = homedir2(), options = {}) {
13266
13456
  }
13267
13457
  function readOptional(path) {
13268
13458
  assertSafePath(path);
13269
- return existsSync8(path) ? readFileSync11(path, "utf8") : null;
13459
+ return existsSync8(path) ? readFileSync12(path, "utf8") : null;
13270
13460
  }
13271
13461
  function jsonObject(text2, path) {
13272
13462
  if (text2 === null)
@@ -13978,7 +14168,7 @@ function hasSkillsOwnershipMarker(dir) {
13978
14168
  try {
13979
14169
  if (!lstatSync15(path).isFile())
13980
14170
  return false;
13981
- const marker = JSON.parse(readFileSync12(path, "utf8"));
14171
+ const marker = JSON.parse(readFileSync13(path, "utf8"));
13982
14172
  return isSkillsOwnershipMarker(marker);
13983
14173
  } catch {
13984
14174
  return false;
@@ -14187,7 +14377,7 @@ function writeManagedSkillDir(dir, skillMd, options) {
14187
14377
  if (dirExists && managed && hasSkillMd && !options.force && isPointerSkillMd(skillMd)) {
14188
14378
  let existingIsStub = false;
14189
14379
  try {
14190
- existingIsStub = isPointerSkillMd(readFileSync12(skillMdPath, "utf-8"));
14380
+ existingIsStub = isPointerSkillMd(readFileSync13(skillMdPath, "utf-8"));
14191
14381
  } catch {
14192
14382
  existingIsStub = false;
14193
14383
  }
@@ -14267,7 +14457,7 @@ function sourceSkillMd(skillPath, name, description, kind, preferBundledDocs = f
14267
14457
  if (kind === undefined || kind === "instruction" || preferBundledDocs) {
14268
14458
  const skillMdPath = join17(skillPath, "SKILL.md");
14269
14459
  if (existsSync9(skillMdPath))
14270
- return readFileSync12(skillMdPath, "utf-8");
14460
+ return readFileSync13(skillMdPath, "utf-8");
14271
14461
  }
14272
14462
  return pointerSkillMd(name, description);
14273
14463
  }
@@ -14307,7 +14497,7 @@ function resolveSkillAlias(name) {
14307
14497
  }
14308
14498
 
14309
14499
  // src/lib/project-state.ts
14310
- import { existsSync as existsSync10, mkdirSync as mkdirSync7, readFileSync as readFileSync13, writeFileSync as writeFileSync6 } from "fs";
14500
+ import { existsSync as existsSync10, mkdirSync as mkdirSync7, readFileSync as readFileSync14, writeFileSync as writeFileSync6 } from "fs";
14311
14501
  import { join as join18 } from "path";
14312
14502
  var VALID_PIN_SOURCES = [
14313
14503
  "official",
@@ -14333,7 +14523,7 @@ function loadProjectConfig(targetDir = process.cwd()) {
14333
14523
  if (!existsSync10(path))
14334
14524
  return null;
14335
14525
  try {
14336
- return normalizeProjectConfig(JSON.parse(readFileSync13(path, "utf-8")));
14526
+ return normalizeProjectConfig(JSON.parse(readFileSync14(path, "utf-8")));
14337
14527
  } catch {
14338
14528
  return null;
14339
14529
  }
@@ -14520,7 +14710,7 @@ function createLocalSkillManifest(name, generateSkillMd) {
14520
14710
  let skillMd = "";
14521
14711
  const skillMdPath = join19(sourcePath, "SKILL.md");
14522
14712
  if (existsSync11(skillMdPath)) {
14523
- skillMd = readFileSync14(skillMdPath, "utf-8");
14713
+ skillMd = readFileSync15(skillMdPath, "utf-8");
14524
14714
  } else if (generateSkillMd) {
14525
14715
  skillMd = generateSkillMd(name) ?? "";
14526
14716
  } else {
@@ -14639,7 +14829,7 @@ function resolveAgentSkillMd(name, generateSkillMd) {
14639
14829
  const sourcePath = getSkillPath(name);
14640
14830
  const skillMdPath = join19(sourcePath, "SKILL.md");
14641
14831
  if (existsSync11(skillMdPath))
14642
- return readFileSync14(skillMdPath, "utf-8");
14832
+ return readFileSync15(skillMdPath, "utf-8");
14643
14833
  if (generateSkillMd)
14644
14834
  return generateSkillMd(name);
14645
14835
  return generateMinimalSkillMd(name);
@@ -14695,14 +14885,14 @@ function readBundledSkillVersion(name) {
14695
14885
  if (!existsSync11(pkgPath))
14696
14886
  return "unknown";
14697
14887
  try {
14698
- const pkg = JSON.parse(readFileSync14(pkgPath, "utf-8"));
14888
+ const pkg = JSON.parse(readFileSync15(pkgPath, "utf-8"));
14699
14889
  return pkg.version || "unknown";
14700
14890
  } catch {
14701
14891
  return "unknown";
14702
14892
  }
14703
14893
  }
14704
14894
  function readFileIfExists(path) {
14705
- return existsSync11(path) ? readFileSync14(path, "utf-8") : null;
14895
+ return existsSync11(path) ? readFileSync15(path, "utf-8") : null;
14706
14896
  }
14707
14897
  function loadProjectConfigCompat(targetDir) {
14708
14898
  return loadProjectConfig(targetDir);
@@ -14750,7 +14940,7 @@ function isInstructionSkillDir(skillPath, meta) {
14750
14940
  if (!existsSync12(skillMdPath))
14751
14941
  return false;
14752
14942
  try {
14753
- return parseSkillFrontmatter(readFileSync15(skillMdPath, "utf-8"))?.kind === "instruction";
14943
+ return parseSkillFrontmatter(readFileSync16(skillMdPath, "utf-8"))?.kind === "instruction";
14754
14944
  } catch {
14755
14945
  return false;
14756
14946
  }
@@ -14801,7 +14991,7 @@ function getSkillRequirements(name) {
14801
14991
  const meta = getSkill(name);
14802
14992
  let dependencies = {};
14803
14993
  try {
14804
- dependencies = JSON.parse(readFileSync15(join20(skillPath, "package.json"), "utf8")).dependencies || {};
14994
+ dependencies = JSON.parse(readFileSync16(join20(skillPath, "package.json"), "utf8")).dependencies || {};
14805
14995
  } catch {}
14806
14996
  return getSkillRequirementsFromContent(name, texts, dependencies, meta);
14807
14997
  }
@@ -14869,7 +15059,7 @@ async function runSkill(name, args, options = {}) {
14869
15059
  }
14870
15060
  let entryPoint2;
14871
15061
  try {
14872
- const pkg = JSON.parse(readFileSync15(pkgPath, "utf-8"));
15062
+ const pkg = JSON.parse(readFileSync16(pkgPath, "utf-8"));
14873
15063
  if (pkg.bin) {
14874
15064
  const binValues = Object.values(pkg.bin);
14875
15065
  entryPoint2 = binValues[0];
@@ -14972,7 +15162,7 @@ function generateSkillMd(name) {
14972
15162
  const pkgPath = join20(skillPath, "package.json");
14973
15163
  if (existsSync12(pkgPath)) {
14974
15164
  try {
14975
- const pkg = JSON.parse(readFileSync15(pkgPath, "utf-8"));
15165
+ const pkg = JSON.parse(readFileSync16(pkgPath, "utf-8"));
14976
15166
  if (pkg.bin) {
14977
15167
  const binKeys = Object.keys(pkg.bin);
14978
15168
  if (binKeys.length > 0)
@@ -15048,7 +15238,7 @@ function extractEnvVars(text2) {
15048
15238
  function readIfExists(path) {
15049
15239
  try {
15050
15240
  if (existsSync12(path)) {
15051
- return readFileSync15(path, "utf-8");
15241
+ return readFileSync16(path, "utf-8");
15052
15242
  }
15053
15243
  } catch {}
15054
15244
  return null;
@@ -16558,7 +16748,7 @@ function read2(path, changes) {
16558
16748
  return null;
16559
16749
  if (!stat2.isFile() || stat2.size > 16 * 1024 * 1024)
16560
16750
  throw new Error(`Unsupported or oversized native discovery input: ${path}`);
16561
- return readFileSync16(path, "utf8");
16751
+ return readFileSync17(path, "utf8");
16562
16752
  }
16563
16753
  function projected(source, changes, budget = discoveryByteBudget()) {
16564
16754
  if (source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || source.hashMode === "claude-settings-v3") {
@@ -17649,7 +17839,7 @@ function discoverSkillsInDir(dir, source = "custom") {
17649
17839
  continue;
17650
17840
  let content;
17651
17841
  try {
17652
- content = readFileSync17(skillMdPath, "utf-8");
17842
+ content = readFileSync18(skillMdPath, "utf-8");
17653
17843
  } catch {
17654
17844
  continue;
17655
17845
  }
@@ -17686,7 +17876,7 @@ function findExtensionSkillPath(name) {
17686
17876
  continue;
17687
17877
  let content;
17688
17878
  try {
17689
- content = readFileSync17(skillMdPath, "utf-8");
17879
+ content = readFileSync18(skillMdPath, "utf-8");
17690
17880
  } catch {
17691
17881
  continue;
17692
17882
  }
@@ -17751,7 +17941,7 @@ function getAllTags() {
17751
17941
  }
17752
17942
  // src/lib/run-state.ts
17753
17943
  import { createHash as createHash17, randomBytes } from "crypto";
17754
- import { existsSync as existsSync15, mkdirSync as mkdirSync10, readFileSync as readFileSync18, readdirSync as readdirSync12, statSync as statSync10, writeFileSync as writeFileSync9 } from "fs";
17944
+ import { existsSync as existsSync15, mkdirSync as mkdirSync10, readFileSync as readFileSync19, readdirSync as readdirSync12, statSync as statSync10, writeFileSync as writeFileSync9 } from "fs";
17755
17945
  import { extname, join as join30, relative as relative6 } from "path";
17756
17946
  function createSkillRun(params, targetDir = process.cwd()) {
17757
17947
  const now = new Date;
@@ -17823,7 +18013,7 @@ function appendRunEvent(context, event, data = {}) {
17823
18013
  const line = JSON.stringify({ ts: new Date().toISOString(), event, ...data }) + `
17824
18014
  `;
17825
18015
  const path = join30(context.runDir, "events.ndjson");
17826
- const previous = existsSync15(path) ? readFileSync18(path, "utf-8") : "";
18016
+ const previous = existsSync15(path) ? readFileSync19(path, "utf-8") : "";
17827
18017
  writeFileSync9(path, previous + line);
17828
18018
  }
17829
18019
  function listSkillRuns(targetDir = process.cwd(), limit = 50) {
@@ -17873,7 +18063,7 @@ function collectRunArtifacts(context) {
17873
18063
  const artifacts = [];
17874
18064
  for (const path of walkFiles(context.exportDir)) {
17875
18065
  const stat2 = statSync10(path);
17876
- const bytes = readFileSync18(path);
18066
+ const bytes = readFileSync19(path);
17877
18067
  artifacts.push({
17878
18068
  path: toProjectRelative(context.targetDir, path),
17879
18069
  mime: mimeForPath(path),
@@ -17888,7 +18078,7 @@ function readRunRecord(runDir) {
17888
18078
  if (!existsSync15(path))
17889
18079
  return null;
17890
18080
  try {
17891
- return JSON.parse(readFileSync18(path, "utf-8"));
18081
+ return JSON.parse(readFileSync19(path, "utf-8"));
17892
18082
  } catch {
17893
18083
  return null;
17894
18084
  }
@@ -18058,7 +18248,7 @@ __export(exports_external, {
18058
18248
  input: () => input,
18059
18249
  includes: () => _includes,
18060
18250
  httpUrl: () => httpUrl,
18061
- hostname: () => hostname2,
18251
+ hostname: () => hostname3,
18062
18252
  hex: () => hex2,
18063
18253
  hash: () => hash2,
18064
18254
  guid: () => guid2,
@@ -19844,7 +20034,7 @@ __export(exports_regexes, {
19844
20034
  idnEmail: () => idnEmail,
19845
20035
  httpProtocol: () => httpProtocol,
19846
20036
  html5Email: () => html5Email,
19847
- hostname: () => hostname,
20037
+ hostname: () => hostname2,
19848
20038
  hex: () => hex,
19849
20039
  guid: () => guid,
19850
20040
  extendedDuration: () => extendedDuration,
@@ -19906,7 +20096,7 @@ var cidrv4 = /^((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(25[0-5]
19906
20096
  var 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])$/;
19907
20097
  var base64 = /^$|^(?:[0-9a-zA-Z+/]{4})*(?:(?:[0-9a-zA-Z+/]{2}==)|(?:[0-9a-zA-Z+/]{3}=))?$/;
19908
20098
  var base64url = /^[A-Za-z0-9_-]*$/;
19909
- var 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])?)*\.?$/;
20099
+ var 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])?)*\.?$/;
19910
20100
  var domain = /^(?=.{1,253}$)([a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,63}$/;
19911
20101
  var httpProtocol = /^https?$/;
19912
20102
  var e164 = /^\+[1-9]\d{6,14}$/;
@@ -20743,9 +20933,9 @@ var asciiTabOrNewline = /[\t\n\r]/g;
20743
20933
  function stripTabAndNewline(value) {
20744
20934
  return value.replace(asciiTabOrNewline, "");
20745
20935
  }
20746
- function urlHostnameOk(url, hostname2) {
20747
- hostname2.lastIndex = 0;
20748
- return hostname2.test(url.hostname);
20936
+ function urlHostnameOk(url, hostname3) {
20937
+ hostname3.lastIndex = 0;
20938
+ return hostname3.test(url.hostname);
20749
20939
  }
20750
20940
  function urlProtocolOk(url, protocol) {
20751
20941
  protocol.lastIndex = 0;
@@ -34133,7 +34323,7 @@ __export(exports_schemas2, {
34133
34323
  int: () => int,
34134
34324
  instanceof: () => _instanceof,
34135
34325
  httpUrl: () => httpUrl,
34136
- hostname: () => hostname2,
34326
+ hostname: () => hostname3,
34137
34327
  hex: () => hex2,
34138
34328
  hash: () => hash2,
34139
34329
  guid: () => guid2,
@@ -34843,7 +35033,7 @@ var ZodCustomStringFormat = /* @__PURE__ */ $constructor("ZodCustomStringFormat"
34843
35033
  function stringFormat(format, fnOrRegex, _params = {}) {
34844
35034
  return _stringFormat(ZodCustomStringFormat, format, fnOrRegex, _params);
34845
35035
  }
34846
- function hostname2(_params) {
35036
+ function hostname3(_params) {
34847
35037
  return _stringFormat(ZodCustomStringFormat, "hostname", exports_regexes.hostname, _params);
34848
35038
  }
34849
35039
  function hex2(_params) {
@@ -39403,7 +39593,7 @@ async function createRemoteSkillsClient(env = process.env) {
39403
39593
  return connection ? new RemoteSkillsClient(connection.apiKey, connection.apiOrigin) : null;
39404
39594
  }
39405
39595
  // src/lib/scheduler.ts
39406
- import { existsSync as existsSync16, readFileSync as readFileSync19, writeFileSync as writeFileSync10, mkdirSync as mkdirSync11 } from "fs";
39596
+ import { existsSync as existsSync16, readFileSync as readFileSync20, writeFileSync as writeFileSync10, mkdirSync as mkdirSync11 } from "fs";
39407
39597
  import { join as join31 } from "path";
39408
39598
  function getSchedulesPath(targetDir = process.cwd()) {
39409
39599
  return join31(targetDir, ".skills", "schedules.json");
@@ -39412,7 +39602,7 @@ function loadSchedules(targetDir = process.cwd()) {
39412
39602
  const path = getSchedulesPath(targetDir);
39413
39603
  if (existsSync16(path)) {
39414
39604
  try {
39415
- return JSON.parse(readFileSync19(path, "utf-8"));
39605
+ return JSON.parse(readFileSync20(path, "utf-8"));
39416
39606
  } catch {}
39417
39607
  }
39418
39608
  return { version: 1, schedules: [] };
@@ -39635,7 +39825,7 @@ function revisionIdOfRecord(record7) {
39635
39825
  return revisionIdOf(record7);
39636
39826
  }
39637
39827
  // src/lib/pull.ts
39638
- import { existsSync as existsSync17, mkdirSync as mkdirSync12, mkdtempSync as mkdtempSync3, readFileSync as readFileSync20, renameSync as renameSync6, rmSync as rmSync5, writeFileSync as writeFileSync11 } from "fs";
39828
+ import { existsSync as existsSync17, mkdirSync as mkdirSync12, mkdtempSync as mkdtempSync3, readFileSync as readFileSync21, renameSync as renameSync6, rmSync as rmSync5, writeFileSync as writeFileSync11 } from "fs";
39639
39829
  import { dirname as dirname19, join as join32 } from "path";
39640
39830
 
39641
39831
  // src/lib/skill-bundles.ts
@@ -39835,7 +40025,7 @@ function reconcileTombstone(slug2, corpusOptions) {
39835
40025
  }
39836
40026
  function readPullMarker(dir) {
39837
40027
  try {
39838
- return JSON.parse(readFileSync20(join32(dir, PULL_MARKER_FILE), "utf-8"));
40028
+ return JSON.parse(readFileSync21(join32(dir, PULL_MARKER_FILE), "utf-8"));
39839
40029
  } catch {
39840
40030
  return null;
39841
40031
  }
@@ -42087,7 +42277,7 @@ import { createHash as createHash21, createHmac as createHmac2 } from "crypto";
42087
42277
  import {
42088
42278
  existsSync as existsSync19,
42089
42279
  mkdirSync as mkdirSync15,
42090
- readFileSync as readFileSync21,
42280
+ readFileSync as readFileSync23,
42091
42281
  readdirSync as readdirSync13,
42092
42282
  statSync as statSync11,
42093
42283
  writeFileSync as writeFileSync13
@@ -42254,7 +42444,7 @@ function exportSkillsLocalSnapshot(targetDir = process.cwd(), options = {}) {
42254
42444
  const files = [];
42255
42445
  if (existsSync19(projectStateDir)) {
42256
42446
  for (const filePath of walkFiles2(projectStateDir)) {
42257
- const bytes = readFileSync21(filePath);
42447
+ const bytes = readFileSync23(filePath);
42258
42448
  const relativePath = toPosix(relative8(targetDir, filePath));
42259
42449
  files.push({
42260
42450
  path: relativePath,
@@ -42672,7 +42862,7 @@ import { createHash as createHash22 } from "crypto";
42672
42862
  import {
42673
42863
  copyFileSync,
42674
42864
  mkdirSync as mkdirSync16,
42675
- readFileSync as readFileSync23,
42865
+ readFileSync as readFileSync25,
42676
42866
  statSync as statSync13,
42677
42867
  writeFileSync as writeFileSync14
42678
42868
  } from "fs";
@@ -42843,7 +43033,7 @@ function validateStationId(stationId) {
42843
43033
  }
42844
43034
  }
42845
43035
  function sha256File(filePath) {
42846
- return createHash22("sha256").update(readFileSync23(filePath)).digest("hex");
43036
+ return createHash22("sha256").update(readFileSync25(filePath)).digest("hex");
42847
43037
  }
42848
43038
  function scanHome(definition, homesRoot) {
42849
43039
  const homePath = homePathFor(definition, homesRoot);
@@ -42999,7 +43189,7 @@ import {
42999
43189
  copyFileSync as copyFileSync2,
43000
43190
  mkdirSync as mkdirSync17,
43001
43191
  readdirSync as readdirSync15,
43002
- readFileSync as readFileSync25,
43192
+ readFileSync as readFileSync26,
43003
43193
  statSync as statSync14,
43004
43194
  writeFileSync as writeFileSync15
43005
43195
  } from "fs";
@@ -43018,7 +43208,7 @@ function readSnapshotManifest(repoRoot, stationId) {
43018
43208
  const manifestPath = join36(snapshotRoot, "sync-manifest.json");
43019
43209
  let manifest;
43020
43210
  try {
43021
- manifest = JSON.parse(readFileSync25(manifestPath, "utf8"));
43211
+ manifest = JSON.parse(readFileSync26(manifestPath, "utf8"));
43022
43212
  } catch (error61) {
43023
43213
  fail("MANIFEST_UNREADABLE", `cannot read snapshot manifest: ${manifestPath}: ${error61.message}`);
43024
43214
  }
@@ -43154,7 +43344,7 @@ function planStationHydration(stationId, repoRoot) {
43154
43344
  for (const copy of copies) {
43155
43345
  let isStub = false;
43156
43346
  try {
43157
- isStub = isPointerSkillMd(readFileSync25(copy.fullPath, "utf8"));
43347
+ isStub = isPointerSkillMd(readFileSync26(copy.fullPath, "utf8"));
43158
43348
  } catch {
43159
43349
  isStub = false;
43160
43350
  }