@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.js CHANGED
@@ -1360,6 +1360,36 @@ function getQueuePath(meshId) {
1360
1360
  const safe = meshId.replace(/[^a-zA-Z0-9_-]/g, "_");
1361
1361
  return (0, import_path4.join)(getLedgerDir(), `${safe}.queue.json`);
1362
1362
  }
1363
+ function getLockPath(meshId) {
1364
+ const safe = meshId.replace(/[^a-zA-Z0-9_-]/g, "_");
1365
+ return (0, import_path4.join)(getLedgerDir(), `${safe}.queue.lock`);
1366
+ }
1367
+ function withQueueLock(meshId, fn) {
1368
+ const lockPath = getLockPath(meshId);
1369
+ let fd = -1;
1370
+ for (let i = 0; i < 10; i++) {
1371
+ try {
1372
+ fd = (0, import_fs4.openSync)(lockPath, "wx");
1373
+ break;
1374
+ } catch {
1375
+ const deadline = Date.now() + 30;
1376
+ while (Date.now() < deadline) {
1377
+ }
1378
+ }
1379
+ }
1380
+ try {
1381
+ return fn();
1382
+ } finally {
1383
+ if (fd !== -1) try {
1384
+ (0, import_fs4.closeSync)(fd);
1385
+ } catch {
1386
+ }
1387
+ try {
1388
+ (0, import_fs4.unlinkSync)(lockPath);
1389
+ } catch {
1390
+ }
1391
+ }
1392
+ }
1363
1393
  function readQueue(meshId) {
1364
1394
  const path28 = getQueuePath(meshId);
1365
1395
  if (!(0, import_fs4.existsSync)(path28)) return [];
@@ -1375,20 +1405,22 @@ function writeQueue(meshId, queue) {
1375
1405
  (0, import_fs4.writeFileSync)(path28, JSON.stringify(queue, null, 2), "utf-8");
1376
1406
  }
1377
1407
  function enqueueTask(meshId, message, opts) {
1378
- const queue = readQueue(meshId);
1379
- const entry = {
1380
- id: (0, import_crypto5.randomUUID)(),
1381
- meshId,
1382
- message,
1383
- status: "pending",
1384
- targetNodeId: opts?.targetNodeId,
1385
- targetSessionId: opts?.targetSessionId,
1386
- createdAt: (/* @__PURE__ */ new Date()).toISOString(),
1387
- updatedAt: (/* @__PURE__ */ new Date()).toISOString()
1388
- };
1389
- queue.push(entry);
1390
- writeQueue(meshId, queue);
1391
- return entry;
1408
+ return withQueueLock(meshId, () => {
1409
+ const queue = readQueue(meshId);
1410
+ const entry = {
1411
+ id: (0, import_crypto5.randomUUID)(),
1412
+ meshId,
1413
+ message,
1414
+ status: "pending",
1415
+ targetNodeId: opts?.targetNodeId,
1416
+ targetSessionId: opts?.targetSessionId,
1417
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
1418
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
1419
+ };
1420
+ queue.push(entry);
1421
+ writeQueue(meshId, queue);
1422
+ return entry;
1423
+ });
1392
1424
  }
1393
1425
  function getQueue(meshId, opts) {
1394
1426
  let queue = readQueue(meshId);
@@ -1399,100 +1431,111 @@ function getQueue(meshId, opts) {
1399
1431
  return queue;
1400
1432
  }
1401
1433
  function claimNextTask(meshId, nodeId, sessionId) {
1402
- const queue = readQueue(meshId);
1403
- const hasActiveAssignment = queue.some((q) => q.status === "assigned" && (q.assignedSessionId === sessionId || q.assignedNodeId === nodeId));
1404
- if (hasActiveAssignment) return null;
1405
- let targetIdx = queue.findIndex((q) => q.status === "pending" && q.targetSessionId === sessionId);
1406
- if (targetIdx === -1) {
1407
- targetIdx = queue.findIndex((q) => q.status === "pending" && q.targetNodeId === nodeId && !q.targetSessionId);
1408
- }
1409
- if (targetIdx === -1) {
1410
- targetIdx = queue.findIndex((q) => q.status === "pending" && !q.targetNodeId && !q.targetSessionId);
1411
- }
1412
- if (targetIdx === -1) return null;
1413
- const entry = queue[targetIdx];
1414
- entry.status = "assigned";
1415
- entry.assignedNodeId = nodeId;
1416
- entry.assignedSessionId = sessionId;
1417
- entry.dispatchTimestamp = (/* @__PURE__ */ new Date()).toISOString();
1418
- entry.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
1419
- writeQueue(meshId, queue);
1420
- return entry;
1434
+ return withQueueLock(meshId, () => {
1435
+ const queue = readQueue(meshId);
1436
+ const hasActiveAssignment = queue.some((q) => q.status === "assigned" && (q.assignedSessionId === sessionId || q.assignedNodeId === nodeId));
1437
+ if (hasActiveAssignment) return null;
1438
+ let targetIdx = queue.findIndex((q) => q.status === "pending" && q.targetSessionId === sessionId);
1439
+ if (targetIdx === -1) {
1440
+ targetIdx = queue.findIndex((q) => q.status === "pending" && q.targetNodeId === nodeId && !q.targetSessionId);
1441
+ }
1442
+ if (targetIdx === -1) {
1443
+ targetIdx = queue.findIndex((q) => q.status === "pending" && !q.targetNodeId && !q.targetSessionId);
1444
+ }
1445
+ if (targetIdx === -1) return null;
1446
+ const entry = queue[targetIdx];
1447
+ entry.status = "assigned";
1448
+ entry.assignedNodeId = nodeId;
1449
+ entry.assignedSessionId = sessionId;
1450
+ entry.dispatchTimestamp = (/* @__PURE__ */ new Date()).toISOString();
1451
+ entry.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
1452
+ writeQueue(meshId, queue);
1453
+ return entry;
1454
+ });
1421
1455
  }
1422
1456
  function updateTaskStatus(meshId, taskId, status) {
1423
- const queue = readQueue(meshId);
1424
- const idx = queue.findIndex((q) => q.id === taskId);
1425
- if (idx === -1) return null;
1426
- queue[idx].status = status;
1427
- queue[idx].updatedAt = (/* @__PURE__ */ new Date()).toISOString();
1428
- writeQueue(meshId, queue);
1429
- return queue[idx];
1457
+ return withQueueLock(meshId, () => {
1458
+ const queue = readQueue(meshId);
1459
+ const idx = queue.findIndex((q) => q.id === taskId);
1460
+ if (idx === -1) return null;
1461
+ queue[idx].status = status;
1462
+ queue[idx].updatedAt = (/* @__PURE__ */ new Date()).toISOString();
1463
+ writeQueue(meshId, queue);
1464
+ return queue[idx];
1465
+ });
1430
1466
  }
1431
1467
  function recordTaskAutoLaunch(meshId, taskId, autoLaunch) {
1432
- const queue = readQueue(meshId);
1433
- const idx = queue.findIndex((q) => q.id === taskId);
1434
- if (idx === -1) return null;
1435
- const now = (/* @__PURE__ */ new Date()).toISOString();
1436
- queue[idx].autoLaunch = {
1437
- ...autoLaunch,
1438
- updatedAt: now
1439
- };
1440
- queue[idx].updatedAt = now;
1441
- writeQueue(meshId, queue);
1442
- return queue[idx];
1468
+ return withQueueLock(meshId, () => {
1469
+ const queue = readQueue(meshId);
1470
+ const idx = queue.findIndex((q) => q.id === taskId);
1471
+ if (idx === -1) return null;
1472
+ const now = (/* @__PURE__ */ new Date()).toISOString();
1473
+ queue[idx].autoLaunch = { ...autoLaunch, updatedAt: now };
1474
+ queue[idx].updatedAt = now;
1475
+ writeQueue(meshId, queue);
1476
+ return queue[idx];
1477
+ });
1443
1478
  }
1444
1479
  function cancelTask(meshId, taskId, opts) {
1445
- const queue = readQueue(meshId);
1446
- const idx = queue.findIndex((q) => q.id === taskId);
1447
- if (idx === -1) return null;
1448
- const now = (/* @__PURE__ */ new Date()).toISOString();
1449
- queue[idx].status = "cancelled";
1450
- queue[idx].updatedAt = now;
1451
- queue[idx].cancelledAt = now;
1452
- if (opts?.reason) queue[idx].cancelReason = opts.reason;
1453
- writeQueue(meshId, queue);
1454
- return queue[idx];
1480
+ return withQueueLock(meshId, () => {
1481
+ const queue = readQueue(meshId);
1482
+ const idx = queue.findIndex((q) => q.id === taskId);
1483
+ if (idx === -1) return null;
1484
+ const now = (/* @__PURE__ */ new Date()).toISOString();
1485
+ queue[idx].status = "cancelled";
1486
+ queue[idx].updatedAt = now;
1487
+ queue[idx].cancelledAt = now;
1488
+ if (opts?.reason) queue[idx].cancelReason = opts.reason;
1489
+ writeQueue(meshId, queue);
1490
+ return queue[idx];
1491
+ });
1455
1492
  }
1456
1493
  function requeueTask(meshId, taskId, opts) {
1457
- const queue = readQueue(meshId);
1458
- const idx = queue.findIndex((q) => q.id === taskId);
1459
- if (idx === -1) return null;
1460
- const entry = queue[idx];
1461
- const now = (/* @__PURE__ */ new Date()).toISOString();
1462
- entry.status = "pending";
1463
- delete entry.assignedNodeId;
1464
- delete entry.assignedSessionId;
1465
- delete entry.cancelledAt;
1466
- delete entry.cancelReason;
1467
- if (opts?.clearTargetNode) delete entry.targetNodeId;
1468
- if (typeof opts?.targetNodeId === "string") entry.targetNodeId = opts.targetNodeId;
1469
- if (opts?.clearTargetSession !== false) delete entry.targetSessionId;
1470
- if (typeof opts?.targetSessionId === "string") entry.targetSessionId = opts.targetSessionId;
1471
- entry.updatedAt = now;
1472
- entry.requeuedAt = now;
1473
- entry.requeueCount = (entry.requeueCount || 0) + 1;
1474
- if (opts?.reason) entry.requeueReason = opts.reason;
1475
- writeQueue(meshId, queue);
1476
- return entry;
1477
- }
1478
- function updateSessionTaskStatus(meshId, sessionId, status) {
1479
- const queue = readQueue(meshId);
1480
- let bestIdx = -1;
1481
- let bestTime = 0;
1482
- for (let i = queue.length - 1; i >= 0; i--) {
1483
- if (queue[i].assignedSessionId === sessionId && queue[i].status === "assigned") {
1494
+ return withQueueLock(meshId, () => {
1495
+ const queue = readQueue(meshId);
1496
+ const idx = queue.findIndex((q) => q.id === taskId);
1497
+ if (idx === -1) return null;
1498
+ const entry = queue[idx];
1499
+ const now = (/* @__PURE__ */ new Date()).toISOString();
1500
+ entry.status = "pending";
1501
+ delete entry.assignedNodeId;
1502
+ delete entry.assignedSessionId;
1503
+ delete entry.cancelledAt;
1504
+ delete entry.cancelReason;
1505
+ if (opts?.clearTargetNode) delete entry.targetNodeId;
1506
+ if (typeof opts?.targetNodeId === "string") entry.targetNodeId = opts.targetNodeId;
1507
+ if (opts?.clearTargetSession !== false) delete entry.targetSessionId;
1508
+ if (typeof opts?.targetSessionId === "string") entry.targetSessionId = opts.targetSessionId;
1509
+ entry.updatedAt = now;
1510
+ entry.requeuedAt = now;
1511
+ entry.requeueCount = (entry.requeueCount || 0) + 1;
1512
+ if (opts?.reason) entry.requeueReason = opts.reason;
1513
+ writeQueue(meshId, queue);
1514
+ return entry;
1515
+ });
1516
+ }
1517
+ function updateSessionTaskStatus(meshId, sessionId, status, opts) {
1518
+ return withQueueLock(meshId, () => {
1519
+ const queue = readQueue(meshId);
1520
+ const occurredAtTime = opts?.occurredAt ? new Date(opts.occurredAt).getTime() : Number.NaN;
1521
+ const hasOccurredAt = Number.isFinite(occurredAtTime);
1522
+ let bestIdx = -1;
1523
+ let bestTime = 0;
1524
+ for (let i = queue.length - 1; i >= 0; i--) {
1525
+ if (queue[i].assignedSessionId !== sessionId || queue[i].status !== "assigned") continue;
1484
1526
  const time = new Date(queue[i].dispatchTimestamp || queue[i].updatedAt).getTime();
1527
+ if (hasOccurredAt && Number.isFinite(time) && time > occurredAtTime) continue;
1485
1528
  if (time > bestTime) {
1486
1529
  bestTime = time;
1487
1530
  bestIdx = i;
1488
1531
  }
1489
1532
  }
1490
- }
1491
- if (bestIdx === -1) return null;
1492
- queue[bestIdx].status = status;
1493
- queue[bestIdx].updatedAt = (/* @__PURE__ */ new Date()).toISOString();
1494
- writeQueue(meshId, queue);
1495
- return queue[bestIdx];
1533
+ if (bestIdx === -1) return null;
1534
+ queue[bestIdx].status = status;
1535
+ queue[bestIdx].updatedAt = (/* @__PURE__ */ new Date()).toISOString();
1536
+ writeQueue(meshId, queue);
1537
+ return queue[bestIdx];
1538
+ });
1496
1539
  }
1497
1540
  function getMeshQueueStats(meshId) {
1498
1541
  const queue = readQueue(meshId);
@@ -1896,18 +1939,75 @@ __export(mesh_events_exports, {
1896
1939
  drainPendingMeshCoordinatorEvents: () => drainPendingMeshCoordinatorEvents,
1897
1940
  getPendingMeshCoordinatorEvents: () => getPendingMeshCoordinatorEvents,
1898
1941
  handleMeshForwardEvent: () => handleMeshForwardEvent,
1942
+ queuePendingMeshCoordinatorEvent: () => queuePendingMeshCoordinatorEvent,
1899
1943
  setupMeshEventForwarding: () => setupMeshEventForwarding,
1900
1944
  triggerMeshQueue: () => triggerMeshQueue,
1901
1945
  tryAssignQueueTask: () => tryAssignQueueTask
1902
1946
  });
1903
- function drainPendingMeshCoordinatorEvents() {
1904
- return pendingMeshCoordinatorEvents.splice(0);
1947
+ function sweepExpiredRemoteIdleSessions() {
1948
+ const now = Date.now();
1949
+ for (const [key, session] of remoteIdleSessions) {
1950
+ if (session.expiresAt <= now) remoteIdleSessions.delete(key);
1951
+ }
1952
+ }
1953
+ function getPendingEventsPath(meshId) {
1954
+ const safe = meshId.replace(/[^a-zA-Z0-9_-]/g, "_");
1955
+ return (0, import_path5.join)(getLedgerDir(), `${safe}.pending-events.jsonl`);
1905
1956
  }
1906
- function getPendingMeshCoordinatorEvents() {
1907
- return pendingMeshCoordinatorEvents.slice();
1957
+ function queuePendingMeshCoordinatorEvent(event) {
1958
+ try {
1959
+ (0, import_fs6.appendFileSync)(getPendingEventsPath(event.meshId), JSON.stringify(event) + "\n", "utf-8");
1960
+ return true;
1961
+ } catch (e) {
1962
+ LOG.warn("MeshEvents", `Failed to persist pending coordinator event: ${e?.message || e}`);
1963
+ return false;
1964
+ }
1908
1965
  }
1909
- function clearPendingMeshCoordinatorEvents() {
1910
- pendingMeshCoordinatorEvents.splice(0);
1966
+ function drainPendingMeshCoordinatorEvents(meshId) {
1967
+ if (!meshId) return [];
1968
+ const path28 = getPendingEventsPath(meshId);
1969
+ if (!(0, import_fs6.existsSync)(path28)) return [];
1970
+ try {
1971
+ const raw = (0, import_fs6.readFileSync)(path28, "utf-8");
1972
+ try {
1973
+ (0, import_fs6.unlinkSync)(path28);
1974
+ } catch {
1975
+ }
1976
+ return raw.split("\n").filter(Boolean).flatMap((line) => {
1977
+ try {
1978
+ return [JSON.parse(line)];
1979
+ } catch {
1980
+ return [];
1981
+ }
1982
+ });
1983
+ } catch {
1984
+ return [];
1985
+ }
1986
+ }
1987
+ function getPendingMeshCoordinatorEvents(meshId) {
1988
+ if (!meshId) return [];
1989
+ const path28 = getPendingEventsPath(meshId);
1990
+ if (!(0, import_fs6.existsSync)(path28)) return [];
1991
+ try {
1992
+ const raw = (0, import_fs6.readFileSync)(path28, "utf-8");
1993
+ return raw.split("\n").filter(Boolean).flatMap((line) => {
1994
+ try {
1995
+ return [JSON.parse(line)];
1996
+ } catch {
1997
+ return [];
1998
+ }
1999
+ });
2000
+ } catch {
2001
+ return [];
2002
+ }
2003
+ }
2004
+ function clearPendingMeshCoordinatorEvents(meshId) {
2005
+ if (!meshId) return;
2006
+ const path28 = getPendingEventsPath(meshId);
2007
+ if ((0, import_fs6.existsSync)(path28)) try {
2008
+ (0, import_fs6.unlinkSync)(path28);
2009
+ } catch {
2010
+ }
1911
2011
  }
1912
2012
  function readNonEmptyString(value) {
1913
2013
  return typeof value === "string" && value.trim() ? value.trim() : "";
@@ -1953,6 +2053,38 @@ function shouldSuppressIntentionalCleanupStop(args) {
1953
2053
  if (isIntentionalCleanupStopMetadata(args.metadataEvent)) return true;
1954
2054
  return hasRecentIntentionalCleanupStop(args.meshId, args.sessionId, args.nodeId);
1955
2055
  }
2056
+ function readEventTimestamp(value) {
2057
+ if (typeof value === "number" && Number.isFinite(value)) return value;
2058
+ if (typeof value === "string" && value.trim()) {
2059
+ const numeric = Number(value);
2060
+ if (Number.isFinite(numeric)) return numeric;
2061
+ const parsed = Date.parse(value);
2062
+ if (Number.isFinite(parsed)) return parsed;
2063
+ }
2064
+ return null;
2065
+ }
2066
+ function buildMeshCompletionFingerprint(args) {
2067
+ const timestampPart = Number.isFinite(args.timestamp) ? String(args.timestamp) : readNonEmptyString(args.finalSummary).slice(0, 200);
2068
+ return [
2069
+ args.meshId,
2070
+ args.event,
2071
+ args.sessionId,
2072
+ args.providerType || "",
2073
+ args.providerSessionId || "",
2074
+ timestampPart
2075
+ ].join("::");
2076
+ }
2077
+ function isDuplicateMeshCompletionEvent(args) {
2078
+ const fingerprint = buildMeshCompletionFingerprint(args);
2079
+ if (!fingerprint) return false;
2080
+ const now = Date.now();
2081
+ for (const [key, seenAt] of recentCompletionFingerprints.entries()) {
2082
+ if (now - seenAt > RECENT_COMPLETION_FINGERPRINT_TTL_MS) recentCompletionFingerprints.delete(key);
2083
+ }
2084
+ if (recentCompletionFingerprints.has(fingerprint)) return true;
2085
+ recentCompletionFingerprints.set(fingerprint, now);
2086
+ return false;
2087
+ }
1956
2088
  function tryAssignQueueTask(components, meshId, nodeId, sessionId, providerType) {
1957
2089
  const task = claimNextTask(meshId, nodeId, sessionId);
1958
2090
  if (!task) {
@@ -1971,7 +2103,16 @@ function tryAssignQueueTask(components, meshId, nodeId, sessionId, providerType)
1971
2103
  message: task.message
1972
2104
  }).catch((e) => {
1973
2105
  LOG.error("MeshQueue", `Failed to dispatch task via P2P to remote node ${nodeId}: ${e?.message}`);
1974
- updateTaskStatus(meshId, task.id, "failed");
2106
+ updateTaskStatus(meshId, task.id, "pending");
2107
+ try {
2108
+ appendLedgerEntry(meshId, {
2109
+ kind: "dispatch_failed",
2110
+ nodeId,
2111
+ sessionId,
2112
+ payload: { taskId: task.id, error: e?.message, retryable: true }
2113
+ });
2114
+ } catch {
2115
+ }
1975
2116
  });
1976
2117
  return true;
1977
2118
  }
@@ -2305,18 +2446,36 @@ function injectMeshSystemMessage(components, args) {
2305
2446
  LOG.info("MeshEvents", `Suppressed ${args.event} for intentionally cleanup-stopped session ${eventSessionId || "(unknown session)"}`);
2306
2447
  return { success: true, forwarded: 0, suppressed: true, intentionalCleanupStop: true };
2307
2448
  }
2449
+ const eventTimestamp = readEventTimestamp(args.metadataEvent.timestamp);
2450
+ if (args.event === "agent:generating_completed" && eventSessionId) {
2451
+ const duplicateCompletion = isDuplicateMeshCompletionEvent({
2452
+ meshId: args.meshId,
2453
+ event: args.event,
2454
+ sessionId: eventSessionId,
2455
+ providerType: readNonEmptyString(args.metadataEvent.providerType) || void 0,
2456
+ providerSessionId: readNonEmptyString(args.metadataEvent.providerSessionId) || void 0,
2457
+ timestamp: eventTimestamp,
2458
+ finalSummary: readNonEmptyString(args.metadataEvent.finalSummary) || void 0
2459
+ });
2460
+ if (duplicateCompletion) {
2461
+ LOG.info("MeshEvents", `Suppressed duplicate completion for mesh ${args.meshId} session ${eventSessionId}`);
2462
+ return { success: true, forwarded: 0, suppressed: true, duplicateCompletion: true };
2463
+ }
2464
+ }
2308
2465
  let completedTaskForLedger = null;
2309
2466
  if (args.event === "agent:generating_completed") {
2310
2467
  const sessionId = resolveEventSessionId(args.metadataEvent, args.sourceInstanceId);
2311
2468
  const nodeId = readNonEmptyString(args.nodeId) || readNonEmptyString(args.metadataEvent.meshNodeId);
2312
2469
  const providerType = readNonEmptyString(args.metadataEvent.providerType);
2313
2470
  if (sessionId) {
2314
- const completedTask = updateSessionTaskStatus(args.meshId, sessionId, "completed");
2471
+ const completedTask = updateSessionTaskStatus(args.meshId, sessionId, "completed", {
2472
+ occurredAt: eventTimestamp !== null ? new Date(eventTimestamp).toISOString() : void 0
2473
+ });
2315
2474
  completedTaskForLedger = completedTask ? { id: completedTask.id } : null;
2316
2475
  if (nodeId && providerType) {
2317
- setTimeout(() => {
2476
+ setImmediate(() => {
2318
2477
  tryAssignQueueTask(components, args.meshId, nodeId, sessionId, providerType);
2319
- }, 500);
2478
+ });
2320
2479
  }
2321
2480
  }
2322
2481
  } else if (args.event === "agent:ready") {
@@ -2354,13 +2513,17 @@ function injectMeshSystemMessage(components, args) {
2354
2513
  }
2355
2514
  }
2356
2515
  if (sessionId && nodeId && providerType) {
2357
- remoteIdleSessions.set(`${nodeId}:${sessionId}`, { nodeId, sessionId, providerType });
2358
- setTimeout(() => {
2516
+ sweepExpiredRemoteIdleSessions();
2517
+ remoteIdleSessions.set(`${nodeId}:${sessionId}`, {
2518
+ nodeId,
2519
+ sessionId,
2520
+ providerType,
2521
+ expiresAt: Date.now() + REMOTE_IDLE_SESSION_TTL_MS
2522
+ });
2523
+ setImmediate(() => {
2359
2524
  const assigned = tryAssignQueueTask(components, args.meshId, nodeId, sessionId, providerType);
2360
- if (assigned) {
2361
- remoteIdleSessions.delete(`${nodeId}:${sessionId}`);
2362
- }
2363
- }, 500);
2525
+ if (assigned) remoteIdleSessions.delete(`${nodeId}:${sessionId}`);
2526
+ });
2364
2527
  }
2365
2528
  } else if (args.event === "agent:generating_started") {
2366
2529
  const sessionId = resolveEventSessionId(args.metadataEvent, args.sourceInstanceId);
@@ -2471,17 +2634,18 @@ function injectMeshSystemMessage(components, args) {
2471
2634
  return true;
2472
2635
  });
2473
2636
  if (coordinatorInstances.length === 0) {
2474
- if (pendingMeshCoordinatorEvents.length < MAX_PENDING_EVENTS) {
2475
- pendingMeshCoordinatorEvents.push({
2476
- event: args.event,
2477
- meshId: args.meshId,
2478
- nodeLabel: args.nodeLabel,
2479
- metadataEvent: {
2480
- ...args.metadataEvent,
2481
- ...recoveryContext ? { recoveryContext } : {}
2482
- },
2483
- queuedAt: Date.now()
2484
- });
2637
+ if (queuePendingMeshCoordinatorEvent({
2638
+ event: args.event,
2639
+ meshId: args.meshId,
2640
+ nodeLabel: args.nodeLabel,
2641
+ nodeId: args.nodeId || void 0,
2642
+ workspace: readNonEmptyString(args.metadataEvent.workspace),
2643
+ metadataEvent: {
2644
+ ...args.metadataEvent,
2645
+ ...recoveryContext ? { recoveryContext } : {}
2646
+ },
2647
+ queuedAt: Date.now()
2648
+ })) {
2485
2649
  LOG.info("MeshEvents", `Queued ${args.event} for MCP coordinator (mesh ${args.meshId})`);
2486
2650
  }
2487
2651
  return { success: true, forwarded: 0 };
@@ -2520,6 +2684,7 @@ function handleMeshForwardEvent(components, payload) {
2520
2684
  providerType: readNonEmptyString(payload.providerType),
2521
2685
  providerSessionId: readNonEmptyString(payload.providerSessionId),
2522
2686
  finalSummary: readNonEmptyString(payload.finalSummary) || readNonEmptyString(payload.summary),
2687
+ ...payload.timestamp !== void 0 ? { timestamp: payload.timestamp } : {},
2523
2688
  intentional: payload.intentional === true,
2524
2689
  intentionalStop: payload.intentionalStop === true,
2525
2690
  operatorCleanup: payload.operatorCleanup === true,
@@ -2562,19 +2727,20 @@ function setupMeshEventForwarding(components) {
2562
2727
  });
2563
2728
  });
2564
2729
  }
2565
- var remoteIdleSessions, MAX_PENDING_EVENTS, pendingMeshCoordinatorEvents, MESH_COORDINATOR_EVENTS, EVENT_TO_LEDGER_KIND, INTENTIONAL_CLEANUP_STOP_SUPPRESSION_MS, autoLaunchInProgress, autoLaunchCooldownUntil, AUTO_LAUNCH_COOLDOWN_MS;
2730
+ var import_fs6, import_path5, 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;
2566
2731
  var init_mesh_events = __esm({
2567
2732
  "src/mesh/mesh-events.ts"() {
2568
2733
  "use strict";
2734
+ import_fs6 = require("fs");
2735
+ import_path5 = require("path");
2569
2736
  init_config();
2570
2737
  init_mesh_config();
2571
2738
  init_cli_detector();
2572
2739
  init_logger();
2573
2740
  init_mesh_ledger();
2574
2741
  init_mesh_work_queue();
2742
+ REMOTE_IDLE_SESSION_TTL_MS = 5 * 60 * 1e3;
2575
2743
  remoteIdleSessions = /* @__PURE__ */ new Map();
2576
- MAX_PENDING_EVENTS = 50;
2577
- pendingMeshCoordinatorEvents = [];
2578
2744
  MESH_COORDINATOR_EVENTS = /* @__PURE__ */ new Set([
2579
2745
  "agent:generating_started",
2580
2746
  "agent:generating_completed",
@@ -2590,6 +2756,8 @@ var init_mesh_events = __esm({
2590
2756
  "monitor:long_generating": "task_stalled"
2591
2757
  };
2592
2758
  INTENTIONAL_CLEANUP_STOP_SUPPRESSION_MS = 30 * 60 * 1e3;
2759
+ RECENT_COMPLETION_FINGERPRINT_TTL_MS = 10 * 60 * 1e3;
2760
+ recentCompletionFingerprints = /* @__PURE__ */ new Map();
2593
2761
  autoLaunchInProgress = /* @__PURE__ */ new Set();
2594
2762
  autoLaunchCooldownUntil = /* @__PURE__ */ new Map();
2595
2763
  AUTO_LAUNCH_COOLDOWN_MS = 5e3;
@@ -5860,6 +6028,7 @@ __export(index_exports, {
5860
6028
  prepareSessionChatTailUpdate: () => prepareSessionChatTailUpdate,
5861
6029
  prepareSessionModalUpdate: () => prepareSessionModalUpdate,
5862
6030
  probeCdpPort: () => probeCdpPort,
6031
+ queuePendingMeshCoordinatorEvent: () => queuePendingMeshCoordinatorEvent,
5863
6032
  readChatHistory: () => readChatHistory,
5864
6033
  readLedgerEntries: () => readLedgerEntries,
5865
6034
  readLedgerSlice: () => readLedgerSlice,
@@ -5913,8 +6082,14 @@ async function getGitRepoStatus(workspace, options = {}) {
5913
6082
  const includeSubmodules = options.includeSubmodules !== false;
5914
6083
  try {
5915
6084
  const repo = await resolveGitRepository(workspace, options);
5916
- const statusOutput = await runGit(repo, ["status", "--porcelain=v2", "--branch"], options);
5917
- const parsed = parsePorcelainV2Status(statusOutput.stdout);
6085
+ let parsed = await readPorcelainStatus(repo, options);
6086
+ let upstreamProbe = getInitialUpstreamProbe(parsed);
6087
+ if (options.refreshUpstream) {
6088
+ upstreamProbe = await refreshTrackedUpstream(repo, parsed, options);
6089
+ if (upstreamProbe.upstreamStatus === "fresh") {
6090
+ parsed = await readPorcelainStatus(repo, options);
6091
+ }
6092
+ }
5918
6093
  const head = await readHead(repo, options);
5919
6094
  const stashCount = await readStashCount(repo, options);
5920
6095
  let submodules;
@@ -5929,6 +6104,9 @@ async function getGitRepoStatus(workspace, options = {}) {
5929
6104
  headCommit: head.commit,
5930
6105
  headMessage: head.message,
5931
6106
  upstream: parsed.upstream,
6107
+ upstreamStatus: parsed.upstream ? upstreamProbe.upstreamStatus : "no_upstream",
6108
+ upstreamFetchedAt: upstreamProbe.upstreamFetchedAt,
6109
+ upstreamFetchError: upstreamProbe.upstreamFetchError,
5932
6110
  ahead: parsed.ahead,
5933
6111
  behind: parsed.behind,
5934
6112
  staged: parsed.staged,
@@ -5953,6 +6131,60 @@ async function getGitRepoStatus(workspace, options = {}) {
5953
6131
  );
5954
6132
  }
5955
6133
  }
6134
+ async function readPorcelainStatus(repo, options) {
6135
+ const statusOutput = await runGit(repo, ["status", "--porcelain=v2", "--branch"], options);
6136
+ return parsePorcelainV2Status(statusOutput.stdout);
6137
+ }
6138
+ function getInitialUpstreamProbe(parsed) {
6139
+ return {
6140
+ upstreamStatus: parsed.upstream ? "unchecked" : "no_upstream"
6141
+ };
6142
+ }
6143
+ async function refreshTrackedUpstream(repo, parsed, options) {
6144
+ if (!parsed.upstream || !parsed.branch) {
6145
+ return { upstreamStatus: "no_upstream" };
6146
+ }
6147
+ const remoteName = await readBranchRemote(repo, parsed.branch, options) ?? inferRemoteName(parsed.upstream);
6148
+ if (!remoteName) {
6149
+ return {
6150
+ upstreamStatus: "stale",
6151
+ upstreamFetchError: `Unable to resolve remote for upstream '${parsed.upstream}'`
6152
+ };
6153
+ }
6154
+ try {
6155
+ await runGit(repo, ["fetch", "--quiet", "--prune", "--no-tags", remoteName], options);
6156
+ return {
6157
+ upstreamStatus: "fresh",
6158
+ upstreamFetchedAt: Date.now()
6159
+ };
6160
+ } catch (error) {
6161
+ return {
6162
+ upstreamStatus: "stale",
6163
+ upstreamFetchError: formatGitError(error)
6164
+ };
6165
+ }
6166
+ }
6167
+ async function readBranchRemote(repo, branch, options) {
6168
+ try {
6169
+ const result = await runGit(repo, ["config", "--get", `branch.${branch}.remote`], options);
6170
+ return result.stdout.trim() || null;
6171
+ } catch {
6172
+ return null;
6173
+ }
6174
+ }
6175
+ function inferRemoteName(upstream) {
6176
+ const [remoteName] = upstream.split("/");
6177
+ return remoteName?.trim() || null;
6178
+ }
6179
+ function formatGitError(error) {
6180
+ if (error instanceof GitCommandError) {
6181
+ return error.stderr || error.message;
6182
+ }
6183
+ if (error instanceof Error) {
6184
+ return error.message;
6185
+ }
6186
+ return String(error);
6187
+ }
5956
6188
  function parsePorcelainV2Status(output) {
5957
6189
  const parsed = {
5958
6190
  branch: null,
@@ -6047,6 +6279,7 @@ function emptyStatus(workspace, lastCheckedAt, error) {
6047
6279
  headCommit: null,
6048
6280
  headMessage: null,
6049
6281
  upstream: null,
6282
+ upstreamStatus: "unavailable",
6050
6283
  ahead: 0,
6051
6284
  behind: 0,
6052
6285
  staged: 0,
@@ -6327,6 +6560,9 @@ function createGitCompactSummary(status, diffSummary) {
6327
6560
  isGitRepo: status.isGitRepo,
6328
6561
  repoRoot: status.repoRoot,
6329
6562
  branch: status.branch,
6563
+ upstreamStatus: status.upstreamStatus,
6564
+ upstreamFetchedAt: status.upstreamFetchedAt,
6565
+ upstreamFetchError: status.upstreamFetchError,
6330
6566
  dirty: status.staged > 0 || status.modified > 0 || status.untracked > 0 || status.deleted > 0 || status.renamed > 0 || conflictCount > 0 || changedFiles > 0,
6331
6567
  changedFiles,
6332
6568
  ahead: status.ahead,
@@ -6671,7 +6907,7 @@ var defaultSnapshotStore = createGitSnapshotStore({
6671
6907
  });
6672
6908
  function createDefaultGitCommandServices() {
6673
6909
  return {
6674
- getStatus: ({ workspace }) => getGitRepoStatus(workspace),
6910
+ getStatus: ({ workspace, refreshUpstream }) => getGitRepoStatus(workspace, { refreshUpstream }),
6675
6911
  getDiffSummary: ({ workspace }) => getGitDiffSummary(workspace),
6676
6912
  getDiffFile: ({ workspace, path: filePath }) => getGitFileDiff(workspace, filePath),
6677
6913
  createSnapshot: ({ workspace, reason, sessionId, turnId }) => defaultSnapshotStore.create({
@@ -6757,7 +6993,7 @@ async function handleGitCommand(command, args, services = defaultGitCommandServi
6757
6993
  switch (command) {
6758
6994
  case "git_status": {
6759
6995
  if (!services.getStatus) return serviceNotImplemented(command);
6760
- const status = await runService(() => services.getStatus({ workspace }));
6996
+ const status = await runService(() => services.getStatus({ workspace, refreshUpstream: optionalBoolean(args?.refreshUpstream) }));
6761
6997
  return "success" in status ? status : { success: true, status };
6762
6998
  }
6763
6999
  case "git_diff_summary": {
@@ -7795,8 +8031,8 @@ var P2pRelayFailureError = class extends Error {
7795
8031
  };
7796
8032
 
7797
8033
  // src/config/state-store.ts
7798
- var import_fs6 = require("fs");
7799
- var import_path5 = require("path");
8034
+ var import_fs7 = require("fs");
8035
+ var import_path6 = require("path");
7800
8036
  init_config();
7801
8037
  var DEFAULT_STATE = {
7802
8038
  recentActivity: [],
@@ -7810,7 +8046,7 @@ function isPlainObject2(value) {
7810
8046
  return !!value && typeof value === "object" && !Array.isArray(value);
7811
8047
  }
7812
8048
  function getStatePath() {
7813
- return (0, import_path5.join)(getConfigDir(), "state.json");
8049
+ return (0, import_path6.join)(getConfigDir(), "state.json");
7814
8050
  }
7815
8051
  function normalizeState(raw) {
7816
8052
  const parsed = isPlainObject2(raw) ? raw : {};
@@ -7846,11 +8082,11 @@ function normalizeState(raw) {
7846
8082
  }
7847
8083
  function loadState() {
7848
8084
  const statePath = getStatePath();
7849
- if (!(0, import_fs6.existsSync)(statePath)) {
8085
+ if (!(0, import_fs7.existsSync)(statePath)) {
7850
8086
  return { ...DEFAULT_STATE };
7851
8087
  }
7852
8088
  try {
7853
- const raw = (0, import_fs6.readFileSync)(statePath, "utf-8");
8089
+ const raw = (0, import_fs7.readFileSync)(statePath, "utf-8");
7854
8090
  return normalizeState(JSON.parse(raw));
7855
8091
  } catch {
7856
8092
  return { ...DEFAULT_STATE };
@@ -7859,7 +8095,7 @@ function loadState() {
7859
8095
  function saveState(state) {
7860
8096
  const statePath = getStatePath();
7861
8097
  const normalized = normalizeState(state);
7862
- (0, import_fs6.writeFileSync)(statePath, JSON.stringify(normalized, null, 2), { encoding: "utf-8", mode: 384 });
8098
+ (0, import_fs7.writeFileSync)(statePath, JSON.stringify(normalized, null, 2), { encoding: "utf-8", mode: 384 });
7863
8099
  }
7864
8100
  function resetState() {
7865
8101
  saveState({ ...DEFAULT_STATE });
@@ -7867,7 +8103,7 @@ function resetState() {
7867
8103
 
7868
8104
  // src/detection/ide-detector.ts
7869
8105
  var import_child_process2 = require("child_process");
7870
- var import_fs7 = require("fs");
8106
+ var import_fs8 = require("fs");
7871
8107
  var import_os2 = require("os");
7872
8108
  var path10 = __toESM(require("path"));
7873
8109
  var BUILTIN_IDE_DEFINITIONS = [];
@@ -7891,7 +8127,7 @@ function findCliCommand(command) {
7891
8127
  if (path10.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~")) {
7892
8128
  const candidate = trimmed.startsWith("~") ? path10.join((0, import_os2.homedir)(), trimmed.slice(1)) : trimmed;
7893
8129
  const resolved = path10.isAbsolute(candidate) ? candidate : path10.resolve(candidate);
7894
- return (0, import_fs7.existsSync)(resolved) ? resolved : null;
8130
+ return (0, import_fs8.existsSync)(resolved) ? resolved : null;
7895
8131
  }
7896
8132
  try {
7897
8133
  const result = (0, import_child_process2.execSync)(
@@ -7922,9 +8158,9 @@ function checkPathExists(paths) {
7922
8158
  if (normalized.includes("*")) {
7923
8159
  const username = home.split(/[\\/]/).pop() || "";
7924
8160
  const resolved = normalized.replace("*", username);
7925
- if ((0, import_fs7.existsSync)(resolved)) return resolved;
8161
+ if ((0, import_fs8.existsSync)(resolved)) return resolved;
7926
8162
  } else {
7927
- if ((0, import_fs7.existsSync)(normalized)) return normalized;
8163
+ if ((0, import_fs8.existsSync)(normalized)) return normalized;
7928
8164
  }
7929
8165
  }
7930
8166
  return null;
@@ -7938,7 +8174,7 @@ async function detectIDEs(providerLoader) {
7938
8174
  let resolvedCli = cliPath;
7939
8175
  if (!resolvedCli && appPath && os22 === "darwin") {
7940
8176
  const bundledCli = `${appPath}/Contents/Resources/app/bin/${def.cli}`;
7941
- if ((0, import_fs7.existsSync)(bundledCli)) resolvedCli = bundledCli;
8177
+ if ((0, import_fs8.existsSync)(bundledCli)) resolvedCli = bundledCli;
7942
8178
  }
7943
8179
  if (!resolvedCli && appPath && os22 === "win32") {
7944
8180
  const { dirname: dirname9 } = await import("path");
@@ -7951,7 +8187,7 @@ async function detectIDEs(providerLoader) {
7951
8187
  `${appDir}\\\\resources\\\\app\\\\bin\\\\${def.cli}.cmd`
7952
8188
  ];
7953
8189
  for (const c of candidates) {
7954
- if ((0, import_fs7.existsSync)(c)) {
8190
+ if ((0, import_fs8.existsSync)(c)) {
7955
8191
  resolvedCli = c;
7956
8192
  break;
7957
8193
  }
@@ -9843,7 +10079,8 @@ var StatusMonitor = class {
9843
10079
  };
9844
10080
 
9845
10081
  // src/providers/chat-message-normalization.ts
9846
- function extractFinalSummaryFromMessages(messages, maxChars = 500) {
10082
+ var DEFAULT_FINAL_SUMMARY_MAX_CHARS = 4e3;
10083
+ function extractFinalSummaryFromMessages(messages, maxChars = DEFAULT_FINAL_SUMMARY_MAX_CHARS) {
9847
10084
  if (!Array.isArray(messages) || messages.length === 0) return "";
9848
10085
  for (let i = messages.length - 1; i >= 0; i--) {
9849
10086
  const msg = messages[i];
@@ -17103,7 +17340,7 @@ var DaemonCommandHandler = class {
17103
17340
  var os13 = __toESM(require("os"));
17104
17341
  var path18 = __toESM(require("path"));
17105
17342
  var crypto4 = __toESM(require("crypto"));
17106
- var import_fs8 = require("fs");
17343
+ var import_fs9 = require("fs");
17107
17344
  var import_child_process6 = require("child_process");
17108
17345
  var import_chalk = __toESM(require("chalk"));
17109
17346
  init_provider_cli_adapter();
@@ -19575,7 +19812,7 @@ function commandExists(command) {
19575
19812
  const trimmed = command.trim();
19576
19813
  if (!trimmed) return false;
19577
19814
  if (isExplicitCommand(trimmed)) {
19578
- return (0, import_fs8.existsSync)(expandExecutable(trimmed));
19815
+ return (0, import_fs9.existsSync)(expandExecutable(trimmed));
19579
19816
  }
19580
19817
  try {
19581
19818
  (0, import_child_process6.execFileSync)(process.platform === "win32" ? "where" : "which", [trimmed], {
@@ -19604,10 +19841,10 @@ function hasCliArg(args, flag) {
19604
19841
  }
19605
19842
  function ensureEmptyDelegatedMcpConfig(workspace) {
19606
19843
  const baseDir = path18.join(os13.tmpdir(), "adhdev-delegated-agent-empty-mcp");
19607
- (0, import_fs8.mkdirSync)(baseDir, { recursive: true });
19844
+ (0, import_fs9.mkdirSync)(baseDir, { recursive: true });
19608
19845
  const workspaceHash = crypto4.createHash("sha256").update(path18.resolve(workspace || os13.tmpdir())).digest("hex").slice(0, 16);
19609
19846
  const filePath = path18.join(baseDir, `${workspaceHash}.json`);
19610
- (0, import_fs8.writeFileSync)(filePath, JSON.stringify({ mcpServers: {} }, null, 2), "utf-8");
19847
+ (0, import_fs9.writeFileSync)(filePath, JSON.stringify({ mcpServers: {} }, null, 2), "utf-8");
19611
19848
  return filePath;
19612
19849
  }
19613
19850
  function buildCoordinatorDelegatedCliLaunchOptions(input) {
@@ -23786,7 +24023,7 @@ async function maybeRunDaemonUpgradeHelperFromEnv() {
23786
24023
 
23787
24024
  // src/commands/router.ts
23788
24025
  var import_os3 = require("os");
23789
- var import_path6 = require("path");
24026
+ var import_path7 = require("path");
23790
24027
  var fs10 = __toESM(require("fs"));
23791
24028
  var CHANNEL_NPM_TAG = { stable: "latest", preview: "next" };
23792
24029
  var CHANNEL_SERVER_URL = {
@@ -23835,55 +24072,45 @@ function readBooleanValue(...values) {
23835
24072
  }
23836
24073
  return void 0;
23837
24074
  }
23838
- function buildCachedInlineMeshGitStatus(node) {
23839
- const cachedStatus = readObjectRecord(node?.cachedStatus);
23840
- const cachedGit = readObjectRecord(cachedStatus.git);
23841
- if (Object.keys(cachedGit).length) {
23842
- const conflictFiles2 = Array.isArray(cachedGit.conflictFiles) ? cachedGit.conflictFiles.filter((value) => typeof value === "string") : [];
23843
- const conflictCount2 = readNumberValue(cachedGit.conflicts) ?? conflictFiles2.length;
23844
- const hasConflicts2 = readBooleanValue(cachedGit.hasConflicts) ?? conflictCount2 > 0;
23845
- const isGitRepo2 = readBooleanValue(cachedGit.isGitRepo);
23846
- if (isGitRepo2 !== void 0) {
23847
- return {
23848
- workspace: readStringValue(cachedGit.workspace, node?.workspace) || "",
23849
- repoRoot: readStringValue(cachedGit.repoRoot, node?.repoRoot, node?.workspace) || null,
23850
- isGitRepo: isGitRepo2,
23851
- branch: readStringValue(cachedGit.branch) ?? null,
23852
- headCommit: readStringValue(cachedGit.headCommit) ?? null,
23853
- headMessage: readStringValue(cachedGit.headMessage) ?? null,
23854
- upstream: readStringValue(cachedGit.upstream) ?? null,
23855
- ahead: readNumberValue(cachedGit.ahead) ?? 0,
23856
- behind: readNumberValue(cachedGit.behind) ?? 0,
23857
- staged: readNumberValue(cachedGit.staged) ?? 0,
23858
- modified: readNumberValue(cachedGit.modified) ?? 0,
23859
- untracked: readNumberValue(cachedGit.untracked) ?? 0,
23860
- deleted: readNumberValue(cachedGit.deleted) ?? 0,
23861
- renamed: readNumberValue(cachedGit.renamed) ?? 0,
23862
- hasConflicts: hasConflicts2,
23863
- conflictFiles: conflictFiles2,
23864
- stashCount: readNumberValue(cachedGit.stashCount) ?? 0,
23865
- lastCheckedAt: readNumberValue(cachedGit.lastCheckedAt) ?? Date.now()
23866
- };
23867
- }
23868
- }
23869
- const rawGit = readObjectRecord(node?.lastGit ?? node?.last_git);
23870
- const gitResult = readObjectRecord(rawGit.result);
23871
- const directStatus = readObjectRecord(rawGit.status);
23872
- const nestedStatus = readObjectRecord(gitResult.status);
23873
- const rawProbe = readObjectRecord(node?.lastProbe ?? node?.last_probe);
23874
- const probeGit = readObjectRecord(rawProbe.git);
23875
- const probeGitResult = readObjectRecord(probeGit.result);
23876
- const probeDirectStatus = readObjectRecord(probeGit.status);
23877
- const probeNestedStatus = readObjectRecord(probeGitResult.status);
23878
- const status = Object.keys(directStatus).length ? directStatus : Object.keys(nestedStatus).length ? nestedStatus : Object.keys(probeDirectStatus).length ? probeDirectStatus : Object.keys(probeNestedStatus).length ? probeNestedStatus : {};
24075
+ function joinRepoPath(root, relativePath) {
24076
+ const normalizedRoot = typeof root === "string" ? root.trim().replace(/[\\/]+$/, "") : "";
24077
+ const normalizedPath = typeof relativePath === "string" ? relativePath.trim() : "";
24078
+ if (!normalizedPath) return void 0;
24079
+ if (/^(?:[A-Za-z]:[\\/]|\/)/.test(normalizedPath)) return normalizedPath;
24080
+ if (!normalizedRoot) return void 0;
24081
+ return `${normalizedRoot}/${normalizedPath.replace(/^[\\/]+/, "")}`;
24082
+ }
24083
+ function readGitSubmodules(value, parentRepoRoot) {
24084
+ if (!Array.isArray(value)) return void 0;
24085
+ const submodules = value.map((entry) => {
24086
+ const submodule = readObjectRecord(entry);
24087
+ const path28 = readStringValue(submodule.path);
24088
+ const commit = readStringValue(submodule.commit);
24089
+ const repoPath = readStringValue(submodule.repoPath, submodule.repo_root) ?? joinRepoPath(parentRepoRoot, path28);
24090
+ if (!path28 || !commit || !repoPath) return null;
24091
+ return {
24092
+ path: path28,
24093
+ commit,
24094
+ repoPath,
24095
+ dirty: readBooleanValue(submodule.dirty) ?? false,
24096
+ outOfSync: readBooleanValue(submodule.outOfSync, submodule.out_of_sync) ?? false,
24097
+ lastCheckedAt: readNumberValue(submodule.lastCheckedAt, submodule.last_checked_at) ?? Date.now(),
24098
+ ...readStringValue(submodule.error) ? { error: readStringValue(submodule.error) } : {}
24099
+ };
24100
+ }).filter((entry) => entry !== null);
24101
+ return submodules.length > 0 ? submodules : void 0;
24102
+ }
24103
+ function normalizeInlineMeshGitStatus(status, node, options) {
23879
24104
  const isGitRepo = readBooleanValue(status.isGitRepo);
23880
24105
  if (!Object.keys(status).length || isGitRepo === void 0) return void 0;
23881
24106
  const conflictFiles = Array.isArray(status.conflictFiles) ? status.conflictFiles.filter((value) => typeof value === "string") : [];
23882
24107
  const conflictCount = readNumberValue(status.conflicts) ?? conflictFiles.length;
23883
24108
  const hasConflicts = readBooleanValue(status.hasConflicts) ?? conflictCount > 0;
24109
+ const repoRoot = readStringValue(status.repoRoot, status.repo_root, node?.repoRoot, node?.repo_root, status.workspace, node?.workspace) || void 0;
24110
+ const submodules = readGitSubmodules(status.submodules, repoRoot);
23884
24111
  return {
23885
24112
  workspace: readStringValue(status.workspace, node?.workspace) || "",
23886
- repoRoot: readStringValue(status.repoRoot, node?.repoRoot, node?.workspace) || null,
24113
+ repoRoot: repoRoot ?? null,
23887
24114
  isGitRepo,
23888
24115
  branch: readStringValue(status.branch) ?? null,
23889
24116
  headCommit: readStringValue(status.headCommit) ?? null,
@@ -23899,29 +24126,412 @@ function buildCachedInlineMeshGitStatus(node) {
23899
24126
  hasConflicts,
23900
24127
  conflictFiles,
23901
24128
  stashCount: readNumberValue(status.stashCount) ?? 0,
23902
- lastCheckedAt: Date.now()
24129
+ lastCheckedAt: options?.lastCheckedAt ?? readNumberValue(status.lastCheckedAt) ?? Date.now(),
24130
+ ...submodules ? { submodules } : {}
23903
24131
  };
23904
24132
  }
23905
- function applyCachedInlineMeshNodeStatus(status, node) {
24133
+ function buildInlineMeshTransitGitStatus(node) {
24134
+ const rawGit = readObjectRecord(node?.lastGit ?? node?.last_git);
24135
+ const gitResult = readObjectRecord(rawGit.result);
24136
+ const directStatus = readObjectRecord(rawGit.status);
24137
+ const nestedStatus = readObjectRecord(gitResult.status);
24138
+ const rawProbe = readObjectRecord(node?.lastProbe ?? node?.last_probe);
24139
+ const probeGit = readObjectRecord(rawProbe.git);
24140
+ const probeGitResult = readObjectRecord(probeGit.result);
24141
+ const probeDirectStatus = readObjectRecord(probeGit.status);
24142
+ const probeNestedStatus = readObjectRecord(probeGitResult.status);
24143
+ const status = Object.keys(directStatus).length ? directStatus : Object.keys(nestedStatus).length ? nestedStatus : Object.keys(probeDirectStatus).length ? probeDirectStatus : Object.keys(probeNestedStatus).length ? probeNestedStatus : {};
24144
+ return normalizeInlineMeshGitStatus(status, node, { lastCheckedAt: Date.now() });
24145
+ }
24146
+ function recordInlineMeshDirectGitTruth(node, git, source) {
24147
+ if (!node || typeof node !== "object" || Array.isArray(node)) return;
24148
+ const checkedAt = readNumberValue(git.lastCheckedAt) ?? Date.now();
24149
+ const updatedAt = new Date(checkedAt).toISOString();
24150
+ const nextGit = {
24151
+ ...git,
24152
+ lastCheckedAt: checkedAt
24153
+ };
24154
+ node.lastGit = {
24155
+ source,
24156
+ checkedAt,
24157
+ status: nextGit
24158
+ };
24159
+ node.last_git = node.lastGit;
24160
+ node.machineStatus = "online";
24161
+ node.updatedAt = updatedAt;
24162
+ node.lastSeenAt = updatedAt;
24163
+ const repoRoot = readStringValue(nextGit.repoRoot);
24164
+ if (repoRoot && !readStringValue(node.repoRoot)) node.repoRoot = repoRoot;
24165
+ }
24166
+ function buildCachedInlineMeshGitStatus(node) {
24167
+ const liveGit = buildInlineMeshTransitGitStatus(node);
24168
+ if (liveGit) return liveGit;
23906
24169
  const cachedStatus = readObjectRecord(node?.cachedStatus);
23907
- const git = buildCachedInlineMeshGitStatus(node);
23908
- const error = readStringValue(cachedStatus.error, node?.error);
23909
- const health = readStringValue(cachedStatus.health, node?.health);
24170
+ const cachedGit = readObjectRecord(cachedStatus.git);
24171
+ if (!Object.keys(cachedGit).length) return void 0;
24172
+ return normalizeInlineMeshGitStatus(cachedGit, node);
24173
+ }
24174
+ function shouldDiscardCachedInlineMeshStatus(node) {
24175
+ const cachedStatus = readObjectRecord(node?.cachedStatus);
24176
+ if (!Object.keys(cachedStatus).length) return false;
24177
+ const cachedGit = readObjectRecord(cachedStatus.git);
24178
+ const workspaceError = readStringValue(cachedStatus.error, node?.error);
24179
+ if (workspaceError && /workspace must be an existing directory/i.test(workspaceError)) return true;
24180
+ const isGitRepo = readBooleanValue(cachedGit.isGitRepo);
24181
+ const branch = readStringValue(cachedGit.branch);
24182
+ const headCommit = readStringValue(cachedGit.headCommit);
24183
+ return isGitRepo === false && !branch && !headCommit;
24184
+ }
24185
+ function stripInlineMeshTransientNodeState(node) {
24186
+ if (!node || typeof node !== "object" || Array.isArray(node)) return node;
24187
+ const {
24188
+ cachedStatus,
24189
+ lastGit: _lastGit,
24190
+ last_git: _lastGitLegacy,
24191
+ lastProbe: _lastProbe,
24192
+ last_probe: _lastProbeLegacy,
24193
+ error: _error,
24194
+ health: _health,
24195
+ machineStatus: _machineStatus,
24196
+ lastSeenAt: _lastSeenAt,
24197
+ last_seen_at: _lastSeenAtLegacy,
24198
+ updatedAt: _updatedAt,
24199
+ updated_at: _updatedAtLegacy,
24200
+ activeSession: _activeSession,
24201
+ active_session: _activeSessionLegacy,
24202
+ activeSessionId: _activeSessionId,
24203
+ active_session_id: _activeSessionIdLegacy,
24204
+ sessionId: _sessionId,
24205
+ session_id: _sessionIdLegacy,
24206
+ providerType: _providerType,
24207
+ provider_type: _providerTypeLegacy,
24208
+ ...rest
24209
+ } = node;
24210
+ if (cachedStatus && !shouldDiscardCachedInlineMeshStatus(node)) {
24211
+ return { ...rest, cachedStatus };
24212
+ }
24213
+ return rest;
24214
+ }
24215
+ function hasInlineMeshTransientNodeState(node) {
24216
+ if (!node || typeof node !== "object" || Array.isArray(node)) return false;
24217
+ 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;
24218
+ }
24219
+ function inlineMeshCarriesTransientNodeTruth(inlineMesh) {
24220
+ if (!inlineMesh || typeof inlineMesh !== "object" || Array.isArray(inlineMesh)) return false;
24221
+ if (!Array.isArray(inlineMesh.nodes) || inlineMesh.nodes.length === 0) return false;
24222
+ return inlineMesh.nodes.some((node) => hasInlineMeshTransientNodeState(node));
24223
+ }
24224
+ function readInlineMeshNodeId(node) {
24225
+ return readStringValue(node?.id, node?.nodeId) || "";
24226
+ }
24227
+ function sanitizeInlineMesh(inlineMesh) {
24228
+ if (!inlineMesh || typeof inlineMesh !== "object" || Array.isArray(inlineMesh)) return inlineMesh;
24229
+ if (!Array.isArray(inlineMesh.nodes)) return inlineMesh;
24230
+ let changed = false;
24231
+ const nodes = inlineMesh.nodes.map((node) => {
24232
+ if (!hasInlineMeshTransientNodeState(node)) return node;
24233
+ changed = true;
24234
+ return stripInlineMeshTransientNodeState(node);
24235
+ });
24236
+ if (!changed) return inlineMesh;
24237
+ return {
24238
+ ...inlineMesh,
24239
+ nodes
24240
+ };
24241
+ }
24242
+ function reconcileInlineMeshCache(cached, incoming) {
24243
+ if (!cached || typeof cached !== "object" || Array.isArray(cached)) return incoming;
24244
+ if (!incoming || typeof incoming !== "object" || Array.isArray(incoming)) return cached;
24245
+ const cachedNodes = Array.isArray(cached.nodes) ? cached.nodes : [];
24246
+ const incomingNodes = Array.isArray(incoming.nodes) ? incoming.nodes : [];
24247
+ if (!cachedNodes.length || !incomingNodes.length) return { ...cached, ...incoming };
24248
+ const incomingById = /* @__PURE__ */ new Map();
24249
+ for (const node of incomingNodes) {
24250
+ const nodeId = readInlineMeshNodeId(node);
24251
+ if (nodeId) incomingById.set(nodeId, node);
24252
+ }
24253
+ const nodes = cachedNodes.map((cachedNode) => {
24254
+ const nodeId = readInlineMeshNodeId(cachedNode);
24255
+ const incomingNode = nodeId ? incomingById.get(nodeId) : void 0;
24256
+ if (!incomingNode) return cachedNode;
24257
+ if (hasInlineMeshTransientNodeState(incomingNode)) {
24258
+ return { ...cachedNode, ...incomingNode };
24259
+ }
24260
+ return { ...stripInlineMeshTransientNodeState(cachedNode), ...incomingNode };
24261
+ });
24262
+ return {
24263
+ ...cached,
24264
+ ...incoming,
24265
+ nodes
24266
+ };
24267
+ }
24268
+ function hasGitWorktreeChanges(git) {
24269
+ if (!git) return false;
24270
+ return Number(git.staged || 0) + Number(git.modified || 0) + Number(git.untracked || 0) + Number(git.deleted || 0) + Number(git.renamed || 0) > 0;
24271
+ }
24272
+ function getGitSubmoduleDriftState(git) {
24273
+ const submodules = Array.isArray(git?.submodules) ? git.submodules : [];
24274
+ let dirty = false;
24275
+ let outOfSync = false;
24276
+ for (const entry of submodules) {
24277
+ const submodule = readObjectRecord(entry);
24278
+ if (readBooleanValue(submodule.dirty) === true) dirty = true;
24279
+ if (readBooleanValue(submodule.outOfSync) === true || !!readStringValue(submodule.error)) outOfSync = true;
24280
+ }
24281
+ return { dirty, outOfSync };
24282
+ }
24283
+ function deriveMeshNodeHealthFromGit(git) {
24284
+ if (!git || readBooleanValue(git.isGitRepo) === false) return "degraded";
24285
+ const branch = readStringValue(git.branch);
24286
+ if (!branch) return "degraded";
24287
+ const submoduleDrift = getGitSubmoduleDriftState(git);
24288
+ if (submoduleDrift.outOfSync) return "degraded";
24289
+ if (submoduleDrift.dirty || hasGitWorktreeChanges(git)) return "dirty";
24290
+ return "online";
24291
+ }
24292
+ function readCachedInlineMeshActiveSessions(node) {
24293
+ const cachedStatus = readObjectRecord(node?.cachedStatus);
24294
+ const activeSession = readObjectRecord(cachedStatus.activeSession);
24295
+ const fallbackSession = Object.keys(activeSession).length ? activeSession : readObjectRecord(node?.activeSession ?? node?.active_session);
24296
+ const sessionId = readStringValue(fallbackSession.id, fallbackSession.sessionId, fallbackSession.session_id, node?.activeSessionId, node?.active_session_id, node?.sessionId, node?.session_id);
24297
+ return sessionId ? [sessionId] : [];
24298
+ }
24299
+ function readCachedInlineMeshActiveSessionDetails(node) {
24300
+ const cachedStatus = readObjectRecord(node?.cachedStatus);
24301
+ const activeSession = readObjectRecord(cachedStatus.activeSession);
24302
+ const fallbackSession = Object.keys(activeSession).length ? activeSession : readObjectRecord(node?.activeSession ?? node?.active_session);
24303
+ const sessionId = readStringValue(
24304
+ fallbackSession.id,
24305
+ fallbackSession.sessionId,
24306
+ fallbackSession.session_id,
24307
+ node?.activeSessionId,
24308
+ node?.active_session_id,
24309
+ node?.sessionId,
24310
+ node?.session_id
24311
+ );
24312
+ if (!sessionId) return [];
24313
+ return [{
24314
+ sessionId,
24315
+ providerType: readStringValue(
24316
+ fallbackSession.providerType,
24317
+ fallbackSession.provider_type,
24318
+ fallbackSession.cliType,
24319
+ fallbackSession.cli_type,
24320
+ fallbackSession.provider,
24321
+ node?.providerType,
24322
+ node?.provider_type
24323
+ ),
24324
+ state: readStringValue(fallbackSession.status, fallbackSession.state, fallbackSession.lifecycle),
24325
+ lifecycle: readStringValue(fallbackSession.lifecycle),
24326
+ title: readStringValue(fallbackSession.title, fallbackSession.displayName, fallbackSession.display_name) ?? null,
24327
+ workspace: readStringValue(fallbackSession.workspace, node?.workspace) ?? null,
24328
+ lastActivityAt: readStringValue(fallbackSession.lastActivityAt, fallbackSession.last_activity_at) ?? null,
24329
+ recoveryState: readStringValue(fallbackSession.recoveryState, fallbackSession.recovery_state) ?? null,
24330
+ isCached: true
24331
+ }];
24332
+ }
24333
+ function readLiveMeshSessionState(record) {
24334
+ return readStringValue(
24335
+ record?.meta?.sessionStatus,
24336
+ record?.meta?.status,
24337
+ record?.meta?.providerStatus,
24338
+ record?.status,
24339
+ record?.state,
24340
+ record?.lifecycle
24341
+ );
24342
+ }
24343
+ function toIsoTimestamp(value) {
24344
+ if (typeof value === "number" && Number.isFinite(value)) return new Date(value).toISOString();
24345
+ const stringValue = readStringValue(value);
24346
+ return stringValue || null;
24347
+ }
24348
+ function synthesizeMeshNodeFreshnessFromConnection(status) {
24349
+ const connection = readObjectRecord(status.connection);
24350
+ const connectionFreshAt = toIsoTimestamp(connection.lastCommandAt ?? connection.lastConnectedAt ?? connection.lastStateChangeAt);
24351
+ const git = readObjectRecord(status.git);
24352
+ const gitCheckedAt = toIsoTimestamp(git.lastCheckedAt);
24353
+ if (!status.lastSeenAt && connectionFreshAt) status.lastSeenAt = connectionFreshAt;
24354
+ if (!status.updatedAt && (gitCheckedAt || connectionFreshAt)) {
24355
+ status.updatedAt = gitCheckedAt ?? connectionFreshAt;
24356
+ }
24357
+ }
24358
+ function finalizeMeshNodeStatus(args) {
24359
+ const { status, node, daemonId, isSelfNode } = args;
24360
+ if (!readStringValue(status.machineStatus)) {
24361
+ const cachedStatus = readObjectRecord(node?.cachedStatus);
24362
+ const machineStatus = readStringValue(cachedStatus.machineStatus, cachedStatus.machine_status, node?.machineStatus);
24363
+ if (machineStatus) status.machineStatus = machineStatus;
24364
+ }
24365
+ synthesizeMeshNodeFreshnessFromConnection(status);
24366
+ const connectionState = readStringValue(readObjectRecord(status.connection).state);
24367
+ status.launchReady = !!daemonId && (readStringValue(status.machineStatus) === "online" || connectionState === "connected" || isSelfNode);
24368
+ }
24369
+ async function probeRemoteMeshGitStatus(args) {
24370
+ if (!args.dispatchMeshCommand) return null;
24371
+ const remoteResult = await Promise.race([
24372
+ args.dispatchMeshCommand(args.daemonId, "git_status", { workspace: args.workspace }),
24373
+ new Promise((_, reject) => setTimeout(() => reject(new Error("timeout")), args.timeoutMs))
24374
+ ]);
24375
+ const remoteGit = remoteResult?.status ?? remoteResult?.git ?? remoteResult;
24376
+ return remoteGit && typeof remoteGit === "object" && typeof remoteGit.isGitRepo === "boolean" ? remoteGit : null;
24377
+ }
24378
+ async function hydrateInlineMeshDirectTruth(args) {
24379
+ const nodes = Array.isArray(args.mesh?.nodes) ? args.mesh.nodes : [];
24380
+ if (!nodes.length) {
24381
+ return {
24382
+ directEvidenceCount: 0,
24383
+ localConfirmedCount: 0,
24384
+ peerAttemptedCount: 0,
24385
+ peerConfirmedCount: 0,
24386
+ unavailableNodeIds: []
24387
+ };
24388
+ }
24389
+ const selectedCoordinatorNodeId = readStringValue(
24390
+ args.mesh?.coordinator?.preferredNodeId,
24391
+ nodes[0]?.id,
24392
+ nodes[0]?.nodeId
24393
+ );
24394
+ let localConfirmedCount = 0;
24395
+ let peerAttemptedCount = 0;
24396
+ let peerConfirmedCount = 0;
24397
+ const unavailableNodeIds = [];
24398
+ for (const [nodeIndex, node] of nodes.entries()) {
24399
+ const nodeId = readStringValue(node?.id, node?.nodeId) || `node_${nodeIndex}`;
24400
+ const workspace = readStringValue(node?.workspace);
24401
+ const daemonId = readStringValue(node?.daemonId);
24402
+ const isSelfNode = Boolean(
24403
+ nodeId && selectedCoordinatorNodeId && nodeId === selectedCoordinatorNodeId
24404
+ ) || Boolean(
24405
+ daemonId && (daemonId === args.localMachineId || daemonId === args.statusInstanceId)
24406
+ ) || Boolean(args.meshSource !== "local_config" && nodeIndex === 0);
24407
+ if (!workspace) {
24408
+ if (!isSelfNode && daemonId) unavailableNodeIds.push(nodeId);
24409
+ continue;
24410
+ }
24411
+ if (isSelfNode && fs10.existsSync(workspace)) {
24412
+ try {
24413
+ const localGit = await getGitRepoStatus(workspace, { timeoutMs: 1e4, refreshUpstream: true });
24414
+ if (localGit?.isGitRepo) {
24415
+ recordInlineMeshDirectGitTruth(node, localGit, "selected_coordinator_local_git");
24416
+ localConfirmedCount += 1;
24417
+ continue;
24418
+ }
24419
+ } catch {
24420
+ }
24421
+ }
24422
+ if (!daemonId || !args.dispatchMeshCommand) {
24423
+ if (!isSelfNode) unavailableNodeIds.push(nodeId);
24424
+ continue;
24425
+ }
24426
+ peerAttemptedCount += 1;
24427
+ try {
24428
+ const remoteGit = await probeRemoteMeshGitStatus({
24429
+ dispatchMeshCommand: args.dispatchMeshCommand,
24430
+ daemonId,
24431
+ workspace,
24432
+ timeoutMs: 8e3
24433
+ });
24434
+ if (remoteGit) {
24435
+ recordInlineMeshDirectGitTruth(node, remoteGit, "selected_coordinator_mesh_p2p_git");
24436
+ peerConfirmedCount += 1;
24437
+ continue;
24438
+ }
24439
+ } catch {
24440
+ }
24441
+ unavailableNodeIds.push(nodeId);
24442
+ }
24443
+ return {
24444
+ directEvidenceCount: localConfirmedCount + peerConfirmedCount,
24445
+ localConfirmedCount,
24446
+ peerAttemptedCount,
24447
+ peerConfirmedCount,
24448
+ unavailableNodeIds
24449
+ };
24450
+ }
24451
+ function summarizeMeshSessionRecord(record) {
24452
+ return {
24453
+ sessionId: readStringValue(record?.sessionId) || "unknown",
24454
+ providerType: readStringValue(record?.providerType),
24455
+ state: readLiveMeshSessionState(record),
24456
+ lifecycle: readStringValue(record?.lifecycle),
24457
+ surfaceKind: getSessionHostSurfaceKind(record),
24458
+ recoveryState: readStringValue(record?.meta?.runtimeRecoveryState) ?? null,
24459
+ workspace: readStringValue(record?.workspace) ?? null,
24460
+ title: readStringValue(record?.displayName, record?.workspaceLabel) ?? null,
24461
+ lastActivityAt: toIsoTimestamp(record?.updatedAt ?? record?.lastActivityAt ?? record?.last_activity_at),
24462
+ isCached: false
24463
+ };
24464
+ }
24465
+ function liveSessionRecordMatchesMeshNode(record, meshId, nodeId) {
24466
+ const recordNodeId = readStringValue(record?.meta?.meshNodeId);
24467
+ if (!recordNodeId || recordNodeId !== nodeId) return false;
24468
+ const recordMeshId = readStringValue(record?.meta?.meshNodeFor);
24469
+ return !recordMeshId || recordMeshId === meshId;
24470
+ }
24471
+ function liveSessionRecordMatchesMeshWorkspace(record, meshId, workspace) {
24472
+ const recordWorkspace = readStringValue(record?.workspace);
24473
+ if (!recordWorkspace || !workspace || recordWorkspace !== workspace) return false;
24474
+ const recordMeshId = readStringValue(record?.meta?.meshNodeFor);
24475
+ if (recordMeshId) return recordMeshId === meshId;
24476
+ return record?.meta?.launchedByCoordinator === true || !!readStringValue(record?.meta?.meshNodeId);
24477
+ }
24478
+ function readLiveMeshNodeWorkspace(args) {
24479
+ const directNodeWorkspace = args.liveSessionRecords.find((record) => liveSessionRecordMatchesMeshNode(record, args.meshId, args.nodeId) && readStringValue(record?.workspace));
24480
+ if (directNodeWorkspace) {
24481
+ return readStringValue(directNodeWorkspace.workspace) || "";
24482
+ }
24483
+ if (args.allowCoordinatorSession) {
24484
+ const coordinatorWorkspace = args.liveSessionRecords.find((record) => readStringValue(record?.meta?.meshCoordinatorFor) === args.meshId && readStringValue(record?.workspace));
24485
+ if (coordinatorWorkspace) {
24486
+ return readStringValue(coordinatorWorkspace.workspace) || "";
24487
+ }
24488
+ }
24489
+ return "";
24490
+ }
24491
+ function collectLiveMeshSessionRecords(args) {
24492
+ const matches = args.liveSessionRecords.filter((record) => {
24493
+ const nodeWorkspace = readStringValue(args.node?.workspace);
24494
+ if (liveSessionRecordMatchesMeshNode(record, args.meshId, args.nodeId)) return true;
24495
+ return !!nodeWorkspace && liveSessionRecordMatchesMeshWorkspace(record, args.meshId, nodeWorkspace);
24496
+ });
24497
+ if (args.allowCoordinatorSession) {
24498
+ for (const record of args.liveSessionRecords) {
24499
+ if (readStringValue(record?.meta?.meshCoordinatorFor) !== args.meshId) continue;
24500
+ const sessionId = readStringValue(record?.sessionId);
24501
+ if (sessionId && matches.some((entry) => readStringValue(entry?.sessionId) === sessionId)) continue;
24502
+ matches.push(record);
24503
+ }
24504
+ }
24505
+ return matches;
24506
+ }
24507
+ function applyCachedInlineMeshNodeStatus(status, node, options) {
24508
+ const cachedStatus = readObjectRecord(node?.cachedStatus);
24509
+ const liveGit = buildInlineMeshTransitGitStatus(node);
24510
+ const git = options?.skipGit ? void 0 : liveGit ?? buildCachedInlineMeshGitStatus(node);
24511
+ const error = options?.skipError ? void 0 : liveGit ? void 0 : readStringValue(cachedStatus.error, node?.error);
24512
+ const health = options?.skipHealth ? void 0 : liveGit ? void 0 : readStringValue(cachedStatus.health, node?.health);
23910
24513
  const machineStatus = readStringValue(cachedStatus.machineStatus, node?.machineStatus);
23911
- if (!git && !error && !health) return false;
23912
- if (!machineStatus && !git && !error) return false;
24514
+ const lastSeenAt = toIsoTimestamp(cachedStatus.lastSeenAt ?? cachedStatus.last_seen_at ?? node?.lastSeenAt ?? node?.last_seen_at);
24515
+ const updatedAt = toIsoTimestamp(cachedStatus.updatedAt ?? cachedStatus.updated_at ?? node?.updatedAt ?? node?.updated_at);
24516
+ const activeSessions = readCachedInlineMeshActiveSessions(node);
24517
+ const activeSessionDetails = readCachedInlineMeshActiveSessionDetails(node);
24518
+ if (!git && !error && !health && !machineStatus && !lastSeenAt && !updatedAt && activeSessions.length === 0) return false;
23913
24519
  if (git) status.git = git;
23914
24520
  if (error) status.error = error;
24521
+ if (machineStatus) status.machineStatus = machineStatus;
24522
+ if (lastSeenAt) status.lastSeenAt = lastSeenAt;
24523
+ if (updatedAt) status.updatedAt = updatedAt;
24524
+ if (activeSessions.length > 0) status.activeSessions = activeSessions;
24525
+ if (activeSessionDetails.length > 0) status.activeSessionDetails = activeSessionDetails;
23915
24526
  if (health) {
23916
24527
  status.health = health;
23917
24528
  return true;
23918
24529
  }
23919
24530
  if (git) {
23920
- const dirty = Number(git.staged || 0) + Number(git.modified || 0) + Number(git.untracked || 0) + Number(git.deleted || 0) + Number(git.renamed || 0) > 0;
23921
- status.health = git.isGitRepo === false ? "degraded" : dirty ? "dirty" : "online";
24531
+ status.health = deriveMeshNodeHealthFromGit(git);
23922
24532
  return true;
23923
24533
  }
23924
- return false;
24534
+ return activeSessions.length > 0 || !!machineStatus || !!lastSeenAt || !!updatedAt;
23925
24535
  }
23926
24536
  async function resolveProviderTypeFromPriority(args) {
23927
24537
  if (!args.providerPriority.length) {
@@ -23951,15 +24561,92 @@ var REFINE_VALIDATION_TIMEOUT_MS = 12e4;
23951
24561
  var REFINE_VALIDATION_OUTPUT_LIMIT_BYTES = 128 * 1024;
23952
24562
  var REFINE_VALIDATION_SUMMARY_CHARS = 2e3;
23953
24563
  var REFINE_VALIDATION_MAX_COMMANDS = 4;
24564
+ var REFINE_PATCH_EQUIVALENCE_OUTPUT_LIMIT_BYTES = 4 * 1024 * 1024;
23954
24565
  function truncateValidationOutput(value) {
23955
24566
  const text = typeof value === "string" ? value : value == null ? "" : String(value);
23956
24567
  if (text.length <= REFINE_VALIDATION_SUMMARY_CHARS) return text;
23957
24568
  return `${text.slice(0, REFINE_VALIDATION_SUMMARY_CHARS)}
23958
24569
  [truncated ${text.length - REFINE_VALIDATION_SUMMARY_CHARS} chars]`;
23959
24570
  }
24571
+ function recordMeshRefineStage(stages, stage, status, startedAt, details) {
24572
+ stages.push({
24573
+ stage,
24574
+ status,
24575
+ durationMs: Date.now() - startedAt,
24576
+ ...details || {}
24577
+ });
24578
+ }
24579
+ async function computeGitPatchId(cwd, fromRef, toRef) {
24580
+ const { execFileSync: execFileSync4 } = await import("child_process");
24581
+ const diff = execFileSync4("git", ["diff", "--patch", "--full-index", fromRef, toRef], {
24582
+ cwd,
24583
+ encoding: "utf8",
24584
+ maxBuffer: REFINE_PATCH_EQUIVALENCE_OUTPUT_LIMIT_BYTES
24585
+ });
24586
+ if (!diff.trim()) return "";
24587
+ const patchId = execFileSync4("git", ["patch-id", "--stable"], {
24588
+ cwd,
24589
+ input: diff,
24590
+ encoding: "utf8",
24591
+ maxBuffer: REFINE_PATCH_EQUIVALENCE_OUTPUT_LIMIT_BYTES
24592
+ }).trim();
24593
+ return patchId.split(/\s+/)[0] || "";
24594
+ }
24595
+ async function runMeshRefinePatchEquivalenceGate(repoRoot, baseHead, branchHead) {
24596
+ const startedAt = Date.now();
24597
+ try {
24598
+ const { execFileSync: execFileSync4 } = await import("child_process");
24599
+ const git = (args) => execFileSync4("git", args, {
24600
+ cwd: repoRoot,
24601
+ encoding: "utf8",
24602
+ maxBuffer: REFINE_PATCH_EQUIVALENCE_OUTPUT_LIMIT_BYTES
24603
+ });
24604
+ const mergeBase = git(["merge-base", baseHead, branchHead]).trim();
24605
+ const mergeTreeStdout = git(["merge-tree", "--write-tree", baseHead, branchHead]);
24606
+ const mergedTree = mergeTreeStdout.trim().split(/\s+/)[0] || "";
24607
+ if (!mergeBase || !mergedTree) {
24608
+ return {
24609
+ status: "failed",
24610
+ equivalent: false,
24611
+ baseHead,
24612
+ branchHead,
24613
+ mergeBase: mergeBase || void 0,
24614
+ mergedTree: mergedTree || void 0,
24615
+ durationMs: Date.now() - startedAt,
24616
+ error: "patch equivalence preflight could not resolve merge-base or synthetic merge tree",
24617
+ stdout: truncateValidationOutput(mergeTreeStdout)
24618
+ };
24619
+ }
24620
+ const expectedPatchId = await computeGitPatchId(repoRoot, mergeBase, branchHead);
24621
+ const actualPatchId = await computeGitPatchId(repoRoot, baseHead, mergedTree);
24622
+ const equivalent = expectedPatchId === actualPatchId;
24623
+ return {
24624
+ status: equivalent ? "passed" : "failed",
24625
+ equivalent,
24626
+ baseHead,
24627
+ branchHead,
24628
+ mergeBase,
24629
+ mergedTree,
24630
+ expectedPatchId,
24631
+ actualPatchId,
24632
+ durationMs: Date.now() - startedAt
24633
+ };
24634
+ } catch (e) {
24635
+ return {
24636
+ status: "failed",
24637
+ equivalent: false,
24638
+ baseHead,
24639
+ branchHead,
24640
+ durationMs: Date.now() - startedAt,
24641
+ error: e?.message || String(e),
24642
+ stdout: truncateValidationOutput(e?.stdout),
24643
+ stderr: truncateValidationOutput(e?.stderr)
24644
+ };
24645
+ }
24646
+ }
23960
24647
  function readPackageScripts(workspace) {
23961
24648
  try {
23962
- const packageJsonPath = (0, import_path6.join)(workspace, "package.json");
24649
+ const packageJsonPath = (0, import_path7.join)(workspace, "package.json");
23963
24650
  const parsed = JSON.parse(fs10.readFileSync(packageJsonPath, "utf-8"));
23964
24651
  return parsed?.scripts && typeof parsed.scripts === "object" && !Array.isArray(parsed.scripts) ? parsed.scripts : {};
23965
24652
  } catch {
@@ -24167,13 +24854,13 @@ function serializeMeshCoordinatorMcpConfig(config, format) {
24167
24854
  }
24168
24855
  function resolveHermesUserHome() {
24169
24856
  const explicitHome = process.env.HERMES_HOME?.trim();
24170
- return explicitHome || (0, import_path6.join)((0, import_os3.homedir)(), ".hermes");
24857
+ return explicitHome || (0, import_path7.join)((0, import_os3.homedir)(), ".hermes");
24171
24858
  }
24172
24859
  function loadHermesCoordinatorBaseConfig(targetConfigPath) {
24173
24860
  const sourceHome = resolveHermesUserHome();
24174
- const sourceConfigPath = (0, import_path6.join)(sourceHome, "config.yaml");
24861
+ const sourceConfigPath = (0, import_path7.join)(sourceHome, "config.yaml");
24175
24862
  if (!fs10.existsSync(sourceConfigPath)) return { config: {}, sourceHome, sourceConfigPath };
24176
- if ((0, import_path6.resolve)(sourceConfigPath) === (0, import_path6.resolve)(targetConfigPath)) return { config: {}, sourceHome, sourceConfigPath };
24863
+ if ((0, import_path7.resolve)(sourceConfigPath) === (0, import_path7.resolve)(targetConfigPath)) return { config: {}, sourceHome, sourceConfigPath };
24177
24864
  const parsed = parseMeshCoordinatorMcpConfig(fs10.readFileSync(sourceConfigPath, "utf-8"), "hermes_config_yaml");
24178
24865
  const { mcp_servers: _mcpServers, ...baseConfig } = parsed;
24179
24866
  return { config: baseConfig, sourceHome, sourceConfigPath };
@@ -24207,10 +24894,10 @@ function stripHermesCoordinatorTempModelProviderOverrides(config) {
24207
24894
  return sanitized;
24208
24895
  }
24209
24896
  function copyHermesCoordinatorCredentialFiles(sourceHome, targetHome) {
24210
- if ((0, import_path6.resolve)(sourceHome) === (0, import_path6.resolve)(targetHome)) return;
24897
+ if ((0, import_path7.resolve)(sourceHome) === (0, import_path7.resolve)(targetHome)) return;
24211
24898
  for (const fileName of [".env", "auth.json"]) {
24212
- const sourcePath = (0, import_path6.join)(sourceHome, fileName);
24213
- const targetPath = (0, import_path6.join)(targetHome, fileName);
24899
+ const sourcePath = (0, import_path7.join)(sourceHome, fileName);
24900
+ const targetPath = (0, import_path7.join)(targetHome, fileName);
24214
24901
  if (!fs10.existsSync(sourcePath)) continue;
24215
24902
  try {
24216
24903
  fs10.copyFileSync(sourcePath, targetPath);
@@ -24314,30 +25001,97 @@ var DaemonCommandRouter = class {
24314
25001
  * Allows the MCP server to query mesh data via get_mesh even when
24315
25002
  * the mesh doesn't exist in the local meshes.json file. */
24316
25003
  inlineMeshCache = /* @__PURE__ */ new Map();
25004
+ /** Coordinator-owned whole-mesh aggregate status snapshots. Browser callers read this by default. */
25005
+ aggregateMeshStatusCache = /* @__PURE__ */ new Map();
24317
25006
  constructor(deps) {
24318
25007
  this.deps = deps;
24319
25008
  }
25009
+ cloneJsonValue(value) {
25010
+ if (typeof structuredClone === "function") return structuredClone(value);
25011
+ return JSON.parse(JSON.stringify(value));
25012
+ }
25013
+ getCachedAggregateMeshStatus(meshId) {
25014
+ const cached = this.aggregateMeshStatusCache.get(meshId);
25015
+ if (!cached?.snapshot || cached.snapshot.success !== true || !Array.isArray(cached.snapshot.nodes)) return null;
25016
+ const snapshot = this.cloneJsonValue(cached.snapshot);
25017
+ const ageMs = Math.max(0, Date.now() - cached.builtAt);
25018
+ const sourceOfTruth = snapshot.sourceOfTruth && typeof snapshot.sourceOfTruth === "object" ? snapshot.sourceOfTruth : {};
25019
+ snapshot.sourceOfTruth = {
25020
+ ...sourceOfTruth,
25021
+ aggregateSnapshot: {
25022
+ ...sourceOfTruth.aggregateSnapshot && typeof sourceOfTruth.aggregateSnapshot === "object" ? sourceOfTruth.aggregateSnapshot : {},
25023
+ owner: "coordinator_daemon_memory",
25024
+ cached: true,
25025
+ source: "memory",
25026
+ refreshReason: "memory_cache_hit",
25027
+ ageMs,
25028
+ cachedAt: new Date(cached.builtAt).toISOString(),
25029
+ returnedAt: (/* @__PURE__ */ new Date()).toISOString()
25030
+ }
25031
+ };
25032
+ return snapshot;
25033
+ }
25034
+ rememberAggregateMeshStatus(meshId, snapshot, refreshReason) {
25035
+ if (!snapshot || typeof snapshot !== "object" || snapshot.success !== true || !Array.isArray(snapshot.nodes)) return snapshot;
25036
+ const builtAt = Date.now();
25037
+ const next = this.cloneJsonValue(snapshot);
25038
+ const sourceOfTruth = next.sourceOfTruth && typeof next.sourceOfTruth === "object" ? next.sourceOfTruth : {};
25039
+ next.sourceOfTruth = {
25040
+ ...sourceOfTruth,
25041
+ aggregateSnapshot: {
25042
+ owner: "coordinator_daemon_memory",
25043
+ cached: false,
25044
+ source: "live_refresh",
25045
+ refreshReason,
25046
+ ageMs: 0,
25047
+ cachedAt: new Date(builtAt).toISOString(),
25048
+ returnedAt: new Date(builtAt).toISOString()
25049
+ }
25050
+ };
25051
+ this.aggregateMeshStatusCache.set(meshId, { builtAt, snapshot: this.cloneJsonValue(next) });
25052
+ return next;
25053
+ }
24320
25054
  getCachedInlineMesh(meshId, inlineMesh) {
24321
25055
  if (inlineMesh && typeof inlineMesh === "object") {
24322
- this.inlineMeshCache.set(meshId, inlineMesh);
24323
- return inlineMesh;
25056
+ return this.warmInlineMeshCache(meshId, inlineMesh);
24324
25057
  }
24325
25058
  return this.inlineMeshCache.get(meshId);
24326
25059
  }
25060
+ warmInlineMeshCache(meshId, inlineMesh) {
25061
+ if (!inlineMesh || typeof inlineMesh !== "object") return void 0;
25062
+ const sanitizedInlineMesh = sanitizeInlineMesh(inlineMesh);
25063
+ const cached = this.inlineMeshCache.get(meshId);
25064
+ if (cached) {
25065
+ const merged = reconcileInlineMeshCache(cached, sanitizedInlineMesh);
25066
+ this.inlineMeshCache.set(meshId, merged);
25067
+ return merged;
25068
+ }
25069
+ this.inlineMeshCache.set(meshId, sanitizedInlineMesh);
25070
+ return sanitizedInlineMesh;
25071
+ }
24327
25072
  async getMeshForCommand(meshId, inlineMesh, options) {
24328
25073
  const preferInline = options?.preferInline === true;
24329
25074
  if (preferInline) {
24330
- const cached2 = this.getCachedInlineMesh(meshId, inlineMesh);
24331
- if (cached2) return { mesh: cached2, inline: true };
25075
+ const cached2 = this.getCachedInlineMesh(meshId);
25076
+ if (cached2) return { mesh: cached2, inline: true, source: "inline_cache" };
25077
+ if (inlineMeshCarriesTransientNodeTruth(inlineMesh)) {
25078
+ this.warmInlineMeshCache(meshId, inlineMesh);
25079
+ return { mesh: inlineMesh, inline: true, source: "inline_bootstrap" };
25080
+ }
24332
25081
  }
24333
25082
  try {
24334
25083
  const { getMesh: getMesh3 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
24335
25084
  const mesh = getMesh3(meshId);
24336
- if (mesh) return { mesh, inline: false };
25085
+ if (mesh) return { mesh, inline: false, source: "local_config" };
24337
25086
  } catch {
24338
25087
  }
24339
- const cached = this.getCachedInlineMesh(meshId, inlineMesh);
24340
- return cached ? { mesh: cached, inline: true } : null;
25088
+ const cached = this.getCachedInlineMesh(meshId);
25089
+ if (cached) return { mesh: cached, inline: true, source: "inline_cache" };
25090
+ const warmedInline = this.warmInlineMeshCache(meshId, inlineMesh);
25091
+ return warmedInline ? { mesh: warmedInline, inline: true, source: "inline_bootstrap" } : null;
25092
+ }
25093
+ invalidateAggregateMeshStatus(meshId) {
25094
+ this.aggregateMeshStatusCache.delete(meshId);
24341
25095
  }
24342
25096
  updateInlineMeshNode(meshId, mesh, node) {
24343
25097
  if (!mesh || !Array.isArray(mesh.nodes) || !node?.id) return;
@@ -24346,6 +25100,7 @@ var DaemonCommandRouter = class {
24346
25100
  else mesh.nodes.push(node);
24347
25101
  mesh.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
24348
25102
  this.inlineMeshCache.set(meshId, mesh);
25103
+ this.invalidateAggregateMeshStatus(meshId);
24349
25104
  }
24350
25105
  removeInlineMeshNode(meshId, mesh, nodeId) {
24351
25106
  if (!mesh || !Array.isArray(mesh.nodes)) return false;
@@ -24354,6 +25109,7 @@ var DaemonCommandRouter = class {
24354
25109
  mesh.nodes.splice(idx, 1);
24355
25110
  mesh.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
24356
25111
  this.inlineMeshCache.set(meshId, mesh);
25112
+ this.invalidateAggregateMeshStatus(meshId);
24357
25113
  return true;
24358
25114
  }
24359
25115
  normalizeMeshSessionCleanupMode(value) {
@@ -24402,7 +25158,7 @@ var DaemonCommandRouter = class {
24402
25158
  }
24403
25159
  const { resolveWorktreePath: resolveWorktreePath2, listWorktrees: listWorktrees2, removeWorktree: removeWorktree2 } = await Promise.resolve().then(() => (init_git_worktree(), git_worktree_exports));
24404
25160
  const normalizePath = (value) => {
24405
- const resolved = (0, import_path6.resolve)(value);
25161
+ const resolved = (0, import_path7.resolve)(value);
24406
25162
  try {
24407
25163
  return fs10.realpathSync(resolved);
24408
25164
  } catch {
@@ -24566,6 +25322,7 @@ var DaemonCommandRouter = class {
24566
25322
  const deletedSessionIds = [];
24567
25323
  const skippedSessionIds = [];
24568
25324
  const skippedLiveSessionIds = [];
25325
+ const skippedCoordinatorSessionIds = [];
24569
25326
  const deleteUnsupportedSessionIds = [];
24570
25327
  const recordsRemainSessionIds = [];
24571
25328
  const errors = [];
@@ -24598,6 +25355,12 @@ var DaemonCommandRouter = class {
24598
25355
  const completed = this.isCompletedHostedSession(record);
24599
25356
  const surfaceKind = getSessionHostSurfaceKind(record);
24600
25357
  const liveRuntime = surfaceKind === "live_runtime";
25358
+ const coordinatorSession = readStringValue(record?.meta?.meshCoordinatorFor) === args.meshId;
25359
+ if (!hasExplicitSessionIds && coordinatorSession) {
25360
+ skippedSessionIds.push(sessionId);
25361
+ skippedCoordinatorSessionIds.push(sessionId);
25362
+ continue;
25363
+ }
24601
25364
  if (!hasExplicitSessionIds && liveRuntime) {
24602
25365
  skippedSessionIds.push(sessionId);
24603
25366
  skippedLiveSessionIds.push(sessionId);
@@ -24663,6 +25426,7 @@ var DaemonCommandRouter = class {
24663
25426
  deletedSessionIds,
24664
25427
  skippedSessionIds,
24665
25428
  skippedLiveSessionIds,
25429
+ skippedCoordinatorSessionIds,
24666
25430
  ...deleteUnsupported ? {
24667
25431
  deleteUnsupported: true,
24668
25432
  effectiveCleanup: args.mode === "stop_and_delete" ? "stopped_only_records_remain" : "delete_unsupported_records_remain",
@@ -24795,7 +25559,8 @@ var DaemonCommandRouter = class {
24795
25559
  return handleMeshForwardEvent({ instanceManager: this.deps.instanceManager }, args);
24796
25560
  }
24797
25561
  case "get_pending_mesh_events": {
24798
- const events = drainPendingMeshCoordinatorEvents();
25562
+ const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
25563
+ const events = drainPendingMeshCoordinatorEvents(meshId || void 0);
24799
25564
  return { success: true, events };
24800
25565
  }
24801
25566
  case "launch_cli":
@@ -25324,15 +26089,39 @@ var DaemonCommandRouter = class {
25324
26089
  case "get_mesh": {
25325
26090
  const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
25326
26091
  if (!meshId) return { success: false, error: "meshId required" };
25327
- try {
25328
- const { getMesh: getMesh3 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
25329
- const mesh = getMesh3(meshId);
25330
- if (mesh) return { success: true, mesh };
25331
- } catch {
26092
+ const meshRecord = await this.getMeshForCommand(meshId, args?.inlineMesh, { preferInline: true });
26093
+ if (!meshRecord?.mesh) return { success: false, error: "Mesh not found" };
26094
+ const requireDirectPeerTruth = args?.requireDirectPeerTruth === true;
26095
+ const directTruth = await hydrateInlineMeshDirectTruth({
26096
+ mesh: meshRecord.mesh,
26097
+ meshSource: meshRecord.source,
26098
+ dispatchMeshCommand: this.deps.dispatchMeshCommand,
26099
+ statusInstanceId: this.deps.statusInstanceId,
26100
+ localMachineId: loadConfig().machineId || ""
26101
+ });
26102
+ const directTruthSatisfied = meshRecord.source !== "inline_bootstrap" || directTruth.directEvidenceCount > 0;
26103
+ const sourceOfTruth = {
26104
+ membership: meshRecord.source === "inline_cache" ? "coordinator_inline_mesh_cache" : meshRecord.source === "local_config" ? "local_mesh_config" : "inline_bootstrap_snapshot",
26105
+ coordinatorOwnsLiveTruth: directTruthSatisfied,
26106
+ directPeerTruth: {
26107
+ required: requireDirectPeerTruth,
26108
+ satisfied: directTruthSatisfied,
26109
+ directEvidenceCount: directTruth.directEvidenceCount,
26110
+ localConfirmedCount: directTruth.localConfirmedCount,
26111
+ peerAttemptedCount: directTruth.peerAttemptedCount,
26112
+ peerConfirmedCount: directTruth.peerConfirmedCount,
26113
+ unavailableNodeIds: directTruth.unavailableNodeIds
26114
+ }
26115
+ };
26116
+ if (requireDirectPeerTruth && !directTruthSatisfied) {
26117
+ return {
26118
+ success: false,
26119
+ code: "mesh_direct_peer_truth_unavailable",
26120
+ error: "Selected coordinator could not confirm direct mesh truth yet. Bootstrap inventory stays unavailable until direct get_mesh probes succeed.",
26121
+ sourceOfTruth
26122
+ };
25332
26123
  }
25333
- const cached = this.inlineMeshCache.get(meshId);
25334
- if (cached) return { success: true, mesh: cached };
25335
- return { success: false, error: "Mesh not found" };
26124
+ return { success: true, mesh: meshRecord.mesh, sourceOfTruth };
25336
26125
  }
25337
26126
  case "create_mesh": {
25338
26127
  const name = typeof args?.name === "string" ? args.name.trim() : "";
@@ -25362,6 +26151,7 @@ var DaemonCommandRouter = class {
25362
26151
  const mesh = updateMesh2(meshId, patch);
25363
26152
  if (!mesh) return { success: false, error: "Mesh not found" };
25364
26153
  this.inlineMeshCache.set(meshId, mesh);
26154
+ this.invalidateAggregateMeshStatus(meshId);
25365
26155
  return { success: true, mesh };
25366
26156
  } catch (e) {
25367
26157
  return { success: false, error: e.message };
@@ -25551,26 +26341,41 @@ var DaemonCommandRouter = class {
25551
26341
  const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
25552
26342
  const nodeId = typeof args?.nodeId === "string" ? args.nodeId.trim() : "";
25553
26343
  if (!meshId || !nodeId) return { success: false, error: "meshId and nodeId required" };
26344
+ const refineStages = [];
25554
26345
  try {
25555
26346
  const meshRecord = await this.getMeshForCommand(meshId, args?.inlineMesh);
25556
26347
  const mesh = meshRecord?.mesh;
25557
26348
  const node = mesh?.nodes?.find((n) => n.id === nodeId || n.nodeId === nodeId);
25558
- if (!node) return { success: false, error: `Node '${nodeId}' not found in mesh` };
26349
+ if (!node) return { success: false, error: `Node '${nodeId}' not found in mesh`, refineStages };
25559
26350
  if (!node.isLocalWorktree || !node.workspace) {
25560
- return { success: false, error: `Refinery requires a local worktree node` };
26351
+ return { success: false, error: `Refinery requires a local worktree node`, refineStages };
25561
26352
  }
25562
26353
  const sourceNode = node.clonedFromNodeId ? mesh?.nodes.find((n) => n.id === node.clonedFromNodeId || n.nodeId === node.clonedFromNodeId) : mesh?.nodes.find((n) => !n.isLocalWorktree);
25563
26354
  const repoRoot = sourceNode?.repoRoot || sourceNode?.workspace;
25564
- if (!repoRoot) return { success: false, error: "Source node repoRoot not found" };
26355
+ if (!repoRoot) return { success: false, error: "Source node repoRoot not found", refineStages };
25565
26356
  const { execFile: execFile3 } = await import("child_process");
25566
26357
  const { promisify: promisify3 } = await import("util");
25567
26358
  const execFileAsync3 = promisify3(execFile3);
26359
+ const resolveStarted = Date.now();
25568
26360
  const { stdout: branchStdout } = await execFileAsync3("git", ["branch", "--show-current"], { cwd: node.workspace, encoding: "utf8" });
25569
26361
  const branch = branchStdout.trim();
25570
- if (!branch) return { success: false, error: "Could not determine branch of the worktree node" };
26362
+ if (!branch) return { success: false, error: "Could not determine branch of the worktree node", refineStages };
25571
26363
  const { stdout: baseBranchStdout } = await execFileAsync3("git", ["branch", "--show-current"], { cwd: repoRoot, encoding: "utf8" });
25572
26364
  const baseBranch = baseBranchStdout.trim();
26365
+ const { stdout: baseHeadStdout } = await execFileAsync3("git", ["rev-parse", "HEAD"], { cwd: repoRoot, encoding: "utf8" });
26366
+ const { stdout: branchHeadStdout } = await execFileAsync3("git", ["rev-parse", branch], { cwd: node.workspace, encoding: "utf8" });
26367
+ const baseHead = baseHeadStdout.trim();
26368
+ const branchHead = branchHeadStdout.trim();
26369
+ recordMeshRefineStage(refineStages, "resolve_refs", "passed", resolveStarted, { branch, baseBranch, baseHead, branchHead });
26370
+ const validationStarted = Date.now();
25573
26371
  const validationSummary = await runMeshRefineValidationGate(mesh, node.workspace);
26372
+ recordMeshRefineStage(
26373
+ refineStages,
26374
+ "validation",
26375
+ validationSummary.status === "passed" ? "passed" : validationSummary.status === "failed" ? "failed" : "skipped",
26376
+ validationStarted,
26377
+ { validationStatus: validationSummary.status, commandsRun: validationSummary.commandsRun.length }
26378
+ );
25574
26379
  if (validationSummary.status === "failed") {
25575
26380
  return {
25576
26381
  success: false,
@@ -25580,6 +26385,7 @@ var DaemonCommandRouter = class {
25580
26385
  branch,
25581
26386
  into: baseBranch,
25582
26387
  validationSummary,
26388
+ refineStages,
25583
26389
  finalBranchConvergenceState: {
25584
26390
  branch,
25585
26391
  baseBranch,
@@ -25599,6 +26405,7 @@ var DaemonCommandRouter = class {
25599
26405
  branch,
25600
26406
  into: baseBranch,
25601
26407
  validationSummary,
26408
+ refineStages,
25602
26409
  finalBranchConvergenceState: {
25603
26410
  branch,
25604
26411
  baseBranch,
@@ -25609,37 +26416,121 @@ var DaemonCommandRouter = class {
25609
26416
  }
25610
26417
  };
25611
26418
  }
26419
+ const patchEquivalenceStarted = Date.now();
26420
+ const patchEquivalence = await runMeshRefinePatchEquivalenceGate(repoRoot, baseHead, branchHead);
26421
+ recordMeshRefineStage(refineStages, "patch_equivalence", patchEquivalence.status, patchEquivalenceStarted, {
26422
+ equivalent: patchEquivalence.equivalent,
26423
+ expectedPatchId: patchEquivalence.expectedPatchId,
26424
+ actualPatchId: patchEquivalence.actualPatchId,
26425
+ error: patchEquivalence.error
26426
+ });
26427
+ if (!patchEquivalence.equivalent) {
26428
+ return {
26429
+ success: false,
26430
+ code: "patch_equivalence_failed",
26431
+ convergenceStatus: "blocked_review",
26432
+ error: "Refinery patch-equivalence preflight failed; merge/refine was not attempted.",
26433
+ branch,
26434
+ into: baseBranch,
26435
+ validationSummary,
26436
+ patchEquivalence,
26437
+ refineStages,
26438
+ finalBranchConvergenceState: {
26439
+ branch,
26440
+ baseBranch,
26441
+ merged: false,
26442
+ removed: false,
26443
+ validation: "passed",
26444
+ patchEquivalence: "failed",
26445
+ status: "blocked_review"
26446
+ }
26447
+ };
26448
+ }
26449
+ let mergeResult;
26450
+ const mergeStarted = Date.now();
25612
26451
  try {
25613
- await execFileAsync3("git", ["merge", "--no-ff", branch, "-m", `Auto-merge branch '${branch}' via Refinery`], { cwd: repoRoot, encoding: "utf8" });
26452
+ const result = await execFileAsync3("git", ["merge", "--no-ff", branch, "-m", `Auto-merge branch '${branch}' via Refinery`], { cwd: repoRoot, encoding: "utf8" });
26453
+ mergeResult = {
26454
+ stdout: truncateValidationOutput(result.stdout),
26455
+ stderr: truncateValidationOutput(result.stderr),
26456
+ durationMs: Date.now() - mergeStarted
26457
+ };
26458
+ recordMeshRefineStage(refineStages, "merge", "passed", mergeStarted, mergeResult);
25614
26459
  } catch (e) {
26460
+ recordMeshRefineStage(refineStages, "merge", "failed", mergeStarted, {
26461
+ error: e?.message || String(e),
26462
+ stdout: truncateValidationOutput(e?.stdout),
26463
+ stderr: truncateValidationOutput(e?.stderr)
26464
+ });
25615
26465
  return {
25616
26466
  success: false,
25617
26467
  error: `Merge failed (conflicts?): ${e.message}`,
25618
26468
  validationSummary,
26469
+ patchEquivalence,
26470
+ refineStages,
25619
26471
  finalBranchConvergenceState: {
25620
26472
  branch,
25621
26473
  baseBranch,
25622
26474
  merged: false,
25623
26475
  removed: false,
25624
26476
  validation: "passed",
26477
+ patchEquivalence: "passed",
25625
26478
  status: "not_mergeable"
25626
26479
  }
25627
26480
  };
25628
26481
  }
26482
+ const cleanupStarted = Date.now();
25629
26483
  const removeResult = await this.execute("remove_mesh_node", {
25630
26484
  meshId,
25631
26485
  nodeId,
25632
- sessionCleanupMode: "kill",
26486
+ sessionCleanupMode: "preserve",
25633
26487
  inlineMesh: args?.inlineMesh
25634
26488
  });
26489
+ recordMeshRefineStage(refineStages, "cleanup", removeResult?.success === false ? "failed" : "passed", cleanupStarted, {
26490
+ removed: removeResult?.removed,
26491
+ code: removeResult?.code,
26492
+ error: removeResult?.error
26493
+ });
26494
+ let ledgerError;
26495
+ const ledgerStarted = Date.now();
25635
26496
  try {
25636
26497
  const { appendLedgerEntry: appendLedgerEntry2 } = await Promise.resolve().then(() => (init_mesh_ledger(), mesh_ledger_exports));
25637
26498
  appendLedgerEntry2(meshId, {
25638
26499
  kind: "node_removed",
25639
26500
  nodeId,
25640
- payload: { refined: true, mergedBranch: branch, into: baseBranch, validationSummary }
26501
+ payload: { refined: true, mergedBranch: branch, into: baseBranch, validationSummary, patchEquivalence }
25641
26502
  });
25642
- } catch {
26503
+ recordMeshRefineStage(refineStages, "ledger", "passed", ledgerStarted);
26504
+ } catch (e) {
26505
+ ledgerError = e?.message || String(e);
26506
+ recordMeshRefineStage(refineStages, "ledger", "failed", ledgerStarted, { error: ledgerError });
26507
+ }
26508
+ const finalBranchConvergenceState = {
26509
+ branch: baseBranch,
26510
+ mergedBranch: branch,
26511
+ baseBranch,
26512
+ merged: true,
26513
+ removed: removeResult?.success !== false,
26514
+ validation: "passed",
26515
+ patchEquivalence: "passed",
26516
+ status: removeResult?.success === false ? "merged_cleanup_failed" : "merged"
26517
+ };
26518
+ if (removeResult?.success === false) {
26519
+ return {
26520
+ success: false,
26521
+ code: "cleanup_failed",
26522
+ error: "Refinery merge completed but worktree cleanup failed; manual cleanup/retry is required.",
26523
+ merged: true,
26524
+ branch,
26525
+ into: baseBranch,
26526
+ removeResult,
26527
+ validationSummary,
26528
+ patchEquivalence,
26529
+ mergeResult,
26530
+ refineStages,
26531
+ ...ledgerError ? { ledgerError } : {},
26532
+ finalBranchConvergenceState
26533
+ };
25643
26534
  }
25644
26535
  return {
25645
26536
  success: true,
@@ -25648,18 +26539,14 @@ var DaemonCommandRouter = class {
25648
26539
  into: baseBranch,
25649
26540
  removeResult,
25650
26541
  validationSummary,
25651
- finalBranchConvergenceState: {
25652
- branch: baseBranch,
25653
- mergedBranch: branch,
25654
- baseBranch,
25655
- merged: true,
25656
- removed: removeResult?.success !== false,
25657
- validation: "passed",
25658
- status: removeResult?.success === false ? "merged_cleanup_failed" : "merged"
25659
- }
26542
+ patchEquivalence,
26543
+ mergeResult,
26544
+ refineStages,
26545
+ ...ledgerError ? { ledgerError } : {},
26546
+ finalBranchConvergenceState
25660
26547
  };
25661
26548
  } catch (e) {
25662
- return { success: false, error: e.message };
26549
+ return { success: false, error: e.message, refineStages };
25663
26550
  }
25664
26551
  }
25665
26552
  case "remove_mesh_node": {
@@ -25700,6 +26587,7 @@ var DaemonCommandRouter = class {
25700
26587
  } else {
25701
26588
  const { removeNode: removeNode3 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
25702
26589
  removed = removeNode3(meshId, nodeId);
26590
+ if (removed) this.invalidateAggregateMeshStatus(meshId);
25703
26591
  }
25704
26592
  if (removed) {
25705
26593
  try {
@@ -25778,6 +26666,7 @@ var DaemonCommandRouter = class {
25778
26666
  policy: { ...sourceNode.policy || {} }
25779
26667
  });
25780
26668
  if (!node) return { success: false, error: "Failed to register worktree node" };
26669
+ this.invalidateAggregateMeshStatus(meshId);
25781
26670
  }
25782
26671
  const initSubmodules = sourceNode.policy?.initSubmodulesOnClone !== false;
25783
26672
  if (initSubmodules) {
@@ -25853,7 +26742,14 @@ var DaemonCommandRouter = class {
25853
26742
  cliType
25854
26743
  };
25855
26744
  }
25856
- const workspace = typeof coordinatorNode.workspace === "string" ? coordinatorNode.workspace.trim() : "";
26745
+ const sessionHostRecords = this.deps.sessionHostControl?.listSessions ? await this.deps.sessionHostControl.listSessions().catch(() => []) : [];
26746
+ const liveMeshSessions = partitionSessionHostRecords(Array.isArray(sessionHostRecords) ? sessionHostRecords : []).liveRuntimes;
26747
+ const workspace = readLiveMeshNodeWorkspace({
26748
+ meshId,
26749
+ nodeId: String(coordinatorNode.id || coordinatorNode.nodeId || preferredCoordinatorNodeId || ""),
26750
+ liveSessionRecords: liveMeshSessions,
26751
+ allowCoordinatorSession: true
26752
+ }) || (typeof coordinatorNode.workspace === "string" ? coordinatorNode.workspace.trim() : "");
25857
26753
  if (!workspace) return { success: false, error: "Coordinator node workspace required", meshId, cliType };
25858
26754
  if (!cliType) {
25859
26755
  const resolved = await resolveProviderTypeFromPriority({
@@ -26015,7 +26911,7 @@ ${block}`);
26015
26911
  workspace
26016
26912
  };
26017
26913
  }
26018
- const { existsSync: existsSync25, readFileSync: readFileSync17, writeFileSync: writeFileSync15, copyFileSync: copyFileSync4, mkdirSync: mkdirSync17 } = await import("fs");
26914
+ const { existsSync: existsSync26, readFileSync: readFileSync18, writeFileSync: writeFileSync15, copyFileSync: copyFileSync4, mkdirSync: mkdirSync17 } = await import("fs");
26019
26915
  const { dirname: dirname9 } = await import("path");
26020
26916
  const mcpConfigPath = coordinatorSetup.configPath;
26021
26917
  const hermesManualFallback = cliType === "hermes-cli" && configFormat === "hermes_config_yaml" ? createHermesManualMeshCoordinatorSetup(meshId, workspace) : null;
@@ -26058,14 +26954,14 @@ ${block}`);
26058
26954
  if (hermesManualFallback) return returnManualFallback(message);
26059
26955
  return { success: false, code: "mesh_coordinator_config_write_failed", error: message, meshId, cliType, workspace };
26060
26956
  }
26061
- const hadExistingMcpConfig = existsSync25(mcpConfigPath);
26957
+ const hadExistingMcpConfig = existsSync26(mcpConfigPath);
26062
26958
  let existingMcpConfig = hermesBaseConfig?.config || {};
26063
26959
  if (hermesBaseConfig) {
26064
26960
  copyHermesCoordinatorCredentialFiles(hermesBaseConfig.sourceHome, dirname9(mcpConfigPath));
26065
26961
  }
26066
26962
  if (hadExistingMcpConfig) {
26067
26963
  try {
26068
- const parsedExistingMcpConfig = parseMeshCoordinatorMcpConfig(readFileSync17(mcpConfigPath, "utf-8"), configFormat);
26964
+ const parsedExistingMcpConfig = parseMeshCoordinatorMcpConfig(readFileSync18(mcpConfigPath, "utf-8"), configFormat);
26069
26965
  const existingCoordinatorConfig = hermesManualFallback ? stripHermesCoordinatorTempModelProviderOverrides(parsedExistingMcpConfig) : parsedExistingMcpConfig;
26070
26966
  existingMcpConfig = { ...existingMcpConfig, ...existingCoordinatorConfig };
26071
26967
  copyFileSync4(mcpConfigPath, mcpConfigPath + ".backup");
@@ -26155,110 +27051,264 @@ ${block}`);
26155
27051
  const meshRecord = await this.getMeshForCommand(meshId, args?.inlineMesh, { preferInline: true });
26156
27052
  const mesh = meshRecord?.mesh;
26157
27053
  if (!mesh) return { success: false, error: "Mesh not found" };
27054
+ const refreshRequested = args?.refresh === true || args?.forceRefresh === true;
27055
+ if (!refreshRequested) {
27056
+ const cachedStatus = this.getCachedAggregateMeshStatus(meshId);
27057
+ if (cachedStatus) return cachedStatus;
27058
+ }
27059
+ const refreshReason = refreshRequested ? "explicit_refresh" : "cold_cache_miss";
26158
27060
  const { getMeshQueueStats: getMeshQueueStats2, getQueue: getQueue2 } = await Promise.resolve().then(() => (init_mesh_work_queue(), mesh_work_queue_exports));
26159
27061
  const queue = getQueue2(meshId);
26160
27062
  const queueSummary = getMeshQueueStats2(meshId);
26161
27063
  const { readLedgerEntries: readLedgerEntries2, getLedgerSummary: getLedgerSummary2 } = await Promise.resolve().then(() => (init_mesh_ledger(), mesh_ledger_exports));
26162
27064
  const ledgerEntries = readLedgerEntries2(meshId, { tail: 20 });
26163
27065
  const ledgerSummary = getLedgerSummary2(meshId);
27066
+ const sessionHostRecords = this.deps.sessionHostControl?.listSessions ? await this.deps.sessionHostControl.listSessions().catch(() => []) : [];
27067
+ const liveMeshSessions = partitionSessionHostRecords(Array.isArray(sessionHostRecords) ? sessionHostRecords : []).liveRuntimes;
27068
+ const localMachineId = loadConfig().machineId || "";
27069
+ const requireDirectPeerTruth = args?.requireDirectPeerTruth === true;
27070
+ const directTruth = requireDirectPeerTruth ? await hydrateInlineMeshDirectTruth({
27071
+ mesh,
27072
+ meshSource: meshRecord.source,
27073
+ dispatchMeshCommand: this.deps.dispatchMeshCommand,
27074
+ statusInstanceId: this.deps.statusInstanceId,
27075
+ localMachineId
27076
+ }) : {
27077
+ directEvidenceCount: 0,
27078
+ localConfirmedCount: 0,
27079
+ peerAttemptedCount: 0,
27080
+ peerConfirmedCount: 0,
27081
+ unavailableNodeIds: []
27082
+ };
27083
+ const directTruthSatisfied = meshRecord.source !== "inline_bootstrap" || directTruth.directEvidenceCount > 0;
27084
+ if (requireDirectPeerTruth && !directTruthSatisfied) {
27085
+ return {
27086
+ success: false,
27087
+ code: "mesh_direct_peer_truth_unavailable",
27088
+ error: "Selected coordinator could not confirm direct mesh truth yet. Bootstrap inventory stays unavailable until direct mesh_status probes succeed.",
27089
+ sourceOfTruth: {
27090
+ membership: meshRecord.source === "inline_cache" ? "coordinator_inline_mesh_cache" : meshRecord.source === "local_config" ? "local_mesh_config" : "inline_bootstrap_snapshot",
27091
+ coordinatorOwnsLiveTruth: false,
27092
+ currentStatus: "direct_peer_truth_unavailable",
27093
+ directPeerTruth: {
27094
+ required: true,
27095
+ satisfied: false,
27096
+ directEvidenceCount: directTruth.directEvidenceCount,
27097
+ localConfirmedCount: directTruth.localConfirmedCount,
27098
+ peerAttemptedCount: directTruth.peerAttemptedCount,
27099
+ peerConfirmedCount: directTruth.peerConfirmedCount,
27100
+ unavailableNodeIds: directTruth.unavailableNodeIds
27101
+ }
27102
+ }
27103
+ };
27104
+ }
27105
+ const directTruthUnavailableNodeIds = new Set(directTruth.unavailableNodeIds);
27106
+ const selectedCoordinatorNodeId = readStringValue(
27107
+ mesh.coordinator?.preferredNodeId,
27108
+ mesh.nodes?.[0]?.id,
27109
+ mesh.nodes?.[0]?.nodeId
27110
+ );
27111
+ const inlineCoordinatorNodeId = meshRecord?.inline && Array.isArray(mesh.nodes) ? selectedCoordinatorNodeId : void 0;
27112
+ const refreshedAt = (/* @__PURE__ */ new Date()).toISOString();
26164
27113
  const nodeStatuses = [];
26165
- for (const node of mesh.nodes || []) {
27114
+ for (const [nodeIndex, node] of (mesh.nodes || []).entries()) {
27115
+ const nodeId = String(node.id || node.nodeId || "");
27116
+ const daemonId = readStringValue(node.daemonId);
27117
+ const providerPriority = readProviderPriorityFromPolicy(node.policy);
27118
+ const isSelfNode = Boolean(
27119
+ nodeId && inlineCoordinatorNodeId && nodeId === inlineCoordinatorNodeId
27120
+ ) || Boolean(
27121
+ daemonId && (daemonId === localMachineId || daemonId === this.deps.statusInstanceId)
27122
+ ) || Boolean(meshRecord?.inline && nodeIndex === 0);
26166
27123
  const status = {
26167
- nodeId: node.id || node.nodeId,
27124
+ nodeId,
26168
27125
  machineLabel: node.machineLabel || node.id || node.nodeId,
26169
27126
  workspace: node.workspace,
26170
27127
  repoRoot: node.repoRoot,
26171
27128
  isLocalWorktree: node.isLocalWorktree,
26172
27129
  worktreeBranch: node.worktreeBranch,
26173
- daemonId: node.daemonId,
27130
+ daemonId,
26174
27131
  machineId: node.machineId,
27132
+ machineStatus: node.machineStatus,
26175
27133
  health: "unknown",
26176
27134
  providers: node.providers || [],
26177
- activeSessions: []
27135
+ providerPriority,
27136
+ activeSessions: [],
27137
+ activeSessionDetails: [],
27138
+ launchReady: false
26178
27139
  };
26179
- if (node.workspace && typeof node.workspace === "string") {
26180
- if (!fs10.existsSync(node.workspace) && applyCachedInlineMeshNodeStatus(status, node)) {
26181
- nodeStatuses.push(status);
26182
- continue;
27140
+ if (isSelfNode) {
27141
+ status.connection = {
27142
+ perspective: "selected_coordinator",
27143
+ source: "mesh_peer_status",
27144
+ state: "self",
27145
+ transport: "local",
27146
+ reported: true,
27147
+ reason: "Selected coordinator daemon",
27148
+ lastStateChangeAt: refreshedAt
27149
+ };
27150
+ } else if (daemonId) {
27151
+ const connection = this.deps.getMeshPeerConnectionStatus?.(daemonId);
27152
+ status.connection = connection ?? {
27153
+ perspective: "selected_coordinator",
27154
+ source: "not_reported",
27155
+ state: "unknown",
27156
+ transport: "unknown",
27157
+ reported: false,
27158
+ reason: "No live mesh peer telemetry reported by the selected coordinator yet."
27159
+ };
27160
+ } else {
27161
+ status.connection = {
27162
+ perspective: "selected_coordinator",
27163
+ source: "not_reported",
27164
+ state: "unknown",
27165
+ transport: "unknown",
27166
+ reported: false,
27167
+ reason: "Node has no daemon id, so mesh transport cannot be reported from the selected coordinator."
27168
+ };
27169
+ }
27170
+ const matchedLiveSessionRecords = collectLiveMeshSessionRecords({
27171
+ meshId,
27172
+ node,
27173
+ nodeId,
27174
+ liveSessionRecords: liveMeshSessions,
27175
+ allowCoordinatorSession: nodeId === selectedCoordinatorNodeId
27176
+ });
27177
+ const workspace = readLiveMeshNodeWorkspace({
27178
+ meshId,
27179
+ nodeId,
27180
+ liveSessionRecords: matchedLiveSessionRecords,
27181
+ allowCoordinatorSession: nodeId === selectedCoordinatorNodeId
27182
+ }) || (typeof node.workspace === "string" ? node.workspace : "");
27183
+ status.workspace = workspace || node.workspace;
27184
+ if (matchedLiveSessionRecords.length > 0) {
27185
+ const sessionIds = matchedLiveSessionRecords.map((record) => typeof record?.sessionId === "string" ? record.sessionId : "").filter(Boolean);
27186
+ const providerTypes = matchedLiveSessionRecords.map((record) => readStringValue(record?.providerType)).filter(Boolean);
27187
+ status.activeSessions = sessionIds;
27188
+ status.activeSessionDetails = matchedLiveSessionRecords.map(summarizeMeshSessionRecord);
27189
+ if (providerTypes.length > 0) {
27190
+ status.providers = Array.from(/* @__PURE__ */ new Set([...Array.isArray(status.providers) ? status.providers : [], ...providerTypes]));
26183
27191
  }
26184
- try {
26185
- const { execFile: execFile3 } = await import("child_process");
26186
- const { promisify: promisify3 } = await import("util");
26187
- const execFileAsync3 = promisify3(execFile3);
26188
- const runGit2 = async (args2) => {
26189
- const result = await execFileAsync3("git", ["-C", node.workspace, ...args2], {
26190
- encoding: "utf8",
26191
- timeout: 1e4
26192
- });
26193
- return result.stdout.trim();
26194
- };
26195
- const branch = await runGit2(["branch", "--show-current"]).catch(() => "");
26196
- const porc = await runGit2(["status", "--porcelain"]).catch(() => "");
26197
- const headCommit = await runGit2(["rev-parse", "--short", "HEAD"]).catch(() => null);
26198
- const headMessage = await runGit2(["log", "-1", "--format=%s"]).catch(() => null);
26199
- const upstream = await runGit2(["rev-parse", "--abbrev-ref", "@{upstream}"]).catch(() => null);
26200
- const aheadBehind = await runGit2(["rev-list", "--left-right", "--count", "@{upstream}...HEAD"]).catch(() => "");
26201
- const stashCount = await runGit2(["stash", "list"]).catch(() => "");
26202
- let ahead = 0, behind = 0;
26203
- if (aheadBehind) {
26204
- const parts = aheadBehind.split(/\s+/);
26205
- if (parts.length >= 2) {
26206
- behind = parseInt(parts[0], 10) || 0;
26207
- ahead = parseInt(parts[1], 10) || 0;
27192
+ }
27193
+ if (workspace) {
27194
+ if (!fs10.existsSync(workspace)) {
27195
+ const inlineTransitGit = buildInlineMeshTransitGitStatus(node);
27196
+ let remoteProbeApplied = false;
27197
+ if (inlineTransitGit) {
27198
+ status.git = inlineTransitGit;
27199
+ status.health = inlineTransitGit.isGitRepo ? deriveMeshNodeHealthFromGit(inlineTransitGit) : "degraded";
27200
+ remoteProbeApplied = true;
27201
+ } else if (!isSelfNode && daemonId && this.deps.dispatchMeshCommand && !directTruthUnavailableNodeIds.has(nodeId)) {
27202
+ try {
27203
+ const remoteGit = await probeRemoteMeshGitStatus({
27204
+ dispatchMeshCommand: this.deps.dispatchMeshCommand,
27205
+ daemonId,
27206
+ workspace,
27207
+ timeoutMs: 8e3
27208
+ });
27209
+ if (remoteGit) {
27210
+ status.git = remoteGit;
27211
+ status.health = remoteGit.isGitRepo ? deriveMeshNodeHealthFromGit(remoteGit) : "degraded";
27212
+ recordInlineMeshDirectGitTruth(node, remoteGit, "selected_coordinator_mesh_p2p_git");
27213
+ remoteProbeApplied = true;
27214
+ }
27215
+ } catch {
27216
+ const refreshedConnection = this.deps.getMeshPeerConnectionStatus?.(daemonId);
27217
+ const refreshedConnectionState = readStringValue(refreshedConnection?.state);
27218
+ if (refreshedConnection && refreshedConnectionState === "connected") {
27219
+ status.connection = refreshedConnection;
27220
+ try {
27221
+ const remoteGit = await probeRemoteMeshGitStatus({
27222
+ dispatchMeshCommand: this.deps.dispatchMeshCommand,
27223
+ daemonId,
27224
+ workspace,
27225
+ timeoutMs: 12e3
27226
+ });
27227
+ if (remoteGit) {
27228
+ status.git = remoteGit;
27229
+ status.health = remoteGit.isGitRepo ? deriveMeshNodeHealthFromGit(remoteGit) : "degraded";
27230
+ recordInlineMeshDirectGitTruth(node, remoteGit, "selected_coordinator_mesh_p2p_git");
27231
+ remoteProbeApplied = true;
27232
+ }
27233
+ } catch {
27234
+ }
27235
+ }
26208
27236
  }
26209
27237
  }
26210
- const dirty = porc.length > 0;
26211
- const lines = porc ? porc.split("\n").filter(Boolean) : [];
26212
- let staged = 0, modified = 0, untracked = 0, deleted = 0, renamed = 0;
26213
- for (const line of lines) {
26214
- const xy = line.slice(0, 2);
26215
- if (xy[0] !== " " && xy[0] !== "?") staged++;
26216
- if (xy[1] === "M") modified++;
26217
- if (xy[1] === "D") deleted++;
26218
- if (xy[0] === "R" || xy[1] === "R") renamed++;
26219
- if (xy === "??") untracked++;
27238
+ if (!remoteProbeApplied) {
27239
+ const connectionState = readStringValue(status.connection?.state);
27240
+ const pendingPeerGitProbe = !inlineTransitGit && !isSelfNode && !!daemonId && (readStringValue(status.machineStatus) === "online" || readStringValue(status.health) === "online" || connectionState === "connecting" || connectionState === "connected" || connectionState === "unknown");
27241
+ if (pendingPeerGitProbe) {
27242
+ status.gitProbePending = true;
27243
+ status.health = "unknown";
27244
+ }
27245
+ if (applyCachedInlineMeshNodeStatus(
27246
+ status,
27247
+ node,
27248
+ pendingPeerGitProbe ? { skipGit: true, skipError: true, skipHealth: true } : void 0
27249
+ )) {
27250
+ finalizeMeshNodeStatus({ status, node, daemonId, isSelfNode });
27251
+ nodeStatuses.push(status);
27252
+ continue;
27253
+ }
27254
+ if (meshRecord?.source === "inline_cache" && !isSelfNode) {
27255
+ finalizeMeshNodeStatus({ status, node, daemonId, isSelfNode });
27256
+ nodeStatuses.push(status);
27257
+ continue;
27258
+ }
26220
27259
  }
26221
- status.git = {
26222
- workspace: node.workspace,
26223
- repoRoot: node.workspace,
26224
- isGitRepo: true,
26225
- branch: branch || null,
26226
- headCommit,
26227
- headMessage,
26228
- upstream,
26229
- ahead,
26230
- behind,
26231
- staged,
26232
- modified,
26233
- untracked,
26234
- deleted,
26235
- renamed,
26236
- hasConflicts: false,
26237
- conflictFiles: [],
26238
- stashCount: stashCount ? stashCount.split("\n").filter(Boolean).length : 0,
26239
- lastCheckedAt: Date.now()
26240
- };
26241
- status.health = branch ? dirty ? "dirty" : "online" : "degraded";
26242
- } catch {
26243
- if (!applyCachedInlineMeshNodeStatus(status, node)) {
26244
- status.health = "degraded";
27260
+ } else {
27261
+ try {
27262
+ const gitStatus = await getGitRepoStatus(workspace, { timeoutMs: 1e4, refreshUpstream: true });
27263
+ status.git = gitStatus;
27264
+ recordInlineMeshDirectGitTruth(node, gitStatus, "selected_coordinator_local_git");
27265
+ if (gitStatus.isGitRepo) {
27266
+ status.health = deriveMeshNodeHealthFromGit(gitStatus);
27267
+ } else {
27268
+ status.health = "degraded";
27269
+ if (gitStatus.error && !status.error) status.error = gitStatus.error;
27270
+ }
27271
+ } catch {
27272
+ if (!applyCachedInlineMeshNodeStatus(status, node)) {
27273
+ status.health = "degraded";
27274
+ }
26245
27275
  }
26246
27276
  }
26247
27277
  } else {
26248
27278
  applyCachedInlineMeshNodeStatus(status, node);
26249
27279
  }
27280
+ finalizeMeshNodeStatus({ status, node, daemonId, isSelfNode });
26250
27281
  nodeStatuses.push(status);
26251
27282
  }
26252
- return {
27283
+ const statusResult = {
26253
27284
  success: true,
26254
27285
  meshId: mesh.id,
26255
27286
  meshName: mesh.name,
26256
27287
  repoIdentity: mesh.repoIdentity,
26257
27288
  defaultBranch: mesh.defaultBranch,
27289
+ refreshedAt,
27290
+ sourceOfTruth: {
27291
+ membership: meshRecord?.source === "inline_cache" ? "coordinator_inline_mesh_cache" : meshRecord?.source === "local_config" ? "local_mesh_config" : "inline_bootstrap_snapshot",
27292
+ coordinatorOwnsLiveTruth: directTruthSatisfied,
27293
+ ...requireDirectPeerTruth ? {
27294
+ currentStatus: directTruthSatisfied ? "live_git_and_session_probes" : "direct_peer_truth_unavailable",
27295
+ directPeerTruth: {
27296
+ required: true,
27297
+ satisfied: directTruthSatisfied,
27298
+ directEvidenceCount: directTruth.directEvidenceCount,
27299
+ localConfirmedCount: directTruth.localConfirmedCount,
27300
+ peerAttemptedCount: directTruth.peerAttemptedCount,
27301
+ peerConfirmedCount: directTruth.peerConfirmedCount,
27302
+ unavailableNodeIds: directTruth.unavailableNodeIds
27303
+ }
27304
+ } : {},
27305
+ historicalEvidenceOnly: ["recoveryHints", "ledger.summary", "queue.summary"]
27306
+ },
26258
27307
  nodes: nodeStatuses,
26259
27308
  queue: { tasks: queue, summary: queueSummary },
26260
27309
  ledger: { entries: ledgerEntries, summary: ledgerSummary }
26261
27310
  };
27311
+ return this.rememberAggregateMeshStatus(meshId, statusResult, refreshReason);
26262
27312
  } catch (e) {
26263
27313
  return { success: false, error: e.message };
26264
27314
  }
@@ -34184,6 +35234,7 @@ async function initDaemonComponents(config) {
34184
35234
  sessionHostControl: config.sessionHostControl,
34185
35235
  statusInstanceId: config.statusInstanceId,
34186
35236
  statusVersion: config.statusVersion,
35237
+ getMeshPeerConnectionStatus: config.getMeshPeerConnectionStatus,
34187
35238
  getCdpLogFn: config.getCdpLogFn || ((ideType) => LOG.forComponent(`CDP:${ideType}`).asLogFn())
34188
35239
  });
34189
35240
  poller = new AgentStreamPoller({
@@ -34459,6 +35510,7 @@ async function shutdownDaemonComponents(components) {
34459
35510
  prepareSessionChatTailUpdate,
34460
35511
  prepareSessionModalUpdate,
34461
35512
  probeCdpPort,
35513
+ queuePendingMeshCoordinatorEvent,
34462
35514
  readChatHistory,
34463
35515
  readLedgerEntries,
34464
35516
  readLedgerSlice,