@schoolai/shipyard 3.34.0-rc.20260924.0 → 3.34.0

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.
@@ -184,7 +184,7 @@ import {
184
184
  translateWarningNotification,
185
185
  unresolveReviewThread,
186
186
  writeCursorApiKeyToVault
187
- } from "./chunk-XTFGUW7P.js";
187
+ } from "./chunk-ACNO5PVJ.js";
188
188
  import {
189
189
  classifySkill,
190
190
  detectSkills,
@@ -226,6 +226,7 @@ import {
226
226
  DiscoveryStateSchema,
227
227
  MCPTokenStore,
228
228
  canonicalMcpServerKey,
229
+ claudeJsonMcpSlice,
229
230
  findUnresolvedVaultRef,
230
231
  getRuntimeDescriptor,
231
232
  getRuntimeDisplayName,
@@ -238,7 +239,7 @@ import {
238
239
  resolveStdioEnv,
239
240
  setTelemetrySink,
240
241
  telemeter
241
- } from "./chunk-PXPGMWVP.js";
242
+ } from "./chunk-LBIOF4SI.js";
242
243
  import {
243
244
  atomicWriteFile,
244
245
  findProjectRoot,
@@ -6746,8 +6747,38 @@ function createCapabilityRefreshCoordinator(deps) {
6746
6747
 
6747
6748
  // src/services/capability-watcher.ts
6748
6749
  import { existsSync as existsSync2, readdirSync, statSync as statSync2 } from "fs";
6750
+ import { readFile as readFile6 } from "fs/promises";
6749
6751
  import { homedir as homedir2 } from "os";
6750
- import { join as join15, sep } from "path";
6752
+ import { basename, join as join15, sep } from "path";
6753
+
6754
+ // src/services/claude-json-mcp-gate.ts
6755
+ function createClaudeJsonMcpGate(deps) {
6756
+ const lastSliceByPath = /* @__PURE__ */ new Map();
6757
+ return {
6758
+ async shouldRefresh(path8) {
6759
+ const slice = await readSlice(deps.readFile, path8);
6760
+ if (slice === null) {
6761
+ lastSliceByPath.delete(path8);
6762
+ return true;
6763
+ }
6764
+ if (lastSliceByPath.get(path8) === slice) {
6765
+ deps.log({ event: "capability_watcher_claude_json_mcp_unchanged", path: path8 });
6766
+ return false;
6767
+ }
6768
+ lastSliceByPath.set(path8, slice);
6769
+ return true;
6770
+ }
6771
+ };
6772
+ }
6773
+ async function readSlice(readFile59, path8) {
6774
+ try {
6775
+ return claudeJsonMcpSlice(await readFile59(path8));
6776
+ } catch {
6777
+ return null;
6778
+ }
6779
+ }
6780
+
6781
+ // src/services/capability-watcher.ts
6751
6782
  var ALL_REFRESH_CLASSES = [
6752
6783
  "mcp",
6753
6784
  "skills",
@@ -6998,6 +7029,10 @@ async function createCapabilityWatcher(deps) {
6998
7029
  let disposed = false;
6999
7030
  let lastErrorAt = null;
7000
7031
  const slots = [];
7032
+ const claudeJsonGate = createClaudeJsonMcpGate({
7033
+ readFile: (path8) => readFile6(path8, "utf-8"),
7034
+ log
7035
+ });
7001
7036
  const fire = (cls) => {
7002
7037
  if (disposed) return;
7003
7038
  const existing = debounceTimers[cls];
@@ -7074,12 +7109,24 @@ async function createCapabilityWatcher(deps) {
7074
7109
  slot.sub = null;
7075
7110
  continue;
7076
7111
  }
7077
- const cls = slot.refreshClass ?? classifyCapabilityPath(e.path, home, shipyardHome);
7078
- if (cls === null) continue;
7079
- droppedCounts[cls] += 1;
7080
- fire(cls);
7112
+ routeChangedPath(slot, e.path);
7081
7113
  }
7082
7114
  };
7115
+ const routeChangedPath = (slot, path8) => {
7116
+ const cls = slot.refreshClass ?? classifyCapabilityPath(path8, home, shipyardHome);
7117
+ if (cls === null) return;
7118
+ if (cls === "mcp" && basename(path8) === ".claude.json") {
7119
+ void fireIfClaudeJsonMcpChanged(path8);
7120
+ return;
7121
+ }
7122
+ droppedCounts[cls] += 1;
7123
+ fire(cls);
7124
+ };
7125
+ const fireIfClaudeJsonMcpChanged = async (path8) => {
7126
+ if (!await claudeJsonGate.shouldRefresh(path8)) return;
7127
+ droppedCounts.mcp += 1;
7128
+ fire("mcp");
7129
+ };
7083
7130
  let pluginCacheSkippedForBudget = 0;
7084
7131
  const subscribeDeps = {
7085
7132
  slots,
@@ -8156,7 +8203,7 @@ function narrow(value) {
8156
8203
  }
8157
8204
 
8158
8205
  // src/services/at-least-once/receive-cursor-jsondoc.ts
8159
- import { mkdir as mkdir5, readFile as readFile6, rename as rename4, unlink as unlink4, writeFile as writeFile8 } from "fs/promises";
8206
+ import { mkdir as mkdir5, readFile as readFile7, rename as rename4, unlink as unlink4, writeFile as writeFile8 } from "fs/promises";
8160
8207
  import { dirname as dirname6, join as join16 } from "path";
8161
8208
  async function unlinkIfExists(path8) {
8162
8209
  try {
@@ -8193,7 +8240,7 @@ var JsonDocReceiveCursor = class {
8193
8240
  }
8194
8241
  let raw;
8195
8242
  try {
8196
- raw = await readFile6(this.#filePath, "utf-8");
8243
+ raw = await readFile7(this.#filePath, "utf-8");
8197
8244
  } catch (err3) {
8198
8245
  if (isEnoent(err3)) {
8199
8246
  this.#cached = null;
@@ -9260,7 +9307,7 @@ import { execFile as execFile4, spawn as spawn3 } from "child_process";
9260
9307
  import {
9261
9308
  mkdir as mkdir6,
9262
9309
  readdir as readdir8,
9263
- readFile as readFile8,
9310
+ readFile as readFile9,
9264
9311
  realpath as realpath2,
9265
9312
  rename as rename5,
9266
9313
  rm as rm5,
@@ -9268,12 +9315,12 @@ import {
9268
9315
  unlink as unlink5,
9269
9316
  writeFile as writeFile9
9270
9317
  } from "fs/promises";
9271
- import { basename as basename3, dirname as dirname8, normalize as normalize2, relative, resolve as resolve2 } from "path";
9318
+ import { basename as basename4, dirname as dirname8, normalize as normalize2, relative, resolve as resolve2 } from "path";
9272
9319
  import { promisify as promisify4 } from "util";
9273
9320
 
9274
9321
  // src/shared/file-io-path-safety.ts
9275
9322
  import { realpath } from "fs/promises";
9276
- import { basename as basename2, dirname as dirname7, join as join18, normalize } from "path";
9323
+ import { basename as basename3, dirname as dirname7, join as join18, normalize } from "path";
9277
9324
  async function safeAbsolutePath(userPath, isHidden2, allowedHiddenNames) {
9278
9325
  const normalized = prepareAbsolutePath(userPath, isHidden2, allowedHiddenNames);
9279
9326
  if (normalized === null) return null;
@@ -9298,7 +9345,7 @@ async function canonicalizeOrRecombine(path8) {
9298
9345
  if (!isEnoent4(err3)) return null;
9299
9346
  const parentCanonical = await realpath(dirname7(path8)).catch(() => null);
9300
9347
  if (parentCanonical === null) return null;
9301
- return join18(parentCanonical, basename2(path8));
9348
+ return join18(parentCanonical, basename3(path8));
9302
9349
  }
9303
9350
  }
9304
9351
  function isEnoent4(err3) {
@@ -9629,7 +9676,7 @@ function classifyFileIOOperation(msg) {
9629
9676
 
9630
9677
  // src/services/file-io/git-read-handlers.ts
9631
9678
  import { execFile as execFile3 } from "child_process";
9632
- import { readFile as readFile7 } from "fs/promises";
9679
+ import { readFile as readFile8 } from "fs/promises";
9633
9680
  import { resolve } from "path";
9634
9681
  import { promisify as promisify3 } from "util";
9635
9682
 
@@ -9917,7 +9964,7 @@ async function handleGitBranchDiffFile(requestId, filePath, mergeBase, ctx) {
9917
9964
  const originalContent = await ctx.readGitObject(`${mergeBase}:${filePath}`) ?? "";
9918
9965
  let modifiedContent;
9919
9966
  try {
9920
- modifiedContent = await readFile7(resolve(ctx.cwd, filePath), "utf-8");
9967
+ modifiedContent = await readFile8(resolve(ctx.cwd, filePath), "utf-8");
9921
9968
  } catch {
9922
9969
  modifiedContent = "";
9923
9970
  }
@@ -10153,7 +10200,7 @@ function handleFileIOChannel(initialCwd, send, log, deps) {
10153
10200
  } catch (err3) {
10154
10201
  if (!(err3 instanceof Error && "code" in err3 && err3.code === "ENOENT")) throw err3;
10155
10202
  const canonicalParent = await realpath2(dirname8(absPath));
10156
- return resolve2(canonicalParent, basename3(absPath));
10203
+ return resolve2(canonicalParent, basename4(absPath));
10157
10204
  }
10158
10205
  }
10159
10206
  async function validateMutationTarget(requestId, userPath, absPath) {
@@ -10371,7 +10418,7 @@ function handleFileIOChannel(initialCwd, send, log, deps) {
10371
10418
  respondError2(requestId, "File too large (>10MB)");
10372
10419
  return;
10373
10420
  }
10374
- const bytes = await readFile8(absPath);
10421
+ const bytes = await readFile9(absPath);
10375
10422
  const metadata = detectTextFileMetadata(bytes);
10376
10423
  textMetadataByPath.set(absPath, metadata);
10377
10424
  const content = decodeTextForRead(bytes, metadata);
@@ -10385,7 +10432,7 @@ function handleFileIOChannel(initialCwd, send, log, deps) {
10385
10432
  let metadata = textMetadataByPath.get(absPath);
10386
10433
  if (!metadata) {
10387
10434
  try {
10388
- metadata = detectTextFileMetadata(await readFile8(absPath));
10435
+ metadata = detectTextFileMetadata(await readFile9(absPath));
10389
10436
  } catch {
10390
10437
  metadata = { eol: "lf", hasUtf8Bom: false };
10391
10438
  }
@@ -10661,7 +10708,7 @@ function handleFileIOChannel(initialCwd, send, log, deps) {
10661
10708
  const indexContent = await readGitObject(`:${safeRelPath}`);
10662
10709
  originalContent = indexContent ?? await readGitObject(`HEAD:${safeRelPath}`) ?? "";
10663
10710
  try {
10664
- modifiedContent = await readFile8(absPath, "utf-8");
10711
+ modifiedContent = await readFile9(absPath, "utf-8");
10665
10712
  } catch {
10666
10713
  modifiedContent = "";
10667
10714
  }
@@ -11155,13 +11202,13 @@ ${validation.error}`;
11155
11202
  }
11156
11203
 
11157
11204
  // src/services/harness/publish-server.ts
11158
- import { readdir as readdir10, readFile as readFile12 } from "fs/promises";
11159
- import { basename as basename5, join as join21 } from "path";
11205
+ import { readdir as readdir10, readFile as readFile13 } from "fs/promises";
11206
+ import { basename as basename6, join as join21 } from "path";
11160
11207
 
11161
11208
  // src/services/publish/published-artifact-store.ts
11162
11209
  import { createHash, randomUUID as randomUUID7 } from "crypto";
11163
11210
  import { mkdirSync as mkdirSync3, readdirSync as readdirSync2, readFileSync as readFileSync3 } from "fs";
11164
- import { mkdir as mkdir7, readFile as readFile9, rename as rename6, unlink as unlink6, writeFile as writeFile10 } from "fs/promises";
11211
+ import { mkdir as mkdir7, readFile as readFile10, rename as rename6, unlink as unlink6, writeFile as writeFile10 } from "fs/promises";
11165
11212
  import { dirname as dirname9, join as join19, relative as relative3 } from "path";
11166
11213
  import { isDeepStrictEqual } from "util";
11167
11214
  var DEBOUNCE_MS = 200;
@@ -11313,7 +11360,7 @@ function createPublishedArtifactStore(opts) {
11313
11360
  const { taskId, bindKind, bindKey } = parsed;
11314
11361
  let raw;
11315
11362
  try {
11316
- raw = await readFile9(filePath, "utf-8");
11363
+ raw = await readFile10(filePath, "utf-8");
11317
11364
  } catch {
11318
11365
  const existing2 = registry.get(taskId)?.get(bindMapKey(bindKind, bindKey));
11319
11366
  if (!existing2) return;
@@ -11422,11 +11469,11 @@ function createPublishedArtifactStore(opts) {
11422
11469
  }
11423
11470
 
11424
11471
  // src/services/harness/framework-detect.ts
11425
- import { readFile as readFile10 } from "fs/promises";
11472
+ import { readFile as readFile11 } from "fs/promises";
11426
11473
  import { join as join20 } from "path";
11427
11474
  async function readJsonFile(filePath) {
11428
11475
  try {
11429
- const raw = await readFile10(filePath, "utf8");
11476
+ const raw = await readFile11(filePath, "utf8");
11430
11477
  return JSON.parse(raw);
11431
11478
  } catch {
11432
11479
  return null;
@@ -11439,7 +11486,7 @@ async function hasNextExportConfig(projectRoot) {
11439
11486
  const candidates = ["next.config.js", "next.config.mjs", "next.config.ts"];
11440
11487
  for (const candidate of candidates) {
11441
11488
  try {
11442
- const content = await readFile10(join20(projectRoot, candidate), "utf8");
11489
+ const content = await readFile11(join20(projectRoot, candidate), "utf8");
11443
11490
  if (/output\s*:\s*['"]export['"]/.test(content)) {
11444
11491
  return true;
11445
11492
  }
@@ -11499,8 +11546,8 @@ async function detectFramework(projectRoot) {
11499
11546
  }
11500
11547
 
11501
11548
  // src/services/harness/publish-deliverable.ts
11502
- import { readFile as readFile11 } from "fs/promises";
11503
- import { basename as basename4 } from "path";
11549
+ import { readFile as readFile12 } from "fs/promises";
11550
+ import { basename as basename5 } from "path";
11504
11551
 
11505
11552
  // src/services/harness/publish-uploader.ts
11506
11553
  async function uploadPublish(params) {
@@ -11654,7 +11701,7 @@ function planFor(recordKind, raw, filePath, mimeType, title) {
11654
11701
  case "screenshot":
11655
11702
  return {
11656
11703
  kind: "image",
11657
- fileName: basename4(filePath),
11704
+ fileName: basename5(filePath),
11658
11705
  body: raw,
11659
11706
  contentType: mimeType ?? imageMime(filePath)
11660
11707
  };
@@ -11713,7 +11760,7 @@ async function runPublishDeliverable(input, ctx, deliverableId) {
11713
11760
  }
11714
11761
  let raw;
11715
11762
  try {
11716
- raw = await readFile11(filePath);
11763
+ raw = await readFile12(filePath);
11717
11764
  } catch (err3) {
11718
11765
  const msg = err3 instanceof Error ? err3.message : String(err3);
11719
11766
  const error = `Failed to read deliverable file: ${msg}`;
@@ -11952,7 +11999,7 @@ async function processFileEntry(fullPath, relativePath, state) {
11952
11999
  }
11953
12000
  let fileContent;
11954
12001
  try {
11955
- fileContent = await readFile12(fullPath);
12002
+ fileContent = await readFile13(fullPath);
11956
12003
  } catch (err3) {
11957
12004
  return `Failed to read file ${fullPath}: ${err3 instanceof Error ? err3.message : String(err3)}`;
11958
12005
  }
@@ -12072,14 +12119,14 @@ async function runPublishSlug(input, ctx, slug) {
12072
12119
  }
12073
12120
  let content;
12074
12121
  try {
12075
- content = await readFile12(viz.filePath);
12122
+ content = await readFile13(viz.filePath);
12076
12123
  } catch (err3) {
12077
12124
  const msg = err3 instanceof Error ? err3.message : String(err3);
12078
12125
  const error = `Failed to read visualization file: ${msg}`;
12079
12126
  ctx.onProgress("failed", error);
12080
12127
  return { ok: false, phase: "uploading", error };
12081
12128
  }
12082
- const originalFileName = basename5(viz.filePath);
12129
+ const originalFileName = basename6(viz.filePath);
12083
12130
  const { fileName, fileContent, contentType } = (() => {
12084
12131
  if (kind === "mermaid") {
12085
12132
  return {
@@ -17173,7 +17220,7 @@ import { readdir as readdir11 } from "fs/promises";
17173
17220
 
17174
17221
  // src/services/storage/repo-index-store.ts
17175
17222
  import { statSync as statSync3 } from "fs";
17176
- import { mkdir as mkdir9, readFile as readFile13, rename as rename7 } from "fs/promises";
17223
+ import { mkdir as mkdir9, readFile as readFile14, rename as rename7 } from "fs/promises";
17177
17224
  import { dirname as dirname10, join as join23 } from "path";
17178
17225
  var REPO_INDEX_FILENAME = "repo-index.json";
17179
17226
  var REPO_INDEX_SCHEMA_VERSION = 1;
@@ -17195,7 +17242,7 @@ function buildRepoIndexStore(dataDir) {
17195
17242
  }
17196
17243
  async function loadFromDisk() {
17197
17244
  try {
17198
- const raw = await readFile13(filePath, "utf-8");
17245
+ const raw = await readFile14(filePath, "utf-8");
17199
17246
  const parsed = JSON.parse(raw);
17200
17247
  const validated = RepoIndexFileSchema.safeParse(parsed);
17201
17248
  if (!validated.success) return;
@@ -18330,7 +18377,7 @@ async function refreshPluginCapabilities(daemon, tokenStore) {
18330
18377
  const userSettings = await daemon.userSettingsStore.getSettings();
18331
18378
  const [updatedMarketplace, updatedMcp, updatedSkills] = await Promise.all([
18332
18379
  detectMarketplacePlugins(daemon.capabilities.marketplacePlugins),
18333
- import("./mcp-servers-ALBYEPNS.js").then(
18380
+ import("./mcp-servers-BQJDDDNT.js").then(
18334
18381
  (m2) => m2.detectMCPServers(
18335
18382
  daemon.capabilities.environments,
18336
18383
  tokenStore,
@@ -19704,7 +19751,7 @@ function isPlainObject(v2) {
19704
19751
  }
19705
19752
 
19706
19753
  // src/services/themes/theme-store.ts
19707
- import { mkdir as mkdir10, readdir as readdir12, readFile as readFile14, rename as rename9, stat as stat9, unlink as unlink7, writeFile as writeFile12 } from "fs/promises";
19754
+ import { mkdir as mkdir10, readdir as readdir12, readFile as readFile15, rename as rename9, stat as stat9, unlink as unlink7, writeFile as writeFile12 } from "fs/promises";
19708
19755
  import { join as join25 } from "path";
19709
19756
 
19710
19757
  // src/shared/store-corruption.ts
@@ -19856,7 +19903,7 @@ function buildThemeStore(dataDir, corruptionLogger) {
19856
19903
  }
19857
19904
  async function readConfigFile() {
19858
19905
  try {
19859
- const raw = await readFile14(configPath, "utf-8");
19906
+ const raw = await readFile15(configPath, "utf-8");
19860
19907
  const parsed = ThemeConfigSchema.safeParse(JSON.parse(raw));
19861
19908
  if (!parsed.success) {
19862
19909
  await quarantineCorruptFile({
@@ -19895,7 +19942,7 @@ function buildThemeStore(dataDir, corruptionLogger) {
19895
19942
  await atomicWrite5(themePath(id), serialized);
19896
19943
  }
19897
19944
  async function readThemeFile(id) {
19898
- const raw = await readFile14(themePath(id), "utf-8");
19945
+ const raw = await readFile15(themePath(id), "utf-8");
19899
19946
  const parsed = VSCodeThemeSchema.safeParse(JSON.parse(raw));
19900
19947
  if (!parsed.success) {
19901
19948
  throw new Error(
@@ -20075,7 +20122,7 @@ function buildThemeStore(dataDir, corruptionLogger) {
20075
20122
  }
20076
20123
 
20077
20124
  // src/services/themes/vscode-scanner.ts
20078
- import { readdir as readdir13, readFile as readFile15, stat as stat10 } from "fs/promises";
20125
+ import { readdir as readdir13, readFile as readFile16, stat as stat10 } from "fs/promises";
20079
20126
  import { homedir as homedir4 } from "os";
20080
20127
  import { dirname as dirname12, join as join26, normalize as normalize3, resolve as resolve5 } from "path";
20081
20128
  var VSCodeThemeEntrySchema = external_exports.object({
@@ -20134,7 +20181,7 @@ var PackageJsonContribSchema = external_exports.object({
20134
20181
  async function tryReadPackageJson(extDir) {
20135
20182
  let pkgRaw;
20136
20183
  try {
20137
- pkgRaw = await readFile15(join26(extDir, "package.json"), "utf-8");
20184
+ pkgRaw = await readFile16(join26(extDir, "package.json"), "utf-8");
20138
20185
  } catch {
20139
20186
  return null;
20140
20187
  }
@@ -20204,7 +20251,7 @@ async function readVSCodeThemeWithIncludes(absolutePath) {
20204
20251
  if (!validateScanPath(filePath)) {
20205
20252
  throw new Error(`Include path outside allowed directories: ${filePath}`);
20206
20253
  }
20207
- const raw = await readFile15(filePath, "utf-8");
20254
+ const raw = await readFile16(filePath, "utf-8");
20208
20255
  const errors = [];
20209
20256
  const parsed = parse2(raw, errors, {
20210
20257
  allowTrailingComma: true,
@@ -20867,7 +20914,7 @@ async function syncCredentialsFromVault(tokenStore, vaultKey, machineId, log, cr
20867
20914
  }
20868
20915
 
20869
20916
  // src/services/credentials/vault-key-manager.ts
20870
- import { mkdir as mkdir11, readFile as readFile16, writeFile as writeFile13 } from "fs/promises";
20917
+ import { mkdir as mkdir11, readFile as readFile17, writeFile as writeFile13 } from "fs/promises";
20871
20918
  import { dirname as dirname13, join as join27 } from "path";
20872
20919
  var V1_PREFIX = "v1:";
20873
20920
  var ELECTRON_SAFE_STORAGE_KEY_FILE = "vault-key.electron-safe-storage";
@@ -20896,7 +20943,7 @@ async function resolveVaultKeyElectron(keyPath, signalingClient, authToken, log)
20896
20943
  }
20897
20944
  async function loadElectronVaultKeyFromDisk(keyPath, log) {
20898
20945
  try {
20899
- return await unwrapElectronVaultKey(await readFile16(keyPath, "utf-8"), log);
20946
+ return await unwrapElectronVaultKey(await readFile17(keyPath, "utf-8"), log);
20900
20947
  } catch {
20901
20948
  return null;
20902
20949
  }
@@ -20915,7 +20962,7 @@ async function unwrapElectronVaultKey(raw, log) {
20915
20962
  async function loadSharedVaultKeyForElectron(sharedKeyPath, electronKeyPath, log) {
20916
20963
  let raw;
20917
20964
  try {
20918
- raw = await readFile16(sharedKeyPath, "utf-8");
20965
+ raw = await readFile17(sharedKeyPath, "utf-8");
20919
20966
  } catch {
20920
20967
  return null;
20921
20968
  }
@@ -20952,7 +20999,7 @@ async function saveVaultKeyElectron(electronKeyPath, sharedKeyPath, hexKey, log)
20952
20999
  }
20953
21000
  async function resolveVaultKeyAes(keyPath, signalingClient, authToken, log) {
20954
21001
  try {
20955
- const cached = await readFile16(keyPath, "utf-8");
21002
+ const cached = await readFile17(keyPath, "utf-8");
20956
21003
  if (cached.trim().length === 64) return cached.trim();
20957
21004
  } catch {
20958
21005
  }
@@ -20994,7 +21041,7 @@ async function resolveVaultKeyFromServer(keyPath, signalingClient, authToken, lo
20994
21041
  async function resolveMachineId(shipyardHome) {
20995
21042
  const idPath = join27(shipyardHome, "machine-id");
20996
21043
  try {
20997
- const cached = await readFile16(idPath, "utf-8");
21044
+ const cached = await readFile17(idPath, "utf-8");
20998
21045
  const trimmed = cached.trim();
20999
21046
  if (trimmed.length > 0) return trimmed;
21000
21047
  } catch {
@@ -21061,7 +21108,7 @@ function isSafeStorageReply(msg) {
21061
21108
 
21062
21109
  // src/services/harness/lsp-agent-server.ts
21063
21110
  import { readFileSync as readFileSync4 } from "fs";
21064
- import { basename as basename6, relative as relative4, resolve as resolve6 } from "path";
21111
+ import { basename as basename7, relative as relative4, resolve as resolve6 } from "path";
21065
21112
  import { fileURLToPath, pathToFileURL } from "url";
21066
21113
  var LspPositionSchema = external_exports.object({ line: external_exports.number(), character: external_exports.number() });
21067
21114
  var LspRangeSchema = external_exports.object({ start: LspPositionSchema, end: LspPositionSchema });
@@ -21144,7 +21191,7 @@ function locationTarget(loc) {
21144
21191
  return { uri: loc.targetUri, range: loc.targetSelectionRange };
21145
21192
  }
21146
21193
  function isSecretFile(absolutePath) {
21147
- const name = basename6(absolutePath);
21194
+ const name = basename7(absolutePath);
21148
21195
  for (const prefix of HIDDEN_PREFIXES) {
21149
21196
  if (name === prefix || name.startsWith(`${prefix}.`)) return true;
21150
21197
  }
@@ -23807,7 +23854,7 @@ var InputController = class {
23807
23854
  import { homedir as homedir5 } from "os";
23808
23855
 
23809
23856
  // src/shared/capabilities/capabilities-cache.ts
23810
- import { mkdir as mkdir12, readFile as readFile17, rename as rename10, unlink as unlink8, writeFile as writeFile14 } from "fs/promises";
23857
+ import { mkdir as mkdir12, readFile as readFile18, rename as rename10, unlink as unlink8, writeFile as writeFile14 } from "fs/promises";
23811
23858
  import { dirname as dirname14, join as join29 } from "path";
23812
23859
  var CAPABILITIES_CACHE_VERSION = 1;
23813
23860
  var GitRepoInfoCacheSchema = external_exports.object({
@@ -23854,7 +23901,7 @@ async function loadCapabilitiesCache() {
23854
23901
  const filePath = cacheFilePath();
23855
23902
  let raw;
23856
23903
  try {
23857
- raw = await readFile17(filePath, "utf8");
23904
+ raw = await readFile18(filePath, "utf8");
23858
23905
  } catch (err3) {
23859
23906
  if (isEnoent(err3)) return EMPTY;
23860
23907
  logger.debug({ err: err3, filePath }, "capabilities-cache: read failed, treating as empty");
@@ -29005,7 +29052,7 @@ function startCollabRehydrate(args) {
29005
29052
  import { join as join33 } from "path";
29006
29053
 
29007
29054
  // src/services/storage/json-document-store.ts
29008
- import { mkdir as mkdir14, readFile as readFile18 } from "fs/promises";
29055
+ import { mkdir as mkdir14, readFile as readFile19 } from "fs/promises";
29009
29056
  import { dirname as dirname15 } from "path";
29010
29057
  var WRITE_DEBOUNCE_MS = 50;
29011
29058
  function applyMutations(records, mutations) {
@@ -29045,7 +29092,7 @@ function buildJsonDocumentStore(opts) {
29045
29092
  }
29046
29093
  async function readFromDisk() {
29047
29094
  try {
29048
- const raw = await readFile18(filePath, "utf-8");
29095
+ const raw = await readFile19(filePath, "utf-8");
29049
29096
  return migrate(JSON.parse(raw));
29050
29097
  } catch (err3) {
29051
29098
  if (isEnoent(err3)) {
@@ -32095,8 +32142,8 @@ async function setupPluginEventWiring(deps) {
32095
32142
  // src/services/plugins/plugin-file-watcher.ts
32096
32143
  import { exec as execCb2 } from "child_process";
32097
32144
  import { existsSync as existsSync6 } from "fs";
32098
- import { readdir as readdir15, readFile as readFile19, stat as stat11 } from "fs/promises";
32099
- import { basename as basename7, dirname as dirname18, join as join36 } from "path";
32145
+ import { readdir as readdir15, readFile as readFile20, stat as stat11 } from "fs/promises";
32146
+ import { basename as basename8, dirname as dirname18, join as join36 } from "path";
32100
32147
  import { pathToFileURL as pathToFileURL2 } from "url";
32101
32148
  import { promisify as promisify7 } from "util";
32102
32149
 
@@ -32249,7 +32296,7 @@ var PluginFileWatcher = class {
32249
32296
  const manifestPath = join36(pluginDir, "plugin.json");
32250
32297
  let manifestRaw;
32251
32298
  try {
32252
- manifestRaw = await readFile19(manifestPath, "utf-8");
32299
+ manifestRaw = await readFile20(manifestPath, "utf-8");
32253
32300
  } catch {
32254
32301
  this.#config.log({ event: "plugin_manifest_missing", pluginId: id, pluginDir });
32255
32302
  return null;
@@ -32285,7 +32332,7 @@ var PluginFileWatcher = class {
32285
32332
  let template = "";
32286
32333
  const templatePath = join36(pluginDir, "template.html");
32287
32334
  try {
32288
- template = await readFile19(templatePath, "utf-8");
32335
+ template = await readFile20(templatePath, "utf-8");
32289
32336
  } catch {
32290
32337
  }
32291
32338
  await this.#loadAndRegisterHandler(id, pluginDir, manifest.title, manifest);
@@ -32482,7 +32529,7 @@ function shouldDescendForNativeScan(entry) {
32482
32529
  return entry.isDirectory() && entry.name !== ".git" && entry.name !== NATIVE_DEP_MARKER_DIR;
32483
32530
  }
32484
32531
  function isNodeBuildReleaseDir(dir) {
32485
- return basename7(dir) === "Release" && basename7(dirname18(dir)) === "build";
32532
+ return basename8(dir) === "Release" && basename8(dirname18(dir)) === "build";
32486
32533
  }
32487
32534
 
32488
32535
  // src/services/port-detection.ts
@@ -33283,7 +33330,7 @@ function handleNativePreviewChannel(port, send, sendBinary, log, options) {
33283
33330
 
33284
33331
  // src/services/channels/asset-channel-handler.ts
33285
33332
  import { readFile as fsReadFile, stat as fsStat2 } from "fs/promises";
33286
- import { basename as basename8, extname } from "path";
33333
+ import { basename as basename9, extname } from "path";
33287
33334
  var UPLOAD_TIMEOUT_MS = 6e4;
33288
33335
  var UPLOAD_STALL_WARN_MS = 1e4;
33289
33336
  var MAX_CONCURRENT_UPLOADS = 10;
@@ -33329,7 +33376,7 @@ function resolveMimeTypeByKind(stored, filePath, kind) {
33329
33376
  return MIME_BY_KIND[kind] ?? "application/octet-stream";
33330
33377
  }
33331
33378
  async function pickDeliverableReadPath(record2, internedPath) {
33332
- if (isLiveDeliverableKind(record2.kind) && record2.sourceFilePath && !isSecretName(basename8(record2.sourceFilePath))) {
33379
+ if (isLiveDeliverableKind(record2.kind) && record2.sourceFilePath && !isSecretName(basename9(record2.sourceFilePath))) {
33333
33380
  try {
33334
33381
  const sourceStats = await fsStat2(record2.sourceFilePath);
33335
33382
  if (sourceStats.isFile()) return record2.sourceFilePath;
@@ -35429,7 +35476,7 @@ function resolveRuntimeAuthIdentity(runtimeAuth, runtimeId) {
35429
35476
  }
35430
35477
 
35431
35478
  // src/shared/capabilities/spinner-verbs-reader.ts
35432
- import { readFile as readFile20 } from "fs/promises";
35479
+ import { readFile as readFile21 } from "fs/promises";
35433
35480
  import { homedir as homedir6 } from "os";
35434
35481
  import { join as join42 } from "path";
35435
35482
  var ClaudeSpinnerVerbsSchema = external_exports.object({
@@ -35461,7 +35508,7 @@ async function readSpinnerVerbs() {
35461
35508
  const parsed = await Promise.all(
35462
35509
  paths.map(async (p2) => {
35463
35510
  try {
35464
- const raw = await readFile20(p2, "utf-8");
35511
+ const raw = await readFile21(p2, "utf-8");
35465
35512
  const json = JSON.parse(raw);
35466
35513
  if (json === null || typeof json !== "object") return null;
35467
35514
  const field2 = Reflect.get(json, "spinnerVerbs");
@@ -35498,7 +35545,7 @@ async function reimportSpinnerVerbs(store, log) {
35498
35545
  }
35499
35546
 
35500
35547
  // src/shared/mcp/oauth-state-store.ts
35501
- import { readFile as readFile21 } from "fs/promises";
35548
+ import { readFile as readFile22 } from "fs/promises";
35502
35549
  import { join as join43 } from "path";
35503
35550
  import {
35504
35551
  OAuthClientInformationFullSchema as OAuthClientInformationFullSchema2,
@@ -35553,7 +35600,7 @@ var MCPOAuthStateStore = class {
35553
35600
  /** Always reads the state map from disk (never the cache). */
35554
35601
  async #readFreshMap() {
35555
35602
  try {
35556
- const raw = await readFile21(this.#filePath(), "utf-8");
35603
+ const raw = await readFile22(this.#filePath(), "utf-8");
35557
35604
  const parsed = StateMapSchema.safeParse(JSON.parse(raw));
35558
35605
  return parsed.success ? parsed.data : {};
35559
35606
  } catch {
@@ -35643,7 +35690,7 @@ function getShipyardSubagentCatalog() {
35643
35690
  }
35644
35691
 
35645
35692
  // src/services/bootstrap/interrupted-turn-resume.ts
35646
- import { readFile as readFile22 } from "fs/promises";
35693
+ import { readFile as readFile23 } from "fs/promises";
35647
35694
  import { join as join44 } from "path";
35648
35695
  var DEFAULT_MAX_AUTO_RESUME_ATTEMPTS = 1;
35649
35696
  var DEFAULT_AUTO_RESUME_WINDOW_MS = 6 * 60 * 60 * 1e3;
@@ -35728,7 +35775,7 @@ var LedgerFileSchema = external_exports.object({
35728
35775
  async function readAutoResumeLedger(ledgerPath, log) {
35729
35776
  let raw;
35730
35777
  try {
35731
- raw = await readFile22(ledgerPath, "utf-8");
35778
+ raw = await readFile23(ledgerPath, "utf-8");
35732
35779
  } catch (err3) {
35733
35780
  if (isEnoent(err3)) return emptyLedger();
35734
35781
  log({
@@ -35920,11 +35967,11 @@ async function scheduleInterruptedTurnResumes(deps) {
35920
35967
  }
35921
35968
 
35922
35969
  // src/services/bootstrap/rehydrate.ts
35923
- import { readFile as readFile24, rename as rename15, writeFile as writeFile17 } from "fs/promises";
35970
+ import { readFile as readFile25, rename as rename15, writeFile as writeFile17 } from "fs/promises";
35924
35971
  import { join as join46 } from "path";
35925
35972
 
35926
35973
  // src/services/collab/collab-queue-persistence.ts
35927
- import { appendFile as appendFile2, mkdir as mkdir16, readdir as readdir16, readFile as readFile23, rename as rename14, rm as rm9, writeFile as writeFile16 } from "fs/promises";
35974
+ import { appendFile as appendFile2, mkdir as mkdir16, readdir as readdir16, readFile as readFile24, rename as rename14, rm as rm9, writeFile as writeFile16 } from "fs/promises";
35928
35975
  import { join as join45 } from "path";
35929
35976
  var PersistedQueueEntrySchema = external_exports.object({
35930
35977
  content: external_exports.array(ContentBlockSchema),
@@ -35979,7 +36026,7 @@ function buildCollabQueuePersistence(dataDir) {
35979
36026
  async read(queueKey) {
35980
36027
  let raw;
35981
36028
  try {
35982
- raw = await readFile23(queuePath(queueKey), "utf-8");
36029
+ raw = await readFile24(queuePath(queueKey), "utf-8");
35983
36030
  } catch (err3) {
35984
36031
  if (isEnoent(err3)) return [];
35985
36032
  throw err3;
@@ -36448,11 +36495,11 @@ async function readRawTasksEnvelope(tasksPath) {
36448
36495
  let raw;
36449
36496
  let fromMigrated = false;
36450
36497
  try {
36451
- raw = await readFile24(tasksPath, "utf-8");
36498
+ raw = await readFile25(tasksPath, "utf-8");
36452
36499
  } catch (err3) {
36453
36500
  if (!isEnoent(err3)) throw err3;
36454
36501
  try {
36455
- raw = await readFile24(`${tasksPath}.migrated`, "utf-8");
36502
+ raw = await readFile25(`${tasksPath}.migrated`, "utf-8");
36456
36503
  fromMigrated = true;
36457
36504
  } catch (err22) {
36458
36505
  if (isEnoent(err22)) return null;
@@ -36627,7 +36674,7 @@ async function sweepStaleTasks(taskStateStore, taskManager, log) {
36627
36674
  }
36628
36675
 
36629
36676
  // src/services/bootstrap/update-status.ts
36630
- import { readFile as readFile25, unlink as unlink10 } from "fs/promises";
36677
+ import { readFile as readFile26, unlink as unlink10 } from "fs/promises";
36631
36678
  import { join as join47 } from "path";
36632
36679
  var UPDATE_STATUS_FILENAME = "update-status.json";
36633
36680
  var RAW_LOG_MAX_CHARS = 500;
@@ -36644,7 +36691,7 @@ async function readAndClearUpdateStatus(shipyardHome, log) {
36644
36691
  const path8 = join47(shipyardHome, UPDATE_STATUS_FILENAME);
36645
36692
  let raw;
36646
36693
  try {
36647
- raw = await readFile25(path8, "utf-8");
36694
+ raw = await readFile26(path8, "utf-8");
36648
36695
  } catch (err3) {
36649
36696
  if (isEnoent(err3)) return null;
36650
36697
  log.warn({ err: err3, path: path8 }, "failed to read update-status.json");
@@ -36731,7 +36778,7 @@ import { readdir as readdir17, rm as rm10, stat as stat14, unlink as unlink12 }
36731
36778
  import { join as join49 } from "path";
36732
36779
 
36733
36780
  // src/services/bootstrap/self-update-lock.ts
36734
- import { mkdir as mkdir17, readFile as readFile26, stat as stat13, unlink as unlink11, writeFile as writeFile18 } from "fs/promises";
36781
+ import { mkdir as mkdir17, readFile as readFile27, stat as stat13, unlink as unlink11, writeFile as writeFile18 } from "fs/promises";
36735
36782
  import { dirname as dirname21, join as join48 } from "path";
36736
36783
  var LOCK_FILENAME = ".lock";
36737
36784
  var STALE_LOCK_MS = 10 * 60 * 1e3;
@@ -36752,7 +36799,7 @@ async function readLockFile(shipyardHome) {
36752
36799
  const path8 = lockPath(shipyardHome);
36753
36800
  let raw;
36754
36801
  try {
36755
- raw = await readFile26(path8, "utf-8");
36802
+ raw = await readFile27(path8, "utf-8");
36756
36803
  } catch {
36757
36804
  return null;
36758
36805
  }
@@ -36769,7 +36816,7 @@ async function readLockFileWithOutcome(shipyardHome) {
36769
36816
  const path8 = lockPath(shipyardHome);
36770
36817
  let raw;
36771
36818
  try {
36772
- raw = await readFile26(path8, "utf-8");
36819
+ raw = await readFile27(path8, "utf-8");
36773
36820
  } catch (err3) {
36774
36821
  if (isEnoent(err3)) return { kind: "absent" };
36775
36822
  return { kind: "read-error", err: err3 };
@@ -36787,7 +36834,7 @@ async function readLockFileWithOutcome(shipyardHome) {
36787
36834
  async function unlinkStaleLock(path8, expected) {
36788
36835
  let current;
36789
36836
  try {
36790
- const raw = await readFile26(path8, "utf-8");
36837
+ const raw = await readFile27(path8, "utf-8");
36791
36838
  const parsed = LockFileSchema.safeParse(JSON.parse(raw));
36792
36839
  current = parsed.success ? parsed.data : null;
36793
36840
  } catch (err3) {
@@ -37168,7 +37215,7 @@ function renderCommentThreads(annotations, renderOne, replyIndent) {
37168
37215
 
37169
37216
  // src/services/harness/comment-server.ts
37170
37217
  import { randomUUID as randomUUID11 } from "crypto";
37171
- import { access as access4, readFile as readFile27 } from "fs/promises";
37218
+ import { access as access4, readFile as readFile28 } from "fs/promises";
37172
37219
  import { join as join50, relative as relative6 } from "path";
37173
37220
 
37174
37221
  // src/services/comment-resource-resolver.ts
@@ -37582,7 +37629,7 @@ function djb2Hash(content) {
37582
37629
  }
37583
37630
  async function readLineContent(absolutePath, lineNumber) {
37584
37631
  try {
37585
- const content = await readFile27(absolutePath, "utf-8");
37632
+ const content = await readFile28(absolutePath, "utf-8");
37586
37633
  const lines = content.split("\n");
37587
37634
  return lines[lineNumber - 1] ?? "";
37588
37635
  } catch {
@@ -39204,11 +39251,11 @@ function wireDaemonBroadcasts(deps) {
39204
39251
  }
39205
39252
 
39206
39253
  // src/services/comments/github-ingest-pipeline.ts
39207
- import { readFile as readFile28 } from "fs/promises";
39254
+ import { readFile as readFile29 } from "fs/promises";
39208
39255
  import { join as join51 } from "path";
39209
39256
  async function readLocalFileContent(cwd, path8) {
39210
39257
  try {
39211
- return await readFile28(join51(cwd, path8), "utf-8");
39258
+ return await readFile29(join51(cwd, path8), "utf-8");
39212
39259
  } catch {
39213
39260
  return getFileAtRef(cwd, path8, "HEAD");
39214
39261
  }
@@ -41154,8 +41201,8 @@ function wireDevServersAndTerminalsResolvers(deps) {
41154
41201
  }
41155
41202
 
41156
41203
  // src/services/file-resource-resolver.ts
41157
- import { readFile as readFile29, stat as stat15 } from "fs/promises";
41158
- import { basename as basename9, join as join52, normalize as normalize4, sep as sep2 } from "path";
41204
+ import { readFile as readFile30, stat as stat15 } from "fs/promises";
41205
+ import { basename as basename10, join as join52, normalize as normalize4, sep as sep2 } from "path";
41159
41206
  var MAX_FILE_SIZE = 10 * 1024 * 1024;
41160
41207
  var MIME_BY_EXT2 = {
41161
41208
  ".ts": "text/typescript",
@@ -41234,7 +41281,7 @@ function createFileResourceResolver(deps) {
41234
41281
  throw new Error(`Not a file: ${relativePath}`);
41235
41282
  }
41236
41283
  if (fileStats.size > MAX_FILE_SIZE) {
41237
- const name = basename9(absolutePath);
41284
+ const name = basename10(absolutePath);
41238
41285
  return {
41239
41286
  uri,
41240
41287
  mimeType: "text/plain",
@@ -41242,19 +41289,19 @@ function createFileResourceResolver(deps) {
41242
41289
  };
41243
41290
  }
41244
41291
  if (isImageExtension(absolutePath)) {
41245
- const buffer2 = await readFile29(absolutePath);
41292
+ const buffer2 = await readFile30(absolutePath);
41246
41293
  return {
41247
41294
  uri,
41248
41295
  mimeType: guessMimeType(absolutePath),
41249
41296
  blob: buffer2.toString("base64")
41250
41297
  };
41251
41298
  }
41252
- const buffer = await readFile29(absolutePath);
41299
+ const buffer = await readFile30(absolutePath);
41253
41300
  if (looksLikeBinary(buffer)) {
41254
41301
  return {
41255
41302
  uri,
41256
41303
  mimeType: "text/plain",
41257
- text: `[Binary file: ${basename9(absolutePath)} (${fileStats.size} bytes)]`
41304
+ text: `[Binary file: ${basename10(absolutePath)} (${fileStats.size} bytes)]`
41258
41305
  };
41259
41306
  }
41260
41307
  return {
@@ -41268,7 +41315,7 @@ function createFileResourceResolver(deps) {
41268
41315
 
41269
41316
  // src/services/git-checkpoint.ts
41270
41317
  import { execFile as execFileCb2 } from "child_process";
41271
- import { readFile as readFile30, stat as stat16, unlink as unlink13, writeFile as writeFile19 } from "fs/promises";
41318
+ import { readFile as readFile31, stat as stat16, unlink as unlink13, writeFile as writeFile19 } from "fs/promises";
41272
41319
  import { join as join53 } from "path";
41273
41320
  import { promisify as promisify8 } from "util";
41274
41321
  var execFile9 = promisify8(execFileCb2);
@@ -41787,7 +41834,7 @@ async function diffCheckpointToWorkingTreeImpl(repoDir, taskId, fromTurnNo, scop
41787
41834
  if (!line || statusMap.has(line)) continue;
41788
41835
  let ins = 0;
41789
41836
  try {
41790
- ins = countLines(await readFile30(join53(repoDir, line), "utf-8"));
41837
+ ins = countLines(await readFile31(join53(repoDir, line), "utf-8"));
41791
41838
  } catch {
41792
41839
  }
41793
41840
  entries.push({ path: line, status: "added", insertions: ins, deletions: 0 });
@@ -41807,7 +41854,7 @@ async function getFileVsWorkingTreeImpl(repoDir, taskId, fromTurnNo, filePath) {
41807
41854
  if (from === "error") return null;
41808
41855
  let modifiedContent;
41809
41856
  try {
41810
- modifiedContent = await readFile30(join53(repoDir, filePath), "utf-8");
41857
+ modifiedContent = await readFile31(join53(repoDir, filePath), "utf-8");
41811
41858
  } catch {
41812
41859
  modifiedContent = "";
41813
41860
  }
@@ -42293,7 +42340,7 @@ Task \`${taskId}\` not found.`;
42293
42340
  // src/services/harness/deliverable-server.ts
42294
42341
  import { randomUUID as randomUUID12 } from "crypto";
42295
42342
  import { copyFile, rm as fsRm, stat as fsStat3, mkdir as mkdir18 } from "fs/promises";
42296
- import { basename as basename10, extname as extname2, join as join54, resolve as resolve8, sep as sep3 } from "path";
42343
+ import { basename as basename11, extname as extname2, join as join54, resolve as resolve8, sep as sep3 } from "path";
42297
42344
  var TOOL_DESCRIPTION2 = [
42298
42345
  "Register a proof-of-work deliverable for this task \u2014 proof a reviewer cannot get from the diff alone.",
42299
42346
  "",
@@ -42485,7 +42532,7 @@ function validateAssetFileMutualExclusion(input) {
42485
42532
  )
42486
42533
  };
42487
42534
  }
42488
- if (hasFilePath && input.filePath != null && isSecretName(basename10(input.filePath))) {
42535
+ if (hasFilePath && input.filePath != null && isSecretName(basename11(input.filePath))) {
42489
42536
  return {
42490
42537
  ok: false,
42491
42538
  error: err2(
@@ -44735,7 +44782,7 @@ function errorResult(message) {
44735
44782
  }
44736
44783
 
44737
44784
  // src/services/harness/visualize-server.ts
44738
- import { readFile as readFile31 } from "fs/promises";
44785
+ import { readFile as readFile32 } from "fs/promises";
44739
44786
 
44740
44787
  // src/services/harness/html-validator.ts
44741
44788
  import { compileFunction } from "vm";
@@ -53604,7 +53651,7 @@ async function resolveContent(inlineContent, filePath) {
53604
53651
  }
53605
53652
  if (filePath) {
53606
53653
  try {
53607
- return { ok: true, content: await readFile31(filePath, "utf-8") };
53654
+ return { ok: true, content: await readFile32(filePath, "utf-8") };
53608
53655
  } catch (err3) {
53609
53656
  const msg = err3 instanceof Error ? err3.message : String(err3);
53610
53657
  return { ok: false, error: `Failed to read file: ${msg}` };
@@ -53686,7 +53733,7 @@ function textResult4(text, isError) {
53686
53733
  }
53687
53734
  async function handlePresentInline(filePath, vizType) {
53688
53735
  try {
53689
- const content = await readFile31(filePath, "utf-8");
53736
+ const content = await readFile32(filePath, "utf-8");
53690
53737
  return {
53691
53738
  content: [
53692
53739
  { type: "text", text: content },
@@ -53735,7 +53782,7 @@ async function refreshCanvasPresentationFromFile(vizWatcher, slug) {
53735
53782
  if (!viz) return { ok: false, title: slug, reason: "no_canvas_element" };
53736
53783
  if (!viz.canvasElementId) return { ok: false, title: viz.title, reason: "no_canvas_element" };
53737
53784
  try {
53738
- const content = await readFile31(viz.filePath, "utf-8");
53785
+ const content = await readFile32(viz.filePath, "utf-8");
53739
53786
  const effects = vizWatcher.registry.refreshCanvasPresentation(slug, content);
53740
53787
  await vizWatcher.executeEffects(effects);
53741
53788
  return { ok: true, title: viz.title };
@@ -53827,7 +53874,7 @@ Fix the content and try again.`
53827
53874
  await ctx.vizWatcher.executeEffects([
53828
53875
  { type: "write_file", filePath: existingFilePath, content }
53829
53876
  ]);
53830
- const persisted = await readFile31(existingFilePath, "utf-8").catch((err3) => {
53877
+ const persisted = await readFile32(existingFilePath, "utf-8").catch((err3) => {
53831
53878
  ctx.log({
53832
53879
  event: "viz_update_reconcile_read_failed",
53833
53880
  filePath: existingFilePath,
@@ -56623,7 +56670,7 @@ var McpCoordinator = class {
56623
56670
  });
56624
56671
  const nextNames = new Set(merge.servers.map((s2) => s2.name));
56625
56672
  const settles = [];
56626
- this.#dropMissingServers(nextNames, settles);
56673
+ this.#dropMissingServers(nextNames, settles, input.reason);
56627
56674
  const disabledChanged = !setsEqual(this.#disabledNames, incomingDisabled);
56628
56675
  this.#disabledNames.clear();
56629
56676
  for (const n of incomingDisabled) this.#disabledNames.add(n);
@@ -56636,13 +56683,23 @@ var McpCoordinator = class {
56636
56683
  });
56637
56684
  }
56638
56685
  /** Drop registry entries for servers no longer present in the fresh merge. */
56639
- #dropMissingServers(nextNames, settles) {
56686
+ #dropMissingServers(nextNames, settles, reason) {
56687
+ const dropped = [];
56640
56688
  for (const known of this.#registry.list()) {
56641
56689
  if (nextNames.has(known.name)) continue;
56690
+ dropped.push(known.name);
56642
56691
  this.#dispatchDisable(known.name, settles);
56643
56692
  this.#registry.remove(known.name);
56644
56693
  this.#resolvedByName.delete(known.name);
56645
56694
  }
56695
+ if (dropped.length > 0) {
56696
+ this.#deps.log({
56697
+ event: "mcp_servers_dropped",
56698
+ names: dropped.sort(),
56699
+ count: dropped.length,
56700
+ reason
56701
+ });
56702
+ }
56646
56703
  }
56647
56704
  /** Register any merged server not yet in the registry; refresh resolved configs for survivors. */
56648
56705
  #registerNewServers(servers, gatewayIdByName, settles) {
@@ -57311,7 +57368,7 @@ import { auth } from "@modelcontextprotocol/sdk/client/auth.js";
57311
57368
  // src/shared/mcp/codex-credentials.ts
57312
57369
  import { execFile as execFileCb3 } from "child_process";
57313
57370
  import { createHash as createHash5 } from "crypto";
57314
- import { readFile as readFile32 } from "fs/promises";
57371
+ import { readFile as readFile33 } from "fs/promises";
57315
57372
  import { homedir as homedir7 } from "os";
57316
57373
  import { join as join57 } from "path";
57317
57374
  import { promisify as promisify9 } from "util";
@@ -57377,7 +57434,7 @@ async function readKeychainStore() {
57377
57434
  async function readCodexMcpCredentials(serverName, serverUrl, codexHome = join57(homedir7(), ".codex")) {
57378
57435
  if (!serverUrl) return null;
57379
57436
  try {
57380
- const raw = await readFile32(join57(codexHome, FALLBACK_FILENAME), "utf-8");
57437
+ const raw = await readFile33(join57(codexHome, FALLBACK_FILENAME), "utf-8");
57381
57438
  const fileResult = CodexCredentialsFileSchema.safeParse(JSON.parse(raw));
57382
57439
  if (fileResult.success) {
57383
57440
  const entry = findEntry2(fileResult.data, serverName, serverUrl);
@@ -80359,7 +80416,7 @@ function stableFingerprint(value) {
80359
80416
 
80360
80417
  // src/services/session/devin-workspace-rule-state.ts
80361
80418
  import { createHash as createHash7 } from "crypto";
80362
- import { mkdir as mkdir23, readFile as readFile33 } from "fs/promises";
80419
+ import { mkdir as mkdir23, readFile as readFile34 } from "fs/promises";
80363
80420
  import { dirname as dirname24, join as join63 } from "path";
80364
80421
  var DevinWorkspaceRuleStateSchema = external_exports.object({
80365
80422
  sessionId: external_exports.string(),
@@ -80376,7 +80433,7 @@ function statePath(dataDir, taskId) {
80376
80433
  }
80377
80434
  async function readDevinWorkspaceRuleState(dataDir, taskId) {
80378
80435
  try {
80379
- const raw = await readFile33(statePath(dataDir, taskId), "utf-8");
80436
+ const raw = await readFile34(statePath(dataDir, taskId), "utf-8");
80380
80437
  const parsed = DevinWorkspaceRuleStateSchema.safeParse(JSON.parse(raw));
80381
80438
  return parsed.success ? parsed.data : null;
80382
80439
  } catch (error) {
@@ -81190,8 +81247,8 @@ import { join as join66 } from "path";
81190
81247
 
81191
81248
  // src/services/harness/visualization-file-watcher.ts
81192
81249
  import { randomUUID as randomUUID18 } from "crypto";
81193
- import { mkdir as mkdir24, readFile as readFile34, rename as rename16, writeFile as writeFile23 } from "fs/promises";
81194
- import { basename as basename11, dirname as dirname25, join as join64 } from "path";
81250
+ import { mkdir as mkdir24, readFile as readFile35, rename as rename16, writeFile as writeFile23 } from "fs/promises";
81251
+ import { basename as basename12, dirname as dirname25, join as join64 } from "path";
81195
81252
  var PREVIEW_DEFAULT_W = 1200;
81196
81253
  var PREVIEW_DEFAULT_H = 800;
81197
81254
  function previewDataToLoroValue(data) {
@@ -81338,7 +81395,7 @@ var VisualizationFileWatcher = class {
81338
81395
  const byTask = /* @__PURE__ */ new Map();
81339
81396
  for (const viz of allViz) {
81340
81397
  try {
81341
- const content = await readFile34(viz.filePath, "utf-8");
81398
+ const content = await readFile35(viz.filePath, "utf-8");
81342
81399
  let items = byTask.get(viz.taskId);
81343
81400
  if (!items) {
81344
81401
  items = [];
@@ -81425,9 +81482,9 @@ var VisualizationFileWatcher = class {
81425
81482
  };
81426
81483
  this.#dirWatchers.set(dirPath, entry);
81427
81484
  const findWatchedFile = (eventPath) => {
81428
- const eventBase = basename11(eventPath);
81485
+ const eventBase = basename12(eventPath);
81429
81486
  for (const wf of this.#watchedFiles) {
81430
- if (dirname25(wf) === dirPath && basename11(wf) === eventBase) return wf;
81487
+ if (dirname25(wf) === dirPath && basename12(wf) === eventBase) return wf;
81431
81488
  }
81432
81489
  return null;
81433
81490
  };
@@ -81602,7 +81659,7 @@ var VisualizationFileWatcher = class {
81602
81659
  let content = effect.content;
81603
81660
  if (!content && effect.filePath) {
81604
81661
  try {
81605
- content = await readFile34(effect.filePath, "utf-8");
81662
+ content = await readFile35(effect.filePath, "utf-8");
81606
81663
  } catch {
81607
81664
  content = "";
81608
81665
  }
@@ -81648,7 +81705,7 @@ var VisualizationFileWatcher = class {
81648
81705
  async #handleFileChange(filePath) {
81649
81706
  let content;
81650
81707
  try {
81651
- content = await readFile34(filePath, "utf-8");
81708
+ content = await readFile35(filePath, "utf-8");
81652
81709
  } catch {
81653
81710
  return;
81654
81711
  }
@@ -85266,7 +85323,7 @@ function createCursorVaultKeyCache() {
85266
85323
  }
85267
85324
 
85268
85325
  // src/services/session/skills/cursor-skill-body-resolver.ts
85269
- import { readFile as readFile35 } from "fs/promises";
85326
+ import { readFile as readFile36 } from "fs/promises";
85270
85327
  function skillKey(name, namespace) {
85271
85328
  return namespace ? `${namespace}:${name}` : name;
85272
85329
  }
@@ -85386,7 +85443,7 @@ function buildCreationSkillDefaults(entries) {
85386
85443
  }
85387
85444
 
85388
85445
  // src/services/skills/skill-resolution-service.ts
85389
- import { mkdir as mkdir26, readFile as readFile37, writeFile as writeFile25 } from "fs/promises";
85446
+ import { mkdir as mkdir26, readFile as readFile38, writeFile as writeFile25 } from "fs/promises";
85390
85447
  import { homedir as homedir10 } from "os";
85391
85448
  import { dirname as dirname28, join as join72, relative as relative9, resolve as resolve14, sep as sep7 } from "path";
85392
85449
 
@@ -85748,8 +85805,8 @@ function poolCandidateBeats(candidate, incumbent) {
85748
85805
  }
85749
85806
 
85750
85807
  // src/services/skills/pool-bundle-index.ts
85751
- import { readdir as readdir21, readFile as readFile36, stat as stat20 } from "fs/promises";
85752
- import { basename as basename12, join as join70 } from "path";
85808
+ import { readdir as readdir21, readFile as readFile37, stat as stat20 } from "fs/promises";
85809
+ import { basename as basename13, join as join70 } from "path";
85753
85810
 
85754
85811
  // src/services/skills/trailing-coalescer.ts
85755
85812
  function buildTrailingCoalescer(run2) {
@@ -85808,7 +85865,7 @@ function buildPoolBundleIndex(deps) {
85808
85865
  cache2.delete(file);
85809
85866
  continue;
85810
85867
  }
85811
- if (entry.record !== null) bySlug.set(basename12(file, ".json"), entry.record);
85868
+ if (entry.record !== null) bySlug.set(basename13(file, ".json"), entry.record);
85812
85869
  }
85813
85870
  return bySlug;
85814
85871
  }
@@ -85820,7 +85877,7 @@ function buildPoolBundleIndex(deps) {
85820
85877
  if (cached?.ino === st.ino && cached.mtimeMs === st.mtimeMs && cached.size === st.size) {
85821
85878
  return;
85822
85879
  }
85823
- const raw = await readFile36(path8, "utf-8");
85880
+ const raw = await readFile37(path8, "utf-8");
85824
85881
  const record2 = withLabel("skillPoolParseBundle", () => parsePoolRecord(raw));
85825
85882
  cache2.set(file, { ino: st.ino, mtimeMs: st.mtimeMs, size: st.size, record: record2 });
85826
85883
  } catch {
@@ -86522,7 +86579,7 @@ function buildSkillResolutionService(deps) {
86522
86579
  const sourcePath = active.path ?? detectedMatch?.sources[0]?.path;
86523
86580
  if (sourcePath !== void 0) {
86524
86581
  try {
86525
- const body = await readFile37(sourcePath, "utf-8");
86582
+ const body = await readFile38(sourcePath, "utf-8");
86526
86583
  return { kind: "ok", body, dir: dirname28(sourcePath), bodyResolution: "native" };
86527
86584
  } catch (err3) {
86528
86585
  deps.log({
@@ -86586,7 +86643,7 @@ function buildSkillResolutionService(deps) {
86586
86643
  async function materializeBorrowBody(candidate) {
86587
86644
  try {
86588
86645
  const sourcePath = candidate.sources[0]?.path;
86589
- const body = candidate.body ?? (sourcePath !== void 0 ? await readFile37(sourcePath, "utf-8") : null);
86646
+ const body = candidate.body ?? (sourcePath !== void 0 ? await readFile38(sourcePath, "utf-8") : null);
86590
86647
  if (body === null) return null;
86591
86648
  await materializeLibrarySkill({
86592
86649
  baseDir: libraryCacheDir,
@@ -86706,7 +86763,7 @@ function buildSkillResolutionService(deps) {
86706
86763
  deps.log({ event: "skill_body_path_rejected", path: path8 });
86707
86764
  return { ok: false, error: "Skill body path is outside the allowed skills roots" };
86708
86765
  }
86709
- const body = await readFile37(path8, "utf-8");
86766
+ const body = await readFile38(path8, "utf-8");
86710
86767
  return { ok: true, contentHash: contentHash3, body };
86711
86768
  }
86712
86769
  async function currentBundleForCwd(cwd) {
@@ -86922,7 +86979,7 @@ function parseJjLines(raw) {
86922
86979
  }
86923
86980
 
86924
86981
  // src/services/storage/annotation-store.ts
86925
- import { mkdir as mkdir27, readFile as readFile38 } from "fs/promises";
86982
+ import { mkdir as mkdir27, readFile as readFile39 } from "fs/promises";
86926
86983
  import { dirname as dirname29, join as join74 } from "path";
86927
86984
  var LegacyBaseFields = external_exports.object({
86928
86985
  commentId: external_exports.string(),
@@ -86981,7 +87038,7 @@ function buildAnnotationStore(dataDir) {
86981
87038
  }
86982
87039
  async function readLegacyFile(path8) {
86983
87040
  try {
86984
- const raw = await readFile38(path8, "utf-8");
87041
+ const raw = await readFile39(path8, "utf-8");
86985
87042
  const parsed = JSON.parse(raw);
86986
87043
  return parsed;
86987
87044
  } catch (err3) {
@@ -87070,7 +87127,7 @@ function buildAnnotationStore(dataDir) {
87070
87127
  if (cached) return cached;
87071
87128
  const fp = filePath(taskId);
87072
87129
  try {
87073
- const raw = await readFile38(fp, "utf-8");
87130
+ const raw = await readFile39(fp, "utf-8");
87074
87131
  const parsed = JSON.parse(raw);
87075
87132
  const migrated = migrateAnnotationStore(parsed);
87076
87133
  const validated = AnnotationStoreSchema.parse(migrated);
@@ -87235,7 +87292,7 @@ function buildAnnotationStore(dataDir) {
87235
87292
  }
87236
87293
 
87237
87294
  // src/services/storage/asset-store.ts
87238
- import { mkdir as mkdir28, readFile as readFile39, rename as rename17, writeFile as writeFile26 } from "fs/promises";
87295
+ import { mkdir as mkdir28, readFile as readFile40, rename as rename17, writeFile as writeFile26 } from "fs/promises";
87239
87296
  import { join as join75 } from "path";
87240
87297
  var UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
87241
87298
  function isValidAssetId(id) {
@@ -87300,23 +87357,23 @@ function buildAssetStore(assetsDir) {
87300
87357
  async read(assetId) {
87301
87358
  validateId2(assetId);
87302
87359
  const [data, meta] = await Promise.all([
87303
- readFile39(binaryPath(assetId)),
87304
- readFile39(metaPath(assetId), "utf-8").then(parseMeta)
87360
+ readFile40(binaryPath(assetId)),
87361
+ readFile40(metaPath(assetId), "utf-8").then(parseMeta)
87305
87362
  ]);
87306
87363
  return { data, meta };
87307
87364
  },
87308
87365
  async readBase64(assetId) {
87309
87366
  validateId2(assetId);
87310
87367
  const [data, meta] = await Promise.all([
87311
- readFile39(binaryPath(assetId)),
87312
- readFile39(metaPath(assetId), "utf-8").then(parseMeta)
87368
+ readFile40(binaryPath(assetId)),
87369
+ readFile40(metaPath(assetId), "utf-8").then(parseMeta)
87313
87370
  ]);
87314
87371
  return { base64: data.toString("base64"), meta };
87315
87372
  },
87316
87373
  async getMeta(assetId) {
87317
87374
  validateId2(assetId);
87318
87375
  try {
87319
- const raw = await readFile39(metaPath(assetId), "utf-8");
87376
+ const raw = await readFile40(metaPath(assetId), "utf-8");
87320
87377
  return parseMeta(raw);
87321
87378
  } catch (err3) {
87322
87379
  if (isEnoent(err3)) return null;
@@ -87387,7 +87444,7 @@ async function seedBuiltInTemplates(store, builtIns, dismissed) {
87387
87444
  }
87388
87445
 
87389
87446
  // src/services/storage/credentials-vault-store.ts
87390
- import { mkdir as mkdir29, readFile as readFile40 } from "fs/promises";
87447
+ import { mkdir as mkdir29, readFile as readFile41 } from "fs/promises";
87391
87448
  import { dirname as dirname30 } from "path";
87392
87449
  function dropInvalidRecords(parsed) {
87393
87450
  if (typeof parsed !== "object" || parsed === null) return parsed;
@@ -87422,7 +87479,7 @@ function buildCredentialsVaultStore(filePath, corruptionLogger) {
87422
87479
  async function readFromDisk() {
87423
87480
  let raw;
87424
87481
  try {
87425
- raw = await readFile40(filePath, "utf-8");
87482
+ raw = await readFile41(filePath, "utf-8");
87426
87483
  } catch (err3) {
87427
87484
  if (isEnoent(err3)) return emptyStore();
87428
87485
  throw err3;
@@ -87514,7 +87571,7 @@ function buildCredentialsVaultStore(filePath, corruptionLogger) {
87514
87571
  }
87515
87572
 
87516
87573
  // src/services/storage/deliverable-store.ts
87517
- import { mkdir as mkdir30, readFile as readFile41 } from "fs/promises";
87574
+ import { mkdir as mkdir30, readFile as readFile42 } from "fs/promises";
87518
87575
  import { dirname as dirname31, join as join76 } from "path";
87519
87576
  var DELIVERABLE_STORE_VERSION = 1;
87520
87577
  var DeliverableStoreSchema = external_exports.object({
@@ -87558,7 +87615,7 @@ function buildDeliverableStore(dataDir) {
87558
87615
  if (cached) return cached;
87559
87616
  const fp = filePath(taskId);
87560
87617
  try {
87561
- const raw = await readFile41(fp, "utf-8");
87618
+ const raw = await readFile42(fp, "utf-8");
87562
87619
  const parsed = JSON.parse(raw);
87563
87620
  const migrated = migrateDeliverableStore(parsed);
87564
87621
  const validated = DeliverableStoreSchema.parse(migrated);
@@ -87940,7 +87997,7 @@ async function byteOffsetAfterLines(fh, lineCount, size) {
87940
87997
  }
87941
87998
 
87942
87999
  // src/services/storage/jsonl-sdk-uuid-stamps.ts
87943
- import { appendFile as appendFile3, readFile as readFile42, rm as rm12, stat as stat22 } from "fs/promises";
88000
+ import { appendFile as appendFile3, readFile as readFile43, rm as rm12, stat as stat22 } from "fs/promises";
87944
88001
  import { join as join77 } from "path";
87945
88002
  var SdkUuidStampSchema = external_exports.object({
87946
88003
  messageId: external_exports.string(),
@@ -88035,7 +88092,7 @@ function createSdkUuidStampSidecar(channelsDir) {
88035
88092
  }
88036
88093
  let raw;
88037
88094
  try {
88038
- raw = await readFile42(target, "utf-8");
88095
+ raw = await readFile43(target, "utf-8");
88039
88096
  } catch (err3) {
88040
88097
  if (isEnoent(err3)) return { stamps: EMPTY_STAMPS, size: 0, mtimeMs: 0 };
88041
88098
  throw err3;
@@ -89116,7 +89173,7 @@ function buildObservableConversationStore(inner) {
89116
89173
 
89117
89174
  // src/services/storage/projects-store.ts
89118
89175
  import { randomUUID as randomUUID22 } from "crypto";
89119
- import { mkdir as mkdir32, readFile as readFile43 } from "fs/promises";
89176
+ import { mkdir as mkdir32, readFile as readFile44 } from "fs/promises";
89120
89177
  import { dirname as dirname32 } from "path";
89121
89178
  var ProjectsArraySchema = external_exports.array(ProjectSchema);
89122
89179
  function buildProjectsStore(filePath) {
@@ -89138,7 +89195,7 @@ function buildProjectsStore(filePath) {
89138
89195
  async function readStore() {
89139
89196
  if (cache2) return cache2;
89140
89197
  try {
89141
- const raw = await readFile43(filePath, "utf-8");
89198
+ const raw = await readFile44(filePath, "utf-8");
89142
89199
  const parsed = JSON.parse(raw);
89143
89200
  const migrated = migrateProjectsStore(parsed);
89144
89201
  cache2 = migrated.projects;
@@ -89167,7 +89224,7 @@ function buildProjectsStore(filePath) {
89167
89224
  }
89168
89225
  async function readFromDisk() {
89169
89226
  try {
89170
- const raw = await readFile43(filePath, "utf-8");
89227
+ const raw = await readFile44(filePath, "utf-8");
89171
89228
  return migrateProjectsStore(JSON.parse(raw)).projects;
89172
89229
  } catch (err3) {
89173
89230
  if (isEnoent(err3)) return [];
@@ -89288,7 +89345,7 @@ function buildProjectsStore(filePath) {
89288
89345
  }
89289
89346
 
89290
89347
  // src/services/storage/rate-limit-store.ts
89291
- import { mkdir as mkdir33, readFile as readFile44 } from "fs/promises";
89348
+ import { mkdir as mkdir33, readFile as readFile45 } from "fs/promises";
89292
89349
  import { dirname as dirname33, join as join81 } from "path";
89293
89350
  var RATE_LIMIT_STORE_VERSION = 4;
89294
89351
  var RateLimitRecordSchema = external_exports.object({
@@ -89499,7 +89556,7 @@ function mergeEvent(prev, incoming, eventTime) {
89499
89556
  }
89500
89557
  async function loadStoreFile(filePath, logger2) {
89501
89558
  try {
89502
- const raw = await readFile44(filePath, "utf-8");
89559
+ const raw = await readFile45(filePath, "utf-8");
89503
89560
  const parsed = JSON.parse(raw);
89504
89561
  const v4 = StoreFileSchemaV4.safeParse(parsed);
89505
89562
  if (v4.success) return v4.data;
@@ -89602,7 +89659,7 @@ async function atomicWrite4(filePath, data) {
89602
89659
  }
89603
89660
 
89604
89661
  // src/services/storage/schedule-store.ts
89605
- import { lstat as lstat6, mkdir as mkdir34, readFile as readFile45, rmdir, writeFile as writeFile27 } from "fs/promises";
89662
+ import { lstat as lstat6, mkdir as mkdir34, readFile as readFile46, rmdir, writeFile as writeFile27 } from "fs/promises";
89606
89663
  import { dirname as dirname34, join as join82 } from "path";
89607
89664
  var STORE_FILE = "schedules.json";
89608
89665
  function emptyState() {
@@ -89706,7 +89763,7 @@ function buildScheduleStore(dataDir, options) {
89706
89763
  async function loadFromDisk() {
89707
89764
  let source;
89708
89765
  try {
89709
- source = await readFile45(filePath, "utf-8");
89766
+ source = await readFile46(filePath, "utf-8");
89710
89767
  } catch (error) {
89711
89768
  if (isEnoent(error)) return { state: emptyState(), source: null, migratedFromVersion: null };
89712
89769
  throw error;
@@ -89731,7 +89788,7 @@ function buildScheduleStore(dataDir, options) {
89731
89788
  if (typeof error !== "object" || error === null || !("code" in error) || error.code !== "EEXIST") {
89732
89789
  throw error;
89733
89790
  }
89734
- const existingBackup = await readFile45(backupPath, "utf-8");
89791
+ const existingBackup = await readFile46(backupPath, "utf-8");
89735
89792
  if (existingBackup !== loaded.source) {
89736
89793
  throw new Error(`Schedule migration backup does not match source: ${backupPath}`);
89737
89794
  }
@@ -89808,7 +89865,7 @@ function buildScheduleStore(dataDir, options) {
89808
89865
  }
89809
89866
 
89810
89867
  // src/services/storage/session-persistence.ts
89811
- import { mkdir as mkdir35, readdir as readdir22, readFile as readFile46, rm as rm13 } from "fs/promises";
89868
+ import { mkdir as mkdir35, readdir as readdir22, readFile as readFile47, rm as rm13 } from "fs/promises";
89812
89869
  import { join as join83 } from "path";
89813
89870
  var PersistedSessionSchema = external_exports.object({
89814
89871
  sessionId: external_exports.string(),
@@ -89840,7 +89897,7 @@ var PersistedSessionSchema = external_exports.object({
89840
89897
  }));
89841
89898
  async function loadOneSessionFile(originalPath, corruptionLogger) {
89842
89899
  try {
89843
- const raw = await readFile46(originalPath, "utf-8");
89900
+ const raw = await readFile47(originalPath, "utf-8");
89844
89901
  return PersistedSessionSchema.parse(JSON.parse(raw));
89845
89902
  } catch (err3) {
89846
89903
  if (isCorruptionError(err3)) {
@@ -89882,7 +89939,7 @@ function buildSessionPersistence(dataDir, corruptionLogger) {
89882
89939
  async load(channelId) {
89883
89940
  const path8 = sessionPath(channelId);
89884
89941
  try {
89885
- const raw = await readFile46(path8, "utf-8");
89942
+ const raw = await readFile47(path8, "utf-8");
89886
89943
  return PersistedSessionSchema.parse(JSON.parse(raw));
89887
89944
  } catch (err3) {
89888
89945
  if (isEnoent(err3)) return null;
@@ -89983,7 +90040,7 @@ function buildTemplateStore(dataDir) {
89983
90040
  }
89984
90041
 
89985
90042
  // src/services/storage/user-settings-store.ts
89986
- import { mkdir as mkdir36, readFile as readFile47 } from "fs/promises";
90043
+ import { mkdir as mkdir36, readFile as readFile48 } from "fs/promises";
89987
90044
  import { dirname as dirname35 } from "path";
89988
90045
  function buildUserSettingsStore(filePath) {
89989
90046
  let cache2 = null;
@@ -90004,7 +90061,7 @@ function buildUserSettingsStore(filePath) {
90004
90061
  async function readStore() {
90005
90062
  if (cache2) return cache2;
90006
90063
  try {
90007
- const raw = await readFile47(filePath, "utf-8");
90064
+ const raw = await readFile48(filePath, "utf-8");
90008
90065
  const parsed = JSON.parse(raw);
90009
90066
  const migrated = migrateUserSettingsStore(parsed);
90010
90067
  cache2 = migrated.settings;
@@ -90051,7 +90108,7 @@ function buildUserSettingsStore(filePath) {
90051
90108
  }
90052
90109
  async function readSettingsFromDisk() {
90053
90110
  try {
90054
- const raw = await readFile47(filePath, "utf-8");
90111
+ const raw = await readFile48(filePath, "utf-8");
90055
90112
  return migrateUserSettingsStore(JSON.parse(raw)).settings;
90056
90113
  } catch (err3) {
90057
90114
  if (isEnoent(err3)) return { ...DEFAULT_USER_SETTINGS };
@@ -96636,7 +96693,7 @@ var Thread = class {
96636
96693
  // src/services/plan/plan-handler.ts
96637
96694
  import { randomUUID as randomUUID24 } from "crypto";
96638
96695
  import { existsSync as existsSync12, readdirSync as readdirSync5, statSync as statSync5 } from "fs";
96639
- import { mkdir as mkdir37, readFile as readFile49, writeFile as writeFile29 } from "fs/promises";
96696
+ import { mkdir as mkdir37, readFile as readFile50, writeFile as writeFile29 } from "fs/promises";
96640
96697
  import { homedir as homedir13 } from "os";
96641
96698
  import { dirname as dirname37, join as join86 } from "path";
96642
96699
 
@@ -96811,8 +96868,8 @@ function decideWatchResolved(trigger, snapshot2) {
96811
96868
  // src/services/plan/plan-file-bridge.ts
96812
96869
  import { createHash as createHash17, randomUUID as randomUUID23 } from "crypto";
96813
96870
  import { existsSync as existsSync10 } from "fs";
96814
- import { readFile as readFile48, rename as rename19, stat as stat25, writeFile as writeFile28 } from "fs/promises";
96815
- import { basename as basename13, dirname as dirname36 } from "path";
96871
+ import { readFile as readFile49, rename as rename19, stat as stat25, writeFile as writeFile28 } from "fs/promises";
96872
+ import { basename as basename14, dirname as dirname36 } from "path";
96816
96873
  var FILE_READ_MAX_RETRIES = 3;
96817
96874
  var FILE_READ_RETRY_BASE_MS = 200;
96818
96875
  var PlanFileBridge = class _PlanFileBridge {
@@ -97021,7 +97078,7 @@ var PlanFileBridge = class _PlanFileBridge {
97021
97078
  async #startDirectoryWatcher(filePath) {
97022
97079
  const dir = dirname36(filePath);
97023
97080
  if (!existsSync10(dir)) return;
97024
- const targetFilename = basename13(filePath);
97081
+ const targetFilename = basename14(filePath);
97025
97082
  let sub;
97026
97083
  try {
97027
97084
  sub = await guardedSubscribe(
@@ -97031,7 +97088,7 @@ var PlanFileBridge = class _PlanFileBridge {
97031
97088
  let matched = false;
97032
97089
  for (const ev of events) {
97033
97090
  if (ev.type === "evicted") continue;
97034
- if (basename13(ev.path) === targetFilename) {
97091
+ if (basename14(ev.path) === targetFilename) {
97035
97092
  matched = true;
97036
97093
  break;
97037
97094
  }
@@ -97237,7 +97294,7 @@ var PlanFileBridge = class _PlanFileBridge {
97237
97294
  let lastError;
97238
97295
  for (let attempt = 0; attempt < FILE_READ_MAX_RETRIES; attempt++) {
97239
97296
  try {
97240
- return await readFile48(filePath, "utf-8");
97297
+ return await readFile49(filePath, "utf-8");
97241
97298
  } catch (err3) {
97242
97299
  lastError = err3;
97243
97300
  const msg = err3 instanceof Error ? err3.message : String(err3);
@@ -98153,7 +98210,7 @@ var PlanHandler = class {
98153
98210
  }
98154
98211
  async #readFileForRehydrate(filePath) {
98155
98212
  try {
98156
- return await readFile49(filePath, "utf-8");
98213
+ return await readFile50(filePath, "utf-8");
98157
98214
  } catch (err3) {
98158
98215
  this.#deps.log({
98159
98216
  event: "plan_bridge_rehydrate_read_failed",
@@ -101502,7 +101559,7 @@ var RewindCheckpointHandler = class _RewindCheckpointHandler {
101502
101559
  };
101503
101560
 
101504
101561
  // src/services/task/side-thread-registry.ts
101505
- import { mkdir as mkdir38, readFile as readFile50, rename as rename20, writeFile as writeFile30 } from "fs/promises";
101562
+ import { mkdir as mkdir38, readFile as readFile51, rename as rename20, writeFile as writeFile30 } from "fs/promises";
101506
101563
  import { dirname as dirname38, join as join87 } from "path";
101507
101564
  var ThreadFileSchema = external_exports.object({
101508
101565
  threads: external_exports.record(external_exports.string(), ThreadMetadataSchema)
@@ -102042,7 +102099,7 @@ var SideThreadRegistry = class {
102042
102099
  const filePath = this.#filePath();
102043
102100
  let raw;
102044
102101
  try {
102045
- raw = await readFile50(filePath, "utf-8");
102102
+ raw = await readFile51(filePath, "utf-8");
102046
102103
  } catch (err3) {
102047
102104
  if (isEnoent(err3)) return;
102048
102105
  throw err3;
@@ -105135,9 +105192,9 @@ function buildProfileRewindCapability(resolve15, runtimeId, primary) {
105135
105192
 
105136
105193
  // src/services/task/cc-task-file-store.ts
105137
105194
  import { existsSync as existsSync13 } from "fs";
105138
- import { readdir as readdir23, readFile as readFile51 } from "fs/promises";
105195
+ import { readdir as readdir23, readFile as readFile52 } from "fs/promises";
105139
105196
  import { homedir as homedir14 } from "os";
105140
- import { basename as basename14, dirname as dirname39, join as join88 } from "path";
105197
+ import { basename as basename15, dirname as dirname39, join as join88 } from "path";
105141
105198
  var VALID_STATUSES = /* @__PURE__ */ new Set(["pending", "in_progress", "completed"]);
105142
105199
  var IDLE_DETACH_MS = 5 * 60 * 1e3;
105143
105200
  var IDLE_SWEEP_INTERVAL_MS = 6e4;
@@ -105154,7 +105211,7 @@ function isCCTaskFile(value) {
105154
105211
  function createCCTaskFileWatcher(listId, log) {
105155
105212
  const sanitizedId = sanitize(listId);
105156
105213
  const dir = join88(homedir14(), ".claude", "tasks", sanitizedId);
105157
- const targetDirName = basename14(dir);
105214
+ const targetDirName = basename15(dir);
105158
105215
  const parentDir = dirname39(dir);
105159
105216
  const watchState = {
105160
105217
  dirSub: null,
@@ -105191,7 +105248,7 @@ function createCCTaskFileWatcher(listId, log) {
105191
105248
  async function readTask(taskId) {
105192
105249
  const filePath = join88(dir, `${taskId}.json`);
105193
105250
  try {
105194
- const raw = await readFile51(filePath, "utf-8");
105251
+ const raw = await readFile52(filePath, "utf-8");
105195
105252
  const parsed = JSON.parse(raw);
105196
105253
  if (isCCTaskFile(parsed)) return parsed;
105197
105254
  log?.({
@@ -110110,18 +110167,33 @@ async function loadResumableSession(sessionPersistence, channelId, taskId, log)
110110
110167
  }
110111
110168
 
110112
110169
  // src/services/task/manager/snapshot-broadcast-gate.ts
110170
+ import { createHash as createHash20 } from "crypto";
110113
110171
  function createSnapshotBroadcastGate() {
110114
110172
  let lastSkills = null;
110173
+ const lastMcpStateHashByScope = /* @__PURE__ */ new Map();
110115
110174
  return {
110116
110175
  admit(msg) {
110176
+ if (msg.type === "mcp_state_snapshot") {
110177
+ lastMcpStateHashByScope.set(mcpStateScope(msg), hashMcpState(msg));
110178
+ return true;
110179
+ }
110117
110180
  if (msg.type !== "skills_snapshot") return true;
110118
110181
  const serialized = JSON.stringify(msg.skills);
110119
110182
  if (serialized === lastSkills) return false;
110120
110183
  lastSkills = serialized;
110121
110184
  return true;
110185
+ },
110186
+ isNewMcpState(msg) {
110187
+ return lastMcpStateHashByScope.get(mcpStateScope(msg)) !== hashMcpState(msg);
110122
110188
  }
110123
110189
  };
110124
110190
  }
110191
+ function mcpStateScope(msg) {
110192
+ return msg.taskId ?? "\0workspace";
110193
+ }
110194
+ function hashMcpState(msg) {
110195
+ return createHash20("sha256").update(JSON.stringify(msg.servers)).digest("base64");
110196
+ }
110125
110197
 
110126
110198
  // src/services/task/manager/task-conversation-mutations.ts
110127
110199
  var MessageAdmissionCancelledError = class extends Error {
@@ -110507,8 +110579,12 @@ function logIfRejected(deps, taskId, repoKind, result) {
110507
110579
 
110508
110580
  // src/services/task/manager/task-manager-mcp-snapshot.ts
110509
110581
  function pushTaskMcpStateSnapshot(ctx, taskId) {
110582
+ const message = buildTaskMcpStateSnapshot(ctx, taskId);
110583
+ if (message) ctx.broadcastControl(message);
110584
+ }
110585
+ function buildTaskMcpStateSnapshot(ctx, taskId) {
110510
110586
  const task = ctx.tasks.get(taskId);
110511
- if (!task) return;
110587
+ if (!task) return null;
110512
110588
  const settings = task.orchestrator.latestSettings;
110513
110589
  const sessionServers = {};
110514
110590
  for (const s2 of ctx.sessionMcpsByTask.get(taskId) ?? []) {
@@ -110535,7 +110611,7 @@ function pushTaskMcpStateSnapshot(ctx, taskId) {
110535
110611
  perTaskSnapshot: settings.mcpServerSnapshot ?? null
110536
110612
  })
110537
110613
  };
110538
- ctx.broadcastControl(message);
110614
+ return message;
110539
110615
  }
110540
110616
  function refreshAllTaskMcpStateSnapshots(ctx, schedule) {
110541
110617
  if (schedule.scheduled) return;
@@ -110543,7 +110619,8 @@ function refreshAllTaskMcpStateSnapshots(ctx, schedule) {
110543
110619
  queueMicrotask(() => {
110544
110620
  schedule.scheduled = false;
110545
110621
  for (const taskId of ctx.tasks.keys()) {
110546
- pushTaskMcpStateSnapshot(ctx, taskId);
110622
+ const message = buildTaskMcpStateSnapshot(ctx, taskId);
110623
+ if (message) ctx.broadcastControlIfChanged(message);
110547
110624
  }
110548
110625
  });
110549
110626
  }
@@ -111430,6 +111507,10 @@ var TaskManager = class {
111430
111507
  }
111431
111508
  }
111432
111509
  }
111510
+ /** FSM-driven `mcp_state_snapshot` fan-out; replay and user pushes use `broadcastControl`, which always sends. */
111511
+ broadcastControlIfChanged(msg) {
111512
+ if (this.#snapshotGate.isNewMcpState(msg)) this.broadcastControl(msg);
111513
+ }
111433
111514
  /** Pub/sub fan-out. `FanoutMessage` narrowing rejects reply/unicast at compile time (#2728 / routing-classification.ts). */
111434
111515
  broadcastControl(msg) {
111435
111516
  if (!this.#snapshotGate.admit(msg)) return;
@@ -111980,6 +112061,7 @@ var TaskManager = class {
111980
112061
  getCapabilities: this.#deps.getCapabilities,
111981
112062
  getMcpCoordinator: this.#deps.getMcpCoordinator,
111982
112063
  broadcastControl: (msg) => this.broadcastControl(msg),
112064
+ broadcastControlIfChanged: (msg) => this.broadcastControlIfChanged(msg),
111983
112065
  applyTaskSettings: (taskId, settings) => this.applyTaskSettings(taskId, settings)
111984
112066
  };
111985
112067
  }
@@ -115507,7 +115589,7 @@ async function createDaemon(deps) {
115507
115589
  await bootstrapPhase(
115508
115590
  "vault_sync_init",
115509
115591
  () => initializeVaultSync(vaultKey, deps, credentialsVaultStore, oauthStateStore, () => {
115510
- refreshCoordinatorFromCaps();
115592
+ refreshCoordinatorFromCaps("vault_sync");
115511
115593
  })
115512
115594
  );
115513
115595
  } else {
@@ -115740,7 +115822,7 @@ async function createDaemon(deps) {
115740
115822
  * non-owner peers (Invariant #7).
115741
115823
  */
115742
115824
  sendStateSnapshot: (msg) => {
115743
- taskManager.broadcastControl(msg);
115825
+ taskManager.broadcastControlIfChanged(msg);
115744
115826
  taskManager.refreshAllTaskMcpStateSnapshots();
115745
115827
  },
115746
115828
  /**
@@ -115802,7 +115884,7 @@ async function createDaemon(deps) {
115802
115884
  });
115803
115885
  }
115804
115886
  }
115805
- function refreshCoordinatorFromCaps() {
115887
+ function refreshCoordinatorFromCaps(reason) {
115806
115888
  const coordinator = mcpCoordinatorRef.current;
115807
115889
  if (!coordinator) return;
115808
115890
  const caps = capabilitiesRef.current;
@@ -115815,7 +115897,8 @@ async function createDaemon(deps) {
115815
115897
  pluginServers,
115816
115898
  userServers,
115817
115899
  disabledNames,
115818
- gatewayIdByName: gatewayIdsFromCapabilities(caps)
115900
+ gatewayIdByName: gatewayIdsFromCapabilities(caps),
115901
+ reason
115819
115902
  }).catch((err3) => {
115820
115903
  deps.log({
115821
115904
  event: "mcp_coordinator_refresh_failed",
@@ -115833,7 +115916,7 @@ async function createDaemon(deps) {
115833
115916
  )
115834
115917
  });
115835
115918
  }
115836
- refreshCoordinatorFromCaps();
115919
+ refreshCoordinatorFromCaps("proxy_auth_required");
115837
115920
  });
115838
115921
  }
115839
115922
  function markConnectedProxyServersAuthed(proxyServer) {
@@ -116135,7 +116218,7 @@ async function createDaemon(deps) {
116135
116218
  },
116136
116219
  set capabilities(c) {
116137
116220
  commitCapabilities(applyPluginSupersession(c));
116138
- refreshCoordinatorFromCaps();
116221
+ refreshCoordinatorFromCaps("capabilities_changed");
116139
116222
  taskManager.refreshAllTaskSkillsSnapshots();
116140
116223
  reBroadcastEnrichedSkillsAfterWarm();
116141
116224
  },
@@ -116286,8 +116369,8 @@ import { existsSync as existsSync15 } from "fs";
116286
116369
 
116287
116370
  // src/services/bootstrap/self-update.ts
116288
116371
  import { execFile as execFile14, spawn as spawn14 } from "child_process";
116289
- import { createHash as createHash20 } from "crypto";
116290
- import { chmod as chmod4, mkdir as mkdir41, readFile as readFile52, rename as rename22, unlink as unlink18, writeFile as writeFile33 } from "fs/promises";
116372
+ import { createHash as createHash21 } from "crypto";
116373
+ import { chmod as chmod4, mkdir as mkdir41, readFile as readFile53, rename as rename22, unlink as unlink18, writeFile as writeFile33 } from "fs/promises";
116291
116374
  import { join as join93 } from "path";
116292
116375
 
116293
116376
  // src/services/bootstrap/self-update-installer-scripts.ts
@@ -116709,8 +116792,8 @@ async function downloadTarball(url2, destPath, fetchFn) {
116709
116792
  }
116710
116793
  async function verifyChecksum(path8, expectedHash) {
116711
116794
  const algo = expectedHash.length === 40 ? "sha1" : "sha256";
116712
- const raw = await readFile52(path8);
116713
- const actual = createHash20(algo).update(raw).digest("hex");
116795
+ const raw = await readFile53(path8);
116796
+ const actual = createHash21(algo).update(raw).digest("hex");
116714
116797
  if (actual !== expectedHash) {
116715
116798
  try {
116716
116799
  await unlink18(path8);
@@ -117836,7 +117919,7 @@ function buildLocalDirectChannelCallbacks(deps) {
117836
117919
  }
117837
117920
 
117838
117921
  // src/services/skills-cache/codex-skills-cache.ts
117839
- import { mkdir as mkdir42, readFile as readFile53, rename as rename23, writeFile as writeFile34 } from "fs/promises";
117922
+ import { mkdir as mkdir42, readFile as readFile54, rename as rename23, writeFile as writeFile34 } from "fs/promises";
117840
117923
  import { dirname as dirname41, join as join94 } from "path";
117841
117924
  var CACHE_FILENAME = "codex-skills-cache.json";
117842
117925
  var SkillInfoCacheEntrySchema = external_exports.object({
@@ -117859,7 +117942,7 @@ function defaultCodexSkillsCachePath(shipyardHome) {
117859
117942
  async function loadCodexSkillsCache(path8) {
117860
117943
  let raw;
117861
117944
  try {
117862
- raw = await readFile53(path8, "utf-8");
117945
+ raw = await readFile54(path8, "utf-8");
117863
117946
  } catch (err3) {
117864
117947
  if (isEnoent(err3)) return null;
117865
117948
  logger.warn(
@@ -117921,7 +118004,7 @@ import { homedir as homedir16 } from "os";
117921
118004
  import { dirname as dirname43, join as join96 } from "path";
117922
118005
 
117923
118006
  // src/services/skills-mirror/manifest.ts
117924
- import { mkdir as mkdir43, readFile as readFile54, rename as rename24, unlink as unlink19, writeFile as writeFile35 } from "fs/promises";
118007
+ import { mkdir as mkdir43, readFile as readFile55, rename as rename24, unlink as unlink19, writeFile as writeFile35 } from "fs/promises";
117925
118008
  import { dirname as dirname42, join as join95 } from "path";
117926
118009
  var MANIFEST_VERSION = 1;
117927
118010
  var ManifestEntrySchema = external_exports.object({
@@ -117946,7 +118029,7 @@ function defaultManifestPath(shipyardHome) {
117946
118029
  }
117947
118030
  async function loadManifest(path8) {
117948
118031
  try {
117949
- const raw = await readFile54(path8, "utf-8");
118032
+ const raw = await readFile55(path8, "utf-8");
117950
118033
  const parsed = ManifestFileSchema.safeParse(JSON.parse(raw));
117951
118034
  if (!parsed.success) return emptyManifest();
117952
118035
  return parsed.data;
@@ -118193,7 +118276,7 @@ async function ensureMirror(skills, config, paths = defaultPaths()) {
118193
118276
  }
118194
118277
 
118195
118278
  // src/services/skills-mirror/prefs.ts
118196
- import { mkdir as mkdir45, readFile as readFile55, rename as rename25, writeFile as writeFile36 } from "fs/promises";
118279
+ import { mkdir as mkdir45, readFile as readFile56, rename as rename25, writeFile as writeFile36 } from "fs/promises";
118197
118280
  import { dirname as dirname44, join as join97 } from "path";
118198
118281
  var SkillsMirrorPrefsSchema = external_exports.object({
118199
118282
  enabled: external_exports.boolean().default(false)
@@ -118207,7 +118290,7 @@ function prefsPath(dataDir) {
118207
118290
  }
118208
118291
  async function loadSkillsMirrorPrefs(dataDir) {
118209
118292
  try {
118210
- const raw = await readFile55(prefsPath(dataDir), "utf-8");
118293
+ const raw = await readFile56(prefsPath(dataDir), "utf-8");
118211
118294
  const parsed = SkillsMirrorPrefsSchema.safeParse(JSON.parse(raw));
118212
118295
  if (!parsed.success) return defaultSkillsMirrorPrefs();
118213
118296
  return parsed.data;
@@ -118250,15 +118333,15 @@ async function reconcileSkillsMirror(args) {
118250
118333
  }
118251
118334
 
118252
118335
  // src/services/storage/daemon-settings-store.ts
118253
- import { createHash as createHash21 } from "crypto";
118254
- import { mkdir as mkdir46, readFile as readFile56 } from "fs/promises";
118336
+ import { createHash as createHash22 } from "crypto";
118337
+ import { mkdir as mkdir46, readFile as readFile57 } from "fs/promises";
118255
118338
  import { join as join98 } from "path";
118256
118339
  var ProjectSettingsSchema = external_exports.object({
118257
118340
  disabledMcpServers: external_exports.array(external_exports.string()).optional(),
118258
118341
  previewMigrationV36Done: external_exports.boolean().default(false)
118259
118342
  });
118260
118343
  function hashProjectPath(projectPath) {
118261
- return createHash21("sha256").update(projectPath).digest("hex").slice(0, 16);
118344
+ return createHash22("sha256").update(projectPath).digest("hex").slice(0, 16);
118262
118345
  }
118263
118346
  function buildDaemonSettingsStore(dataDir) {
118264
118347
  const settingsDir = join98(dataDir, "settings");
@@ -118271,7 +118354,7 @@ function buildDaemonSettingsStore(dataDir) {
118271
118354
  return {
118272
118355
  async load(projectPath) {
118273
118356
  try {
118274
- const raw = await readFile56(settingsPath(projectPath), "utf-8");
118357
+ const raw = await readFile57(settingsPath(projectPath), "utf-8");
118275
118358
  return ProjectSettingsSchema.parse(JSON.parse(raw));
118276
118359
  } catch (err3) {
118277
118360
  if (isEnoent(err3)) return ProjectSettingsSchema.parse({});
@@ -118287,7 +118370,7 @@ function buildDaemonSettingsStore(dataDir) {
118287
118370
  }
118288
118371
 
118289
118372
  // src/services/storage/plugin-config-store.ts
118290
- import { mkdir as mkdir47, readFile as readFile57 } from "fs/promises";
118373
+ import { mkdir as mkdir47, readFile as readFile58 } from "fs/promises";
118291
118374
  import { join as join99 } from "path";
118292
118375
  function buildPluginConfigStore(pluginsDir) {
118293
118376
  const cache2 = /* @__PURE__ */ new Map();
@@ -118298,7 +118381,7 @@ function buildPluginConfigStore(pluginsDir) {
118298
118381
  async function readConfigFromDisk(pluginId) {
118299
118382
  const fp = configPath(pluginId);
118300
118383
  try {
118301
- const raw = await readFile57(fp, "utf-8");
118384
+ const raw = await readFile58(fp, "utf-8");
118302
118385
  const parsed = JSON.parse(raw);
118303
118386
  if (typeof parsed === "object" && parsed !== null && !Array.isArray(parsed)) {
118304
118387
  return Object.fromEntries(Object.entries(parsed));
@@ -119442,4 +119525,4 @@ export {
119442
119525
  decideWorkspaceScope,
119443
119526
  serve
119444
119527
  };
119445
- //# sourceMappingURL=serve-VMGXVCO7.js.map
119528
+ //# sourceMappingURL=serve-NWLZH6MD.js.map