@adhdev/daemon-standalone 1.0.39-rc.1 → 1.0.39-rc.10

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/public/index.html CHANGED
@@ -7,9 +7,9 @@
7
7
  <meta name="description" content="ADHDev self-hosted dashboard for controlling AI agents" />
8
8
  <link rel="icon" href="/otter-logo.png" />
9
9
  <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&display=swap" rel="stylesheet" />
10
- <script type="module" crossorigin src="/assets/index-B7t7s0FW.js"></script>
11
- <link rel="modulepreload" crossorigin href="/assets/vendor-cL4V2vaO.js">
12
- <link rel="stylesheet" crossorigin href="/assets/index-69StxR7K.css">
10
+ <script type="module" crossorigin src="/assets/index-Hsc3-7gC.js"></script>
11
+ <link rel="modulepreload" crossorigin href="/assets/vendor-DgFmqOGd.js">
12
+ <link rel="stylesheet" crossorigin href="/assets/index-BRvsAKU_.css">
13
13
  </head>
14
14
  <body>
15
15
  <!-- Apply theme immediately to prevent FOIT (Flash of Incorrect Theme) -->
@@ -937,7 +937,7 @@ function isLocalControlPlaneNode(ctx, node) {
937
937
  // src/tools/mesh-tool-schemas.ts
938
938
  var MESH_STATUS_TOOL = {
939
939
  name: "mesh_status",
940
- description: "Get the current status of all nodes in the repo mesh \u2014 health, git state, active sessions, recovery hints, and recommended next steps. Use this to decide which node to send work to or how to recover from failures. Also reports the running daemon build per daemonId under top-level daemonBuilds ({commit, commitShort, version}); when a live daemon was built from a commit BEHIND its workspace HEAD it adds staleDaemonBuilds[] + staleDaemonBuildWarning \u2014 meaning a just-merged refinery/mesh-tool fix is NOT yet live on that daemon (awaiting deploy/restart; a local dist rebuild does not update a cloud daemon). Do not repeatedly call this to wait for generating delegated work; wait for pendingCoordinatorEvents/completion events or an explicit user status request.",
940
+ description: `Get the current status of all nodes in the repo mesh \u2014 health, git state, active sessions, recovery hints, and recommended next steps. Use this to decide which node to send work to or how to recover from failures. Also reports the running daemon build per daemonId under top-level daemonBuilds ({commit, commitShort, version}); when a live daemon was built from a commit BEHIND its workspace HEAD it adds staleDaemonBuilds[] + staleDaemonBuildWarning \u2014 meaning a just-merged refinery/mesh-tool fix is NOT yet live on that daemon (awaiting deploy/restart; a local dist rebuild does not update a cloud daemon). When a daemon has a durable failed-upgrade notice on record it adds daemonUpgradeFailures{daemonId \u2192 {summary, recordedAt, ageLabel, targetVersion, noticePath, logPath}} + daemonUpgradeFailureWarning \u2014 meaning that daemon's LAST upgrade attempt failed and was rolled back, so it is still on the PREVIOUS version (an upgrade/restart response only ever reports "scheduled", never success). Do not repeatedly call this to wait for generating delegated work; wait for pendingCoordinatorEvents/completion events or an explicit user status request.`,
941
941
  inputSchema: {
942
942
  type: "object",
943
943
  properties: {
@@ -967,7 +967,7 @@ var MESH_ENQUEUE_TASK_TOOL = {
967
967
  type: "object",
968
968
  properties: {
969
969
  message: { type: "string", description: "The task instruction for the agent." },
970
- task_mode: { type: "string", enum: ["code_change", "validation", "live_debug_readonly", "launch_app", "convergence"], description: "Optional task-mode contract. live_debug_readonly rejects obvious write/commit/push/deploy/destructive instructions before dispatch." },
970
+ task_mode: { type: "string", enum: ["code_change", "validation", "live_debug_readonly", "launch_app", "convergence"], description: "Optional task-mode contract. live_debug_readonly rejects obvious write/commit/push/deploy/destructive instructions before dispatch \u2014 and in exchange runs without the one-active-per-node write isolation (N read-only tasks may run in parallel on one busy node, no worktree needed) under a separate, larger read-only concurrency cap. Prefer it for investigation/diagnosis: it is the cheaper mode to schedule, not just the restricted one." },
971
971
  taskMode: { type: "string", enum: ["code_change", "validation", "live_debug_readonly", "launch_app", "convergence"], description: "CamelCase alias for task_mode." },
972
972
  readonly: { type: "boolean", description: "Optional read-only axis (orthogonal to task_mode). When true the task runs without the one-active-per-node write isolation (N read-only tasks may run in parallel on one node), is counted under the read-only safety cap, and rejects write/commit/push/deploy/destructive instructions like live_debug_readonly. Equivalent to task_mode=live_debug_readonly but composable with any task_mode." },
973
973
  read_only: { type: "boolean", description: "Snake-case alias for readonly." },
@@ -1884,7 +1884,7 @@ function summarizeCompactSubmodules(submodules) {
1884
1884
  ...outOfSync.length > 0 ? { outOfSyncPaths: outOfSync } : {}
1885
1885
  };
1886
1886
  }
1887
- var MESH_COMPACT_PRESERVED_MARKER_FIELDS = ["dataFreshness", "quota"];
1887
+ var MESH_COMPACT_PRESERVED_MARKER_FIELDS = ["dataFreshness", "quota", "isLocalWorktree"];
1888
1888
  function summarizeNodeQuota(quota) {
1889
1889
  if (!quota || typeof quota !== "object" || Array.isArray(quota)) return void 0;
1890
1890
  const out = {};
@@ -1960,6 +1960,27 @@ function compactNodeSeverity(entry) {
1960
1960
  if (entry.staleDaemonBuild || entry.submodulesOutOfSync || entry.recoveryHints) return 1;
1961
1961
  return 0;
1962
1962
  }
1963
+ function pinnedRepresentativeNodeIds(compacted) {
1964
+ const byDaemon = /* @__PURE__ */ new Map();
1965
+ for (const n of compacted) {
1966
+ if (!n || typeof n !== "object") continue;
1967
+ const daemonId = typeof n.daemonId === "string" && n.daemonId ? n.daemonId : "";
1968
+ if (!daemonId) continue;
1969
+ const current = byDaemon.get(daemonId);
1970
+ if (!current) {
1971
+ byDaemon.set(daemonId, n);
1972
+ continue;
1973
+ }
1974
+ if (current.isLocalWorktree === true && n.isLocalWorktree !== true) {
1975
+ byDaemon.set(daemonId, n);
1976
+ }
1977
+ }
1978
+ const pinned = /* @__PURE__ */ new Set();
1979
+ for (const n of byDaemon.values()) {
1980
+ if (n?.nodeId !== void 0) pinned.add(String(n.nodeId));
1981
+ }
1982
+ return pinned;
1983
+ }
1963
1984
  function isNoteworthyCompactNode(entry) {
1964
1985
  if (!entry || typeof entry !== "object") return true;
1965
1986
  if (entry.health && entry.health !== "online") return true;
@@ -2383,14 +2404,32 @@ function findNode(mesh, nodeId) {
2383
2404
  }
2384
2405
  var DUPLICATE_DISPATCH_WINDOW_MS = 6e4;
2385
2406
  async function refreshMeshFromDaemon(ctx) {
2407
+ const settledNodeIds = /* @__PURE__ */ new Set();
2386
2408
  try {
2387
2409
  const result = await ctx.transport.command("get_mesh", { meshId: ctx.mesh.id });
2388
- if (!result?.success || !Array.isArray(result.mesh?.nodes)) return;
2410
+ if (!result?.success || !Array.isArray(result.mesh?.nodes)) return { settledNodeIds };
2389
2411
  const refreshedNodes = result.mesh.nodes.filter((n) => n?.id).map((n) => n);
2390
- ctx.mesh.nodes.splice(0, ctx.mesh.nodes.length, ...refreshedNodes);
2412
+ const merged = [...refreshedNodes];
2413
+ for (const existing of ctx.mesh.nodes) {
2414
+ const existingId = existing?.id;
2415
+ if (!existingId) continue;
2416
+ if (merged.some((n) => (0, import_daemon_core4.meshNodeIdMatches)(n, existingId))) continue;
2417
+ if (isLocalControlPlaneNode(ctx, existing)) {
2418
+ settledNodeIds.add(existingId);
2419
+ continue;
2420
+ }
2421
+ const clonedFromNodeId = readString(existing?.clonedFromNodeId) || readString(existing?.cloned_from_node_id);
2422
+ if (clonedFromNodeId && refreshedNodes.some((n) => (0, import_daemon_core4.meshNodeIdMatches)(n, clonedFromNodeId))) {
2423
+ settledNodeIds.add(existingId);
2424
+ continue;
2425
+ }
2426
+ merged.push(existing);
2427
+ }
2428
+ ctx.mesh.nodes.splice(0, ctx.mesh.nodes.length, ...merged);
2391
2429
  ctx.mesh.updatedAt = result.mesh.updatedAt ?? ctx.mesh.updatedAt;
2392
2430
  } catch {
2393
2431
  }
2432
+ return { settledNodeIds };
2394
2433
  }
2395
2434
  async function syncCoordinatorDaemonMeshCache(ctx) {
2396
2435
  if (!(ctx.transport instanceof IpcTransport)) return;
@@ -2402,19 +2441,71 @@ async function syncCoordinatorDaemonMeshCache(ctx) {
2402
2441
  } catch {
2403
2442
  }
2404
2443
  }
2444
+ async function resolveNodeFromOwningDaemons(ctx, nodeId) {
2445
+ const transport = ctx.transport;
2446
+ if (typeof transport?.meshCommand !== "function") return { node: null, ownerUnreachable: false };
2447
+ const localDaemonId = ctx.localDaemonId;
2448
+ const candidates = [];
2449
+ const pushCandidate = (id) => {
2450
+ if (typeof id !== "string" || !id.trim()) return;
2451
+ if (localDaemonId && (0, import_daemon_core4.daemonIdsEquivalent)(id, localDaemonId)) return;
2452
+ if (!candidates.includes(id)) candidates.push(id);
2453
+ };
2454
+ for (const node of ctx.mesh.nodes) pushCandidate(node?.daemonId);
2455
+ pushCandidate(ctx.mesh?.meshHost?.hostDaemonId);
2456
+ if (candidates.length === 0) return { node: null, ownerUnreachable: false };
2457
+ let ownerUnreachable = false;
2458
+ for (const daemonId of candidates) {
2459
+ let result;
2460
+ try {
2461
+ result = await transport.meshCommand(daemonId, "get_mesh", { meshId: ctx.mesh.id });
2462
+ } catch {
2463
+ ownerUnreachable = true;
2464
+ continue;
2465
+ }
2466
+ const nodes = result?.mesh?.nodes ?? result?.result?.mesh?.nodes;
2467
+ if (!result?.success || !Array.isArray(nodes)) {
2468
+ if (result && result.success === false) ownerUnreachable = true;
2469
+ continue;
2470
+ }
2471
+ const found = nodes.find((n) => n?.id && (0, import_daemon_core4.meshNodeIdMatches)(n, nodeId));
2472
+ if (!found) continue;
2473
+ const existingIndex = ctx.mesh.nodes.findIndex((n) => (0, import_daemon_core4.meshNodeIdMatches)(n, nodeId));
2474
+ if (existingIndex >= 0) ctx.mesh.nodes[existingIndex] = found;
2475
+ else ctx.mesh.nodes.push(found);
2476
+ return { node: found, ownerUnreachable: false };
2477
+ }
2478
+ return { node: null, ownerUnreachable };
2479
+ }
2405
2480
  async function findNodeWithRefresh(ctx, nodeId) {
2406
2481
  const hit = ctx.mesh.nodes.find((n) => (0, import_daemon_core4.meshNodeIdMatches)(n, nodeId));
2407
2482
  if (hit && !hit.isLocalWorktree) return hit;
2408
- await refreshMeshFromDaemon(ctx);
2483
+ const { settledNodeIds } = await refreshMeshFromDaemon(ctx);
2409
2484
  const refreshed = ctx.mesh.nodes.find((n) => (0, import_daemon_core4.meshNodeIdMatches)(n, nodeId));
2410
- if (!refreshed) throw new Error(`Node '${nodeId}' is not a member of mesh '${ctx.mesh.name}'`);
2411
- return refreshed;
2485
+ if (refreshed) return refreshed;
2486
+ if (settledNodeIds.has(nodeId)) {
2487
+ throw new Error(`Node '${nodeId}' is not a member of mesh '${ctx.mesh.name}'`);
2488
+ }
2489
+ const owned = await resolveNodeFromOwningDaemons(ctx, nodeId);
2490
+ if (owned.node) return owned.node;
2491
+ if (owned.ownerUnreachable) {
2492
+ const err = new Error(
2493
+ `Node '${nodeId}' could not be resolved: the daemon that owns it is unreachable. This is NOT proof of non-membership \u2014 retry once the owning daemon is online.`
2494
+ );
2495
+ err.code = "mesh_node_owner_unreachable";
2496
+ throw err;
2497
+ }
2498
+ throw new Error(`Node '${nodeId}' is not a member of mesh '${ctx.mesh.name}'`);
2412
2499
  }
2413
2500
  async function findOptionalNodeWithRefresh(ctx, nodeId) {
2414
2501
  const hit = ctx.mesh.nodes.find((n) => (0, import_daemon_core4.meshNodeIdMatches)(n, nodeId));
2415
2502
  if (hit && !hit.isLocalWorktree) return hit;
2416
- await refreshMeshFromDaemon(ctx);
2417
- return ctx.mesh.nodes.find((n) => (0, import_daemon_core4.meshNodeIdMatches)(n, nodeId)) ?? null;
2503
+ const { settledNodeIds } = await refreshMeshFromDaemon(ctx);
2504
+ const refreshed = ctx.mesh.nodes.find((n) => (0, import_daemon_core4.meshNodeIdMatches)(n, nodeId));
2505
+ if (refreshed) return refreshed;
2506
+ if (settledNodeIds.has(nodeId)) return null;
2507
+ const owned = await resolveNodeFromOwningDaemons(ctx, nodeId);
2508
+ return owned.node;
2418
2509
  }
2419
2510
  function hasRecentDuplicateDispatch(ctx, args) {
2420
2511
  const now = Date.now();
@@ -2832,8 +2923,8 @@ function assignFullGitSnapshot(entry, status) {
2832
2923
  if (!status || typeof status !== "object" || Array.isArray(status)) return;
2833
2924
  entry.git = status;
2834
2925
  }
2835
- var COMPACT_DETAILED_NODES_BYTE_BUDGET = 9e3;
2836
- var COMPACT_NODES_TOTAL_BYTE_BUDGET = 11500;
2926
+ var COMPACT_DETAILED_NODES_BYTE_BUDGET = 32e3;
2927
+ var COMPACT_NODES_TOTAL_BYTE_BUDGET = 4e4;
2837
2928
  var COMPACT_MISSIONS_BYTE_BUDGET = 6e3;
2838
2929
  function extractLaunchPayload(value) {
2839
2930
  return findNestedPayload(value, (payload) => Boolean(payload?.sessionId || payload?.id || payload?.runtimeSessionId));
@@ -3348,12 +3439,35 @@ async function collectLiveStatusProbe(ctx, node) {
3348
3439
  const statusResult = await commandForNode(ctx, node, "get_status_metadata", {}, { statusProbe: true });
3349
3440
  return {
3350
3441
  sessions: extractStatusMetadataSessions(statusResult),
3351
- daemonBuild: extractDaemonBuildInfo(statusResult)
3442
+ daemonBuild: extractDaemonBuildInfo(statusResult),
3443
+ upgradeFailure: extractUpgradeFailureSummary(statusResult)
3352
3444
  };
3353
3445
  } catch {
3354
3446
  return { sessions: [] };
3355
3447
  }
3356
3448
  }
3449
+ var UPGRADE_FAILURE_SUMMARY_MAX_CHARS = 200;
3450
+ function extractUpgradeFailureSummary(value) {
3451
+ const payload = unwrapCommandPayload(value);
3452
+ const raw = payload?.upgradeFailure && typeof payload.upgradeFailure === "object" ? payload.upgradeFailure : value?.upgradeFailure && typeof value.upgradeFailure === "object" ? value.upgradeFailure : void 0;
3453
+ if (!raw) return void 0;
3454
+ const notice = readString(raw.notice) || "";
3455
+ const noticePath = readString(raw.noticePath) || "";
3456
+ if (!notice && !noticePath) return void 0;
3457
+ const bodyLine = notice.split(/\r?\n/).map((line) => line.trim()).find((line) => line && !/^\[[^\]\n]+\]$/.test(line)) || "";
3458
+ const summary = bodyLine.length > UPGRADE_FAILURE_SUMMARY_MAX_CHARS ? `${bodyLine.slice(0, UPGRADE_FAILURE_SUMMARY_MAX_CHARS)}\u2026` : bodyLine;
3459
+ const recordedAt = readString(raw.recordedAt);
3460
+ const ageLabel = readString(raw.ageLabel);
3461
+ const targetVersion = readString(raw.targetVersion);
3462
+ return {
3463
+ summary,
3464
+ ...recordedAt ? { recordedAt } : {},
3465
+ ...ageLabel ? { ageLabel } : {},
3466
+ ...targetVersion ? { targetVersion } : {},
3467
+ noticePath,
3468
+ logPath: readString(raw.logPath) || ""
3469
+ };
3470
+ }
3357
3471
  function extractDaemonBuildInfo(value) {
3358
3472
  const payload = unwrapCommandPayload(value);
3359
3473
  const build = payload?.daemonBuild && typeof payload.daemonBuild === "object" ? payload.daemonBuild : value?.daemonBuild && typeof value.daemonBuild === "object" ? value.daemonBuild : void 0;
@@ -3787,6 +3901,10 @@ async function meshStatus(ctx, args = {}) {
3787
3901
  machine: buildNodeMachineIdentity(ctx, node),
3788
3902
  daemonId: readNodeDaemonId(node),
3789
3903
  machineId: readNodeMachineId(node),
3904
+ // Needed by the compact fold to distinguish a machine (repo-root) node
3905
+ // from a worktree node: the per-daemon representative pin keeps machine
3906
+ // nodes out of the fold so a deploy roster can never lose a machine.
3907
+ isLocalWorktree: node.isLocalWorktree === true,
3790
3908
  ...getNodeLaunchReadiness(node),
3791
3909
  ...buildNodeCapabilityExposure(node)
3792
3910
  };
@@ -3896,6 +4014,7 @@ async function meshStatus(ctx, args = {}) {
3896
4014
  const statusProbe = await collectLiveStatusProbe(ctx, node);
3897
4015
  const liveSessions = statusProbe.sessions;
3898
4016
  if (statusProbe.daemonBuild) entry.daemonBuild = statusProbe.daemonBuild;
4017
+ if (statusProbe.upgradeFailure) entry.upgradeFailure = statusProbe.upgradeFailure;
3899
4018
  if (liveSessions.length > 0) {
3900
4019
  entry.sessions = liveSessions.map((s) => {
3901
4020
  const coordinatorMeshId = typeof s.coordinator?.meshId === "string" ? s.coordinator.meshId : void 0;
@@ -3993,6 +4112,21 @@ async function meshStatus(ctx, args = {}) {
3993
4112
  daemonBuilds[daemonId] = entry.daemonBuild;
3994
4113
  }
3995
4114
  }
4115
+ const daemonMachines = {};
4116
+ const daemonQuotas = {};
4117
+ for (const entry of results) {
4118
+ const daemonId = typeof entry?.daemonId === "string" && entry.daemonId ? entry.daemonId : "";
4119
+ if (!daemonId) continue;
4120
+ if (entry?.machine && !(daemonId in daemonMachines)) daemonMachines[daemonId] = entry.machine;
4121
+ if (entry?.quota && !(daemonId in daemonQuotas)) daemonQuotas[daemonId] = entry.quota;
4122
+ }
4123
+ const daemonUpgradeFailures = {};
4124
+ for (const entry of results) {
4125
+ const daemonId = typeof entry?.daemonId === "string" && entry.daemonId ? entry.daemonId : "";
4126
+ if (daemonId && entry?.upgradeFailure && !(daemonId in daemonUpgradeFailures)) {
4127
+ daemonUpgradeFailures[daemonId] = entry.upgradeFailure;
4128
+ }
4129
+ }
3996
4130
  const staleDaemonBuilds = [];
3997
4131
  const seenStale = /* @__PURE__ */ new Set();
3998
4132
  for (const entry of results) {
@@ -4055,20 +4189,36 @@ async function meshStatus(ctx, args = {}) {
4055
4189
  if (!includeSessions) delete next.sessions;
4056
4190
  }
4057
4191
  if (next.daemonBuild !== void 0) delete next.daemonBuild;
4192
+ if (next.machine && typeof next.machine === "object") {
4193
+ const m = next.machine;
4194
+ next.machine = {
4195
+ daemonId: m.daemonId,
4196
+ displayName: m.displayName,
4197
+ sameMachine: m.sameMachine,
4198
+ seeDaemonMachines: true
4199
+ };
4200
+ }
4201
+ if (next.upgradeFailure !== void 0) delete next.upgradeFailure;
4058
4202
  return next;
4059
4203
  });
4204
+ const pinnedIds = pinnedRepresentativeNodeIds(compacted);
4060
4205
  const noteworthy = compacted.filter((n) => n && typeof n === "object" && isNoteworthyCompactNode(n));
4061
- const ranked = [...noteworthy].sort((a, b) => compactNodeSeverity(b) - compactNodeSeverity(a));
4206
+ const bySeverityDesc = (a, b) => compactNodeSeverity(b) - compactNodeSeverity(a);
4207
+ const isPinned = (n) => pinnedIds.has(String(n?.nodeId));
4208
+ const ranked = [
4209
+ ...compacted.filter((n) => n && typeof n === "object" && isPinned(n)).sort(bySeverityDesc),
4210
+ ...noteworthy.filter((n) => !isPinned(n)).sort(bySeverityDesc)
4211
+ ];
4062
4212
  const detailedIds = /* @__PURE__ */ new Set();
4063
4213
  let detailSpent = 0;
4064
4214
  for (const n of ranked) {
4065
4215
  const cost = JSON.stringify(n).length + 1;
4066
- if (detailedIds.size === 0 || detailSpent + cost <= COMPACT_DETAILED_NODES_BYTE_BUDGET) {
4216
+ if (detailedIds.size === 0 || isPinned(n) || detailSpent + cost <= COMPACT_DETAILED_NODES_BYTE_BUDGET) {
4067
4217
  detailedIds.add(String(n.nodeId));
4068
4218
  detailSpent += cost;
4069
4219
  }
4070
4220
  }
4071
- const stubOrder = [...compacted].filter((n) => n && typeof n === "object").sort((a, b) => compactNodeSeverity(b) - compactNodeSeverity(a));
4221
+ const stubOrder = [...compacted].filter((n) => n && typeof n === "object").sort(bySeverityDesc);
4072
4222
  const keptIds = new Set(detailedIds);
4073
4223
  let totalSpent = detailSpent;
4074
4224
  for (const n of stubOrder) {
@@ -4141,6 +4291,14 @@ async function meshStatus(ctx, args = {}) {
4141
4291
  ...compact && foldedNodesSummary ? { foldedNodes: foldedNodesSummary } : {},
4142
4292
  ...compact && Object.keys(daemonSessions).length > 0 ? { daemonSessions } : {},
4143
4293
  ...Object.keys(daemonBuilds).length > 0 ? { daemonBuilds } : {},
4294
+ // Per-daemon machine identity / provider quota, recorded once per daemonId
4295
+ // instead of repeated on every node sharing that daemon. Both modes.
4296
+ ...Object.keys(daemonMachines).length > 0 ? { daemonMachines } : {},
4297
+ ...Object.keys(daemonQuotas).length > 0 ? { daemonQuotas } : {},
4298
+ ...Object.keys(daemonUpgradeFailures).length > 0 ? {
4299
+ daemonUpgradeFailures,
4300
+ daemonUpgradeFailureWarning: `One or more daemons have a failed-upgrade notice on record: that daemon's LAST upgrade failed and rolled back, so it is still on the PREVIOUS version. An upgrade/restart response only reports "scheduled", never success \u2014 do not read a prior success as proof the version changed. The notice persists until a later upgrade succeeds, so check targetVersion/recordedAt: a target other than the running version is a stale earlier attempt. Full body at noticePath, trace at logPath.`
4301
+ } : {},
4144
4302
  ...staleDaemonBuilds.length > 0 ? { staleDaemonBuilds } : {},
4145
4303
  ...daemonAffectingStaleBuilds.length > 0 ? {
4146
4304
  staleDaemonBuildWarning: "One or more live daemons were built from a commit behind the workspace HEAD with daemon-runtime package changes. Merged refinery/mesh-tool fixes are NOT live on those daemons until they are rebuilt/redeployed and restarted \u2014 a local daemon-core dist rebuild does not update a cloud daemon. Do not assume a just-merged fix is active."
@@ -4271,7 +4429,7 @@ async function meshStatus(ctx, args = {}) {
4271
4429
  }
4272
4430
  } catch {
4273
4431
  }
4274
- return JSON.stringify(response, null, 2);
4432
+ return JSON.stringify(response);
4275
4433
  }
4276
4434
  async function meshListNodes(ctx) {
4277
4435
  await refreshMeshFromDaemon(ctx);