@adhdev/daemon-core 0.9.82-rc.4 → 0.9.82-rc.41

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -1351,13 +1351,43 @@ __export(mesh_work_queue_exports, {
1351
1351
  updateSessionTaskStatus: () => updateSessionTaskStatus,
1352
1352
  updateTaskStatus: () => updateTaskStatus
1353
1353
  });
1354
- import { existsSync as existsSync6, writeFileSync as writeFileSync3, readFileSync as readFileSync4 } from "fs";
1354
+ import { existsSync as existsSync6, writeFileSync as writeFileSync3, readFileSync as readFileSync4, openSync, closeSync, unlinkSync } from "fs";
1355
1355
  import { join as join6 } from "path";
1356
1356
  import { randomUUID as randomUUID5 } from "crypto";
1357
1357
  function getQueuePath(meshId) {
1358
1358
  const safe = meshId.replace(/[^a-zA-Z0-9_-]/g, "_");
1359
1359
  return join6(getLedgerDir(), `${safe}.queue.json`);
1360
1360
  }
1361
+ function getLockPath(meshId) {
1362
+ const safe = meshId.replace(/[^a-zA-Z0-9_-]/g, "_");
1363
+ return join6(getLedgerDir(), `${safe}.queue.lock`);
1364
+ }
1365
+ function withQueueLock(meshId, fn) {
1366
+ const lockPath = getLockPath(meshId);
1367
+ let fd = -1;
1368
+ for (let i = 0; i < 10; i++) {
1369
+ try {
1370
+ fd = openSync(lockPath, "wx");
1371
+ break;
1372
+ } catch {
1373
+ const deadline = Date.now() + 30;
1374
+ while (Date.now() < deadline) {
1375
+ }
1376
+ }
1377
+ }
1378
+ try {
1379
+ return fn();
1380
+ } finally {
1381
+ if (fd !== -1) try {
1382
+ closeSync(fd);
1383
+ } catch {
1384
+ }
1385
+ try {
1386
+ unlinkSync(lockPath);
1387
+ } catch {
1388
+ }
1389
+ }
1390
+ }
1361
1391
  function readQueue(meshId) {
1362
1392
  const path28 = getQueuePath(meshId);
1363
1393
  if (!existsSync6(path28)) return [];
@@ -1373,20 +1403,22 @@ function writeQueue(meshId, queue) {
1373
1403
  writeFileSync3(path28, JSON.stringify(queue, null, 2), "utf-8");
1374
1404
  }
1375
1405
  function enqueueTask(meshId, message, opts) {
1376
- const queue = readQueue(meshId);
1377
- const entry = {
1378
- id: randomUUID5(),
1379
- meshId,
1380
- message,
1381
- status: "pending",
1382
- targetNodeId: opts?.targetNodeId,
1383
- targetSessionId: opts?.targetSessionId,
1384
- createdAt: (/* @__PURE__ */ new Date()).toISOString(),
1385
- updatedAt: (/* @__PURE__ */ new Date()).toISOString()
1386
- };
1387
- queue.push(entry);
1388
- writeQueue(meshId, queue);
1389
- return entry;
1406
+ return withQueueLock(meshId, () => {
1407
+ const queue = readQueue(meshId);
1408
+ const entry = {
1409
+ id: randomUUID5(),
1410
+ meshId,
1411
+ message,
1412
+ status: "pending",
1413
+ targetNodeId: opts?.targetNodeId,
1414
+ targetSessionId: opts?.targetSessionId,
1415
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
1416
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
1417
+ };
1418
+ queue.push(entry);
1419
+ writeQueue(meshId, queue);
1420
+ return entry;
1421
+ });
1390
1422
  }
1391
1423
  function getQueue(meshId, opts) {
1392
1424
  let queue = readQueue(meshId);
@@ -1397,100 +1429,111 @@ function getQueue(meshId, opts) {
1397
1429
  return queue;
1398
1430
  }
1399
1431
  function claimNextTask(meshId, nodeId, sessionId) {
1400
- const queue = readQueue(meshId);
1401
- const hasActiveAssignment = queue.some((q) => q.status === "assigned" && (q.assignedSessionId === sessionId || q.assignedNodeId === nodeId));
1402
- if (hasActiveAssignment) return null;
1403
- let targetIdx = queue.findIndex((q) => q.status === "pending" && q.targetSessionId === sessionId);
1404
- if (targetIdx === -1) {
1405
- targetIdx = queue.findIndex((q) => q.status === "pending" && q.targetNodeId === nodeId && !q.targetSessionId);
1406
- }
1407
- if (targetIdx === -1) {
1408
- targetIdx = queue.findIndex((q) => q.status === "pending" && !q.targetNodeId && !q.targetSessionId);
1409
- }
1410
- if (targetIdx === -1) return null;
1411
- const entry = queue[targetIdx];
1412
- entry.status = "assigned";
1413
- entry.assignedNodeId = nodeId;
1414
- entry.assignedSessionId = sessionId;
1415
- entry.dispatchTimestamp = (/* @__PURE__ */ new Date()).toISOString();
1416
- entry.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
1417
- writeQueue(meshId, queue);
1418
- return entry;
1432
+ return withQueueLock(meshId, () => {
1433
+ const queue = readQueue(meshId);
1434
+ const hasActiveAssignment = queue.some((q) => q.status === "assigned" && (q.assignedSessionId === sessionId || q.assignedNodeId === nodeId));
1435
+ if (hasActiveAssignment) return null;
1436
+ let targetIdx = queue.findIndex((q) => q.status === "pending" && q.targetSessionId === sessionId);
1437
+ if (targetIdx === -1) {
1438
+ targetIdx = queue.findIndex((q) => q.status === "pending" && q.targetNodeId === nodeId && !q.targetSessionId);
1439
+ }
1440
+ if (targetIdx === -1) {
1441
+ targetIdx = queue.findIndex((q) => q.status === "pending" && !q.targetNodeId && !q.targetSessionId);
1442
+ }
1443
+ if (targetIdx === -1) return null;
1444
+ const entry = queue[targetIdx];
1445
+ entry.status = "assigned";
1446
+ entry.assignedNodeId = nodeId;
1447
+ entry.assignedSessionId = sessionId;
1448
+ entry.dispatchTimestamp = (/* @__PURE__ */ new Date()).toISOString();
1449
+ entry.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
1450
+ writeQueue(meshId, queue);
1451
+ return entry;
1452
+ });
1419
1453
  }
1420
1454
  function updateTaskStatus(meshId, taskId, status) {
1421
- const queue = readQueue(meshId);
1422
- const idx = queue.findIndex((q) => q.id === taskId);
1423
- if (idx === -1) return null;
1424
- queue[idx].status = status;
1425
- queue[idx].updatedAt = (/* @__PURE__ */ new Date()).toISOString();
1426
- writeQueue(meshId, queue);
1427
- return queue[idx];
1455
+ return withQueueLock(meshId, () => {
1456
+ const queue = readQueue(meshId);
1457
+ const idx = queue.findIndex((q) => q.id === taskId);
1458
+ if (idx === -1) return null;
1459
+ queue[idx].status = status;
1460
+ queue[idx].updatedAt = (/* @__PURE__ */ new Date()).toISOString();
1461
+ writeQueue(meshId, queue);
1462
+ return queue[idx];
1463
+ });
1428
1464
  }
1429
1465
  function recordTaskAutoLaunch(meshId, taskId, autoLaunch) {
1430
- const queue = readQueue(meshId);
1431
- const idx = queue.findIndex((q) => q.id === taskId);
1432
- if (idx === -1) return null;
1433
- const now = (/* @__PURE__ */ new Date()).toISOString();
1434
- queue[idx].autoLaunch = {
1435
- ...autoLaunch,
1436
- updatedAt: now
1437
- };
1438
- queue[idx].updatedAt = now;
1439
- writeQueue(meshId, queue);
1440
- return queue[idx];
1466
+ return withQueueLock(meshId, () => {
1467
+ const queue = readQueue(meshId);
1468
+ const idx = queue.findIndex((q) => q.id === taskId);
1469
+ if (idx === -1) return null;
1470
+ const now = (/* @__PURE__ */ new Date()).toISOString();
1471
+ queue[idx].autoLaunch = { ...autoLaunch, updatedAt: now };
1472
+ queue[idx].updatedAt = now;
1473
+ writeQueue(meshId, queue);
1474
+ return queue[idx];
1475
+ });
1441
1476
  }
1442
1477
  function cancelTask(meshId, taskId, opts) {
1443
- const queue = readQueue(meshId);
1444
- const idx = queue.findIndex((q) => q.id === taskId);
1445
- if (idx === -1) return null;
1446
- const now = (/* @__PURE__ */ new Date()).toISOString();
1447
- queue[idx].status = "cancelled";
1448
- queue[idx].updatedAt = now;
1449
- queue[idx].cancelledAt = now;
1450
- if (opts?.reason) queue[idx].cancelReason = opts.reason;
1451
- writeQueue(meshId, queue);
1452
- return queue[idx];
1478
+ return withQueueLock(meshId, () => {
1479
+ const queue = readQueue(meshId);
1480
+ const idx = queue.findIndex((q) => q.id === taskId);
1481
+ if (idx === -1) return null;
1482
+ const now = (/* @__PURE__ */ new Date()).toISOString();
1483
+ queue[idx].status = "cancelled";
1484
+ queue[idx].updatedAt = now;
1485
+ queue[idx].cancelledAt = now;
1486
+ if (opts?.reason) queue[idx].cancelReason = opts.reason;
1487
+ writeQueue(meshId, queue);
1488
+ return queue[idx];
1489
+ });
1453
1490
  }
1454
1491
  function requeueTask(meshId, taskId, opts) {
1455
- const queue = readQueue(meshId);
1456
- const idx = queue.findIndex((q) => q.id === taskId);
1457
- if (idx === -1) return null;
1458
- const entry = queue[idx];
1459
- const now = (/* @__PURE__ */ new Date()).toISOString();
1460
- entry.status = "pending";
1461
- delete entry.assignedNodeId;
1462
- delete entry.assignedSessionId;
1463
- delete entry.cancelledAt;
1464
- delete entry.cancelReason;
1465
- if (opts?.clearTargetNode) delete entry.targetNodeId;
1466
- if (typeof opts?.targetNodeId === "string") entry.targetNodeId = opts.targetNodeId;
1467
- if (opts?.clearTargetSession !== false) delete entry.targetSessionId;
1468
- if (typeof opts?.targetSessionId === "string") entry.targetSessionId = opts.targetSessionId;
1469
- entry.updatedAt = now;
1470
- entry.requeuedAt = now;
1471
- entry.requeueCount = (entry.requeueCount || 0) + 1;
1472
- if (opts?.reason) entry.requeueReason = opts.reason;
1473
- writeQueue(meshId, queue);
1474
- return entry;
1475
- }
1476
- function updateSessionTaskStatus(meshId, sessionId, status) {
1477
- const queue = readQueue(meshId);
1478
- let bestIdx = -1;
1479
- let bestTime = 0;
1480
- for (let i = queue.length - 1; i >= 0; i--) {
1481
- if (queue[i].assignedSessionId === sessionId && queue[i].status === "assigned") {
1492
+ return withQueueLock(meshId, () => {
1493
+ const queue = readQueue(meshId);
1494
+ const idx = queue.findIndex((q) => q.id === taskId);
1495
+ if (idx === -1) return null;
1496
+ const entry = queue[idx];
1497
+ const now = (/* @__PURE__ */ new Date()).toISOString();
1498
+ entry.status = "pending";
1499
+ delete entry.assignedNodeId;
1500
+ delete entry.assignedSessionId;
1501
+ delete entry.cancelledAt;
1502
+ delete entry.cancelReason;
1503
+ if (opts?.clearTargetNode) delete entry.targetNodeId;
1504
+ if (typeof opts?.targetNodeId === "string") entry.targetNodeId = opts.targetNodeId;
1505
+ if (opts?.clearTargetSession !== false) delete entry.targetSessionId;
1506
+ if (typeof opts?.targetSessionId === "string") entry.targetSessionId = opts.targetSessionId;
1507
+ entry.updatedAt = now;
1508
+ entry.requeuedAt = now;
1509
+ entry.requeueCount = (entry.requeueCount || 0) + 1;
1510
+ if (opts?.reason) entry.requeueReason = opts.reason;
1511
+ writeQueue(meshId, queue);
1512
+ return entry;
1513
+ });
1514
+ }
1515
+ function updateSessionTaskStatus(meshId, sessionId, status, opts) {
1516
+ return withQueueLock(meshId, () => {
1517
+ const queue = readQueue(meshId);
1518
+ const occurredAtTime = opts?.occurredAt ? new Date(opts.occurredAt).getTime() : Number.NaN;
1519
+ const hasOccurredAt = Number.isFinite(occurredAtTime);
1520
+ let bestIdx = -1;
1521
+ let bestTime = 0;
1522
+ for (let i = queue.length - 1; i >= 0; i--) {
1523
+ if (queue[i].assignedSessionId !== sessionId || queue[i].status !== "assigned") continue;
1482
1524
  const time = new Date(queue[i].dispatchTimestamp || queue[i].updatedAt).getTime();
1525
+ if (hasOccurredAt && Number.isFinite(time) && time > occurredAtTime) continue;
1483
1526
  if (time > bestTime) {
1484
1527
  bestTime = time;
1485
1528
  bestIdx = i;
1486
1529
  }
1487
1530
  }
1488
- }
1489
- if (bestIdx === -1) return null;
1490
- queue[bestIdx].status = status;
1491
- queue[bestIdx].updatedAt = (/* @__PURE__ */ new Date()).toISOString();
1492
- writeQueue(meshId, queue);
1493
- return queue[bestIdx];
1531
+ if (bestIdx === -1) return null;
1532
+ queue[bestIdx].status = status;
1533
+ queue[bestIdx].updatedAt = (/* @__PURE__ */ new Date()).toISOString();
1534
+ writeQueue(meshId, queue);
1535
+ return queue[bestIdx];
1536
+ });
1494
1537
  }
1495
1538
  function getMeshQueueStats(meshId) {
1496
1539
  const queue = readQueue(meshId);
@@ -1890,18 +1933,77 @@ __export(mesh_events_exports, {
1890
1933
  drainPendingMeshCoordinatorEvents: () => drainPendingMeshCoordinatorEvents,
1891
1934
  getPendingMeshCoordinatorEvents: () => getPendingMeshCoordinatorEvents,
1892
1935
  handleMeshForwardEvent: () => handleMeshForwardEvent,
1936
+ queuePendingMeshCoordinatorEvent: () => queuePendingMeshCoordinatorEvent,
1893
1937
  setupMeshEventForwarding: () => setupMeshEventForwarding,
1894
1938
  triggerMeshQueue: () => triggerMeshQueue,
1895
1939
  tryAssignQueueTask: () => tryAssignQueueTask
1896
1940
  });
1897
- function drainPendingMeshCoordinatorEvents() {
1898
- return pendingMeshCoordinatorEvents.splice(0);
1941
+ import { appendFileSync as appendFileSync3, existsSync as existsSync9, readFileSync as readFileSync5, unlinkSync as unlinkSync3 } from "fs";
1942
+ import { join as join9 } from "path";
1943
+ function sweepExpiredRemoteIdleSessions() {
1944
+ const now = Date.now();
1945
+ for (const [key, session] of remoteIdleSessions) {
1946
+ if (session.expiresAt <= now) remoteIdleSessions.delete(key);
1947
+ }
1899
1948
  }
1900
- function getPendingMeshCoordinatorEvents() {
1901
- return pendingMeshCoordinatorEvents.slice();
1949
+ function getPendingEventsPath(meshId) {
1950
+ const safe = meshId.replace(/[^a-zA-Z0-9_-]/g, "_");
1951
+ return join9(getLedgerDir(), `${safe}.pending-events.jsonl`);
1952
+ }
1953
+ function queuePendingMeshCoordinatorEvent(event) {
1954
+ try {
1955
+ appendFileSync3(getPendingEventsPath(event.meshId), JSON.stringify(event) + "\n", "utf-8");
1956
+ return true;
1957
+ } catch (e) {
1958
+ LOG.warn("MeshEvents", `Failed to persist pending coordinator event: ${e?.message || e}`);
1959
+ return false;
1960
+ }
1902
1961
  }
1903
- function clearPendingMeshCoordinatorEvents() {
1904
- pendingMeshCoordinatorEvents.splice(0);
1962
+ function drainPendingMeshCoordinatorEvents(meshId) {
1963
+ if (!meshId) return [];
1964
+ const path28 = getPendingEventsPath(meshId);
1965
+ if (!existsSync9(path28)) return [];
1966
+ try {
1967
+ const raw = readFileSync5(path28, "utf-8");
1968
+ try {
1969
+ unlinkSync3(path28);
1970
+ } catch {
1971
+ }
1972
+ return raw.split("\n").filter(Boolean).flatMap((line) => {
1973
+ try {
1974
+ return [JSON.parse(line)];
1975
+ } catch {
1976
+ return [];
1977
+ }
1978
+ });
1979
+ } catch {
1980
+ return [];
1981
+ }
1982
+ }
1983
+ function getPendingMeshCoordinatorEvents(meshId) {
1984
+ if (!meshId) return [];
1985
+ const path28 = getPendingEventsPath(meshId);
1986
+ if (!existsSync9(path28)) return [];
1987
+ try {
1988
+ const raw = readFileSync5(path28, "utf-8");
1989
+ return raw.split("\n").filter(Boolean).flatMap((line) => {
1990
+ try {
1991
+ return [JSON.parse(line)];
1992
+ } catch {
1993
+ return [];
1994
+ }
1995
+ });
1996
+ } catch {
1997
+ return [];
1998
+ }
1999
+ }
2000
+ function clearPendingMeshCoordinatorEvents(meshId) {
2001
+ if (!meshId) return;
2002
+ const path28 = getPendingEventsPath(meshId);
2003
+ if (existsSync9(path28)) try {
2004
+ unlinkSync3(path28);
2005
+ } catch {
2006
+ }
1905
2007
  }
1906
2008
  function readNonEmptyString(value) {
1907
2009
  return typeof value === "string" && value.trim() ? value.trim() : "";
@@ -1947,6 +2049,38 @@ function shouldSuppressIntentionalCleanupStop(args) {
1947
2049
  if (isIntentionalCleanupStopMetadata(args.metadataEvent)) return true;
1948
2050
  return hasRecentIntentionalCleanupStop(args.meshId, args.sessionId, args.nodeId);
1949
2051
  }
2052
+ function readEventTimestamp(value) {
2053
+ if (typeof value === "number" && Number.isFinite(value)) return value;
2054
+ if (typeof value === "string" && value.trim()) {
2055
+ const numeric = Number(value);
2056
+ if (Number.isFinite(numeric)) return numeric;
2057
+ const parsed = Date.parse(value);
2058
+ if (Number.isFinite(parsed)) return parsed;
2059
+ }
2060
+ return null;
2061
+ }
2062
+ function buildMeshCompletionFingerprint(args) {
2063
+ const timestampPart = Number.isFinite(args.timestamp) ? String(args.timestamp) : readNonEmptyString(args.finalSummary).slice(0, 200);
2064
+ return [
2065
+ args.meshId,
2066
+ args.event,
2067
+ args.sessionId,
2068
+ args.providerType || "",
2069
+ args.providerSessionId || "",
2070
+ timestampPart
2071
+ ].join("::");
2072
+ }
2073
+ function isDuplicateMeshCompletionEvent(args) {
2074
+ const fingerprint = buildMeshCompletionFingerprint(args);
2075
+ if (!fingerprint) return false;
2076
+ const now = Date.now();
2077
+ for (const [key, seenAt] of recentCompletionFingerprints.entries()) {
2078
+ if (now - seenAt > RECENT_COMPLETION_FINGERPRINT_TTL_MS) recentCompletionFingerprints.delete(key);
2079
+ }
2080
+ if (recentCompletionFingerprints.has(fingerprint)) return true;
2081
+ recentCompletionFingerprints.set(fingerprint, now);
2082
+ return false;
2083
+ }
1950
2084
  function tryAssignQueueTask(components, meshId, nodeId, sessionId, providerType) {
1951
2085
  const task = claimNextTask(meshId, nodeId, sessionId);
1952
2086
  if (!task) {
@@ -1965,7 +2099,16 @@ function tryAssignQueueTask(components, meshId, nodeId, sessionId, providerType)
1965
2099
  message: task.message
1966
2100
  }).catch((e) => {
1967
2101
  LOG.error("MeshQueue", `Failed to dispatch task via P2P to remote node ${nodeId}: ${e?.message}`);
1968
- updateTaskStatus(meshId, task.id, "failed");
2102
+ updateTaskStatus(meshId, task.id, "pending");
2103
+ try {
2104
+ appendLedgerEntry(meshId, {
2105
+ kind: "dispatch_failed",
2106
+ nodeId,
2107
+ sessionId,
2108
+ payload: { taskId: task.id, error: e?.message, retryable: true }
2109
+ });
2110
+ } catch {
2111
+ }
1969
2112
  });
1970
2113
  return true;
1971
2114
  }
@@ -2299,18 +2442,36 @@ function injectMeshSystemMessage(components, args) {
2299
2442
  LOG.info("MeshEvents", `Suppressed ${args.event} for intentionally cleanup-stopped session ${eventSessionId || "(unknown session)"}`);
2300
2443
  return { success: true, forwarded: 0, suppressed: true, intentionalCleanupStop: true };
2301
2444
  }
2445
+ const eventTimestamp = readEventTimestamp(args.metadataEvent.timestamp);
2446
+ if (args.event === "agent:generating_completed" && eventSessionId) {
2447
+ const duplicateCompletion = isDuplicateMeshCompletionEvent({
2448
+ meshId: args.meshId,
2449
+ event: args.event,
2450
+ sessionId: eventSessionId,
2451
+ providerType: readNonEmptyString(args.metadataEvent.providerType) || void 0,
2452
+ providerSessionId: readNonEmptyString(args.metadataEvent.providerSessionId) || void 0,
2453
+ timestamp: eventTimestamp,
2454
+ finalSummary: readNonEmptyString(args.metadataEvent.finalSummary) || void 0
2455
+ });
2456
+ if (duplicateCompletion) {
2457
+ LOG.info("MeshEvents", `Suppressed duplicate completion for mesh ${args.meshId} session ${eventSessionId}`);
2458
+ return { success: true, forwarded: 0, suppressed: true, duplicateCompletion: true };
2459
+ }
2460
+ }
2302
2461
  let completedTaskForLedger = null;
2303
2462
  if (args.event === "agent:generating_completed") {
2304
2463
  const sessionId = resolveEventSessionId(args.metadataEvent, args.sourceInstanceId);
2305
2464
  const nodeId = readNonEmptyString(args.nodeId) || readNonEmptyString(args.metadataEvent.meshNodeId);
2306
2465
  const providerType = readNonEmptyString(args.metadataEvent.providerType);
2307
2466
  if (sessionId) {
2308
- const completedTask = updateSessionTaskStatus(args.meshId, sessionId, "completed");
2467
+ const completedTask = updateSessionTaskStatus(args.meshId, sessionId, "completed", {
2468
+ occurredAt: eventTimestamp !== null ? new Date(eventTimestamp).toISOString() : void 0
2469
+ });
2309
2470
  completedTaskForLedger = completedTask ? { id: completedTask.id } : null;
2310
2471
  if (nodeId && providerType) {
2311
- setTimeout(() => {
2472
+ setImmediate(() => {
2312
2473
  tryAssignQueueTask(components, args.meshId, nodeId, sessionId, providerType);
2313
- }, 500);
2474
+ });
2314
2475
  }
2315
2476
  }
2316
2477
  } else if (args.event === "agent:ready") {
@@ -2348,13 +2509,17 @@ function injectMeshSystemMessage(components, args) {
2348
2509
  }
2349
2510
  }
2350
2511
  if (sessionId && nodeId && providerType) {
2351
- remoteIdleSessions.set(`${nodeId}:${sessionId}`, { nodeId, sessionId, providerType });
2352
- setTimeout(() => {
2512
+ sweepExpiredRemoteIdleSessions();
2513
+ remoteIdleSessions.set(`${nodeId}:${sessionId}`, {
2514
+ nodeId,
2515
+ sessionId,
2516
+ providerType,
2517
+ expiresAt: Date.now() + REMOTE_IDLE_SESSION_TTL_MS
2518
+ });
2519
+ setImmediate(() => {
2353
2520
  const assigned = tryAssignQueueTask(components, args.meshId, nodeId, sessionId, providerType);
2354
- if (assigned) {
2355
- remoteIdleSessions.delete(`${nodeId}:${sessionId}`);
2356
- }
2357
- }, 500);
2521
+ if (assigned) remoteIdleSessions.delete(`${nodeId}:${sessionId}`);
2522
+ });
2358
2523
  }
2359
2524
  } else if (args.event === "agent:generating_started") {
2360
2525
  const sessionId = resolveEventSessionId(args.metadataEvent, args.sourceInstanceId);
@@ -2465,17 +2630,18 @@ function injectMeshSystemMessage(components, args) {
2465
2630
  return true;
2466
2631
  });
2467
2632
  if (coordinatorInstances.length === 0) {
2468
- if (pendingMeshCoordinatorEvents.length < MAX_PENDING_EVENTS) {
2469
- pendingMeshCoordinatorEvents.push({
2470
- event: args.event,
2471
- meshId: args.meshId,
2472
- nodeLabel: args.nodeLabel,
2473
- metadataEvent: {
2474
- ...args.metadataEvent,
2475
- ...recoveryContext ? { recoveryContext } : {}
2476
- },
2477
- queuedAt: Date.now()
2478
- });
2633
+ if (queuePendingMeshCoordinatorEvent({
2634
+ event: args.event,
2635
+ meshId: args.meshId,
2636
+ nodeLabel: args.nodeLabel,
2637
+ nodeId: args.nodeId || void 0,
2638
+ workspace: readNonEmptyString(args.metadataEvent.workspace),
2639
+ metadataEvent: {
2640
+ ...args.metadataEvent,
2641
+ ...recoveryContext ? { recoveryContext } : {}
2642
+ },
2643
+ queuedAt: Date.now()
2644
+ })) {
2479
2645
  LOG.info("MeshEvents", `Queued ${args.event} for MCP coordinator (mesh ${args.meshId})`);
2480
2646
  }
2481
2647
  return { success: true, forwarded: 0 };
@@ -2514,6 +2680,7 @@ function handleMeshForwardEvent(components, payload) {
2514
2680
  providerType: readNonEmptyString(payload.providerType),
2515
2681
  providerSessionId: readNonEmptyString(payload.providerSessionId),
2516
2682
  finalSummary: readNonEmptyString(payload.finalSummary) || readNonEmptyString(payload.summary),
2683
+ ...payload.timestamp !== void 0 ? { timestamp: payload.timestamp } : {},
2517
2684
  intentional: payload.intentional === true,
2518
2685
  intentionalStop: payload.intentionalStop === true,
2519
2686
  operatorCleanup: payload.operatorCleanup === true,
@@ -2556,7 +2723,7 @@ function setupMeshEventForwarding(components) {
2556
2723
  });
2557
2724
  });
2558
2725
  }
2559
- var remoteIdleSessions, MAX_PENDING_EVENTS, pendingMeshCoordinatorEvents, MESH_COORDINATOR_EVENTS, EVENT_TO_LEDGER_KIND, INTENTIONAL_CLEANUP_STOP_SUPPRESSION_MS, autoLaunchInProgress, autoLaunchCooldownUntil, AUTO_LAUNCH_COOLDOWN_MS;
2726
+ var REMOTE_IDLE_SESSION_TTL_MS, remoteIdleSessions, MESH_COORDINATOR_EVENTS, EVENT_TO_LEDGER_KIND, INTENTIONAL_CLEANUP_STOP_SUPPRESSION_MS, RECENT_COMPLETION_FINGERPRINT_TTL_MS, recentCompletionFingerprints, autoLaunchInProgress, autoLaunchCooldownUntil, AUTO_LAUNCH_COOLDOWN_MS;
2560
2727
  var init_mesh_events = __esm({
2561
2728
  "src/mesh/mesh-events.ts"() {
2562
2729
  "use strict";
@@ -2566,9 +2733,8 @@ var init_mesh_events = __esm({
2566
2733
  init_logger();
2567
2734
  init_mesh_ledger();
2568
2735
  init_mesh_work_queue();
2736
+ REMOTE_IDLE_SESSION_TTL_MS = 5 * 60 * 1e3;
2569
2737
  remoteIdleSessions = /* @__PURE__ */ new Map();
2570
- MAX_PENDING_EVENTS = 50;
2571
- pendingMeshCoordinatorEvents = [];
2572
2738
  MESH_COORDINATOR_EVENTS = /* @__PURE__ */ new Set([
2573
2739
  "agent:generating_started",
2574
2740
  "agent:generating_completed",
@@ -2584,6 +2750,8 @@ var init_mesh_events = __esm({
2584
2750
  "monitor:long_generating": "task_stalled"
2585
2751
  };
2586
2752
  INTENTIONAL_CLEANUP_STOP_SUPPRESSION_MS = 30 * 60 * 1e3;
2753
+ RECENT_COMPLETION_FINGERPRINT_TTL_MS = 10 * 60 * 1e3;
2754
+ recentCompletionFingerprints = /* @__PURE__ */ new Map();
2587
2755
  autoLaunchInProgress = /* @__PURE__ */ new Set();
2588
2756
  autoLaunchCooldownUntil = /* @__PURE__ */ new Map();
2589
2757
  AUTO_LAUNCH_COOLDOWN_MS = 5e3;
@@ -5676,8 +5844,14 @@ async function getGitRepoStatus(workspace, options = {}) {
5676
5844
  const includeSubmodules = options.includeSubmodules !== false;
5677
5845
  try {
5678
5846
  const repo = await resolveGitRepository(workspace, options);
5679
- const statusOutput = await runGit(repo, ["status", "--porcelain=v2", "--branch"], options);
5680
- const parsed = parsePorcelainV2Status(statusOutput.stdout);
5847
+ let parsed = await readPorcelainStatus(repo, options);
5848
+ let upstreamProbe = getInitialUpstreamProbe(parsed);
5849
+ if (options.refreshUpstream) {
5850
+ upstreamProbe = await refreshTrackedUpstream(repo, parsed, options);
5851
+ if (upstreamProbe.upstreamStatus === "fresh") {
5852
+ parsed = await readPorcelainStatus(repo, options);
5853
+ }
5854
+ }
5681
5855
  const head = await readHead(repo, options);
5682
5856
  const stashCount = await readStashCount(repo, options);
5683
5857
  let submodules;
@@ -5692,6 +5866,9 @@ async function getGitRepoStatus(workspace, options = {}) {
5692
5866
  headCommit: head.commit,
5693
5867
  headMessage: head.message,
5694
5868
  upstream: parsed.upstream,
5869
+ upstreamStatus: parsed.upstream ? upstreamProbe.upstreamStatus : "no_upstream",
5870
+ upstreamFetchedAt: upstreamProbe.upstreamFetchedAt,
5871
+ upstreamFetchError: upstreamProbe.upstreamFetchError,
5695
5872
  ahead: parsed.ahead,
5696
5873
  behind: parsed.behind,
5697
5874
  staged: parsed.staged,
@@ -5716,6 +5893,60 @@ async function getGitRepoStatus(workspace, options = {}) {
5716
5893
  );
5717
5894
  }
5718
5895
  }
5896
+ async function readPorcelainStatus(repo, options) {
5897
+ const statusOutput = await runGit(repo, ["status", "--porcelain=v2", "--branch"], options);
5898
+ return parsePorcelainV2Status(statusOutput.stdout);
5899
+ }
5900
+ function getInitialUpstreamProbe(parsed) {
5901
+ return {
5902
+ upstreamStatus: parsed.upstream ? "unchecked" : "no_upstream"
5903
+ };
5904
+ }
5905
+ async function refreshTrackedUpstream(repo, parsed, options) {
5906
+ if (!parsed.upstream || !parsed.branch) {
5907
+ return { upstreamStatus: "no_upstream" };
5908
+ }
5909
+ const remoteName = await readBranchRemote(repo, parsed.branch, options) ?? inferRemoteName(parsed.upstream);
5910
+ if (!remoteName) {
5911
+ return {
5912
+ upstreamStatus: "stale",
5913
+ upstreamFetchError: `Unable to resolve remote for upstream '${parsed.upstream}'`
5914
+ };
5915
+ }
5916
+ try {
5917
+ await runGit(repo, ["fetch", "--quiet", "--prune", "--no-tags", remoteName], options);
5918
+ return {
5919
+ upstreamStatus: "fresh",
5920
+ upstreamFetchedAt: Date.now()
5921
+ };
5922
+ } catch (error) {
5923
+ return {
5924
+ upstreamStatus: "stale",
5925
+ upstreamFetchError: formatGitError(error)
5926
+ };
5927
+ }
5928
+ }
5929
+ async function readBranchRemote(repo, branch, options) {
5930
+ try {
5931
+ const result = await runGit(repo, ["config", "--get", `branch.${branch}.remote`], options);
5932
+ return result.stdout.trim() || null;
5933
+ } catch {
5934
+ return null;
5935
+ }
5936
+ }
5937
+ function inferRemoteName(upstream) {
5938
+ const [remoteName] = upstream.split("/");
5939
+ return remoteName?.trim() || null;
5940
+ }
5941
+ function formatGitError(error) {
5942
+ if (error instanceof GitCommandError) {
5943
+ return error.stderr || error.message;
5944
+ }
5945
+ if (error instanceof Error) {
5946
+ return error.message;
5947
+ }
5948
+ return String(error);
5949
+ }
5719
5950
  function parsePorcelainV2Status(output) {
5720
5951
  const parsed = {
5721
5952
  branch: null,
@@ -5810,6 +6041,7 @@ function emptyStatus(workspace, lastCheckedAt, error) {
5810
6041
  headCommit: null,
5811
6042
  headMessage: null,
5812
6043
  upstream: null,
6044
+ upstreamStatus: "unavailable",
5813
6045
  ahead: 0,
5814
6046
  behind: 0,
5815
6047
  staged: 0,
@@ -6090,6 +6322,9 @@ function createGitCompactSummary(status, diffSummary) {
6090
6322
  isGitRepo: status.isGitRepo,
6091
6323
  repoRoot: status.repoRoot,
6092
6324
  branch: status.branch,
6325
+ upstreamStatus: status.upstreamStatus,
6326
+ upstreamFetchedAt: status.upstreamFetchedAt,
6327
+ upstreamFetchError: status.upstreamFetchError,
6093
6328
  dirty: status.staged > 0 || status.modified > 0 || status.untracked > 0 || status.deleted > 0 || status.renamed > 0 || conflictCount > 0 || changedFiles > 0,
6094
6329
  changedFiles,
6095
6330
  ahead: status.ahead,
@@ -6434,7 +6669,7 @@ var defaultSnapshotStore = createGitSnapshotStore({
6434
6669
  });
6435
6670
  function createDefaultGitCommandServices() {
6436
6671
  return {
6437
- getStatus: ({ workspace }) => getGitRepoStatus(workspace),
6672
+ getStatus: ({ workspace, refreshUpstream }) => getGitRepoStatus(workspace, { refreshUpstream }),
6438
6673
  getDiffSummary: ({ workspace }) => getGitDiffSummary(workspace),
6439
6674
  getDiffFile: ({ workspace, path: filePath }) => getGitFileDiff(workspace, filePath),
6440
6675
  createSnapshot: ({ workspace, reason, sessionId, turnId }) => defaultSnapshotStore.create({
@@ -6520,7 +6755,7 @@ async function handleGitCommand(command, args, services = defaultGitCommandServi
6520
6755
  switch (command) {
6521
6756
  case "git_status": {
6522
6757
  if (!services.getStatus) return serviceNotImplemented(command);
6523
- const status = await runService(() => services.getStatus({ workspace }));
6758
+ const status = await runService(() => services.getStatus({ workspace, refreshUpstream: optionalBoolean(args?.refreshUpstream) }));
6524
6759
  return "success" in status ? status : { success: true, status };
6525
6760
  }
6526
6761
  case "git_diff_summary": {
@@ -7559,8 +7794,8 @@ var P2pRelayFailureError = class extends Error {
7559
7794
 
7560
7795
  // src/config/state-store.ts
7561
7796
  init_config();
7562
- import { existsSync as existsSync9, readFileSync as readFileSync5, writeFileSync as writeFileSync4 } from "fs";
7563
- import { join as join9 } from "path";
7797
+ import { existsSync as existsSync10, readFileSync as readFileSync6, writeFileSync as writeFileSync4 } from "fs";
7798
+ import { join as join10 } from "path";
7564
7799
  var DEFAULT_STATE = {
7565
7800
  recentActivity: [],
7566
7801
  savedProviderSessions: [],
@@ -7573,7 +7808,7 @@ function isPlainObject2(value) {
7573
7808
  return !!value && typeof value === "object" && !Array.isArray(value);
7574
7809
  }
7575
7810
  function getStatePath() {
7576
- return join9(getConfigDir(), "state.json");
7811
+ return join10(getConfigDir(), "state.json");
7577
7812
  }
7578
7813
  function normalizeState(raw) {
7579
7814
  const parsed = isPlainObject2(raw) ? raw : {};
@@ -7609,11 +7844,11 @@ function normalizeState(raw) {
7609
7844
  }
7610
7845
  function loadState() {
7611
7846
  const statePath = getStatePath();
7612
- if (!existsSync9(statePath)) {
7847
+ if (!existsSync10(statePath)) {
7613
7848
  return { ...DEFAULT_STATE };
7614
7849
  }
7615
7850
  try {
7616
- const raw = readFileSync5(statePath, "utf-8");
7851
+ const raw = readFileSync6(statePath, "utf-8");
7617
7852
  return normalizeState(JSON.parse(raw));
7618
7853
  } catch {
7619
7854
  return { ...DEFAULT_STATE };
@@ -7630,7 +7865,7 @@ function resetState() {
7630
7865
 
7631
7866
  // src/detection/ide-detector.ts
7632
7867
  import { execSync } from "child_process";
7633
- import { existsSync as existsSync10 } from "fs";
7868
+ import { existsSync as existsSync11 } from "fs";
7634
7869
  import { platform as platform2, homedir as homedir5 } from "os";
7635
7870
  import * as path10 from "path";
7636
7871
  var BUILTIN_IDE_DEFINITIONS = [];
@@ -7654,7 +7889,7 @@ function findCliCommand(command) {
7654
7889
  if (path10.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~")) {
7655
7890
  const candidate = trimmed.startsWith("~") ? path10.join(homedir5(), trimmed.slice(1)) : trimmed;
7656
7891
  const resolved = path10.isAbsolute(candidate) ? candidate : path10.resolve(candidate);
7657
- return existsSync10(resolved) ? resolved : null;
7892
+ return existsSync11(resolved) ? resolved : null;
7658
7893
  }
7659
7894
  try {
7660
7895
  const result = execSync(
@@ -7685,9 +7920,9 @@ function checkPathExists(paths) {
7685
7920
  if (normalized.includes("*")) {
7686
7921
  const username = home.split(/[\\/]/).pop() || "";
7687
7922
  const resolved = normalized.replace("*", username);
7688
- if (existsSync10(resolved)) return resolved;
7923
+ if (existsSync11(resolved)) return resolved;
7689
7924
  } else {
7690
- if (existsSync10(normalized)) return normalized;
7925
+ if (existsSync11(normalized)) return normalized;
7691
7926
  }
7692
7927
  }
7693
7928
  return null;
@@ -7701,7 +7936,7 @@ async function detectIDEs(providerLoader) {
7701
7936
  let resolvedCli = cliPath;
7702
7937
  if (!resolvedCli && appPath && os22 === "darwin") {
7703
7938
  const bundledCli = `${appPath}/Contents/Resources/app/bin/${def.cli}`;
7704
- if (existsSync10(bundledCli)) resolvedCli = bundledCli;
7939
+ if (existsSync11(bundledCli)) resolvedCli = bundledCli;
7705
7940
  }
7706
7941
  if (!resolvedCli && appPath && os22 === "win32") {
7707
7942
  const { dirname: dirname9 } = await import("path");
@@ -7714,7 +7949,7 @@ async function detectIDEs(providerLoader) {
7714
7949
  `${appDir}\\\\resources\\\\app\\\\bin\\\\${def.cli}.cmd`
7715
7950
  ];
7716
7951
  for (const c of candidates) {
7717
- if (existsSync10(c)) {
7952
+ if (existsSync11(c)) {
7718
7953
  resolvedCli = c;
7719
7954
  break;
7720
7955
  }
@@ -9606,7 +9841,8 @@ var StatusMonitor = class {
9606
9841
  };
9607
9842
 
9608
9843
  // src/providers/chat-message-normalization.ts
9609
- function extractFinalSummaryFromMessages(messages, maxChars = 500) {
9844
+ var DEFAULT_FINAL_SUMMARY_MAX_CHARS = 4e3;
9845
+ function extractFinalSummaryFromMessages(messages, maxChars = DEFAULT_FINAL_SUMMARY_MAX_CHARS) {
9610
9846
  if (!Array.isArray(messages) || messages.length === 0) return "";
9611
9847
  for (let i = messages.length - 1; i >= 0; i--) {
9612
9848
  const msg = messages[i];
@@ -16869,7 +17105,7 @@ init_config();
16869
17105
  import * as os13 from "os";
16870
17106
  import * as path18 from "path";
16871
17107
  import * as crypto4 from "crypto";
16872
- import { existsSync as existsSync14, mkdirSync as mkdirSync9, writeFileSync as writeFileSync9 } from "fs";
17108
+ import { existsSync as existsSync15, mkdirSync as mkdirSync9, writeFileSync as writeFileSync9 } from "fs";
16873
17109
  import { execFileSync } from "child_process";
16874
17110
  import chalk from "chalk";
16875
17111
 
@@ -19343,7 +19579,7 @@ function commandExists(command) {
19343
19579
  const trimmed = command.trim();
19344
19580
  if (!trimmed) return false;
19345
19581
  if (isExplicitCommand(trimmed)) {
19346
- return existsSync14(expandExecutable(trimmed));
19582
+ return existsSync15(expandExecutable(trimmed));
19347
19583
  }
19348
19584
  try {
19349
19585
  execFileSync(process.platform === "win32" ? "where" : "which", [trimmed], {
@@ -22612,10 +22848,10 @@ import * as yaml from "js-yaml";
22612
22848
  // src/commands/mesh-coordinator.ts
22613
22849
  import { execFileSync as execFileSync2 } from "child_process";
22614
22850
  import { createHash as createHash2 } from "crypto";
22615
- import { existsSync as existsSync17, readdirSync as readdirSync7, realpathSync as realpathSync2 } from "fs";
22851
+ import { existsSync as existsSync18, readdirSync as readdirSync7, realpathSync as realpathSync2 } from "fs";
22616
22852
  import { createRequire as createRequire2 } from "module";
22617
22853
  import * as os17 from "os";
22618
- import { dirname as dirname4, isAbsolute as isAbsolute11, join as join20, resolve as resolve13 } from "path";
22854
+ import { dirname as dirname4, isAbsolute as isAbsolute11, join as join21, resolve as resolve13 } from "path";
22619
22855
  var DEFAULT_SERVER_NAME = "adhdev-mesh";
22620
22856
  var DEFAULT_ADHDEV_MCP_COMMAND = "adhdev-mcp";
22621
22857
  var HERMES_CLI_TYPE = "hermes-cli";
@@ -22638,7 +22874,7 @@ function resolveHermesMeshCoordinatorSetup(options) {
22638
22874
  reason: "Could not resolve the ADHDev MCP server entrypoint and a Node runtime with WebSocket support for daemon IPC mode"
22639
22875
  };
22640
22876
  }
22641
- const configPath = join20(resolveHermesCoordinatorHome(options.meshId, options.workspace), "config.yaml");
22877
+ const configPath = join21(resolveHermesCoordinatorHome(options.meshId, options.workspace), "config.yaml");
22642
22878
  if (!configPath.trim()) {
22643
22879
  return createHermesManualMeshCoordinatorSetup(options.meshId, options.workspace);
22644
22880
  }
@@ -22759,14 +22995,14 @@ function resolveHermesCoordinatorHome(meshId, workspace) {
22759
22995
  const key = `${meshId || "mesh"}
22760
22996
  ${resolve13(workspace || os17.tmpdir())}`;
22761
22997
  const hash = createHash2("sha256").update(key).digest("hex").slice(0, 16);
22762
- return join20(os17.tmpdir(), `adhdev-hermes-mesh-coordinator-${hash}`);
22998
+ return join21(os17.tmpdir(), `adhdev-hermes-mesh-coordinator-${hash}`);
22763
22999
  }
22764
23000
  function resolveMcpConfigPath(configPath, workspace) {
22765
23001
  const trimmed = configPath.trim();
22766
23002
  if (trimmed === "~") return os17.homedir();
22767
- if (trimmed.startsWith("~/")) return join20(os17.homedir(), trimmed.slice(2));
23003
+ if (trimmed.startsWith("~/")) return join21(os17.homedir(), trimmed.slice(2));
22768
23004
  if (isAbsolute11(trimmed)) return trimmed;
22769
- return join20(workspace, trimmed);
23005
+ return join21(workspace, trimmed);
22770
23006
  }
22771
23007
  function resolveAdhdevMcpServerLaunch(options) {
22772
23008
  const entryPath = resolveAdhdevMcpEntryPath(options.adhdevMcpEntryPath);
@@ -22822,15 +23058,15 @@ function addNodeCandidatesFromPath(pathValue, addCandidate) {
22822
23058
  for (const entry of (pathValue || "").split(":")) {
22823
23059
  const dir = entry.trim();
22824
23060
  if (!dir) continue;
22825
- addCandidate(join20(dir, "node"));
23061
+ addCandidate(join21(dir, "node"));
22826
23062
  }
22827
23063
  }
22828
23064
  function addNodeCandidatesFromNvm(homeDir, addCandidate) {
22829
- const versionsDir = join20(homeDir, ".nvm", "versions", "node");
23065
+ const versionsDir = join21(homeDir, ".nvm", "versions", "node");
22830
23066
  try {
22831
23067
  const versionDirs = readdirSync7(versionsDir, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name).sort(compareNodeVersionNamesDescending);
22832
23068
  for (const versionDir of versionDirs) {
22833
- addCandidate(join20(versionsDir, versionDir, "bin", "node"));
23069
+ addCandidate(join21(versionsDir, versionDir, "bin", "node"));
22834
23070
  }
22835
23071
  } catch {
22836
23072
  }
@@ -22881,7 +23117,7 @@ function resolveAdhdevMcpEntryPath(explicitPath) {
22881
23117
  if (normalized) return normalized;
22882
23118
  }
22883
23119
  try {
22884
- const requireBase = process.argv[1] ? normalizeExistingPath(process.argv[1]) || process.argv[1] : join20(process.cwd(), "adhdev-daemon.js");
23120
+ const requireBase = process.argv[1] ? normalizeExistingPath(process.argv[1]) || process.argv[1] : join21(process.cwd(), "adhdev-daemon.js");
22885
23121
  const req = createRequire2(requireBase);
22886
23122
  const resolvedModule = req.resolve("@adhdev/mcp-server");
22887
23123
  return normalizeExistingPath(resolvedModule) || resolvedModule;
@@ -22891,7 +23127,7 @@ function resolveAdhdevMcpEntryPath(explicitPath) {
22891
23127
  }
22892
23128
  function normalizeExistingPath(filePath) {
22893
23129
  try {
22894
- if (!existsSync17(filePath)) return null;
23130
+ if (!existsSync18(filePath)) return null;
22895
23131
  return realpathSync2.native(filePath);
22896
23132
  } catch {
22897
23133
  return null;
@@ -23603,55 +23839,45 @@ function readBooleanValue(...values) {
23603
23839
  }
23604
23840
  return void 0;
23605
23841
  }
23606
- function buildCachedInlineMeshGitStatus(node) {
23607
- const cachedStatus = readObjectRecord(node?.cachedStatus);
23608
- const cachedGit = readObjectRecord(cachedStatus.git);
23609
- if (Object.keys(cachedGit).length) {
23610
- const conflictFiles2 = Array.isArray(cachedGit.conflictFiles) ? cachedGit.conflictFiles.filter((value) => typeof value === "string") : [];
23611
- const conflictCount2 = readNumberValue(cachedGit.conflicts) ?? conflictFiles2.length;
23612
- const hasConflicts2 = readBooleanValue(cachedGit.hasConflicts) ?? conflictCount2 > 0;
23613
- const isGitRepo2 = readBooleanValue(cachedGit.isGitRepo);
23614
- if (isGitRepo2 !== void 0) {
23615
- return {
23616
- workspace: readStringValue(cachedGit.workspace, node?.workspace) || "",
23617
- repoRoot: readStringValue(cachedGit.repoRoot, node?.repoRoot, node?.workspace) || null,
23618
- isGitRepo: isGitRepo2,
23619
- branch: readStringValue(cachedGit.branch) ?? null,
23620
- headCommit: readStringValue(cachedGit.headCommit) ?? null,
23621
- headMessage: readStringValue(cachedGit.headMessage) ?? null,
23622
- upstream: readStringValue(cachedGit.upstream) ?? null,
23623
- ahead: readNumberValue(cachedGit.ahead) ?? 0,
23624
- behind: readNumberValue(cachedGit.behind) ?? 0,
23625
- staged: readNumberValue(cachedGit.staged) ?? 0,
23626
- modified: readNumberValue(cachedGit.modified) ?? 0,
23627
- untracked: readNumberValue(cachedGit.untracked) ?? 0,
23628
- deleted: readNumberValue(cachedGit.deleted) ?? 0,
23629
- renamed: readNumberValue(cachedGit.renamed) ?? 0,
23630
- hasConflicts: hasConflicts2,
23631
- conflictFiles: conflictFiles2,
23632
- stashCount: readNumberValue(cachedGit.stashCount) ?? 0,
23633
- lastCheckedAt: readNumberValue(cachedGit.lastCheckedAt) ?? Date.now()
23634
- };
23635
- }
23636
- }
23637
- const rawGit = readObjectRecord(node?.lastGit ?? node?.last_git);
23638
- const gitResult = readObjectRecord(rawGit.result);
23639
- const directStatus = readObjectRecord(rawGit.status);
23640
- const nestedStatus = readObjectRecord(gitResult.status);
23641
- const rawProbe = readObjectRecord(node?.lastProbe ?? node?.last_probe);
23642
- const probeGit = readObjectRecord(rawProbe.git);
23643
- const probeGitResult = readObjectRecord(probeGit.result);
23644
- const probeDirectStatus = readObjectRecord(probeGit.status);
23645
- const probeNestedStatus = readObjectRecord(probeGitResult.status);
23646
- const status = Object.keys(directStatus).length ? directStatus : Object.keys(nestedStatus).length ? nestedStatus : Object.keys(probeDirectStatus).length ? probeDirectStatus : Object.keys(probeNestedStatus).length ? probeNestedStatus : {};
23842
+ function joinRepoPath(root, relativePath) {
23843
+ const normalizedRoot = typeof root === "string" ? root.trim().replace(/[\\/]+$/, "") : "";
23844
+ const normalizedPath = typeof relativePath === "string" ? relativePath.trim() : "";
23845
+ if (!normalizedPath) return void 0;
23846
+ if (/^(?:[A-Za-z]:[\\/]|\/)/.test(normalizedPath)) return normalizedPath;
23847
+ if (!normalizedRoot) return void 0;
23848
+ return `${normalizedRoot}/${normalizedPath.replace(/^[\\/]+/, "")}`;
23849
+ }
23850
+ function readGitSubmodules(value, parentRepoRoot) {
23851
+ if (!Array.isArray(value)) return void 0;
23852
+ const submodules = value.map((entry) => {
23853
+ const submodule = readObjectRecord(entry);
23854
+ const path28 = readStringValue(submodule.path);
23855
+ const commit = readStringValue(submodule.commit);
23856
+ const repoPath = readStringValue(submodule.repoPath, submodule.repo_root) ?? joinRepoPath(parentRepoRoot, path28);
23857
+ if (!path28 || !commit || !repoPath) return null;
23858
+ return {
23859
+ path: path28,
23860
+ commit,
23861
+ repoPath,
23862
+ dirty: readBooleanValue(submodule.dirty) ?? false,
23863
+ outOfSync: readBooleanValue(submodule.outOfSync, submodule.out_of_sync) ?? false,
23864
+ lastCheckedAt: readNumberValue(submodule.lastCheckedAt, submodule.last_checked_at) ?? Date.now(),
23865
+ ...readStringValue(submodule.error) ? { error: readStringValue(submodule.error) } : {}
23866
+ };
23867
+ }).filter((entry) => entry !== null);
23868
+ return submodules.length > 0 ? submodules : void 0;
23869
+ }
23870
+ function normalizeInlineMeshGitStatus(status, node, options) {
23647
23871
  const isGitRepo = readBooleanValue(status.isGitRepo);
23648
23872
  if (!Object.keys(status).length || isGitRepo === void 0) return void 0;
23649
23873
  const conflictFiles = Array.isArray(status.conflictFiles) ? status.conflictFiles.filter((value) => typeof value === "string") : [];
23650
23874
  const conflictCount = readNumberValue(status.conflicts) ?? conflictFiles.length;
23651
23875
  const hasConflicts = readBooleanValue(status.hasConflicts) ?? conflictCount > 0;
23876
+ const repoRoot = readStringValue(status.repoRoot, status.repo_root, node?.repoRoot, node?.repo_root, status.workspace, node?.workspace) || void 0;
23877
+ const submodules = readGitSubmodules(status.submodules, repoRoot);
23652
23878
  return {
23653
23879
  workspace: readStringValue(status.workspace, node?.workspace) || "",
23654
- repoRoot: readStringValue(status.repoRoot, node?.repoRoot, node?.workspace) || null,
23880
+ repoRoot: repoRoot ?? null,
23655
23881
  isGitRepo,
23656
23882
  branch: readStringValue(status.branch) ?? null,
23657
23883
  headCommit: readStringValue(status.headCommit) ?? null,
@@ -23667,29 +23893,412 @@ function buildCachedInlineMeshGitStatus(node) {
23667
23893
  hasConflicts,
23668
23894
  conflictFiles,
23669
23895
  stashCount: readNumberValue(status.stashCount) ?? 0,
23670
- lastCheckedAt: Date.now()
23896
+ lastCheckedAt: options?.lastCheckedAt ?? readNumberValue(status.lastCheckedAt) ?? Date.now(),
23897
+ ...submodules ? { submodules } : {}
23671
23898
  };
23672
23899
  }
23673
- function applyCachedInlineMeshNodeStatus(status, node) {
23900
+ function buildInlineMeshTransitGitStatus(node) {
23901
+ const rawGit = readObjectRecord(node?.lastGit ?? node?.last_git);
23902
+ const gitResult = readObjectRecord(rawGit.result);
23903
+ const directStatus = readObjectRecord(rawGit.status);
23904
+ const nestedStatus = readObjectRecord(gitResult.status);
23905
+ const rawProbe = readObjectRecord(node?.lastProbe ?? node?.last_probe);
23906
+ const probeGit = readObjectRecord(rawProbe.git);
23907
+ const probeGitResult = readObjectRecord(probeGit.result);
23908
+ const probeDirectStatus = readObjectRecord(probeGit.status);
23909
+ const probeNestedStatus = readObjectRecord(probeGitResult.status);
23910
+ const status = Object.keys(directStatus).length ? directStatus : Object.keys(nestedStatus).length ? nestedStatus : Object.keys(probeDirectStatus).length ? probeDirectStatus : Object.keys(probeNestedStatus).length ? probeNestedStatus : {};
23911
+ return normalizeInlineMeshGitStatus(status, node, { lastCheckedAt: Date.now() });
23912
+ }
23913
+ function recordInlineMeshDirectGitTruth(node, git, source) {
23914
+ if (!node || typeof node !== "object" || Array.isArray(node)) return;
23915
+ const checkedAt = readNumberValue(git.lastCheckedAt) ?? Date.now();
23916
+ const updatedAt = new Date(checkedAt).toISOString();
23917
+ const nextGit = {
23918
+ ...git,
23919
+ lastCheckedAt: checkedAt
23920
+ };
23921
+ node.lastGit = {
23922
+ source,
23923
+ checkedAt,
23924
+ status: nextGit
23925
+ };
23926
+ node.last_git = node.lastGit;
23927
+ node.machineStatus = "online";
23928
+ node.updatedAt = updatedAt;
23929
+ node.lastSeenAt = updatedAt;
23930
+ const repoRoot = readStringValue(nextGit.repoRoot);
23931
+ if (repoRoot && !readStringValue(node.repoRoot)) node.repoRoot = repoRoot;
23932
+ }
23933
+ function buildCachedInlineMeshGitStatus(node) {
23934
+ const liveGit = buildInlineMeshTransitGitStatus(node);
23935
+ if (liveGit) return liveGit;
23674
23936
  const cachedStatus = readObjectRecord(node?.cachedStatus);
23675
- const git = buildCachedInlineMeshGitStatus(node);
23676
- const error = readStringValue(cachedStatus.error, node?.error);
23677
- const health = readStringValue(cachedStatus.health, node?.health);
23937
+ const cachedGit = readObjectRecord(cachedStatus.git);
23938
+ if (!Object.keys(cachedGit).length) return void 0;
23939
+ return normalizeInlineMeshGitStatus(cachedGit, node);
23940
+ }
23941
+ function shouldDiscardCachedInlineMeshStatus(node) {
23942
+ const cachedStatus = readObjectRecord(node?.cachedStatus);
23943
+ if (!Object.keys(cachedStatus).length) return false;
23944
+ const cachedGit = readObjectRecord(cachedStatus.git);
23945
+ const workspaceError = readStringValue(cachedStatus.error, node?.error);
23946
+ if (workspaceError && /workspace must be an existing directory/i.test(workspaceError)) return true;
23947
+ const isGitRepo = readBooleanValue(cachedGit.isGitRepo);
23948
+ const branch = readStringValue(cachedGit.branch);
23949
+ const headCommit = readStringValue(cachedGit.headCommit);
23950
+ return isGitRepo === false && !branch && !headCommit;
23951
+ }
23952
+ function stripInlineMeshTransientNodeState(node) {
23953
+ if (!node || typeof node !== "object" || Array.isArray(node)) return node;
23954
+ const {
23955
+ cachedStatus,
23956
+ lastGit: _lastGit,
23957
+ last_git: _lastGitLegacy,
23958
+ lastProbe: _lastProbe,
23959
+ last_probe: _lastProbeLegacy,
23960
+ error: _error,
23961
+ health: _health,
23962
+ machineStatus: _machineStatus,
23963
+ lastSeenAt: _lastSeenAt,
23964
+ last_seen_at: _lastSeenAtLegacy,
23965
+ updatedAt: _updatedAt,
23966
+ updated_at: _updatedAtLegacy,
23967
+ activeSession: _activeSession,
23968
+ active_session: _activeSessionLegacy,
23969
+ activeSessionId: _activeSessionId,
23970
+ active_session_id: _activeSessionIdLegacy,
23971
+ sessionId: _sessionId,
23972
+ session_id: _sessionIdLegacy,
23973
+ providerType: _providerType,
23974
+ provider_type: _providerTypeLegacy,
23975
+ ...rest
23976
+ } = node;
23977
+ if (cachedStatus && !shouldDiscardCachedInlineMeshStatus(node)) {
23978
+ return { ...rest, cachedStatus };
23979
+ }
23980
+ return rest;
23981
+ }
23982
+ function hasInlineMeshTransientNodeState(node) {
23983
+ if (!node || typeof node !== "object" || Array.isArray(node)) return false;
23984
+ return "cachedStatus" in node || "lastGit" in node || "last_git" in node || "lastProbe" in node || "last_probe" in node || "error" in node || "health" in node || "machineStatus" in node || "lastSeenAt" in node || "last_seen_at" in node || "updatedAt" in node || "updated_at" in node || "activeSession" in node || "active_session" in node || "activeSessionId" in node || "active_session_id" in node || "sessionId" in node || "session_id" in node || "providerType" in node || "provider_type" in node;
23985
+ }
23986
+ function inlineMeshCarriesTransientNodeTruth(inlineMesh) {
23987
+ if (!inlineMesh || typeof inlineMesh !== "object" || Array.isArray(inlineMesh)) return false;
23988
+ if (!Array.isArray(inlineMesh.nodes) || inlineMesh.nodes.length === 0) return false;
23989
+ return inlineMesh.nodes.some((node) => hasInlineMeshTransientNodeState(node));
23990
+ }
23991
+ function readInlineMeshNodeId(node) {
23992
+ return readStringValue(node?.id, node?.nodeId) || "";
23993
+ }
23994
+ function sanitizeInlineMesh(inlineMesh) {
23995
+ if (!inlineMesh || typeof inlineMesh !== "object" || Array.isArray(inlineMesh)) return inlineMesh;
23996
+ if (!Array.isArray(inlineMesh.nodes)) return inlineMesh;
23997
+ let changed = false;
23998
+ const nodes = inlineMesh.nodes.map((node) => {
23999
+ if (!hasInlineMeshTransientNodeState(node)) return node;
24000
+ changed = true;
24001
+ return stripInlineMeshTransientNodeState(node);
24002
+ });
24003
+ if (!changed) return inlineMesh;
24004
+ return {
24005
+ ...inlineMesh,
24006
+ nodes
24007
+ };
24008
+ }
24009
+ function reconcileInlineMeshCache(cached, incoming) {
24010
+ if (!cached || typeof cached !== "object" || Array.isArray(cached)) return incoming;
24011
+ if (!incoming || typeof incoming !== "object" || Array.isArray(incoming)) return cached;
24012
+ const cachedNodes = Array.isArray(cached.nodes) ? cached.nodes : [];
24013
+ const incomingNodes = Array.isArray(incoming.nodes) ? incoming.nodes : [];
24014
+ if (!cachedNodes.length || !incomingNodes.length) return { ...cached, ...incoming };
24015
+ const incomingById = /* @__PURE__ */ new Map();
24016
+ for (const node of incomingNodes) {
24017
+ const nodeId = readInlineMeshNodeId(node);
24018
+ if (nodeId) incomingById.set(nodeId, node);
24019
+ }
24020
+ const nodes = cachedNodes.map((cachedNode) => {
24021
+ const nodeId = readInlineMeshNodeId(cachedNode);
24022
+ const incomingNode = nodeId ? incomingById.get(nodeId) : void 0;
24023
+ if (!incomingNode) return cachedNode;
24024
+ if (hasInlineMeshTransientNodeState(incomingNode)) {
24025
+ return { ...cachedNode, ...incomingNode };
24026
+ }
24027
+ return { ...stripInlineMeshTransientNodeState(cachedNode), ...incomingNode };
24028
+ });
24029
+ return {
24030
+ ...cached,
24031
+ ...incoming,
24032
+ nodes
24033
+ };
24034
+ }
24035
+ function hasGitWorktreeChanges(git) {
24036
+ if (!git) return false;
24037
+ return Number(git.staged || 0) + Number(git.modified || 0) + Number(git.untracked || 0) + Number(git.deleted || 0) + Number(git.renamed || 0) > 0;
24038
+ }
24039
+ function getGitSubmoduleDriftState(git) {
24040
+ const submodules = Array.isArray(git?.submodules) ? git.submodules : [];
24041
+ let dirty = false;
24042
+ let outOfSync = false;
24043
+ for (const entry of submodules) {
24044
+ const submodule = readObjectRecord(entry);
24045
+ if (readBooleanValue(submodule.dirty) === true) dirty = true;
24046
+ if (readBooleanValue(submodule.outOfSync) === true || !!readStringValue(submodule.error)) outOfSync = true;
24047
+ }
24048
+ return { dirty, outOfSync };
24049
+ }
24050
+ function deriveMeshNodeHealthFromGit(git) {
24051
+ if (!git || readBooleanValue(git.isGitRepo) === false) return "degraded";
24052
+ const branch = readStringValue(git.branch);
24053
+ if (!branch) return "degraded";
24054
+ const submoduleDrift = getGitSubmoduleDriftState(git);
24055
+ if (submoduleDrift.outOfSync) return "degraded";
24056
+ if (submoduleDrift.dirty || hasGitWorktreeChanges(git)) return "dirty";
24057
+ return "online";
24058
+ }
24059
+ function readCachedInlineMeshActiveSessions(node) {
24060
+ const cachedStatus = readObjectRecord(node?.cachedStatus);
24061
+ const activeSession = readObjectRecord(cachedStatus.activeSession);
24062
+ const fallbackSession = Object.keys(activeSession).length ? activeSession : readObjectRecord(node?.activeSession ?? node?.active_session);
24063
+ const sessionId = readStringValue(fallbackSession.id, fallbackSession.sessionId, fallbackSession.session_id, node?.activeSessionId, node?.active_session_id, node?.sessionId, node?.session_id);
24064
+ return sessionId ? [sessionId] : [];
24065
+ }
24066
+ function readCachedInlineMeshActiveSessionDetails(node) {
24067
+ const cachedStatus = readObjectRecord(node?.cachedStatus);
24068
+ const activeSession = readObjectRecord(cachedStatus.activeSession);
24069
+ const fallbackSession = Object.keys(activeSession).length ? activeSession : readObjectRecord(node?.activeSession ?? node?.active_session);
24070
+ const sessionId = readStringValue(
24071
+ fallbackSession.id,
24072
+ fallbackSession.sessionId,
24073
+ fallbackSession.session_id,
24074
+ node?.activeSessionId,
24075
+ node?.active_session_id,
24076
+ node?.sessionId,
24077
+ node?.session_id
24078
+ );
24079
+ if (!sessionId) return [];
24080
+ return [{
24081
+ sessionId,
24082
+ providerType: readStringValue(
24083
+ fallbackSession.providerType,
24084
+ fallbackSession.provider_type,
24085
+ fallbackSession.cliType,
24086
+ fallbackSession.cli_type,
24087
+ fallbackSession.provider,
24088
+ node?.providerType,
24089
+ node?.provider_type
24090
+ ),
24091
+ state: readStringValue(fallbackSession.status, fallbackSession.state, fallbackSession.lifecycle),
24092
+ lifecycle: readStringValue(fallbackSession.lifecycle),
24093
+ title: readStringValue(fallbackSession.title, fallbackSession.displayName, fallbackSession.display_name) ?? null,
24094
+ workspace: readStringValue(fallbackSession.workspace, node?.workspace) ?? null,
24095
+ lastActivityAt: readStringValue(fallbackSession.lastActivityAt, fallbackSession.last_activity_at) ?? null,
24096
+ recoveryState: readStringValue(fallbackSession.recoveryState, fallbackSession.recovery_state) ?? null,
24097
+ isCached: true
24098
+ }];
24099
+ }
24100
+ function readLiveMeshSessionState(record) {
24101
+ return readStringValue(
24102
+ record?.meta?.sessionStatus,
24103
+ record?.meta?.status,
24104
+ record?.meta?.providerStatus,
24105
+ record?.status,
24106
+ record?.state,
24107
+ record?.lifecycle
24108
+ );
24109
+ }
24110
+ function toIsoTimestamp(value) {
24111
+ if (typeof value === "number" && Number.isFinite(value)) return new Date(value).toISOString();
24112
+ const stringValue = readStringValue(value);
24113
+ return stringValue || null;
24114
+ }
24115
+ function synthesizeMeshNodeFreshnessFromConnection(status) {
24116
+ const connection = readObjectRecord(status.connection);
24117
+ const connectionFreshAt = toIsoTimestamp(connection.lastCommandAt ?? connection.lastConnectedAt ?? connection.lastStateChangeAt);
24118
+ const git = readObjectRecord(status.git);
24119
+ const gitCheckedAt = toIsoTimestamp(git.lastCheckedAt);
24120
+ if (!status.lastSeenAt && connectionFreshAt) status.lastSeenAt = connectionFreshAt;
24121
+ if (!status.updatedAt && (gitCheckedAt || connectionFreshAt)) {
24122
+ status.updatedAt = gitCheckedAt ?? connectionFreshAt;
24123
+ }
24124
+ }
24125
+ function finalizeMeshNodeStatus(args) {
24126
+ const { status, node, daemonId, isSelfNode } = args;
24127
+ if (!readStringValue(status.machineStatus)) {
24128
+ const cachedStatus = readObjectRecord(node?.cachedStatus);
24129
+ const machineStatus = readStringValue(cachedStatus.machineStatus, cachedStatus.machine_status, node?.machineStatus);
24130
+ if (machineStatus) status.machineStatus = machineStatus;
24131
+ }
24132
+ synthesizeMeshNodeFreshnessFromConnection(status);
24133
+ const connectionState = readStringValue(readObjectRecord(status.connection).state);
24134
+ status.launchReady = !!daemonId && (readStringValue(status.machineStatus) === "online" || connectionState === "connected" || isSelfNode);
24135
+ }
24136
+ async function probeRemoteMeshGitStatus(args) {
24137
+ if (!args.dispatchMeshCommand) return null;
24138
+ const remoteResult = await Promise.race([
24139
+ args.dispatchMeshCommand(args.daemonId, "git_status", { workspace: args.workspace }),
24140
+ new Promise((_, reject) => setTimeout(() => reject(new Error("timeout")), args.timeoutMs))
24141
+ ]);
24142
+ const remoteGit = remoteResult?.status ?? remoteResult?.git ?? remoteResult;
24143
+ return remoteGit && typeof remoteGit === "object" && typeof remoteGit.isGitRepo === "boolean" ? remoteGit : null;
24144
+ }
24145
+ async function hydrateInlineMeshDirectTruth(args) {
24146
+ const nodes = Array.isArray(args.mesh?.nodes) ? args.mesh.nodes : [];
24147
+ if (!nodes.length) {
24148
+ return {
24149
+ directEvidenceCount: 0,
24150
+ localConfirmedCount: 0,
24151
+ peerAttemptedCount: 0,
24152
+ peerConfirmedCount: 0,
24153
+ unavailableNodeIds: []
24154
+ };
24155
+ }
24156
+ const selectedCoordinatorNodeId = readStringValue(
24157
+ args.mesh?.coordinator?.preferredNodeId,
24158
+ nodes[0]?.id,
24159
+ nodes[0]?.nodeId
24160
+ );
24161
+ let localConfirmedCount = 0;
24162
+ let peerAttemptedCount = 0;
24163
+ let peerConfirmedCount = 0;
24164
+ const unavailableNodeIds = [];
24165
+ for (const [nodeIndex, node] of nodes.entries()) {
24166
+ const nodeId = readStringValue(node?.id, node?.nodeId) || `node_${nodeIndex}`;
24167
+ const workspace = readStringValue(node?.workspace);
24168
+ const daemonId = readStringValue(node?.daemonId);
24169
+ const isSelfNode = Boolean(
24170
+ nodeId && selectedCoordinatorNodeId && nodeId === selectedCoordinatorNodeId
24171
+ ) || Boolean(
24172
+ daemonId && (daemonId === args.localMachineId || daemonId === args.statusInstanceId)
24173
+ ) || Boolean(args.meshSource !== "local_config" && nodeIndex === 0);
24174
+ if (!workspace) {
24175
+ if (!isSelfNode && daemonId) unavailableNodeIds.push(nodeId);
24176
+ continue;
24177
+ }
24178
+ if (isSelfNode && fs10.existsSync(workspace)) {
24179
+ try {
24180
+ const localGit = await getGitRepoStatus(workspace, { timeoutMs: 1e4, refreshUpstream: true });
24181
+ if (localGit?.isGitRepo) {
24182
+ recordInlineMeshDirectGitTruth(node, localGit, "selected_coordinator_local_git");
24183
+ localConfirmedCount += 1;
24184
+ continue;
24185
+ }
24186
+ } catch {
24187
+ }
24188
+ }
24189
+ if (!daemonId || !args.dispatchMeshCommand) {
24190
+ if (!isSelfNode) unavailableNodeIds.push(nodeId);
24191
+ continue;
24192
+ }
24193
+ peerAttemptedCount += 1;
24194
+ try {
24195
+ const remoteGit = await probeRemoteMeshGitStatus({
24196
+ dispatchMeshCommand: args.dispatchMeshCommand,
24197
+ daemonId,
24198
+ workspace,
24199
+ timeoutMs: 8e3
24200
+ });
24201
+ if (remoteGit) {
24202
+ recordInlineMeshDirectGitTruth(node, remoteGit, "selected_coordinator_mesh_p2p_git");
24203
+ peerConfirmedCount += 1;
24204
+ continue;
24205
+ }
24206
+ } catch {
24207
+ }
24208
+ unavailableNodeIds.push(nodeId);
24209
+ }
24210
+ return {
24211
+ directEvidenceCount: localConfirmedCount + peerConfirmedCount,
24212
+ localConfirmedCount,
24213
+ peerAttemptedCount,
24214
+ peerConfirmedCount,
24215
+ unavailableNodeIds
24216
+ };
24217
+ }
24218
+ function summarizeMeshSessionRecord(record) {
24219
+ return {
24220
+ sessionId: readStringValue(record?.sessionId) || "unknown",
24221
+ providerType: readStringValue(record?.providerType),
24222
+ state: readLiveMeshSessionState(record),
24223
+ lifecycle: readStringValue(record?.lifecycle),
24224
+ surfaceKind: getSessionHostSurfaceKind(record),
24225
+ recoveryState: readStringValue(record?.meta?.runtimeRecoveryState) ?? null,
24226
+ workspace: readStringValue(record?.workspace) ?? null,
24227
+ title: readStringValue(record?.displayName, record?.workspaceLabel) ?? null,
24228
+ lastActivityAt: toIsoTimestamp(record?.updatedAt ?? record?.lastActivityAt ?? record?.last_activity_at),
24229
+ isCached: false
24230
+ };
24231
+ }
24232
+ function liveSessionRecordMatchesMeshNode(record, meshId, nodeId) {
24233
+ const recordNodeId = readStringValue(record?.meta?.meshNodeId);
24234
+ if (!recordNodeId || recordNodeId !== nodeId) return false;
24235
+ const recordMeshId = readStringValue(record?.meta?.meshNodeFor);
24236
+ return !recordMeshId || recordMeshId === meshId;
24237
+ }
24238
+ function liveSessionRecordMatchesMeshWorkspace(record, meshId, workspace) {
24239
+ const recordWorkspace = readStringValue(record?.workspace);
24240
+ if (!recordWorkspace || !workspace || recordWorkspace !== workspace) return false;
24241
+ const recordMeshId = readStringValue(record?.meta?.meshNodeFor);
24242
+ if (recordMeshId) return recordMeshId === meshId;
24243
+ return record?.meta?.launchedByCoordinator === true || !!readStringValue(record?.meta?.meshNodeId);
24244
+ }
24245
+ function readLiveMeshNodeWorkspace(args) {
24246
+ const directNodeWorkspace = args.liveSessionRecords.find((record) => liveSessionRecordMatchesMeshNode(record, args.meshId, args.nodeId) && readStringValue(record?.workspace));
24247
+ if (directNodeWorkspace) {
24248
+ return readStringValue(directNodeWorkspace.workspace) || "";
24249
+ }
24250
+ if (args.allowCoordinatorSession) {
24251
+ const coordinatorWorkspace = args.liveSessionRecords.find((record) => readStringValue(record?.meta?.meshCoordinatorFor) === args.meshId && readStringValue(record?.workspace));
24252
+ if (coordinatorWorkspace) {
24253
+ return readStringValue(coordinatorWorkspace.workspace) || "";
24254
+ }
24255
+ }
24256
+ return "";
24257
+ }
24258
+ function collectLiveMeshSessionRecords(args) {
24259
+ const matches = args.liveSessionRecords.filter((record) => {
24260
+ const nodeWorkspace = readStringValue(args.node?.workspace);
24261
+ if (liveSessionRecordMatchesMeshNode(record, args.meshId, args.nodeId)) return true;
24262
+ return !!nodeWorkspace && liveSessionRecordMatchesMeshWorkspace(record, args.meshId, nodeWorkspace);
24263
+ });
24264
+ if (args.allowCoordinatorSession) {
24265
+ for (const record of args.liveSessionRecords) {
24266
+ if (readStringValue(record?.meta?.meshCoordinatorFor) !== args.meshId) continue;
24267
+ const sessionId = readStringValue(record?.sessionId);
24268
+ if (sessionId && matches.some((entry) => readStringValue(entry?.sessionId) === sessionId)) continue;
24269
+ matches.push(record);
24270
+ }
24271
+ }
24272
+ return matches;
24273
+ }
24274
+ function applyCachedInlineMeshNodeStatus(status, node, options) {
24275
+ const cachedStatus = readObjectRecord(node?.cachedStatus);
24276
+ const liveGit = buildInlineMeshTransitGitStatus(node);
24277
+ const git = options?.skipGit ? void 0 : liveGit ?? buildCachedInlineMeshGitStatus(node);
24278
+ const error = options?.skipError ? void 0 : liveGit ? void 0 : readStringValue(cachedStatus.error, node?.error);
24279
+ const health = options?.skipHealth ? void 0 : liveGit ? void 0 : readStringValue(cachedStatus.health, node?.health);
23678
24280
  const machineStatus = readStringValue(cachedStatus.machineStatus, node?.machineStatus);
23679
- if (!git && !error && !health) return false;
23680
- if (!machineStatus && !git && !error) return false;
24281
+ const lastSeenAt = toIsoTimestamp(cachedStatus.lastSeenAt ?? cachedStatus.last_seen_at ?? node?.lastSeenAt ?? node?.last_seen_at);
24282
+ const updatedAt = toIsoTimestamp(cachedStatus.updatedAt ?? cachedStatus.updated_at ?? node?.updatedAt ?? node?.updated_at);
24283
+ const activeSessions = readCachedInlineMeshActiveSessions(node);
24284
+ const activeSessionDetails = readCachedInlineMeshActiveSessionDetails(node);
24285
+ if (!git && !error && !health && !machineStatus && !lastSeenAt && !updatedAt && activeSessions.length === 0) return false;
23681
24286
  if (git) status.git = git;
23682
24287
  if (error) status.error = error;
24288
+ if (machineStatus) status.machineStatus = machineStatus;
24289
+ if (lastSeenAt) status.lastSeenAt = lastSeenAt;
24290
+ if (updatedAt) status.updatedAt = updatedAt;
24291
+ if (activeSessions.length > 0) status.activeSessions = activeSessions;
24292
+ if (activeSessionDetails.length > 0) status.activeSessionDetails = activeSessionDetails;
23683
24293
  if (health) {
23684
24294
  status.health = health;
23685
24295
  return true;
23686
24296
  }
23687
24297
  if (git) {
23688
- const dirty = Number(git.staged || 0) + Number(git.modified || 0) + Number(git.untracked || 0) + Number(git.deleted || 0) + Number(git.renamed || 0) > 0;
23689
- status.health = git.isGitRepo === false ? "degraded" : dirty ? "dirty" : "online";
24298
+ status.health = deriveMeshNodeHealthFromGit(git);
23690
24299
  return true;
23691
24300
  }
23692
- return false;
24301
+ return activeSessions.length > 0 || !!machineStatus || !!lastSeenAt || !!updatedAt;
23693
24302
  }
23694
24303
  async function resolveProviderTypeFromPriority(args) {
23695
24304
  if (!args.providerPriority.length) {
@@ -23719,12 +24328,89 @@ var REFINE_VALIDATION_TIMEOUT_MS = 12e4;
23719
24328
  var REFINE_VALIDATION_OUTPUT_LIMIT_BYTES = 128 * 1024;
23720
24329
  var REFINE_VALIDATION_SUMMARY_CHARS = 2e3;
23721
24330
  var REFINE_VALIDATION_MAX_COMMANDS = 4;
24331
+ var REFINE_PATCH_EQUIVALENCE_OUTPUT_LIMIT_BYTES = 4 * 1024 * 1024;
23722
24332
  function truncateValidationOutput(value) {
23723
24333
  const text = typeof value === "string" ? value : value == null ? "" : String(value);
23724
24334
  if (text.length <= REFINE_VALIDATION_SUMMARY_CHARS) return text;
23725
24335
  return `${text.slice(0, REFINE_VALIDATION_SUMMARY_CHARS)}
23726
24336
  [truncated ${text.length - REFINE_VALIDATION_SUMMARY_CHARS} chars]`;
23727
24337
  }
24338
+ function recordMeshRefineStage(stages, stage, status, startedAt, details) {
24339
+ stages.push({
24340
+ stage,
24341
+ status,
24342
+ durationMs: Date.now() - startedAt,
24343
+ ...details || {}
24344
+ });
24345
+ }
24346
+ async function computeGitPatchId(cwd, fromRef, toRef) {
24347
+ const { execFileSync: execFileSync4 } = await import("child_process");
24348
+ const diff = execFileSync4("git", ["diff", "--patch", "--full-index", fromRef, toRef], {
24349
+ cwd,
24350
+ encoding: "utf8",
24351
+ maxBuffer: REFINE_PATCH_EQUIVALENCE_OUTPUT_LIMIT_BYTES
24352
+ });
24353
+ if (!diff.trim()) return "";
24354
+ const patchId = execFileSync4("git", ["patch-id", "--stable"], {
24355
+ cwd,
24356
+ input: diff,
24357
+ encoding: "utf8",
24358
+ maxBuffer: REFINE_PATCH_EQUIVALENCE_OUTPUT_LIMIT_BYTES
24359
+ }).trim();
24360
+ return patchId.split(/\s+/)[0] || "";
24361
+ }
24362
+ async function runMeshRefinePatchEquivalenceGate(repoRoot, baseHead, branchHead) {
24363
+ const startedAt = Date.now();
24364
+ try {
24365
+ const { execFileSync: execFileSync4 } = await import("child_process");
24366
+ const git = (args) => execFileSync4("git", args, {
24367
+ cwd: repoRoot,
24368
+ encoding: "utf8",
24369
+ maxBuffer: REFINE_PATCH_EQUIVALENCE_OUTPUT_LIMIT_BYTES
24370
+ });
24371
+ const mergeBase = git(["merge-base", baseHead, branchHead]).trim();
24372
+ const mergeTreeStdout = git(["merge-tree", "--write-tree", baseHead, branchHead]);
24373
+ const mergedTree = mergeTreeStdout.trim().split(/\s+/)[0] || "";
24374
+ if (!mergeBase || !mergedTree) {
24375
+ return {
24376
+ status: "failed",
24377
+ equivalent: false,
24378
+ baseHead,
24379
+ branchHead,
24380
+ mergeBase: mergeBase || void 0,
24381
+ mergedTree: mergedTree || void 0,
24382
+ durationMs: Date.now() - startedAt,
24383
+ error: "patch equivalence preflight could not resolve merge-base or synthetic merge tree",
24384
+ stdout: truncateValidationOutput(mergeTreeStdout)
24385
+ };
24386
+ }
24387
+ const expectedPatchId = await computeGitPatchId(repoRoot, mergeBase, branchHead);
24388
+ const actualPatchId = await computeGitPatchId(repoRoot, baseHead, mergedTree);
24389
+ const equivalent = expectedPatchId === actualPatchId;
24390
+ return {
24391
+ status: equivalent ? "passed" : "failed",
24392
+ equivalent,
24393
+ baseHead,
24394
+ branchHead,
24395
+ mergeBase,
24396
+ mergedTree,
24397
+ expectedPatchId,
24398
+ actualPatchId,
24399
+ durationMs: Date.now() - startedAt
24400
+ };
24401
+ } catch (e) {
24402
+ return {
24403
+ status: "failed",
24404
+ equivalent: false,
24405
+ baseHead,
24406
+ branchHead,
24407
+ durationMs: Date.now() - startedAt,
24408
+ error: e?.message || String(e),
24409
+ stdout: truncateValidationOutput(e?.stdout),
24410
+ stderr: truncateValidationOutput(e?.stderr)
24411
+ };
24412
+ }
24413
+ }
23728
24414
  function readPackageScripts(workspace) {
23729
24415
  try {
23730
24416
  const packageJsonPath = pathJoin(workspace, "package.json");
@@ -24082,30 +24768,97 @@ var DaemonCommandRouter = class {
24082
24768
  * Allows the MCP server to query mesh data via get_mesh even when
24083
24769
  * the mesh doesn't exist in the local meshes.json file. */
24084
24770
  inlineMeshCache = /* @__PURE__ */ new Map();
24771
+ /** Coordinator-owned whole-mesh aggregate status snapshots. Browser callers read this by default. */
24772
+ aggregateMeshStatusCache = /* @__PURE__ */ new Map();
24085
24773
  constructor(deps) {
24086
24774
  this.deps = deps;
24087
24775
  }
24776
+ cloneJsonValue(value) {
24777
+ if (typeof structuredClone === "function") return structuredClone(value);
24778
+ return JSON.parse(JSON.stringify(value));
24779
+ }
24780
+ getCachedAggregateMeshStatus(meshId) {
24781
+ const cached = this.aggregateMeshStatusCache.get(meshId);
24782
+ if (!cached?.snapshot || cached.snapshot.success !== true || !Array.isArray(cached.snapshot.nodes)) return null;
24783
+ const snapshot = this.cloneJsonValue(cached.snapshot);
24784
+ const ageMs = Math.max(0, Date.now() - cached.builtAt);
24785
+ const sourceOfTruth = snapshot.sourceOfTruth && typeof snapshot.sourceOfTruth === "object" ? snapshot.sourceOfTruth : {};
24786
+ snapshot.sourceOfTruth = {
24787
+ ...sourceOfTruth,
24788
+ aggregateSnapshot: {
24789
+ ...sourceOfTruth.aggregateSnapshot && typeof sourceOfTruth.aggregateSnapshot === "object" ? sourceOfTruth.aggregateSnapshot : {},
24790
+ owner: "coordinator_daemon_memory",
24791
+ cached: true,
24792
+ source: "memory",
24793
+ refreshReason: "memory_cache_hit",
24794
+ ageMs,
24795
+ cachedAt: new Date(cached.builtAt).toISOString(),
24796
+ returnedAt: (/* @__PURE__ */ new Date()).toISOString()
24797
+ }
24798
+ };
24799
+ return snapshot;
24800
+ }
24801
+ rememberAggregateMeshStatus(meshId, snapshot, refreshReason) {
24802
+ if (!snapshot || typeof snapshot !== "object" || snapshot.success !== true || !Array.isArray(snapshot.nodes)) return snapshot;
24803
+ const builtAt = Date.now();
24804
+ const next = this.cloneJsonValue(snapshot);
24805
+ const sourceOfTruth = next.sourceOfTruth && typeof next.sourceOfTruth === "object" ? next.sourceOfTruth : {};
24806
+ next.sourceOfTruth = {
24807
+ ...sourceOfTruth,
24808
+ aggregateSnapshot: {
24809
+ owner: "coordinator_daemon_memory",
24810
+ cached: false,
24811
+ source: "live_refresh",
24812
+ refreshReason,
24813
+ ageMs: 0,
24814
+ cachedAt: new Date(builtAt).toISOString(),
24815
+ returnedAt: new Date(builtAt).toISOString()
24816
+ }
24817
+ };
24818
+ this.aggregateMeshStatusCache.set(meshId, { builtAt, snapshot: this.cloneJsonValue(next) });
24819
+ return next;
24820
+ }
24088
24821
  getCachedInlineMesh(meshId, inlineMesh) {
24089
24822
  if (inlineMesh && typeof inlineMesh === "object") {
24090
- this.inlineMeshCache.set(meshId, inlineMesh);
24091
- return inlineMesh;
24823
+ return this.warmInlineMeshCache(meshId, inlineMesh);
24092
24824
  }
24093
24825
  return this.inlineMeshCache.get(meshId);
24094
24826
  }
24827
+ warmInlineMeshCache(meshId, inlineMesh) {
24828
+ if (!inlineMesh || typeof inlineMesh !== "object") return void 0;
24829
+ const sanitizedInlineMesh = sanitizeInlineMesh(inlineMesh);
24830
+ const cached = this.inlineMeshCache.get(meshId);
24831
+ if (cached) {
24832
+ const merged = reconcileInlineMeshCache(cached, sanitizedInlineMesh);
24833
+ this.inlineMeshCache.set(meshId, merged);
24834
+ return merged;
24835
+ }
24836
+ this.inlineMeshCache.set(meshId, sanitizedInlineMesh);
24837
+ return sanitizedInlineMesh;
24838
+ }
24095
24839
  async getMeshForCommand(meshId, inlineMesh, options) {
24096
24840
  const preferInline = options?.preferInline === true;
24097
24841
  if (preferInline) {
24098
- const cached2 = this.getCachedInlineMesh(meshId, inlineMesh);
24099
- if (cached2) return { mesh: cached2, inline: true };
24842
+ const cached2 = this.getCachedInlineMesh(meshId);
24843
+ if (cached2) return { mesh: cached2, inline: true, source: "inline_cache" };
24844
+ if (inlineMeshCarriesTransientNodeTruth(inlineMesh)) {
24845
+ this.warmInlineMeshCache(meshId, inlineMesh);
24846
+ return { mesh: inlineMesh, inline: true, source: "inline_bootstrap" };
24847
+ }
24100
24848
  }
24101
24849
  try {
24102
24850
  const { getMesh: getMesh3 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
24103
24851
  const mesh = getMesh3(meshId);
24104
- if (mesh) return { mesh, inline: false };
24852
+ if (mesh) return { mesh, inline: false, source: "local_config" };
24105
24853
  } catch {
24106
24854
  }
24107
- const cached = this.getCachedInlineMesh(meshId, inlineMesh);
24108
- return cached ? { mesh: cached, inline: true } : null;
24855
+ const cached = this.getCachedInlineMesh(meshId);
24856
+ if (cached) return { mesh: cached, inline: true, source: "inline_cache" };
24857
+ const warmedInline = this.warmInlineMeshCache(meshId, inlineMesh);
24858
+ return warmedInline ? { mesh: warmedInline, inline: true, source: "inline_bootstrap" } : null;
24859
+ }
24860
+ invalidateAggregateMeshStatus(meshId) {
24861
+ this.aggregateMeshStatusCache.delete(meshId);
24109
24862
  }
24110
24863
  updateInlineMeshNode(meshId, mesh, node) {
24111
24864
  if (!mesh || !Array.isArray(mesh.nodes) || !node?.id) return;
@@ -24114,6 +24867,7 @@ var DaemonCommandRouter = class {
24114
24867
  else mesh.nodes.push(node);
24115
24868
  mesh.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
24116
24869
  this.inlineMeshCache.set(meshId, mesh);
24870
+ this.invalidateAggregateMeshStatus(meshId);
24117
24871
  }
24118
24872
  removeInlineMeshNode(meshId, mesh, nodeId) {
24119
24873
  if (!mesh || !Array.isArray(mesh.nodes)) return false;
@@ -24122,6 +24876,7 @@ var DaemonCommandRouter = class {
24122
24876
  mesh.nodes.splice(idx, 1);
24123
24877
  mesh.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
24124
24878
  this.inlineMeshCache.set(meshId, mesh);
24879
+ this.invalidateAggregateMeshStatus(meshId);
24125
24880
  return true;
24126
24881
  }
24127
24882
  normalizeMeshSessionCleanupMode(value) {
@@ -24334,6 +25089,7 @@ var DaemonCommandRouter = class {
24334
25089
  const deletedSessionIds = [];
24335
25090
  const skippedSessionIds = [];
24336
25091
  const skippedLiveSessionIds = [];
25092
+ const skippedCoordinatorSessionIds = [];
24337
25093
  const deleteUnsupportedSessionIds = [];
24338
25094
  const recordsRemainSessionIds = [];
24339
25095
  const errors = [];
@@ -24366,6 +25122,12 @@ var DaemonCommandRouter = class {
24366
25122
  const completed = this.isCompletedHostedSession(record);
24367
25123
  const surfaceKind = getSessionHostSurfaceKind(record);
24368
25124
  const liveRuntime = surfaceKind === "live_runtime";
25125
+ const coordinatorSession = readStringValue(record?.meta?.meshCoordinatorFor) === args.meshId;
25126
+ if (!hasExplicitSessionIds && coordinatorSession) {
25127
+ skippedSessionIds.push(sessionId);
25128
+ skippedCoordinatorSessionIds.push(sessionId);
25129
+ continue;
25130
+ }
24369
25131
  if (!hasExplicitSessionIds && liveRuntime) {
24370
25132
  skippedSessionIds.push(sessionId);
24371
25133
  skippedLiveSessionIds.push(sessionId);
@@ -24431,6 +25193,7 @@ var DaemonCommandRouter = class {
24431
25193
  deletedSessionIds,
24432
25194
  skippedSessionIds,
24433
25195
  skippedLiveSessionIds,
25196
+ skippedCoordinatorSessionIds,
24434
25197
  ...deleteUnsupported ? {
24435
25198
  deleteUnsupported: true,
24436
25199
  effectiveCleanup: args.mode === "stop_and_delete" ? "stopped_only_records_remain" : "delete_unsupported_records_remain",
@@ -24563,7 +25326,8 @@ var DaemonCommandRouter = class {
24563
25326
  return handleMeshForwardEvent({ instanceManager: this.deps.instanceManager }, args);
24564
25327
  }
24565
25328
  case "get_pending_mesh_events": {
24566
- const events = drainPendingMeshCoordinatorEvents();
25329
+ const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
25330
+ const events = drainPendingMeshCoordinatorEvents(meshId || void 0);
24567
25331
  return { success: true, events };
24568
25332
  }
24569
25333
  case "launch_cli":
@@ -25092,15 +25856,39 @@ var DaemonCommandRouter = class {
25092
25856
  case "get_mesh": {
25093
25857
  const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
25094
25858
  if (!meshId) return { success: false, error: "meshId required" };
25095
- try {
25096
- const { getMesh: getMesh3 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
25097
- const mesh = getMesh3(meshId);
25098
- if (mesh) return { success: true, mesh };
25099
- } catch {
25859
+ const meshRecord = await this.getMeshForCommand(meshId, args?.inlineMesh, { preferInline: true });
25860
+ if (!meshRecord?.mesh) return { success: false, error: "Mesh not found" };
25861
+ const requireDirectPeerTruth = args?.requireDirectPeerTruth === true;
25862
+ const directTruth = await hydrateInlineMeshDirectTruth({
25863
+ mesh: meshRecord.mesh,
25864
+ meshSource: meshRecord.source,
25865
+ dispatchMeshCommand: this.deps.dispatchMeshCommand,
25866
+ statusInstanceId: this.deps.statusInstanceId,
25867
+ localMachineId: loadConfig().machineId || ""
25868
+ });
25869
+ const directTruthSatisfied = meshRecord.source !== "inline_bootstrap" || directTruth.directEvidenceCount > 0;
25870
+ const sourceOfTruth = {
25871
+ membership: meshRecord.source === "inline_cache" ? "coordinator_inline_mesh_cache" : meshRecord.source === "local_config" ? "local_mesh_config" : "inline_bootstrap_snapshot",
25872
+ coordinatorOwnsLiveTruth: directTruthSatisfied,
25873
+ directPeerTruth: {
25874
+ required: requireDirectPeerTruth,
25875
+ satisfied: directTruthSatisfied,
25876
+ directEvidenceCount: directTruth.directEvidenceCount,
25877
+ localConfirmedCount: directTruth.localConfirmedCount,
25878
+ peerAttemptedCount: directTruth.peerAttemptedCount,
25879
+ peerConfirmedCount: directTruth.peerConfirmedCount,
25880
+ unavailableNodeIds: directTruth.unavailableNodeIds
25881
+ }
25882
+ };
25883
+ if (requireDirectPeerTruth && !directTruthSatisfied) {
25884
+ return {
25885
+ success: false,
25886
+ code: "mesh_direct_peer_truth_unavailable",
25887
+ error: "Selected coordinator could not confirm direct mesh truth yet. Bootstrap inventory stays unavailable until direct get_mesh probes succeed.",
25888
+ sourceOfTruth
25889
+ };
25100
25890
  }
25101
- const cached = this.inlineMeshCache.get(meshId);
25102
- if (cached) return { success: true, mesh: cached };
25103
- return { success: false, error: "Mesh not found" };
25891
+ return { success: true, mesh: meshRecord.mesh, sourceOfTruth };
25104
25892
  }
25105
25893
  case "create_mesh": {
25106
25894
  const name = typeof args?.name === "string" ? args.name.trim() : "";
@@ -25130,6 +25918,7 @@ var DaemonCommandRouter = class {
25130
25918
  const mesh = updateMesh2(meshId, patch);
25131
25919
  if (!mesh) return { success: false, error: "Mesh not found" };
25132
25920
  this.inlineMeshCache.set(meshId, mesh);
25921
+ this.invalidateAggregateMeshStatus(meshId);
25133
25922
  return { success: true, mesh };
25134
25923
  } catch (e) {
25135
25924
  return { success: false, error: e.message };
@@ -25319,26 +26108,41 @@ var DaemonCommandRouter = class {
25319
26108
  const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
25320
26109
  const nodeId = typeof args?.nodeId === "string" ? args.nodeId.trim() : "";
25321
26110
  if (!meshId || !nodeId) return { success: false, error: "meshId and nodeId required" };
26111
+ const refineStages = [];
25322
26112
  try {
25323
26113
  const meshRecord = await this.getMeshForCommand(meshId, args?.inlineMesh);
25324
26114
  const mesh = meshRecord?.mesh;
25325
26115
  const node = mesh?.nodes?.find((n) => n.id === nodeId || n.nodeId === nodeId);
25326
- if (!node) return { success: false, error: `Node '${nodeId}' not found in mesh` };
26116
+ if (!node) return { success: false, error: `Node '${nodeId}' not found in mesh`, refineStages };
25327
26117
  if (!node.isLocalWorktree || !node.workspace) {
25328
- return { success: false, error: `Refinery requires a local worktree node` };
26118
+ return { success: false, error: `Refinery requires a local worktree node`, refineStages };
25329
26119
  }
25330
26120
  const sourceNode = node.clonedFromNodeId ? mesh?.nodes.find((n) => n.id === node.clonedFromNodeId || n.nodeId === node.clonedFromNodeId) : mesh?.nodes.find((n) => !n.isLocalWorktree);
25331
26121
  const repoRoot = sourceNode?.repoRoot || sourceNode?.workspace;
25332
- if (!repoRoot) return { success: false, error: "Source node repoRoot not found" };
26122
+ if (!repoRoot) return { success: false, error: "Source node repoRoot not found", refineStages };
25333
26123
  const { execFile: execFile3 } = await import("child_process");
25334
26124
  const { promisify: promisify3 } = await import("util");
25335
26125
  const execFileAsync3 = promisify3(execFile3);
26126
+ const resolveStarted = Date.now();
25336
26127
  const { stdout: branchStdout } = await execFileAsync3("git", ["branch", "--show-current"], { cwd: node.workspace, encoding: "utf8" });
25337
26128
  const branch = branchStdout.trim();
25338
- if (!branch) return { success: false, error: "Could not determine branch of the worktree node" };
26129
+ if (!branch) return { success: false, error: "Could not determine branch of the worktree node", refineStages };
25339
26130
  const { stdout: baseBranchStdout } = await execFileAsync3("git", ["branch", "--show-current"], { cwd: repoRoot, encoding: "utf8" });
25340
26131
  const baseBranch = baseBranchStdout.trim();
26132
+ const { stdout: baseHeadStdout } = await execFileAsync3("git", ["rev-parse", "HEAD"], { cwd: repoRoot, encoding: "utf8" });
26133
+ const { stdout: branchHeadStdout } = await execFileAsync3("git", ["rev-parse", branch], { cwd: node.workspace, encoding: "utf8" });
26134
+ const baseHead = baseHeadStdout.trim();
26135
+ const branchHead = branchHeadStdout.trim();
26136
+ recordMeshRefineStage(refineStages, "resolve_refs", "passed", resolveStarted, { branch, baseBranch, baseHead, branchHead });
26137
+ const validationStarted = Date.now();
25341
26138
  const validationSummary = await runMeshRefineValidationGate(mesh, node.workspace);
26139
+ recordMeshRefineStage(
26140
+ refineStages,
26141
+ "validation",
26142
+ validationSummary.status === "passed" ? "passed" : validationSummary.status === "failed" ? "failed" : "skipped",
26143
+ validationStarted,
26144
+ { validationStatus: validationSummary.status, commandsRun: validationSummary.commandsRun.length }
26145
+ );
25342
26146
  if (validationSummary.status === "failed") {
25343
26147
  return {
25344
26148
  success: false,
@@ -25348,6 +26152,7 @@ var DaemonCommandRouter = class {
25348
26152
  branch,
25349
26153
  into: baseBranch,
25350
26154
  validationSummary,
26155
+ refineStages,
25351
26156
  finalBranchConvergenceState: {
25352
26157
  branch,
25353
26158
  baseBranch,
@@ -25367,6 +26172,7 @@ var DaemonCommandRouter = class {
25367
26172
  branch,
25368
26173
  into: baseBranch,
25369
26174
  validationSummary,
26175
+ refineStages,
25370
26176
  finalBranchConvergenceState: {
25371
26177
  branch,
25372
26178
  baseBranch,
@@ -25377,37 +26183,121 @@ var DaemonCommandRouter = class {
25377
26183
  }
25378
26184
  };
25379
26185
  }
26186
+ const patchEquivalenceStarted = Date.now();
26187
+ const patchEquivalence = await runMeshRefinePatchEquivalenceGate(repoRoot, baseHead, branchHead);
26188
+ recordMeshRefineStage(refineStages, "patch_equivalence", patchEquivalence.status, patchEquivalenceStarted, {
26189
+ equivalent: patchEquivalence.equivalent,
26190
+ expectedPatchId: patchEquivalence.expectedPatchId,
26191
+ actualPatchId: patchEquivalence.actualPatchId,
26192
+ error: patchEquivalence.error
26193
+ });
26194
+ if (!patchEquivalence.equivalent) {
26195
+ return {
26196
+ success: false,
26197
+ code: "patch_equivalence_failed",
26198
+ convergenceStatus: "blocked_review",
26199
+ error: "Refinery patch-equivalence preflight failed; merge/refine was not attempted.",
26200
+ branch,
26201
+ into: baseBranch,
26202
+ validationSummary,
26203
+ patchEquivalence,
26204
+ refineStages,
26205
+ finalBranchConvergenceState: {
26206
+ branch,
26207
+ baseBranch,
26208
+ merged: false,
26209
+ removed: false,
26210
+ validation: "passed",
26211
+ patchEquivalence: "failed",
26212
+ status: "blocked_review"
26213
+ }
26214
+ };
26215
+ }
26216
+ let mergeResult;
26217
+ const mergeStarted = Date.now();
25380
26218
  try {
25381
- await execFileAsync3("git", ["merge", "--no-ff", branch, "-m", `Auto-merge branch '${branch}' via Refinery`], { cwd: repoRoot, encoding: "utf8" });
26219
+ const result = await execFileAsync3("git", ["merge", "--no-ff", branch, "-m", `Auto-merge branch '${branch}' via Refinery`], { cwd: repoRoot, encoding: "utf8" });
26220
+ mergeResult = {
26221
+ stdout: truncateValidationOutput(result.stdout),
26222
+ stderr: truncateValidationOutput(result.stderr),
26223
+ durationMs: Date.now() - mergeStarted
26224
+ };
26225
+ recordMeshRefineStage(refineStages, "merge", "passed", mergeStarted, mergeResult);
25382
26226
  } catch (e) {
26227
+ recordMeshRefineStage(refineStages, "merge", "failed", mergeStarted, {
26228
+ error: e?.message || String(e),
26229
+ stdout: truncateValidationOutput(e?.stdout),
26230
+ stderr: truncateValidationOutput(e?.stderr)
26231
+ });
25383
26232
  return {
25384
26233
  success: false,
25385
26234
  error: `Merge failed (conflicts?): ${e.message}`,
25386
26235
  validationSummary,
26236
+ patchEquivalence,
26237
+ refineStages,
25387
26238
  finalBranchConvergenceState: {
25388
26239
  branch,
25389
26240
  baseBranch,
25390
26241
  merged: false,
25391
26242
  removed: false,
25392
26243
  validation: "passed",
26244
+ patchEquivalence: "passed",
25393
26245
  status: "not_mergeable"
25394
26246
  }
25395
26247
  };
25396
26248
  }
26249
+ const cleanupStarted = Date.now();
25397
26250
  const removeResult = await this.execute("remove_mesh_node", {
25398
26251
  meshId,
25399
26252
  nodeId,
25400
- sessionCleanupMode: "kill",
26253
+ sessionCleanupMode: "preserve",
25401
26254
  inlineMesh: args?.inlineMesh
25402
26255
  });
26256
+ recordMeshRefineStage(refineStages, "cleanup", removeResult?.success === false ? "failed" : "passed", cleanupStarted, {
26257
+ removed: removeResult?.removed,
26258
+ code: removeResult?.code,
26259
+ error: removeResult?.error
26260
+ });
26261
+ let ledgerError;
26262
+ const ledgerStarted = Date.now();
25403
26263
  try {
25404
26264
  const { appendLedgerEntry: appendLedgerEntry2 } = await Promise.resolve().then(() => (init_mesh_ledger(), mesh_ledger_exports));
25405
26265
  appendLedgerEntry2(meshId, {
25406
26266
  kind: "node_removed",
25407
26267
  nodeId,
25408
- payload: { refined: true, mergedBranch: branch, into: baseBranch, validationSummary }
26268
+ payload: { refined: true, mergedBranch: branch, into: baseBranch, validationSummary, patchEquivalence }
25409
26269
  });
25410
- } catch {
26270
+ recordMeshRefineStage(refineStages, "ledger", "passed", ledgerStarted);
26271
+ } catch (e) {
26272
+ ledgerError = e?.message || String(e);
26273
+ recordMeshRefineStage(refineStages, "ledger", "failed", ledgerStarted, { error: ledgerError });
26274
+ }
26275
+ const finalBranchConvergenceState = {
26276
+ branch: baseBranch,
26277
+ mergedBranch: branch,
26278
+ baseBranch,
26279
+ merged: true,
26280
+ removed: removeResult?.success !== false,
26281
+ validation: "passed",
26282
+ patchEquivalence: "passed",
26283
+ status: removeResult?.success === false ? "merged_cleanup_failed" : "merged"
26284
+ };
26285
+ if (removeResult?.success === false) {
26286
+ return {
26287
+ success: false,
26288
+ code: "cleanup_failed",
26289
+ error: "Refinery merge completed but worktree cleanup failed; manual cleanup/retry is required.",
26290
+ merged: true,
26291
+ branch,
26292
+ into: baseBranch,
26293
+ removeResult,
26294
+ validationSummary,
26295
+ patchEquivalence,
26296
+ mergeResult,
26297
+ refineStages,
26298
+ ...ledgerError ? { ledgerError } : {},
26299
+ finalBranchConvergenceState
26300
+ };
25411
26301
  }
25412
26302
  return {
25413
26303
  success: true,
@@ -25416,18 +26306,14 @@ var DaemonCommandRouter = class {
25416
26306
  into: baseBranch,
25417
26307
  removeResult,
25418
26308
  validationSummary,
25419
- finalBranchConvergenceState: {
25420
- branch: baseBranch,
25421
- mergedBranch: branch,
25422
- baseBranch,
25423
- merged: true,
25424
- removed: removeResult?.success !== false,
25425
- validation: "passed",
25426
- status: removeResult?.success === false ? "merged_cleanup_failed" : "merged"
25427
- }
26309
+ patchEquivalence,
26310
+ mergeResult,
26311
+ refineStages,
26312
+ ...ledgerError ? { ledgerError } : {},
26313
+ finalBranchConvergenceState
25428
26314
  };
25429
26315
  } catch (e) {
25430
- return { success: false, error: e.message };
26316
+ return { success: false, error: e.message, refineStages };
25431
26317
  }
25432
26318
  }
25433
26319
  case "remove_mesh_node": {
@@ -25468,6 +26354,7 @@ var DaemonCommandRouter = class {
25468
26354
  } else {
25469
26355
  const { removeNode: removeNode3 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
25470
26356
  removed = removeNode3(meshId, nodeId);
26357
+ if (removed) this.invalidateAggregateMeshStatus(meshId);
25471
26358
  }
25472
26359
  if (removed) {
25473
26360
  try {
@@ -25546,6 +26433,7 @@ var DaemonCommandRouter = class {
25546
26433
  policy: { ...sourceNode.policy || {} }
25547
26434
  });
25548
26435
  if (!node) return { success: false, error: "Failed to register worktree node" };
26436
+ this.invalidateAggregateMeshStatus(meshId);
25549
26437
  }
25550
26438
  const initSubmodules = sourceNode.policy?.initSubmodulesOnClone !== false;
25551
26439
  if (initSubmodules) {
@@ -25621,7 +26509,14 @@ var DaemonCommandRouter = class {
25621
26509
  cliType
25622
26510
  };
25623
26511
  }
25624
- const workspace = typeof coordinatorNode.workspace === "string" ? coordinatorNode.workspace.trim() : "";
26512
+ const sessionHostRecords = this.deps.sessionHostControl?.listSessions ? await this.deps.sessionHostControl.listSessions().catch(() => []) : [];
26513
+ const liveMeshSessions = partitionSessionHostRecords(Array.isArray(sessionHostRecords) ? sessionHostRecords : []).liveRuntimes;
26514
+ const workspace = readLiveMeshNodeWorkspace({
26515
+ meshId,
26516
+ nodeId: String(coordinatorNode.id || coordinatorNode.nodeId || preferredCoordinatorNodeId || ""),
26517
+ liveSessionRecords: liveMeshSessions,
26518
+ allowCoordinatorSession: true
26519
+ }) || (typeof coordinatorNode.workspace === "string" ? coordinatorNode.workspace.trim() : "");
25625
26520
  if (!workspace) return { success: false, error: "Coordinator node workspace required", meshId, cliType };
25626
26521
  if (!cliType) {
25627
26522
  const resolved = await resolveProviderTypeFromPriority({
@@ -25783,7 +26678,7 @@ ${block}`);
25783
26678
  workspace
25784
26679
  };
25785
26680
  }
25786
- const { existsSync: existsSync25, readFileSync: readFileSync17, writeFileSync: writeFileSync15, copyFileSync: copyFileSync4, mkdirSync: mkdirSync17 } = await import("fs");
26681
+ const { existsSync: existsSync26, readFileSync: readFileSync18, writeFileSync: writeFileSync15, copyFileSync: copyFileSync4, mkdirSync: mkdirSync17 } = await import("fs");
25787
26682
  const { dirname: dirname9 } = await import("path");
25788
26683
  const mcpConfigPath = coordinatorSetup.configPath;
25789
26684
  const hermesManualFallback = cliType === "hermes-cli" && configFormat === "hermes_config_yaml" ? createHermesManualMeshCoordinatorSetup(meshId, workspace) : null;
@@ -25826,14 +26721,14 @@ ${block}`);
25826
26721
  if (hermesManualFallback) return returnManualFallback(message);
25827
26722
  return { success: false, code: "mesh_coordinator_config_write_failed", error: message, meshId, cliType, workspace };
25828
26723
  }
25829
- const hadExistingMcpConfig = existsSync25(mcpConfigPath);
26724
+ const hadExistingMcpConfig = existsSync26(mcpConfigPath);
25830
26725
  let existingMcpConfig = hermesBaseConfig?.config || {};
25831
26726
  if (hermesBaseConfig) {
25832
26727
  copyHermesCoordinatorCredentialFiles(hermesBaseConfig.sourceHome, dirname9(mcpConfigPath));
25833
26728
  }
25834
26729
  if (hadExistingMcpConfig) {
25835
26730
  try {
25836
- const parsedExistingMcpConfig = parseMeshCoordinatorMcpConfig(readFileSync17(mcpConfigPath, "utf-8"), configFormat);
26731
+ const parsedExistingMcpConfig = parseMeshCoordinatorMcpConfig(readFileSync18(mcpConfigPath, "utf-8"), configFormat);
25837
26732
  const existingCoordinatorConfig = hermesManualFallback ? stripHermesCoordinatorTempModelProviderOverrides(parsedExistingMcpConfig) : parsedExistingMcpConfig;
25838
26733
  existingMcpConfig = { ...existingMcpConfig, ...existingCoordinatorConfig };
25839
26734
  copyFileSync4(mcpConfigPath, mcpConfigPath + ".backup");
@@ -25923,110 +26818,264 @@ ${block}`);
25923
26818
  const meshRecord = await this.getMeshForCommand(meshId, args?.inlineMesh, { preferInline: true });
25924
26819
  const mesh = meshRecord?.mesh;
25925
26820
  if (!mesh) return { success: false, error: "Mesh not found" };
26821
+ const refreshRequested = args?.refresh === true || args?.forceRefresh === true;
26822
+ if (!refreshRequested) {
26823
+ const cachedStatus = this.getCachedAggregateMeshStatus(meshId);
26824
+ if (cachedStatus) return cachedStatus;
26825
+ }
26826
+ const refreshReason = refreshRequested ? "explicit_refresh" : "cold_cache_miss";
25926
26827
  const { getMeshQueueStats: getMeshQueueStats2, getQueue: getQueue2 } = await Promise.resolve().then(() => (init_mesh_work_queue(), mesh_work_queue_exports));
25927
26828
  const queue = getQueue2(meshId);
25928
26829
  const queueSummary = getMeshQueueStats2(meshId);
25929
26830
  const { readLedgerEntries: readLedgerEntries2, getLedgerSummary: getLedgerSummary2 } = await Promise.resolve().then(() => (init_mesh_ledger(), mesh_ledger_exports));
25930
26831
  const ledgerEntries = readLedgerEntries2(meshId, { tail: 20 });
25931
26832
  const ledgerSummary = getLedgerSummary2(meshId);
26833
+ const sessionHostRecords = this.deps.sessionHostControl?.listSessions ? await this.deps.sessionHostControl.listSessions().catch(() => []) : [];
26834
+ const liveMeshSessions = partitionSessionHostRecords(Array.isArray(sessionHostRecords) ? sessionHostRecords : []).liveRuntimes;
26835
+ const localMachineId = loadConfig().machineId || "";
26836
+ const requireDirectPeerTruth = args?.requireDirectPeerTruth === true;
26837
+ const directTruth = requireDirectPeerTruth ? await hydrateInlineMeshDirectTruth({
26838
+ mesh,
26839
+ meshSource: meshRecord.source,
26840
+ dispatchMeshCommand: this.deps.dispatchMeshCommand,
26841
+ statusInstanceId: this.deps.statusInstanceId,
26842
+ localMachineId
26843
+ }) : {
26844
+ directEvidenceCount: 0,
26845
+ localConfirmedCount: 0,
26846
+ peerAttemptedCount: 0,
26847
+ peerConfirmedCount: 0,
26848
+ unavailableNodeIds: []
26849
+ };
26850
+ const directTruthSatisfied = meshRecord.source !== "inline_bootstrap" || directTruth.directEvidenceCount > 0;
26851
+ if (requireDirectPeerTruth && !directTruthSatisfied) {
26852
+ return {
26853
+ success: false,
26854
+ code: "mesh_direct_peer_truth_unavailable",
26855
+ error: "Selected coordinator could not confirm direct mesh truth yet. Bootstrap inventory stays unavailable until direct mesh_status probes succeed.",
26856
+ sourceOfTruth: {
26857
+ membership: meshRecord.source === "inline_cache" ? "coordinator_inline_mesh_cache" : meshRecord.source === "local_config" ? "local_mesh_config" : "inline_bootstrap_snapshot",
26858
+ coordinatorOwnsLiveTruth: false,
26859
+ currentStatus: "direct_peer_truth_unavailable",
26860
+ directPeerTruth: {
26861
+ required: true,
26862
+ satisfied: false,
26863
+ directEvidenceCount: directTruth.directEvidenceCount,
26864
+ localConfirmedCount: directTruth.localConfirmedCount,
26865
+ peerAttemptedCount: directTruth.peerAttemptedCount,
26866
+ peerConfirmedCount: directTruth.peerConfirmedCount,
26867
+ unavailableNodeIds: directTruth.unavailableNodeIds
26868
+ }
26869
+ }
26870
+ };
26871
+ }
26872
+ const directTruthUnavailableNodeIds = new Set(directTruth.unavailableNodeIds);
26873
+ const selectedCoordinatorNodeId = readStringValue(
26874
+ mesh.coordinator?.preferredNodeId,
26875
+ mesh.nodes?.[0]?.id,
26876
+ mesh.nodes?.[0]?.nodeId
26877
+ );
26878
+ const inlineCoordinatorNodeId = meshRecord?.inline && Array.isArray(mesh.nodes) ? selectedCoordinatorNodeId : void 0;
26879
+ const refreshedAt = (/* @__PURE__ */ new Date()).toISOString();
25932
26880
  const nodeStatuses = [];
25933
- for (const node of mesh.nodes || []) {
26881
+ for (const [nodeIndex, node] of (mesh.nodes || []).entries()) {
26882
+ const nodeId = String(node.id || node.nodeId || "");
26883
+ const daemonId = readStringValue(node.daemonId);
26884
+ const providerPriority = readProviderPriorityFromPolicy(node.policy);
26885
+ const isSelfNode = Boolean(
26886
+ nodeId && inlineCoordinatorNodeId && nodeId === inlineCoordinatorNodeId
26887
+ ) || Boolean(
26888
+ daemonId && (daemonId === localMachineId || daemonId === this.deps.statusInstanceId)
26889
+ ) || Boolean(meshRecord?.inline && nodeIndex === 0);
25934
26890
  const status = {
25935
- nodeId: node.id || node.nodeId,
26891
+ nodeId,
25936
26892
  machineLabel: node.machineLabel || node.id || node.nodeId,
25937
26893
  workspace: node.workspace,
25938
26894
  repoRoot: node.repoRoot,
25939
26895
  isLocalWorktree: node.isLocalWorktree,
25940
26896
  worktreeBranch: node.worktreeBranch,
25941
- daemonId: node.daemonId,
26897
+ daemonId,
25942
26898
  machineId: node.machineId,
26899
+ machineStatus: node.machineStatus,
25943
26900
  health: "unknown",
25944
26901
  providers: node.providers || [],
25945
- activeSessions: []
26902
+ providerPriority,
26903
+ activeSessions: [],
26904
+ activeSessionDetails: [],
26905
+ launchReady: false
25946
26906
  };
25947
- if (node.workspace && typeof node.workspace === "string") {
25948
- if (!fs10.existsSync(node.workspace) && applyCachedInlineMeshNodeStatus(status, node)) {
25949
- nodeStatuses.push(status);
25950
- continue;
26907
+ if (isSelfNode) {
26908
+ status.connection = {
26909
+ perspective: "selected_coordinator",
26910
+ source: "mesh_peer_status",
26911
+ state: "self",
26912
+ transport: "local",
26913
+ reported: true,
26914
+ reason: "Selected coordinator daemon",
26915
+ lastStateChangeAt: refreshedAt
26916
+ };
26917
+ } else if (daemonId) {
26918
+ const connection = this.deps.getMeshPeerConnectionStatus?.(daemonId);
26919
+ status.connection = connection ?? {
26920
+ perspective: "selected_coordinator",
26921
+ source: "not_reported",
26922
+ state: "unknown",
26923
+ transport: "unknown",
26924
+ reported: false,
26925
+ reason: "No live mesh peer telemetry reported by the selected coordinator yet."
26926
+ };
26927
+ } else {
26928
+ status.connection = {
26929
+ perspective: "selected_coordinator",
26930
+ source: "not_reported",
26931
+ state: "unknown",
26932
+ transport: "unknown",
26933
+ reported: false,
26934
+ reason: "Node has no daemon id, so mesh transport cannot be reported from the selected coordinator."
26935
+ };
26936
+ }
26937
+ const matchedLiveSessionRecords = collectLiveMeshSessionRecords({
26938
+ meshId,
26939
+ node,
26940
+ nodeId,
26941
+ liveSessionRecords: liveMeshSessions,
26942
+ allowCoordinatorSession: nodeId === selectedCoordinatorNodeId
26943
+ });
26944
+ const workspace = readLiveMeshNodeWorkspace({
26945
+ meshId,
26946
+ nodeId,
26947
+ liveSessionRecords: matchedLiveSessionRecords,
26948
+ allowCoordinatorSession: nodeId === selectedCoordinatorNodeId
26949
+ }) || (typeof node.workspace === "string" ? node.workspace : "");
26950
+ status.workspace = workspace || node.workspace;
26951
+ if (matchedLiveSessionRecords.length > 0) {
26952
+ const sessionIds = matchedLiveSessionRecords.map((record) => typeof record?.sessionId === "string" ? record.sessionId : "").filter(Boolean);
26953
+ const providerTypes = matchedLiveSessionRecords.map((record) => readStringValue(record?.providerType)).filter(Boolean);
26954
+ status.activeSessions = sessionIds;
26955
+ status.activeSessionDetails = matchedLiveSessionRecords.map(summarizeMeshSessionRecord);
26956
+ if (providerTypes.length > 0) {
26957
+ status.providers = Array.from(/* @__PURE__ */ new Set([...Array.isArray(status.providers) ? status.providers : [], ...providerTypes]));
25951
26958
  }
25952
- try {
25953
- const { execFile: execFile3 } = await import("child_process");
25954
- const { promisify: promisify3 } = await import("util");
25955
- const execFileAsync3 = promisify3(execFile3);
25956
- const runGit2 = async (args2) => {
25957
- const result = await execFileAsync3("git", ["-C", node.workspace, ...args2], {
25958
- encoding: "utf8",
25959
- timeout: 1e4
25960
- });
25961
- return result.stdout.trim();
25962
- };
25963
- const branch = await runGit2(["branch", "--show-current"]).catch(() => "");
25964
- const porc = await runGit2(["status", "--porcelain"]).catch(() => "");
25965
- const headCommit = await runGit2(["rev-parse", "--short", "HEAD"]).catch(() => null);
25966
- const headMessage = await runGit2(["log", "-1", "--format=%s"]).catch(() => null);
25967
- const upstream = await runGit2(["rev-parse", "--abbrev-ref", "@{upstream}"]).catch(() => null);
25968
- const aheadBehind = await runGit2(["rev-list", "--left-right", "--count", "@{upstream}...HEAD"]).catch(() => "");
25969
- const stashCount = await runGit2(["stash", "list"]).catch(() => "");
25970
- let ahead = 0, behind = 0;
25971
- if (aheadBehind) {
25972
- const parts = aheadBehind.split(/\s+/);
25973
- if (parts.length >= 2) {
25974
- behind = parseInt(parts[0], 10) || 0;
25975
- ahead = parseInt(parts[1], 10) || 0;
26959
+ }
26960
+ if (workspace) {
26961
+ if (!fs10.existsSync(workspace)) {
26962
+ const inlineTransitGit = buildInlineMeshTransitGitStatus(node);
26963
+ let remoteProbeApplied = false;
26964
+ if (inlineTransitGit) {
26965
+ status.git = inlineTransitGit;
26966
+ status.health = inlineTransitGit.isGitRepo ? deriveMeshNodeHealthFromGit(inlineTransitGit) : "degraded";
26967
+ remoteProbeApplied = true;
26968
+ } else if (!isSelfNode && daemonId && this.deps.dispatchMeshCommand && !directTruthUnavailableNodeIds.has(nodeId)) {
26969
+ try {
26970
+ const remoteGit = await probeRemoteMeshGitStatus({
26971
+ dispatchMeshCommand: this.deps.dispatchMeshCommand,
26972
+ daemonId,
26973
+ workspace,
26974
+ timeoutMs: 8e3
26975
+ });
26976
+ if (remoteGit) {
26977
+ status.git = remoteGit;
26978
+ status.health = remoteGit.isGitRepo ? deriveMeshNodeHealthFromGit(remoteGit) : "degraded";
26979
+ recordInlineMeshDirectGitTruth(node, remoteGit, "selected_coordinator_mesh_p2p_git");
26980
+ remoteProbeApplied = true;
26981
+ }
26982
+ } catch {
26983
+ const refreshedConnection = this.deps.getMeshPeerConnectionStatus?.(daemonId);
26984
+ const refreshedConnectionState = readStringValue(refreshedConnection?.state);
26985
+ if (refreshedConnection && refreshedConnectionState === "connected") {
26986
+ status.connection = refreshedConnection;
26987
+ try {
26988
+ const remoteGit = await probeRemoteMeshGitStatus({
26989
+ dispatchMeshCommand: this.deps.dispatchMeshCommand,
26990
+ daemonId,
26991
+ workspace,
26992
+ timeoutMs: 12e3
26993
+ });
26994
+ if (remoteGit) {
26995
+ status.git = remoteGit;
26996
+ status.health = remoteGit.isGitRepo ? deriveMeshNodeHealthFromGit(remoteGit) : "degraded";
26997
+ recordInlineMeshDirectGitTruth(node, remoteGit, "selected_coordinator_mesh_p2p_git");
26998
+ remoteProbeApplied = true;
26999
+ }
27000
+ } catch {
27001
+ }
27002
+ }
25976
27003
  }
25977
27004
  }
25978
- const dirty = porc.length > 0;
25979
- const lines = porc ? porc.split("\n").filter(Boolean) : [];
25980
- let staged = 0, modified = 0, untracked = 0, deleted = 0, renamed = 0;
25981
- for (const line of lines) {
25982
- const xy = line.slice(0, 2);
25983
- if (xy[0] !== " " && xy[0] !== "?") staged++;
25984
- if (xy[1] === "M") modified++;
25985
- if (xy[1] === "D") deleted++;
25986
- if (xy[0] === "R" || xy[1] === "R") renamed++;
25987
- if (xy === "??") untracked++;
27005
+ if (!remoteProbeApplied) {
27006
+ const connectionState = readStringValue(status.connection?.state);
27007
+ const pendingPeerGitProbe = !inlineTransitGit && !isSelfNode && !!daemonId && (readStringValue(status.machineStatus) === "online" || readStringValue(status.health) === "online" || connectionState === "connecting" || connectionState === "connected" || connectionState === "unknown");
27008
+ if (pendingPeerGitProbe) {
27009
+ status.gitProbePending = true;
27010
+ status.health = "unknown";
27011
+ }
27012
+ if (applyCachedInlineMeshNodeStatus(
27013
+ status,
27014
+ node,
27015
+ pendingPeerGitProbe ? { skipGit: true, skipError: true, skipHealth: true } : void 0
27016
+ )) {
27017
+ finalizeMeshNodeStatus({ status, node, daemonId, isSelfNode });
27018
+ nodeStatuses.push(status);
27019
+ continue;
27020
+ }
27021
+ if (meshRecord?.source === "inline_cache" && !isSelfNode) {
27022
+ finalizeMeshNodeStatus({ status, node, daemonId, isSelfNode });
27023
+ nodeStatuses.push(status);
27024
+ continue;
27025
+ }
25988
27026
  }
25989
- status.git = {
25990
- workspace: node.workspace,
25991
- repoRoot: node.workspace,
25992
- isGitRepo: true,
25993
- branch: branch || null,
25994
- headCommit,
25995
- headMessage,
25996
- upstream,
25997
- ahead,
25998
- behind,
25999
- staged,
26000
- modified,
26001
- untracked,
26002
- deleted,
26003
- renamed,
26004
- hasConflicts: false,
26005
- conflictFiles: [],
26006
- stashCount: stashCount ? stashCount.split("\n").filter(Boolean).length : 0,
26007
- lastCheckedAt: Date.now()
26008
- };
26009
- status.health = branch ? dirty ? "dirty" : "online" : "degraded";
26010
- } catch {
26011
- if (!applyCachedInlineMeshNodeStatus(status, node)) {
26012
- status.health = "degraded";
27027
+ } else {
27028
+ try {
27029
+ const gitStatus = await getGitRepoStatus(workspace, { timeoutMs: 1e4, refreshUpstream: true });
27030
+ status.git = gitStatus;
27031
+ recordInlineMeshDirectGitTruth(node, gitStatus, "selected_coordinator_local_git");
27032
+ if (gitStatus.isGitRepo) {
27033
+ status.health = deriveMeshNodeHealthFromGit(gitStatus);
27034
+ } else {
27035
+ status.health = "degraded";
27036
+ if (gitStatus.error && !status.error) status.error = gitStatus.error;
27037
+ }
27038
+ } catch {
27039
+ if (!applyCachedInlineMeshNodeStatus(status, node)) {
27040
+ status.health = "degraded";
27041
+ }
26013
27042
  }
26014
27043
  }
26015
27044
  } else {
26016
27045
  applyCachedInlineMeshNodeStatus(status, node);
26017
27046
  }
27047
+ finalizeMeshNodeStatus({ status, node, daemonId, isSelfNode });
26018
27048
  nodeStatuses.push(status);
26019
27049
  }
26020
- return {
27050
+ const statusResult = {
26021
27051
  success: true,
26022
27052
  meshId: mesh.id,
26023
27053
  meshName: mesh.name,
26024
27054
  repoIdentity: mesh.repoIdentity,
26025
27055
  defaultBranch: mesh.defaultBranch,
27056
+ refreshedAt,
27057
+ sourceOfTruth: {
27058
+ membership: meshRecord?.source === "inline_cache" ? "coordinator_inline_mesh_cache" : meshRecord?.source === "local_config" ? "local_mesh_config" : "inline_bootstrap_snapshot",
27059
+ coordinatorOwnsLiveTruth: directTruthSatisfied,
27060
+ ...requireDirectPeerTruth ? {
27061
+ currentStatus: directTruthSatisfied ? "live_git_and_session_probes" : "direct_peer_truth_unavailable",
27062
+ directPeerTruth: {
27063
+ required: true,
27064
+ satisfied: directTruthSatisfied,
27065
+ directEvidenceCount: directTruth.directEvidenceCount,
27066
+ localConfirmedCount: directTruth.localConfirmedCount,
27067
+ peerAttemptedCount: directTruth.peerAttemptedCount,
27068
+ peerConfirmedCount: directTruth.peerConfirmedCount,
27069
+ unavailableNodeIds: directTruth.unavailableNodeIds
27070
+ }
27071
+ } : {},
27072
+ historicalEvidenceOnly: ["recoveryHints", "ledger.summary", "queue.summary"]
27073
+ },
26026
27074
  nodes: nodeStatuses,
26027
27075
  queue: { tasks: queue, summary: queueSummary },
26028
27076
  ledger: { entries: ledgerEntries, summary: ledgerSummary }
26029
27077
  };
27078
+ return this.rememberAggregateMeshStatus(meshId, statusResult, refreshReason);
26030
27079
  } catch (e) {
26031
27080
  return { success: false, error: e.message };
26032
27081
  }
@@ -33957,6 +35006,7 @@ async function initDaemonComponents(config) {
33957
35006
  sessionHostControl: config.sessionHostControl,
33958
35007
  statusInstanceId: config.statusInstanceId,
33959
35008
  statusVersion: config.statusVersion,
35009
+ getMeshPeerConnectionStatus: config.getMeshPeerConnectionStatus,
33960
35010
  getCdpLogFn: config.getCdpLogFn || ((ideType) => LOG.forComponent(`CDP:${ideType}`).asLogFn())
33961
35011
  });
33962
35012
  poller = new AgentStreamPoller({
@@ -34231,6 +35281,7 @@ export {
34231
35281
  prepareSessionChatTailUpdate,
34232
35282
  prepareSessionModalUpdate,
34233
35283
  probeCdpPort,
35284
+ queuePendingMeshCoordinatorEvent,
34234
35285
  readChatHistory,
34235
35286
  readLedgerEntries,
34236
35287
  readLedgerSlice,