@adhdev/daemon-core 0.9.82-rc.3 → 0.9.82-rc.31

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -1351,13 +1351,43 @@ __export(mesh_work_queue_exports, {
1351
1351
  updateSessionTaskStatus: () => updateSessionTaskStatus,
1352
1352
  updateTaskStatus: () => updateTaskStatus
1353
1353
  });
1354
- import { existsSync as existsSync6, writeFileSync as writeFileSync3, readFileSync as readFileSync4 } from "fs";
1354
+ import { existsSync as existsSync6, writeFileSync as writeFileSync3, readFileSync as readFileSync4, openSync, closeSync, unlinkSync } from "fs";
1355
1355
  import { join as join6 } from "path";
1356
1356
  import { randomUUID as randomUUID5 } from "crypto";
1357
1357
  function getQueuePath(meshId) {
1358
1358
  const safe = meshId.replace(/[^a-zA-Z0-9_-]/g, "_");
1359
1359
  return join6(getLedgerDir(), `${safe}.queue.json`);
1360
1360
  }
1361
+ function getLockPath(meshId) {
1362
+ const safe = meshId.replace(/[^a-zA-Z0-9_-]/g, "_");
1363
+ return join6(getLedgerDir(), `${safe}.queue.lock`);
1364
+ }
1365
+ function withQueueLock(meshId, fn) {
1366
+ const lockPath = getLockPath(meshId);
1367
+ let fd = -1;
1368
+ for (let i = 0; i < 10; i++) {
1369
+ try {
1370
+ fd = openSync(lockPath, "wx");
1371
+ break;
1372
+ } catch {
1373
+ const deadline = Date.now() + 30;
1374
+ while (Date.now() < deadline) {
1375
+ }
1376
+ }
1377
+ }
1378
+ try {
1379
+ return fn();
1380
+ } finally {
1381
+ if (fd !== -1) try {
1382
+ closeSync(fd);
1383
+ } catch {
1384
+ }
1385
+ try {
1386
+ unlinkSync(lockPath);
1387
+ } catch {
1388
+ }
1389
+ }
1390
+ }
1361
1391
  function readQueue(meshId) {
1362
1392
  const path28 = getQueuePath(meshId);
1363
1393
  if (!existsSync6(path28)) return [];
@@ -1373,20 +1403,22 @@ function writeQueue(meshId, queue) {
1373
1403
  writeFileSync3(path28, JSON.stringify(queue, null, 2), "utf-8");
1374
1404
  }
1375
1405
  function enqueueTask(meshId, message, opts) {
1376
- const queue = readQueue(meshId);
1377
- const entry = {
1378
- id: randomUUID5(),
1379
- meshId,
1380
- message,
1381
- status: "pending",
1382
- targetNodeId: opts?.targetNodeId,
1383
- targetSessionId: opts?.targetSessionId,
1384
- createdAt: (/* @__PURE__ */ new Date()).toISOString(),
1385
- updatedAt: (/* @__PURE__ */ new Date()).toISOString()
1386
- };
1387
- queue.push(entry);
1388
- writeQueue(meshId, queue);
1389
- return entry;
1406
+ return withQueueLock(meshId, () => {
1407
+ const queue = readQueue(meshId);
1408
+ const entry = {
1409
+ id: randomUUID5(),
1410
+ meshId,
1411
+ message,
1412
+ status: "pending",
1413
+ targetNodeId: opts?.targetNodeId,
1414
+ targetSessionId: opts?.targetSessionId,
1415
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
1416
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
1417
+ };
1418
+ queue.push(entry);
1419
+ writeQueue(meshId, queue);
1420
+ return entry;
1421
+ });
1390
1422
  }
1391
1423
  function getQueue(meshId, opts) {
1392
1424
  let queue = readQueue(meshId);
@@ -1397,100 +1429,111 @@ function getQueue(meshId, opts) {
1397
1429
  return queue;
1398
1430
  }
1399
1431
  function claimNextTask(meshId, nodeId, sessionId) {
1400
- const queue = readQueue(meshId);
1401
- const hasActiveAssignment = queue.some((q) => q.status === "assigned" && (q.assignedSessionId === sessionId || q.assignedNodeId === nodeId));
1402
- if (hasActiveAssignment) return null;
1403
- let targetIdx = queue.findIndex((q) => q.status === "pending" && q.targetSessionId === sessionId);
1404
- if (targetIdx === -1) {
1405
- targetIdx = queue.findIndex((q) => q.status === "pending" && q.targetNodeId === nodeId && !q.targetSessionId);
1406
- }
1407
- if (targetIdx === -1) {
1408
- targetIdx = queue.findIndex((q) => q.status === "pending" && !q.targetNodeId && !q.targetSessionId);
1409
- }
1410
- if (targetIdx === -1) return null;
1411
- const entry = queue[targetIdx];
1412
- entry.status = "assigned";
1413
- entry.assignedNodeId = nodeId;
1414
- entry.assignedSessionId = sessionId;
1415
- entry.dispatchTimestamp = (/* @__PURE__ */ new Date()).toISOString();
1416
- entry.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
1417
- writeQueue(meshId, queue);
1418
- return entry;
1432
+ return withQueueLock(meshId, () => {
1433
+ const queue = readQueue(meshId);
1434
+ const hasActiveAssignment = queue.some((q) => q.status === "assigned" && (q.assignedSessionId === sessionId || q.assignedNodeId === nodeId));
1435
+ if (hasActiveAssignment) return null;
1436
+ let targetIdx = queue.findIndex((q) => q.status === "pending" && q.targetSessionId === sessionId);
1437
+ if (targetIdx === -1) {
1438
+ targetIdx = queue.findIndex((q) => q.status === "pending" && q.targetNodeId === nodeId && !q.targetSessionId);
1439
+ }
1440
+ if (targetIdx === -1) {
1441
+ targetIdx = queue.findIndex((q) => q.status === "pending" && !q.targetNodeId && !q.targetSessionId);
1442
+ }
1443
+ if (targetIdx === -1) return null;
1444
+ const entry = queue[targetIdx];
1445
+ entry.status = "assigned";
1446
+ entry.assignedNodeId = nodeId;
1447
+ entry.assignedSessionId = sessionId;
1448
+ entry.dispatchTimestamp = (/* @__PURE__ */ new Date()).toISOString();
1449
+ entry.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
1450
+ writeQueue(meshId, queue);
1451
+ return entry;
1452
+ });
1419
1453
  }
1420
1454
  function updateTaskStatus(meshId, taskId, status) {
1421
- const queue = readQueue(meshId);
1422
- const idx = queue.findIndex((q) => q.id === taskId);
1423
- if (idx === -1) return null;
1424
- queue[idx].status = status;
1425
- queue[idx].updatedAt = (/* @__PURE__ */ new Date()).toISOString();
1426
- writeQueue(meshId, queue);
1427
- return queue[idx];
1455
+ return withQueueLock(meshId, () => {
1456
+ const queue = readQueue(meshId);
1457
+ const idx = queue.findIndex((q) => q.id === taskId);
1458
+ if (idx === -1) return null;
1459
+ queue[idx].status = status;
1460
+ queue[idx].updatedAt = (/* @__PURE__ */ new Date()).toISOString();
1461
+ writeQueue(meshId, queue);
1462
+ return queue[idx];
1463
+ });
1428
1464
  }
1429
1465
  function recordTaskAutoLaunch(meshId, taskId, autoLaunch) {
1430
- const queue = readQueue(meshId);
1431
- const idx = queue.findIndex((q) => q.id === taskId);
1432
- if (idx === -1) return null;
1433
- const now = (/* @__PURE__ */ new Date()).toISOString();
1434
- queue[idx].autoLaunch = {
1435
- ...autoLaunch,
1436
- updatedAt: now
1437
- };
1438
- queue[idx].updatedAt = now;
1439
- writeQueue(meshId, queue);
1440
- return queue[idx];
1466
+ return withQueueLock(meshId, () => {
1467
+ const queue = readQueue(meshId);
1468
+ const idx = queue.findIndex((q) => q.id === taskId);
1469
+ if (idx === -1) return null;
1470
+ const now = (/* @__PURE__ */ new Date()).toISOString();
1471
+ queue[idx].autoLaunch = { ...autoLaunch, updatedAt: now };
1472
+ queue[idx].updatedAt = now;
1473
+ writeQueue(meshId, queue);
1474
+ return queue[idx];
1475
+ });
1441
1476
  }
1442
1477
  function cancelTask(meshId, taskId, opts) {
1443
- const queue = readQueue(meshId);
1444
- const idx = queue.findIndex((q) => q.id === taskId);
1445
- if (idx === -1) return null;
1446
- const now = (/* @__PURE__ */ new Date()).toISOString();
1447
- queue[idx].status = "cancelled";
1448
- queue[idx].updatedAt = now;
1449
- queue[idx].cancelledAt = now;
1450
- if (opts?.reason) queue[idx].cancelReason = opts.reason;
1451
- writeQueue(meshId, queue);
1452
- return queue[idx];
1478
+ return withQueueLock(meshId, () => {
1479
+ const queue = readQueue(meshId);
1480
+ const idx = queue.findIndex((q) => q.id === taskId);
1481
+ if (idx === -1) return null;
1482
+ const now = (/* @__PURE__ */ new Date()).toISOString();
1483
+ queue[idx].status = "cancelled";
1484
+ queue[idx].updatedAt = now;
1485
+ queue[idx].cancelledAt = now;
1486
+ if (opts?.reason) queue[idx].cancelReason = opts.reason;
1487
+ writeQueue(meshId, queue);
1488
+ return queue[idx];
1489
+ });
1453
1490
  }
1454
1491
  function requeueTask(meshId, taskId, opts) {
1455
- const queue = readQueue(meshId);
1456
- const idx = queue.findIndex((q) => q.id === taskId);
1457
- if (idx === -1) return null;
1458
- const entry = queue[idx];
1459
- const now = (/* @__PURE__ */ new Date()).toISOString();
1460
- entry.status = "pending";
1461
- delete entry.assignedNodeId;
1462
- delete entry.assignedSessionId;
1463
- delete entry.cancelledAt;
1464
- delete entry.cancelReason;
1465
- if (opts?.clearTargetNode) delete entry.targetNodeId;
1466
- if (typeof opts?.targetNodeId === "string") entry.targetNodeId = opts.targetNodeId;
1467
- if (opts?.clearTargetSession !== false) delete entry.targetSessionId;
1468
- if (typeof opts?.targetSessionId === "string") entry.targetSessionId = opts.targetSessionId;
1469
- entry.updatedAt = now;
1470
- entry.requeuedAt = now;
1471
- entry.requeueCount = (entry.requeueCount || 0) + 1;
1472
- if (opts?.reason) entry.requeueReason = opts.reason;
1473
- writeQueue(meshId, queue);
1474
- return entry;
1475
- }
1476
- function updateSessionTaskStatus(meshId, sessionId, status) {
1477
- const queue = readQueue(meshId);
1478
- let bestIdx = -1;
1479
- let bestTime = 0;
1480
- for (let i = queue.length - 1; i >= 0; i--) {
1481
- if (queue[i].assignedSessionId === sessionId && queue[i].status === "assigned") {
1492
+ return withQueueLock(meshId, () => {
1493
+ const queue = readQueue(meshId);
1494
+ const idx = queue.findIndex((q) => q.id === taskId);
1495
+ if (idx === -1) return null;
1496
+ const entry = queue[idx];
1497
+ const now = (/* @__PURE__ */ new Date()).toISOString();
1498
+ entry.status = "pending";
1499
+ delete entry.assignedNodeId;
1500
+ delete entry.assignedSessionId;
1501
+ delete entry.cancelledAt;
1502
+ delete entry.cancelReason;
1503
+ if (opts?.clearTargetNode) delete entry.targetNodeId;
1504
+ if (typeof opts?.targetNodeId === "string") entry.targetNodeId = opts.targetNodeId;
1505
+ if (opts?.clearTargetSession !== false) delete entry.targetSessionId;
1506
+ if (typeof opts?.targetSessionId === "string") entry.targetSessionId = opts.targetSessionId;
1507
+ entry.updatedAt = now;
1508
+ entry.requeuedAt = now;
1509
+ entry.requeueCount = (entry.requeueCount || 0) + 1;
1510
+ if (opts?.reason) entry.requeueReason = opts.reason;
1511
+ writeQueue(meshId, queue);
1512
+ return entry;
1513
+ });
1514
+ }
1515
+ function updateSessionTaskStatus(meshId, sessionId, status, opts) {
1516
+ return withQueueLock(meshId, () => {
1517
+ const queue = readQueue(meshId);
1518
+ const occurredAtTime = opts?.occurredAt ? new Date(opts.occurredAt).getTime() : Number.NaN;
1519
+ const hasOccurredAt = Number.isFinite(occurredAtTime);
1520
+ let bestIdx = -1;
1521
+ let bestTime = 0;
1522
+ for (let i = queue.length - 1; i >= 0; i--) {
1523
+ if (queue[i].assignedSessionId !== sessionId || queue[i].status !== "assigned") continue;
1482
1524
  const time = new Date(queue[i].dispatchTimestamp || queue[i].updatedAt).getTime();
1525
+ if (hasOccurredAt && Number.isFinite(time) && time > occurredAtTime) continue;
1483
1526
  if (time > bestTime) {
1484
1527
  bestTime = time;
1485
1528
  bestIdx = i;
1486
1529
  }
1487
1530
  }
1488
- }
1489
- if (bestIdx === -1) return null;
1490
- queue[bestIdx].status = status;
1491
- queue[bestIdx].updatedAt = (/* @__PURE__ */ new Date()).toISOString();
1492
- writeQueue(meshId, queue);
1493
- return queue[bestIdx];
1531
+ if (bestIdx === -1) return null;
1532
+ queue[bestIdx].status = status;
1533
+ queue[bestIdx].updatedAt = (/* @__PURE__ */ new Date()).toISOString();
1534
+ writeQueue(meshId, queue);
1535
+ return queue[bestIdx];
1536
+ });
1494
1537
  }
1495
1538
  function getMeshQueueStats(meshId) {
1496
1539
  const queue = readQueue(meshId);
@@ -1890,18 +1933,77 @@ __export(mesh_events_exports, {
1890
1933
  drainPendingMeshCoordinatorEvents: () => drainPendingMeshCoordinatorEvents,
1891
1934
  getPendingMeshCoordinatorEvents: () => getPendingMeshCoordinatorEvents,
1892
1935
  handleMeshForwardEvent: () => handleMeshForwardEvent,
1936
+ queuePendingMeshCoordinatorEvent: () => queuePendingMeshCoordinatorEvent,
1893
1937
  setupMeshEventForwarding: () => setupMeshEventForwarding,
1894
1938
  triggerMeshQueue: () => triggerMeshQueue,
1895
1939
  tryAssignQueueTask: () => tryAssignQueueTask
1896
1940
  });
1897
- function drainPendingMeshCoordinatorEvents() {
1898
- return pendingMeshCoordinatorEvents.splice(0);
1941
+ import { appendFileSync as appendFileSync3, existsSync as existsSync9, readFileSync as readFileSync5, unlinkSync as unlinkSync3 } from "fs";
1942
+ import { join as join9 } from "path";
1943
+ function sweepExpiredRemoteIdleSessions() {
1944
+ const now = Date.now();
1945
+ for (const [key, session] of remoteIdleSessions) {
1946
+ if (session.expiresAt <= now) remoteIdleSessions.delete(key);
1947
+ }
1948
+ }
1949
+ function getPendingEventsPath(meshId) {
1950
+ const safe = meshId.replace(/[^a-zA-Z0-9_-]/g, "_");
1951
+ return join9(getLedgerDir(), `${safe}.pending-events.jsonl`);
1899
1952
  }
1900
- function getPendingMeshCoordinatorEvents() {
1901
- return pendingMeshCoordinatorEvents.slice();
1953
+ function queuePendingMeshCoordinatorEvent(event) {
1954
+ try {
1955
+ appendFileSync3(getPendingEventsPath(event.meshId), JSON.stringify(event) + "\n", "utf-8");
1956
+ return true;
1957
+ } catch (e) {
1958
+ LOG.warn("MeshEvents", `Failed to persist pending coordinator event: ${e?.message || e}`);
1959
+ return false;
1960
+ }
1902
1961
  }
1903
- function clearPendingMeshCoordinatorEvents() {
1904
- pendingMeshCoordinatorEvents.splice(0);
1962
+ function drainPendingMeshCoordinatorEvents(meshId) {
1963
+ if (!meshId) return [];
1964
+ const path28 = getPendingEventsPath(meshId);
1965
+ if (!existsSync9(path28)) return [];
1966
+ try {
1967
+ const raw = readFileSync5(path28, "utf-8");
1968
+ try {
1969
+ unlinkSync3(path28);
1970
+ } catch {
1971
+ }
1972
+ return raw.split("\n").filter(Boolean).flatMap((line) => {
1973
+ try {
1974
+ return [JSON.parse(line)];
1975
+ } catch {
1976
+ return [];
1977
+ }
1978
+ });
1979
+ } catch {
1980
+ return [];
1981
+ }
1982
+ }
1983
+ function getPendingMeshCoordinatorEvents(meshId) {
1984
+ if (!meshId) return [];
1985
+ const path28 = getPendingEventsPath(meshId);
1986
+ if (!existsSync9(path28)) return [];
1987
+ try {
1988
+ const raw = readFileSync5(path28, "utf-8");
1989
+ return raw.split("\n").filter(Boolean).flatMap((line) => {
1990
+ try {
1991
+ return [JSON.parse(line)];
1992
+ } catch {
1993
+ return [];
1994
+ }
1995
+ });
1996
+ } catch {
1997
+ return [];
1998
+ }
1999
+ }
2000
+ function clearPendingMeshCoordinatorEvents(meshId) {
2001
+ if (!meshId) return;
2002
+ const path28 = getPendingEventsPath(meshId);
2003
+ if (existsSync9(path28)) try {
2004
+ unlinkSync3(path28);
2005
+ } catch {
2006
+ }
1905
2007
  }
1906
2008
  function readNonEmptyString(value) {
1907
2009
  return typeof value === "string" && value.trim() ? value.trim() : "";
@@ -1947,6 +2049,38 @@ function shouldSuppressIntentionalCleanupStop(args) {
1947
2049
  if (isIntentionalCleanupStopMetadata(args.metadataEvent)) return true;
1948
2050
  return hasRecentIntentionalCleanupStop(args.meshId, args.sessionId, args.nodeId);
1949
2051
  }
2052
+ function readEventTimestamp(value) {
2053
+ if (typeof value === "number" && Number.isFinite(value)) return value;
2054
+ if (typeof value === "string" && value.trim()) {
2055
+ const numeric = Number(value);
2056
+ if (Number.isFinite(numeric)) return numeric;
2057
+ const parsed = Date.parse(value);
2058
+ if (Number.isFinite(parsed)) return parsed;
2059
+ }
2060
+ return null;
2061
+ }
2062
+ function buildMeshCompletionFingerprint(args) {
2063
+ const timestampPart = Number.isFinite(args.timestamp) ? String(args.timestamp) : readNonEmptyString(args.finalSummary).slice(0, 200);
2064
+ return [
2065
+ args.meshId,
2066
+ args.event,
2067
+ args.sessionId,
2068
+ args.providerType || "",
2069
+ args.providerSessionId || "",
2070
+ timestampPart
2071
+ ].join("::");
2072
+ }
2073
+ function isDuplicateMeshCompletionEvent(args) {
2074
+ const fingerprint = buildMeshCompletionFingerprint(args);
2075
+ if (!fingerprint) return false;
2076
+ const now = Date.now();
2077
+ for (const [key, seenAt] of recentCompletionFingerprints.entries()) {
2078
+ if (now - seenAt > RECENT_COMPLETION_FINGERPRINT_TTL_MS) recentCompletionFingerprints.delete(key);
2079
+ }
2080
+ if (recentCompletionFingerprints.has(fingerprint)) return true;
2081
+ recentCompletionFingerprints.set(fingerprint, now);
2082
+ return false;
2083
+ }
1950
2084
  function tryAssignQueueTask(components, meshId, nodeId, sessionId, providerType) {
1951
2085
  const task = claimNextTask(meshId, nodeId, sessionId);
1952
2086
  if (!task) {
@@ -1965,7 +2099,16 @@ function tryAssignQueueTask(components, meshId, nodeId, sessionId, providerType)
1965
2099
  message: task.message
1966
2100
  }).catch((e) => {
1967
2101
  LOG.error("MeshQueue", `Failed to dispatch task via P2P to remote node ${nodeId}: ${e?.message}`);
1968
- updateTaskStatus(meshId, task.id, "failed");
2102
+ updateTaskStatus(meshId, task.id, "pending");
2103
+ try {
2104
+ appendLedgerEntry(meshId, {
2105
+ kind: "dispatch_failed",
2106
+ nodeId,
2107
+ sessionId,
2108
+ payload: { taskId: task.id, error: e?.message, retryable: true }
2109
+ });
2110
+ } catch {
2111
+ }
1969
2112
  });
1970
2113
  return true;
1971
2114
  }
@@ -2299,18 +2442,36 @@ function injectMeshSystemMessage(components, args) {
2299
2442
  LOG.info("MeshEvents", `Suppressed ${args.event} for intentionally cleanup-stopped session ${eventSessionId || "(unknown session)"}`);
2300
2443
  return { success: true, forwarded: 0, suppressed: true, intentionalCleanupStop: true };
2301
2444
  }
2445
+ const eventTimestamp = readEventTimestamp(args.metadataEvent.timestamp);
2446
+ if (args.event === "agent:generating_completed" && eventSessionId) {
2447
+ const duplicateCompletion = isDuplicateMeshCompletionEvent({
2448
+ meshId: args.meshId,
2449
+ event: args.event,
2450
+ sessionId: eventSessionId,
2451
+ providerType: readNonEmptyString(args.metadataEvent.providerType) || void 0,
2452
+ providerSessionId: readNonEmptyString(args.metadataEvent.providerSessionId) || void 0,
2453
+ timestamp: eventTimestamp,
2454
+ finalSummary: readNonEmptyString(args.metadataEvent.finalSummary) || void 0
2455
+ });
2456
+ if (duplicateCompletion) {
2457
+ LOG.info("MeshEvents", `Suppressed duplicate completion for mesh ${args.meshId} session ${eventSessionId}`);
2458
+ return { success: true, forwarded: 0, suppressed: true, duplicateCompletion: true };
2459
+ }
2460
+ }
2302
2461
  let completedTaskForLedger = null;
2303
2462
  if (args.event === "agent:generating_completed") {
2304
2463
  const sessionId = resolveEventSessionId(args.metadataEvent, args.sourceInstanceId);
2305
2464
  const nodeId = readNonEmptyString(args.nodeId) || readNonEmptyString(args.metadataEvent.meshNodeId);
2306
2465
  const providerType = readNonEmptyString(args.metadataEvent.providerType);
2307
2466
  if (sessionId) {
2308
- const completedTask = updateSessionTaskStatus(args.meshId, sessionId, "completed");
2467
+ const completedTask = updateSessionTaskStatus(args.meshId, sessionId, "completed", {
2468
+ occurredAt: eventTimestamp !== null ? new Date(eventTimestamp).toISOString() : void 0
2469
+ });
2309
2470
  completedTaskForLedger = completedTask ? { id: completedTask.id } : null;
2310
2471
  if (nodeId && providerType) {
2311
- setTimeout(() => {
2472
+ setImmediate(() => {
2312
2473
  tryAssignQueueTask(components, args.meshId, nodeId, sessionId, providerType);
2313
- }, 500);
2474
+ });
2314
2475
  }
2315
2476
  }
2316
2477
  } else if (args.event === "agent:ready") {
@@ -2348,13 +2509,17 @@ function injectMeshSystemMessage(components, args) {
2348
2509
  }
2349
2510
  }
2350
2511
  if (sessionId && nodeId && providerType) {
2351
- remoteIdleSessions.set(`${nodeId}:${sessionId}`, { nodeId, sessionId, providerType });
2352
- setTimeout(() => {
2512
+ sweepExpiredRemoteIdleSessions();
2513
+ remoteIdleSessions.set(`${nodeId}:${sessionId}`, {
2514
+ nodeId,
2515
+ sessionId,
2516
+ providerType,
2517
+ expiresAt: Date.now() + REMOTE_IDLE_SESSION_TTL_MS
2518
+ });
2519
+ setImmediate(() => {
2353
2520
  const assigned = tryAssignQueueTask(components, args.meshId, nodeId, sessionId, providerType);
2354
- if (assigned) {
2355
- remoteIdleSessions.delete(`${nodeId}:${sessionId}`);
2356
- }
2357
- }, 500);
2521
+ if (assigned) remoteIdleSessions.delete(`${nodeId}:${sessionId}`);
2522
+ });
2358
2523
  }
2359
2524
  } else if (args.event === "agent:generating_started") {
2360
2525
  const sessionId = resolveEventSessionId(args.metadataEvent, args.sourceInstanceId);
@@ -2465,17 +2630,18 @@ function injectMeshSystemMessage(components, args) {
2465
2630
  return true;
2466
2631
  });
2467
2632
  if (coordinatorInstances.length === 0) {
2468
- if (pendingMeshCoordinatorEvents.length < MAX_PENDING_EVENTS) {
2469
- pendingMeshCoordinatorEvents.push({
2470
- event: args.event,
2471
- meshId: args.meshId,
2472
- nodeLabel: args.nodeLabel,
2473
- metadataEvent: {
2474
- ...args.metadataEvent,
2475
- ...recoveryContext ? { recoveryContext } : {}
2476
- },
2477
- queuedAt: Date.now()
2478
- });
2633
+ if (queuePendingMeshCoordinatorEvent({
2634
+ event: args.event,
2635
+ meshId: args.meshId,
2636
+ nodeLabel: args.nodeLabel,
2637
+ nodeId: args.nodeId || void 0,
2638
+ workspace: readNonEmptyString(args.metadataEvent.workspace),
2639
+ metadataEvent: {
2640
+ ...args.metadataEvent,
2641
+ ...recoveryContext ? { recoveryContext } : {}
2642
+ },
2643
+ queuedAt: Date.now()
2644
+ })) {
2479
2645
  LOG.info("MeshEvents", `Queued ${args.event} for MCP coordinator (mesh ${args.meshId})`);
2480
2646
  }
2481
2647
  return { success: true, forwarded: 0 };
@@ -2514,6 +2680,7 @@ function handleMeshForwardEvent(components, payload) {
2514
2680
  providerType: readNonEmptyString(payload.providerType),
2515
2681
  providerSessionId: readNonEmptyString(payload.providerSessionId),
2516
2682
  finalSummary: readNonEmptyString(payload.finalSummary) || readNonEmptyString(payload.summary),
2683
+ ...payload.timestamp !== void 0 ? { timestamp: payload.timestamp } : {},
2517
2684
  intentional: payload.intentional === true,
2518
2685
  intentionalStop: payload.intentionalStop === true,
2519
2686
  operatorCleanup: payload.operatorCleanup === true,
@@ -2556,7 +2723,7 @@ function setupMeshEventForwarding(components) {
2556
2723
  });
2557
2724
  });
2558
2725
  }
2559
- var remoteIdleSessions, MAX_PENDING_EVENTS, pendingMeshCoordinatorEvents, MESH_COORDINATOR_EVENTS, EVENT_TO_LEDGER_KIND, INTENTIONAL_CLEANUP_STOP_SUPPRESSION_MS, autoLaunchInProgress, autoLaunchCooldownUntil, AUTO_LAUNCH_COOLDOWN_MS;
2726
+ var REMOTE_IDLE_SESSION_TTL_MS, remoteIdleSessions, MESH_COORDINATOR_EVENTS, EVENT_TO_LEDGER_KIND, INTENTIONAL_CLEANUP_STOP_SUPPRESSION_MS, RECENT_COMPLETION_FINGERPRINT_TTL_MS, recentCompletionFingerprints, autoLaunchInProgress, autoLaunchCooldownUntil, AUTO_LAUNCH_COOLDOWN_MS;
2560
2727
  var init_mesh_events = __esm({
2561
2728
  "src/mesh/mesh-events.ts"() {
2562
2729
  "use strict";
@@ -2566,9 +2733,8 @@ var init_mesh_events = __esm({
2566
2733
  init_logger();
2567
2734
  init_mesh_ledger();
2568
2735
  init_mesh_work_queue();
2736
+ REMOTE_IDLE_SESSION_TTL_MS = 5 * 60 * 1e3;
2569
2737
  remoteIdleSessions = /* @__PURE__ */ new Map();
2570
- MAX_PENDING_EVENTS = 50;
2571
- pendingMeshCoordinatorEvents = [];
2572
2738
  MESH_COORDINATOR_EVENTS = /* @__PURE__ */ new Set([
2573
2739
  "agent:generating_started",
2574
2740
  "agent:generating_completed",
@@ -2584,6 +2750,8 @@ var init_mesh_events = __esm({
2584
2750
  "monitor:long_generating": "task_stalled"
2585
2751
  };
2586
2752
  INTENTIONAL_CLEANUP_STOP_SUPPRESSION_MS = 30 * 60 * 1e3;
2753
+ RECENT_COMPLETION_FINGERPRINT_TTL_MS = 10 * 60 * 1e3;
2754
+ recentCompletionFingerprints = /* @__PURE__ */ new Map();
2587
2755
  autoLaunchInProgress = /* @__PURE__ */ new Set();
2588
2756
  autoLaunchCooldownUntil = /* @__PURE__ */ new Map();
2589
2757
  AUTO_LAUNCH_COOLDOWN_MS = 5e3;
@@ -5676,8 +5844,14 @@ async function getGitRepoStatus(workspace, options = {}) {
5676
5844
  const includeSubmodules = options.includeSubmodules !== false;
5677
5845
  try {
5678
5846
  const repo = await resolveGitRepository(workspace, options);
5679
- const statusOutput = await runGit(repo, ["status", "--porcelain=v2", "--branch"], options);
5680
- const parsed = parsePorcelainV2Status(statusOutput.stdout);
5847
+ let parsed = await readPorcelainStatus(repo, options);
5848
+ let upstreamProbe = getInitialUpstreamProbe(parsed);
5849
+ if (options.refreshUpstream) {
5850
+ upstreamProbe = await refreshTrackedUpstream(repo, parsed, options);
5851
+ if (upstreamProbe.upstreamStatus === "fresh") {
5852
+ parsed = await readPorcelainStatus(repo, options);
5853
+ }
5854
+ }
5681
5855
  const head = await readHead(repo, options);
5682
5856
  const stashCount = await readStashCount(repo, options);
5683
5857
  let submodules;
@@ -5692,6 +5866,9 @@ async function getGitRepoStatus(workspace, options = {}) {
5692
5866
  headCommit: head.commit,
5693
5867
  headMessage: head.message,
5694
5868
  upstream: parsed.upstream,
5869
+ upstreamStatus: parsed.upstream ? upstreamProbe.upstreamStatus : "no_upstream",
5870
+ upstreamFetchedAt: upstreamProbe.upstreamFetchedAt,
5871
+ upstreamFetchError: upstreamProbe.upstreamFetchError,
5695
5872
  ahead: parsed.ahead,
5696
5873
  behind: parsed.behind,
5697
5874
  staged: parsed.staged,
@@ -5716,6 +5893,60 @@ async function getGitRepoStatus(workspace, options = {}) {
5716
5893
  );
5717
5894
  }
5718
5895
  }
5896
+ async function readPorcelainStatus(repo, options) {
5897
+ const statusOutput = await runGit(repo, ["status", "--porcelain=v2", "--branch"], options);
5898
+ return parsePorcelainV2Status(statusOutput.stdout);
5899
+ }
5900
+ function getInitialUpstreamProbe(parsed) {
5901
+ return {
5902
+ upstreamStatus: parsed.upstream ? "unchecked" : "no_upstream"
5903
+ };
5904
+ }
5905
+ async function refreshTrackedUpstream(repo, parsed, options) {
5906
+ if (!parsed.upstream || !parsed.branch) {
5907
+ return { upstreamStatus: "no_upstream" };
5908
+ }
5909
+ const remoteName = await readBranchRemote(repo, parsed.branch, options) ?? inferRemoteName(parsed.upstream);
5910
+ if (!remoteName) {
5911
+ return {
5912
+ upstreamStatus: "stale",
5913
+ upstreamFetchError: `Unable to resolve remote for upstream '${parsed.upstream}'`
5914
+ };
5915
+ }
5916
+ try {
5917
+ await runGit(repo, ["fetch", "--quiet", "--prune", "--no-tags", remoteName], options);
5918
+ return {
5919
+ upstreamStatus: "fresh",
5920
+ upstreamFetchedAt: Date.now()
5921
+ };
5922
+ } catch (error) {
5923
+ return {
5924
+ upstreamStatus: "stale",
5925
+ upstreamFetchError: formatGitError(error)
5926
+ };
5927
+ }
5928
+ }
5929
+ async function readBranchRemote(repo, branch, options) {
5930
+ try {
5931
+ const result = await runGit(repo, ["config", "--get", `branch.${branch}.remote`], options);
5932
+ return result.stdout.trim() || null;
5933
+ } catch {
5934
+ return null;
5935
+ }
5936
+ }
5937
+ function inferRemoteName(upstream) {
5938
+ const [remoteName] = upstream.split("/");
5939
+ return remoteName?.trim() || null;
5940
+ }
5941
+ function formatGitError(error) {
5942
+ if (error instanceof GitCommandError) {
5943
+ return error.stderr || error.message;
5944
+ }
5945
+ if (error instanceof Error) {
5946
+ return error.message;
5947
+ }
5948
+ return String(error);
5949
+ }
5719
5950
  function parsePorcelainV2Status(output) {
5720
5951
  const parsed = {
5721
5952
  branch: null,
@@ -5810,6 +6041,7 @@ function emptyStatus(workspace, lastCheckedAt, error) {
5810
6041
  headCommit: null,
5811
6042
  headMessage: null,
5812
6043
  upstream: null,
6044
+ upstreamStatus: "unavailable",
5813
6045
  ahead: 0,
5814
6046
  behind: 0,
5815
6047
  staged: 0,
@@ -6090,6 +6322,9 @@ function createGitCompactSummary(status, diffSummary) {
6090
6322
  isGitRepo: status.isGitRepo,
6091
6323
  repoRoot: status.repoRoot,
6092
6324
  branch: status.branch,
6325
+ upstreamStatus: status.upstreamStatus,
6326
+ upstreamFetchedAt: status.upstreamFetchedAt,
6327
+ upstreamFetchError: status.upstreamFetchError,
6093
6328
  dirty: status.staged > 0 || status.modified > 0 || status.untracked > 0 || status.deleted > 0 || status.renamed > 0 || conflictCount > 0 || changedFiles > 0,
6094
6329
  changedFiles,
6095
6330
  ahead: status.ahead,
@@ -6434,7 +6669,7 @@ var defaultSnapshotStore = createGitSnapshotStore({
6434
6669
  });
6435
6670
  function createDefaultGitCommandServices() {
6436
6671
  return {
6437
- getStatus: ({ workspace }) => getGitRepoStatus(workspace),
6672
+ getStatus: ({ workspace, refreshUpstream }) => getGitRepoStatus(workspace, { refreshUpstream }),
6438
6673
  getDiffSummary: ({ workspace }) => getGitDiffSummary(workspace),
6439
6674
  getDiffFile: ({ workspace, path: filePath }) => getGitFileDiff(workspace, filePath),
6440
6675
  createSnapshot: ({ workspace, reason, sessionId, turnId }) => defaultSnapshotStore.create({
@@ -6520,7 +6755,7 @@ async function handleGitCommand(command, args, services = defaultGitCommandServi
6520
6755
  switch (command) {
6521
6756
  case "git_status": {
6522
6757
  if (!services.getStatus) return serviceNotImplemented(command);
6523
- const status = await runService(() => services.getStatus({ workspace }));
6758
+ const status = await runService(() => services.getStatus({ workspace, refreshUpstream: optionalBoolean(args?.refreshUpstream) }));
6524
6759
  return "success" in status ? status : { success: true, status };
6525
6760
  }
6526
6761
  case "git_diff_summary": {
@@ -7559,8 +7794,8 @@ var P2pRelayFailureError = class extends Error {
7559
7794
 
7560
7795
  // src/config/state-store.ts
7561
7796
  init_config();
7562
- import { existsSync as existsSync9, readFileSync as readFileSync5, writeFileSync as writeFileSync4 } from "fs";
7563
- import { join as join9 } from "path";
7797
+ import { existsSync as existsSync10, readFileSync as readFileSync6, writeFileSync as writeFileSync4 } from "fs";
7798
+ import { join as join10 } from "path";
7564
7799
  var DEFAULT_STATE = {
7565
7800
  recentActivity: [],
7566
7801
  savedProviderSessions: [],
@@ -7573,7 +7808,7 @@ function isPlainObject2(value) {
7573
7808
  return !!value && typeof value === "object" && !Array.isArray(value);
7574
7809
  }
7575
7810
  function getStatePath() {
7576
- return join9(getConfigDir(), "state.json");
7811
+ return join10(getConfigDir(), "state.json");
7577
7812
  }
7578
7813
  function normalizeState(raw) {
7579
7814
  const parsed = isPlainObject2(raw) ? raw : {};
@@ -7609,11 +7844,11 @@ function normalizeState(raw) {
7609
7844
  }
7610
7845
  function loadState() {
7611
7846
  const statePath = getStatePath();
7612
- if (!existsSync9(statePath)) {
7847
+ if (!existsSync10(statePath)) {
7613
7848
  return { ...DEFAULT_STATE };
7614
7849
  }
7615
7850
  try {
7616
- const raw = readFileSync5(statePath, "utf-8");
7851
+ const raw = readFileSync6(statePath, "utf-8");
7617
7852
  return normalizeState(JSON.parse(raw));
7618
7853
  } catch {
7619
7854
  return { ...DEFAULT_STATE };
@@ -7630,7 +7865,7 @@ function resetState() {
7630
7865
 
7631
7866
  // src/detection/ide-detector.ts
7632
7867
  import { execSync } from "child_process";
7633
- import { existsSync as existsSync10 } from "fs";
7868
+ import { existsSync as existsSync11 } from "fs";
7634
7869
  import { platform as platform2, homedir as homedir5 } from "os";
7635
7870
  import * as path10 from "path";
7636
7871
  var BUILTIN_IDE_DEFINITIONS = [];
@@ -7654,7 +7889,7 @@ function findCliCommand(command) {
7654
7889
  if (path10.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~")) {
7655
7890
  const candidate = trimmed.startsWith("~") ? path10.join(homedir5(), trimmed.slice(1)) : trimmed;
7656
7891
  const resolved = path10.isAbsolute(candidate) ? candidate : path10.resolve(candidate);
7657
- return existsSync10(resolved) ? resolved : null;
7892
+ return existsSync11(resolved) ? resolved : null;
7658
7893
  }
7659
7894
  try {
7660
7895
  const result = execSync(
@@ -7685,9 +7920,9 @@ function checkPathExists(paths) {
7685
7920
  if (normalized.includes("*")) {
7686
7921
  const username = home.split(/[\\/]/).pop() || "";
7687
7922
  const resolved = normalized.replace("*", username);
7688
- if (existsSync10(resolved)) return resolved;
7923
+ if (existsSync11(resolved)) return resolved;
7689
7924
  } else {
7690
- if (existsSync10(normalized)) return normalized;
7925
+ if (existsSync11(normalized)) return normalized;
7691
7926
  }
7692
7927
  }
7693
7928
  return null;
@@ -7701,7 +7936,7 @@ async function detectIDEs(providerLoader) {
7701
7936
  let resolvedCli = cliPath;
7702
7937
  if (!resolvedCli && appPath && os22 === "darwin") {
7703
7938
  const bundledCli = `${appPath}/Contents/Resources/app/bin/${def.cli}`;
7704
- if (existsSync10(bundledCli)) resolvedCli = bundledCli;
7939
+ if (existsSync11(bundledCli)) resolvedCli = bundledCli;
7705
7940
  }
7706
7941
  if (!resolvedCli && appPath && os22 === "win32") {
7707
7942
  const { dirname: dirname9 } = await import("path");
@@ -7714,7 +7949,7 @@ async function detectIDEs(providerLoader) {
7714
7949
  `${appDir}\\\\resources\\\\app\\\\bin\\\\${def.cli}.cmd`
7715
7950
  ];
7716
7951
  for (const c of candidates) {
7717
- if (existsSync10(c)) {
7952
+ if (existsSync11(c)) {
7718
7953
  resolvedCli = c;
7719
7954
  break;
7720
7955
  }
@@ -9606,7 +9841,8 @@ var StatusMonitor = class {
9606
9841
  };
9607
9842
 
9608
9843
  // src/providers/chat-message-normalization.ts
9609
- function extractFinalSummaryFromMessages(messages, maxChars = 500) {
9844
+ var DEFAULT_FINAL_SUMMARY_MAX_CHARS = 4e3;
9845
+ function extractFinalSummaryFromMessages(messages, maxChars = DEFAULT_FINAL_SUMMARY_MAX_CHARS) {
9610
9846
  if (!Array.isArray(messages) || messages.length === 0) return "";
9611
9847
  for (let i = messages.length - 1; i >= 0; i--) {
9612
9848
  const msg = messages[i];
@@ -16869,7 +17105,7 @@ init_config();
16869
17105
  import * as os13 from "os";
16870
17106
  import * as path18 from "path";
16871
17107
  import * as crypto4 from "crypto";
16872
- import { existsSync as existsSync14, mkdirSync as mkdirSync9, writeFileSync as writeFileSync9 } from "fs";
17108
+ import { existsSync as existsSync15, mkdirSync as mkdirSync9, writeFileSync as writeFileSync9 } from "fs";
16873
17109
  import { execFileSync } from "child_process";
16874
17110
  import chalk from "chalk";
16875
17111
 
@@ -19343,7 +19579,7 @@ function commandExists(command) {
19343
19579
  const trimmed = command.trim();
19344
19580
  if (!trimmed) return false;
19345
19581
  if (isExplicitCommand(trimmed)) {
19346
- return existsSync14(expandExecutable(trimmed));
19582
+ return existsSync15(expandExecutable(trimmed));
19347
19583
  }
19348
19584
  try {
19349
19585
  execFileSync(process.platform === "win32" ? "where" : "which", [trimmed], {
@@ -22612,10 +22848,10 @@ import * as yaml from "js-yaml";
22612
22848
  // src/commands/mesh-coordinator.ts
22613
22849
  import { execFileSync as execFileSync2 } from "child_process";
22614
22850
  import { createHash as createHash2 } from "crypto";
22615
- import { existsSync as existsSync17, readdirSync as readdirSync7, realpathSync as realpathSync2 } from "fs";
22851
+ import { existsSync as existsSync18, readdirSync as readdirSync7, realpathSync as realpathSync2 } from "fs";
22616
22852
  import { createRequire as createRequire2 } from "module";
22617
22853
  import * as os17 from "os";
22618
- import { dirname as dirname4, isAbsolute as isAbsolute11, join as join20, resolve as resolve13 } from "path";
22854
+ import { dirname as dirname4, isAbsolute as isAbsolute11, join as join21, resolve as resolve13 } from "path";
22619
22855
  var DEFAULT_SERVER_NAME = "adhdev-mesh";
22620
22856
  var DEFAULT_ADHDEV_MCP_COMMAND = "adhdev-mcp";
22621
22857
  var HERMES_CLI_TYPE = "hermes-cli";
@@ -22638,7 +22874,7 @@ function resolveHermesMeshCoordinatorSetup(options) {
22638
22874
  reason: "Could not resolve the ADHDev MCP server entrypoint and a Node runtime with WebSocket support for daemon IPC mode"
22639
22875
  };
22640
22876
  }
22641
- const configPath = join20(resolveHermesCoordinatorHome(options.meshId, options.workspace), "config.yaml");
22877
+ const configPath = join21(resolveHermesCoordinatorHome(options.meshId, options.workspace), "config.yaml");
22642
22878
  if (!configPath.trim()) {
22643
22879
  return createHermesManualMeshCoordinatorSetup(options.meshId, options.workspace);
22644
22880
  }
@@ -22759,14 +22995,14 @@ function resolveHermesCoordinatorHome(meshId, workspace) {
22759
22995
  const key = `${meshId || "mesh"}
22760
22996
  ${resolve13(workspace || os17.tmpdir())}`;
22761
22997
  const hash = createHash2("sha256").update(key).digest("hex").slice(0, 16);
22762
- return join20(os17.tmpdir(), `adhdev-hermes-mesh-coordinator-${hash}`);
22998
+ return join21(os17.tmpdir(), `adhdev-hermes-mesh-coordinator-${hash}`);
22763
22999
  }
22764
23000
  function resolveMcpConfigPath(configPath, workspace) {
22765
23001
  const trimmed = configPath.trim();
22766
23002
  if (trimmed === "~") return os17.homedir();
22767
- if (trimmed.startsWith("~/")) return join20(os17.homedir(), trimmed.slice(2));
23003
+ if (trimmed.startsWith("~/")) return join21(os17.homedir(), trimmed.slice(2));
22768
23004
  if (isAbsolute11(trimmed)) return trimmed;
22769
- return join20(workspace, trimmed);
23005
+ return join21(workspace, trimmed);
22770
23006
  }
22771
23007
  function resolveAdhdevMcpServerLaunch(options) {
22772
23008
  const entryPath = resolveAdhdevMcpEntryPath(options.adhdevMcpEntryPath);
@@ -22822,15 +23058,15 @@ function addNodeCandidatesFromPath(pathValue, addCandidate) {
22822
23058
  for (const entry of (pathValue || "").split(":")) {
22823
23059
  const dir = entry.trim();
22824
23060
  if (!dir) continue;
22825
- addCandidate(join20(dir, "node"));
23061
+ addCandidate(join21(dir, "node"));
22826
23062
  }
22827
23063
  }
22828
23064
  function addNodeCandidatesFromNvm(homeDir, addCandidate) {
22829
- const versionsDir = join20(homeDir, ".nvm", "versions", "node");
23065
+ const versionsDir = join21(homeDir, ".nvm", "versions", "node");
22830
23066
  try {
22831
23067
  const versionDirs = readdirSync7(versionsDir, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name).sort(compareNodeVersionNamesDescending);
22832
23068
  for (const versionDir of versionDirs) {
22833
- addCandidate(join20(versionsDir, versionDir, "bin", "node"));
23069
+ addCandidate(join21(versionsDir, versionDir, "bin", "node"));
22834
23070
  }
22835
23071
  } catch {
22836
23072
  }
@@ -22881,7 +23117,7 @@ function resolveAdhdevMcpEntryPath(explicitPath) {
22881
23117
  if (normalized) return normalized;
22882
23118
  }
22883
23119
  try {
22884
- const requireBase = process.argv[1] ? normalizeExistingPath(process.argv[1]) || process.argv[1] : join20(process.cwd(), "adhdev-daemon.js");
23120
+ const requireBase = process.argv[1] ? normalizeExistingPath(process.argv[1]) || process.argv[1] : join21(process.cwd(), "adhdev-daemon.js");
22885
23121
  const req = createRequire2(requireBase);
22886
23122
  const resolvedModule = req.resolve("@adhdev/mcp-server");
22887
23123
  return normalizeExistingPath(resolvedModule) || resolvedModule;
@@ -22891,7 +23127,7 @@ function resolveAdhdevMcpEntryPath(explicitPath) {
22891
23127
  }
22892
23128
  function normalizeExistingPath(filePath) {
22893
23129
  try {
22894
- if (!existsSync17(filePath)) return null;
23130
+ if (!existsSync18(filePath)) return null;
22895
23131
  return realpathSync2.native(filePath);
22896
23132
  } catch {
22897
23133
  return null;
@@ -23603,55 +23839,45 @@ function readBooleanValue(...values) {
23603
23839
  }
23604
23840
  return void 0;
23605
23841
  }
23606
- function buildCachedInlineMeshGitStatus(node) {
23607
- const cachedStatus = readObjectRecord(node?.cachedStatus);
23608
- const cachedGit = readObjectRecord(cachedStatus.git);
23609
- if (Object.keys(cachedGit).length) {
23610
- const conflictFiles2 = Array.isArray(cachedGit.conflictFiles) ? cachedGit.conflictFiles.filter((value) => typeof value === "string") : [];
23611
- const conflictCount2 = readNumberValue(cachedGit.conflicts) ?? conflictFiles2.length;
23612
- const hasConflicts2 = readBooleanValue(cachedGit.hasConflicts) ?? conflictCount2 > 0;
23613
- const isGitRepo2 = readBooleanValue(cachedGit.isGitRepo);
23614
- if (isGitRepo2 !== void 0) {
23615
- return {
23616
- workspace: readStringValue(cachedGit.workspace, node?.workspace) || "",
23617
- repoRoot: readStringValue(cachedGit.repoRoot, node?.repoRoot, node?.workspace) || null,
23618
- isGitRepo: isGitRepo2,
23619
- branch: readStringValue(cachedGit.branch) ?? null,
23620
- headCommit: readStringValue(cachedGit.headCommit) ?? null,
23621
- headMessage: readStringValue(cachedGit.headMessage) ?? null,
23622
- upstream: readStringValue(cachedGit.upstream) ?? null,
23623
- ahead: readNumberValue(cachedGit.ahead) ?? 0,
23624
- behind: readNumberValue(cachedGit.behind) ?? 0,
23625
- staged: readNumberValue(cachedGit.staged) ?? 0,
23626
- modified: readNumberValue(cachedGit.modified) ?? 0,
23627
- untracked: readNumberValue(cachedGit.untracked) ?? 0,
23628
- deleted: readNumberValue(cachedGit.deleted) ?? 0,
23629
- renamed: readNumberValue(cachedGit.renamed) ?? 0,
23630
- hasConflicts: hasConflicts2,
23631
- conflictFiles: conflictFiles2,
23632
- stashCount: readNumberValue(cachedGit.stashCount) ?? 0,
23633
- lastCheckedAt: readNumberValue(cachedGit.lastCheckedAt) ?? Date.now()
23634
- };
23635
- }
23636
- }
23637
- const rawGit = readObjectRecord(node?.lastGit ?? node?.last_git);
23638
- const gitResult = readObjectRecord(rawGit.result);
23639
- const directStatus = readObjectRecord(rawGit.status);
23640
- const nestedStatus = readObjectRecord(gitResult.status);
23641
- const rawProbe = readObjectRecord(node?.lastProbe ?? node?.last_probe);
23642
- const probeGit = readObjectRecord(rawProbe.git);
23643
- const probeGitResult = readObjectRecord(probeGit.result);
23644
- const probeDirectStatus = readObjectRecord(probeGit.status);
23645
- const probeNestedStatus = readObjectRecord(probeGitResult.status);
23646
- const status = Object.keys(directStatus).length ? directStatus : Object.keys(nestedStatus).length ? nestedStatus : Object.keys(probeDirectStatus).length ? probeDirectStatus : Object.keys(probeNestedStatus).length ? probeNestedStatus : {};
23842
+ function joinRepoPath(root, relativePath) {
23843
+ const normalizedRoot = typeof root === "string" ? root.trim().replace(/[\\/]+$/, "") : "";
23844
+ const normalizedPath = typeof relativePath === "string" ? relativePath.trim() : "";
23845
+ if (!normalizedPath) return void 0;
23846
+ if (/^(?:[A-Za-z]:[\\/]|\/)/.test(normalizedPath)) return normalizedPath;
23847
+ if (!normalizedRoot) return void 0;
23848
+ return `${normalizedRoot}/${normalizedPath.replace(/^[\\/]+/, "")}`;
23849
+ }
23850
+ function readGitSubmodules(value, parentRepoRoot) {
23851
+ if (!Array.isArray(value)) return void 0;
23852
+ const submodules = value.map((entry) => {
23853
+ const submodule = readObjectRecord(entry);
23854
+ const path28 = readStringValue(submodule.path);
23855
+ const commit = readStringValue(submodule.commit);
23856
+ const repoPath = readStringValue(submodule.repoPath, submodule.repo_root) ?? joinRepoPath(parentRepoRoot, path28);
23857
+ if (!path28 || !commit || !repoPath) return null;
23858
+ return {
23859
+ path: path28,
23860
+ commit,
23861
+ repoPath,
23862
+ dirty: readBooleanValue(submodule.dirty) ?? false,
23863
+ outOfSync: readBooleanValue(submodule.outOfSync, submodule.out_of_sync) ?? false,
23864
+ lastCheckedAt: readNumberValue(submodule.lastCheckedAt, submodule.last_checked_at) ?? Date.now(),
23865
+ ...readStringValue(submodule.error) ? { error: readStringValue(submodule.error) } : {}
23866
+ };
23867
+ }).filter((entry) => entry !== null);
23868
+ return submodules.length > 0 ? submodules : void 0;
23869
+ }
23870
+ function normalizeInlineMeshGitStatus(status, node, options) {
23647
23871
  const isGitRepo = readBooleanValue(status.isGitRepo);
23648
23872
  if (!Object.keys(status).length || isGitRepo === void 0) return void 0;
23649
23873
  const conflictFiles = Array.isArray(status.conflictFiles) ? status.conflictFiles.filter((value) => typeof value === "string") : [];
23650
23874
  const conflictCount = readNumberValue(status.conflicts) ?? conflictFiles.length;
23651
23875
  const hasConflicts = readBooleanValue(status.hasConflicts) ?? conflictCount > 0;
23876
+ const repoRoot = readStringValue(status.repoRoot, status.repo_root, node?.repoRoot, node?.repo_root, status.workspace, node?.workspace) || void 0;
23877
+ const submodules = readGitSubmodules(status.submodules, repoRoot);
23652
23878
  return {
23653
23879
  workspace: readStringValue(status.workspace, node?.workspace) || "",
23654
- repoRoot: readStringValue(status.repoRoot, node?.repoRoot, node?.workspace) || null,
23880
+ repoRoot: repoRoot ?? null,
23655
23881
  isGitRepo,
23656
23882
  branch: readStringValue(status.branch) ?? null,
23657
23883
  headCommit: readStringValue(status.headCommit) ?? null,
@@ -23667,29 +23893,407 @@ function buildCachedInlineMeshGitStatus(node) {
23667
23893
  hasConflicts,
23668
23894
  conflictFiles,
23669
23895
  stashCount: readNumberValue(status.stashCount) ?? 0,
23670
- lastCheckedAt: Date.now()
23896
+ lastCheckedAt: options?.lastCheckedAt ?? readNumberValue(status.lastCheckedAt) ?? Date.now(),
23897
+ ...submodules ? { submodules } : {}
23898
+ };
23899
+ }
23900
+ function buildInlineMeshTransitGitStatus(node) {
23901
+ const rawGit = readObjectRecord(node?.lastGit ?? node?.last_git);
23902
+ const gitResult = readObjectRecord(rawGit.result);
23903
+ const directStatus = readObjectRecord(rawGit.status);
23904
+ const nestedStatus = readObjectRecord(gitResult.status);
23905
+ const rawProbe = readObjectRecord(node?.lastProbe ?? node?.last_probe);
23906
+ const probeGit = readObjectRecord(rawProbe.git);
23907
+ const probeGitResult = readObjectRecord(probeGit.result);
23908
+ const probeDirectStatus = readObjectRecord(probeGit.status);
23909
+ const probeNestedStatus = readObjectRecord(probeGitResult.status);
23910
+ const status = Object.keys(directStatus).length ? directStatus : Object.keys(nestedStatus).length ? nestedStatus : Object.keys(probeDirectStatus).length ? probeDirectStatus : Object.keys(probeNestedStatus).length ? probeNestedStatus : {};
23911
+ return normalizeInlineMeshGitStatus(status, node, { lastCheckedAt: Date.now() });
23912
+ }
23913
+ function recordInlineMeshDirectGitTruth(node, git, source) {
23914
+ if (!node || typeof node !== "object" || Array.isArray(node)) return;
23915
+ const checkedAt = readNumberValue(git.lastCheckedAt) ?? Date.now();
23916
+ const updatedAt = new Date(checkedAt).toISOString();
23917
+ const nextGit = {
23918
+ ...git,
23919
+ lastCheckedAt: checkedAt
23671
23920
  };
23921
+ node.lastGit = {
23922
+ source,
23923
+ checkedAt,
23924
+ status: nextGit
23925
+ };
23926
+ node.last_git = node.lastGit;
23927
+ node.machineStatus = "online";
23928
+ node.updatedAt = updatedAt;
23929
+ node.lastSeenAt = updatedAt;
23930
+ const repoRoot = readStringValue(nextGit.repoRoot);
23931
+ if (repoRoot && !readStringValue(node.repoRoot)) node.repoRoot = repoRoot;
23672
23932
  }
23673
- function applyCachedInlineMeshNodeStatus(status, node) {
23933
+ function buildCachedInlineMeshGitStatus(node) {
23934
+ const liveGit = buildInlineMeshTransitGitStatus(node);
23935
+ if (liveGit) return liveGit;
23674
23936
  const cachedStatus = readObjectRecord(node?.cachedStatus);
23675
- const git = buildCachedInlineMeshGitStatus(node);
23676
- const error = readStringValue(cachedStatus.error, node?.error);
23677
- const health = readStringValue(cachedStatus.health, node?.health);
23937
+ const cachedGit = readObjectRecord(cachedStatus.git);
23938
+ if (!Object.keys(cachedGit).length) return void 0;
23939
+ return normalizeInlineMeshGitStatus(cachedGit, node);
23940
+ }
23941
+ function shouldDiscardCachedInlineMeshStatus(node) {
23942
+ const cachedStatus = readObjectRecord(node?.cachedStatus);
23943
+ if (!Object.keys(cachedStatus).length) return false;
23944
+ const cachedGit = readObjectRecord(cachedStatus.git);
23945
+ const workspaceError = readStringValue(cachedStatus.error, node?.error);
23946
+ if (workspaceError && /workspace must be an existing directory/i.test(workspaceError)) return true;
23947
+ const isGitRepo = readBooleanValue(cachedGit.isGitRepo);
23948
+ const branch = readStringValue(cachedGit.branch);
23949
+ const headCommit = readStringValue(cachedGit.headCommit);
23950
+ return isGitRepo === false && !branch && !headCommit;
23951
+ }
23952
+ function stripInlineMeshTransientNodeState(node) {
23953
+ if (!node || typeof node !== "object" || Array.isArray(node)) return node;
23954
+ const {
23955
+ cachedStatus,
23956
+ lastGit: _lastGit,
23957
+ last_git: _lastGitLegacy,
23958
+ lastProbe: _lastProbe,
23959
+ last_probe: _lastProbeLegacy,
23960
+ error: _error,
23961
+ health: _health,
23962
+ machineStatus: _machineStatus,
23963
+ lastSeenAt: _lastSeenAt,
23964
+ last_seen_at: _lastSeenAtLegacy,
23965
+ updatedAt: _updatedAt,
23966
+ updated_at: _updatedAtLegacy,
23967
+ activeSession: _activeSession,
23968
+ active_session: _activeSessionLegacy,
23969
+ activeSessionId: _activeSessionId,
23970
+ active_session_id: _activeSessionIdLegacy,
23971
+ sessionId: _sessionId,
23972
+ session_id: _sessionIdLegacy,
23973
+ providerType: _providerType,
23974
+ provider_type: _providerTypeLegacy,
23975
+ ...rest
23976
+ } = node;
23977
+ if (cachedStatus && !shouldDiscardCachedInlineMeshStatus(node)) {
23978
+ return { ...rest, cachedStatus };
23979
+ }
23980
+ return rest;
23981
+ }
23982
+ function hasInlineMeshTransientNodeState(node) {
23983
+ if (!node || typeof node !== "object" || Array.isArray(node)) return false;
23984
+ return "cachedStatus" in node || "lastGit" in node || "last_git" in node || "lastProbe" in node || "last_probe" in node || "error" in node || "health" in node || "machineStatus" in node || "lastSeenAt" in node || "last_seen_at" in node || "updatedAt" in node || "updated_at" in node || "activeSession" in node || "active_session" in node || "activeSessionId" in node || "active_session_id" in node || "sessionId" in node || "session_id" in node || "providerType" in node || "provider_type" in node;
23985
+ }
23986
+ function readInlineMeshNodeId(node) {
23987
+ return readStringValue(node?.id, node?.nodeId) || "";
23988
+ }
23989
+ function sanitizeInlineMesh(inlineMesh) {
23990
+ if (!inlineMesh || typeof inlineMesh !== "object" || Array.isArray(inlineMesh)) return inlineMesh;
23991
+ if (!Array.isArray(inlineMesh.nodes)) return inlineMesh;
23992
+ let changed = false;
23993
+ const nodes = inlineMesh.nodes.map((node) => {
23994
+ if (!hasInlineMeshTransientNodeState(node)) return node;
23995
+ changed = true;
23996
+ return stripInlineMeshTransientNodeState(node);
23997
+ });
23998
+ if (!changed) return inlineMesh;
23999
+ return {
24000
+ ...inlineMesh,
24001
+ nodes
24002
+ };
24003
+ }
24004
+ function reconcileInlineMeshCache(cached, incoming) {
24005
+ if (!cached || typeof cached !== "object" || Array.isArray(cached)) return incoming;
24006
+ if (!incoming || typeof incoming !== "object" || Array.isArray(incoming)) return cached;
24007
+ const cachedNodes = Array.isArray(cached.nodes) ? cached.nodes : [];
24008
+ const incomingNodes = Array.isArray(incoming.nodes) ? incoming.nodes : [];
24009
+ if (!cachedNodes.length || !incomingNodes.length) return { ...cached, ...incoming };
24010
+ const incomingById = /* @__PURE__ */ new Map();
24011
+ for (const node of incomingNodes) {
24012
+ const nodeId = readInlineMeshNodeId(node);
24013
+ if (nodeId) incomingById.set(nodeId, node);
24014
+ }
24015
+ const nodes = cachedNodes.map((cachedNode) => {
24016
+ const nodeId = readInlineMeshNodeId(cachedNode);
24017
+ const incomingNode = nodeId ? incomingById.get(nodeId) : void 0;
24018
+ if (!incomingNode) return cachedNode;
24019
+ if (hasInlineMeshTransientNodeState(incomingNode)) {
24020
+ return { ...cachedNode, ...incomingNode };
24021
+ }
24022
+ return { ...stripInlineMeshTransientNodeState(cachedNode), ...incomingNode };
24023
+ });
24024
+ return {
24025
+ ...cached,
24026
+ ...incoming,
24027
+ nodes
24028
+ };
24029
+ }
24030
+ function hasGitWorktreeChanges(git) {
24031
+ if (!git) return false;
24032
+ return Number(git.staged || 0) + Number(git.modified || 0) + Number(git.untracked || 0) + Number(git.deleted || 0) + Number(git.renamed || 0) > 0;
24033
+ }
24034
+ function getGitSubmoduleDriftState(git) {
24035
+ const submodules = Array.isArray(git?.submodules) ? git.submodules : [];
24036
+ let dirty = false;
24037
+ let outOfSync = false;
24038
+ for (const entry of submodules) {
24039
+ const submodule = readObjectRecord(entry);
24040
+ if (readBooleanValue(submodule.dirty) === true) dirty = true;
24041
+ if (readBooleanValue(submodule.outOfSync) === true || !!readStringValue(submodule.error)) outOfSync = true;
24042
+ }
24043
+ return { dirty, outOfSync };
24044
+ }
24045
+ function deriveMeshNodeHealthFromGit(git) {
24046
+ if (!git || readBooleanValue(git.isGitRepo) === false) return "degraded";
24047
+ const branch = readStringValue(git.branch);
24048
+ if (!branch) return "degraded";
24049
+ const submoduleDrift = getGitSubmoduleDriftState(git);
24050
+ if (submoduleDrift.outOfSync) return "degraded";
24051
+ if (submoduleDrift.dirty || hasGitWorktreeChanges(git)) return "dirty";
24052
+ return "online";
24053
+ }
24054
+ function readCachedInlineMeshActiveSessions(node) {
24055
+ const cachedStatus = readObjectRecord(node?.cachedStatus);
24056
+ const activeSession = readObjectRecord(cachedStatus.activeSession);
24057
+ const fallbackSession = Object.keys(activeSession).length ? activeSession : readObjectRecord(node?.activeSession ?? node?.active_session);
24058
+ const sessionId = readStringValue(fallbackSession.id, fallbackSession.sessionId, fallbackSession.session_id, node?.activeSessionId, node?.active_session_id, node?.sessionId, node?.session_id);
24059
+ return sessionId ? [sessionId] : [];
24060
+ }
24061
+ function readCachedInlineMeshActiveSessionDetails(node) {
24062
+ const cachedStatus = readObjectRecord(node?.cachedStatus);
24063
+ const activeSession = readObjectRecord(cachedStatus.activeSession);
24064
+ const fallbackSession = Object.keys(activeSession).length ? activeSession : readObjectRecord(node?.activeSession ?? node?.active_session);
24065
+ const sessionId = readStringValue(
24066
+ fallbackSession.id,
24067
+ fallbackSession.sessionId,
24068
+ fallbackSession.session_id,
24069
+ node?.activeSessionId,
24070
+ node?.active_session_id,
24071
+ node?.sessionId,
24072
+ node?.session_id
24073
+ );
24074
+ if (!sessionId) return [];
24075
+ return [{
24076
+ sessionId,
24077
+ providerType: readStringValue(
24078
+ fallbackSession.providerType,
24079
+ fallbackSession.provider_type,
24080
+ fallbackSession.cliType,
24081
+ fallbackSession.cli_type,
24082
+ fallbackSession.provider,
24083
+ node?.providerType,
24084
+ node?.provider_type
24085
+ ),
24086
+ state: readStringValue(fallbackSession.status, fallbackSession.state, fallbackSession.lifecycle),
24087
+ lifecycle: readStringValue(fallbackSession.lifecycle),
24088
+ title: readStringValue(fallbackSession.title, fallbackSession.displayName, fallbackSession.display_name) ?? null,
24089
+ workspace: readStringValue(fallbackSession.workspace, node?.workspace) ?? null,
24090
+ lastActivityAt: readStringValue(fallbackSession.lastActivityAt, fallbackSession.last_activity_at) ?? null,
24091
+ recoveryState: readStringValue(fallbackSession.recoveryState, fallbackSession.recovery_state) ?? null,
24092
+ isCached: true
24093
+ }];
24094
+ }
24095
+ function readLiveMeshSessionState(record) {
24096
+ return readStringValue(
24097
+ record?.meta?.sessionStatus,
24098
+ record?.meta?.status,
24099
+ record?.meta?.providerStatus,
24100
+ record?.status,
24101
+ record?.state,
24102
+ record?.lifecycle
24103
+ );
24104
+ }
24105
+ function toIsoTimestamp(value) {
24106
+ if (typeof value === "number" && Number.isFinite(value)) return new Date(value).toISOString();
24107
+ const stringValue = readStringValue(value);
24108
+ return stringValue || null;
24109
+ }
24110
+ function synthesizeMeshNodeFreshnessFromConnection(status) {
24111
+ const connection = readObjectRecord(status.connection);
24112
+ const connectionFreshAt = toIsoTimestamp(connection.lastCommandAt ?? connection.lastConnectedAt ?? connection.lastStateChangeAt);
24113
+ const git = readObjectRecord(status.git);
24114
+ const gitCheckedAt = toIsoTimestamp(git.lastCheckedAt);
24115
+ if (!status.lastSeenAt && connectionFreshAt) status.lastSeenAt = connectionFreshAt;
24116
+ if (!status.updatedAt && (gitCheckedAt || connectionFreshAt)) {
24117
+ status.updatedAt = gitCheckedAt ?? connectionFreshAt;
24118
+ }
24119
+ }
24120
+ function finalizeMeshNodeStatus(args) {
24121
+ const { status, node, daemonId, isSelfNode } = args;
24122
+ if (!readStringValue(status.machineStatus)) {
24123
+ const cachedStatus = readObjectRecord(node?.cachedStatus);
24124
+ const machineStatus = readStringValue(cachedStatus.machineStatus, cachedStatus.machine_status, node?.machineStatus);
24125
+ if (machineStatus) status.machineStatus = machineStatus;
24126
+ }
24127
+ synthesizeMeshNodeFreshnessFromConnection(status);
24128
+ const connectionState = readStringValue(readObjectRecord(status.connection).state);
24129
+ status.launchReady = !!daemonId && (readStringValue(status.machineStatus) === "online" || connectionState === "connected" || isSelfNode);
24130
+ }
24131
+ async function probeRemoteMeshGitStatus(args) {
24132
+ if (!args.dispatchMeshCommand) return null;
24133
+ const remoteResult = await Promise.race([
24134
+ args.dispatchMeshCommand(args.daemonId, "git_status", { workspace: args.workspace }),
24135
+ new Promise((_, reject) => setTimeout(() => reject(new Error("timeout")), args.timeoutMs))
24136
+ ]);
24137
+ const remoteGit = remoteResult?.status ?? remoteResult?.git ?? remoteResult;
24138
+ return remoteGit && typeof remoteGit === "object" && typeof remoteGit.isGitRepo === "boolean" ? remoteGit : null;
24139
+ }
24140
+ async function hydrateInlineMeshDirectTruth(args) {
24141
+ const nodes = Array.isArray(args.mesh?.nodes) ? args.mesh.nodes : [];
24142
+ if (!nodes.length) {
24143
+ return {
24144
+ directEvidenceCount: 0,
24145
+ localConfirmedCount: 0,
24146
+ peerAttemptedCount: 0,
24147
+ peerConfirmedCount: 0,
24148
+ unavailableNodeIds: []
24149
+ };
24150
+ }
24151
+ const selectedCoordinatorNodeId = readStringValue(
24152
+ args.mesh?.coordinator?.preferredNodeId,
24153
+ nodes[0]?.id,
24154
+ nodes[0]?.nodeId
24155
+ );
24156
+ let localConfirmedCount = 0;
24157
+ let peerAttemptedCount = 0;
24158
+ let peerConfirmedCount = 0;
24159
+ const unavailableNodeIds = [];
24160
+ for (const [nodeIndex, node] of nodes.entries()) {
24161
+ const nodeId = readStringValue(node?.id, node?.nodeId) || `node_${nodeIndex}`;
24162
+ const workspace = readStringValue(node?.workspace);
24163
+ const daemonId = readStringValue(node?.daemonId);
24164
+ const isSelfNode = Boolean(
24165
+ nodeId && selectedCoordinatorNodeId && nodeId === selectedCoordinatorNodeId
24166
+ ) || Boolean(
24167
+ daemonId && (daemonId === args.localMachineId || daemonId === args.statusInstanceId)
24168
+ ) || Boolean(args.meshSource !== "local_config" && nodeIndex === 0);
24169
+ if (!workspace) {
24170
+ if (!isSelfNode && daemonId) unavailableNodeIds.push(nodeId);
24171
+ continue;
24172
+ }
24173
+ if (isSelfNode && fs10.existsSync(workspace)) {
24174
+ try {
24175
+ const localGit = await getGitRepoStatus(workspace, { timeoutMs: 1e4, refreshUpstream: true });
24176
+ if (localGit?.isGitRepo) {
24177
+ recordInlineMeshDirectGitTruth(node, localGit, "selected_coordinator_local_git");
24178
+ localConfirmedCount += 1;
24179
+ continue;
24180
+ }
24181
+ } catch {
24182
+ }
24183
+ }
24184
+ if (!daemonId || !args.dispatchMeshCommand) {
24185
+ if (!isSelfNode) unavailableNodeIds.push(nodeId);
24186
+ continue;
24187
+ }
24188
+ peerAttemptedCount += 1;
24189
+ try {
24190
+ const remoteGit = await probeRemoteMeshGitStatus({
24191
+ dispatchMeshCommand: args.dispatchMeshCommand,
24192
+ daemonId,
24193
+ workspace,
24194
+ timeoutMs: 8e3
24195
+ });
24196
+ if (remoteGit) {
24197
+ recordInlineMeshDirectGitTruth(node, remoteGit, "selected_coordinator_mesh_p2p_git");
24198
+ peerConfirmedCount += 1;
24199
+ continue;
24200
+ }
24201
+ } catch {
24202
+ }
24203
+ unavailableNodeIds.push(nodeId);
24204
+ }
24205
+ return {
24206
+ directEvidenceCount: localConfirmedCount + peerConfirmedCount,
24207
+ localConfirmedCount,
24208
+ peerAttemptedCount,
24209
+ peerConfirmedCount,
24210
+ unavailableNodeIds
24211
+ };
24212
+ }
24213
+ function summarizeMeshSessionRecord(record) {
24214
+ return {
24215
+ sessionId: readStringValue(record?.sessionId) || "unknown",
24216
+ providerType: readStringValue(record?.providerType),
24217
+ state: readLiveMeshSessionState(record),
24218
+ lifecycle: readStringValue(record?.lifecycle),
24219
+ surfaceKind: getSessionHostSurfaceKind(record),
24220
+ recoveryState: readStringValue(record?.meta?.runtimeRecoveryState) ?? null,
24221
+ workspace: readStringValue(record?.workspace) ?? null,
24222
+ title: readStringValue(record?.displayName, record?.workspaceLabel) ?? null,
24223
+ lastActivityAt: toIsoTimestamp(record?.updatedAt ?? record?.lastActivityAt ?? record?.last_activity_at),
24224
+ isCached: false
24225
+ };
24226
+ }
24227
+ function liveSessionRecordMatchesMeshNode(record, meshId, nodeId) {
24228
+ const recordNodeId = readStringValue(record?.meta?.meshNodeId);
24229
+ if (!recordNodeId || recordNodeId !== nodeId) return false;
24230
+ const recordMeshId = readStringValue(record?.meta?.meshNodeFor);
24231
+ return !recordMeshId || recordMeshId === meshId;
24232
+ }
24233
+ function liveSessionRecordMatchesMeshWorkspace(record, meshId, workspace) {
24234
+ const recordWorkspace = readStringValue(record?.workspace);
24235
+ if (!recordWorkspace || !workspace || recordWorkspace !== workspace) return false;
24236
+ const recordMeshId = readStringValue(record?.meta?.meshNodeFor);
24237
+ if (recordMeshId) return recordMeshId === meshId;
24238
+ return record?.meta?.launchedByCoordinator === true || !!readStringValue(record?.meta?.meshNodeId);
24239
+ }
24240
+ function readLiveMeshNodeWorkspace(args) {
24241
+ const directNodeWorkspace = args.liveSessionRecords.find((record) => liveSessionRecordMatchesMeshNode(record, args.meshId, args.nodeId) && readStringValue(record?.workspace));
24242
+ if (directNodeWorkspace) {
24243
+ return readStringValue(directNodeWorkspace.workspace) || "";
24244
+ }
24245
+ if (args.allowCoordinatorSession) {
24246
+ const coordinatorWorkspace = args.liveSessionRecords.find((record) => readStringValue(record?.meta?.meshCoordinatorFor) === args.meshId && readStringValue(record?.workspace));
24247
+ if (coordinatorWorkspace) {
24248
+ return readStringValue(coordinatorWorkspace.workspace) || "";
24249
+ }
24250
+ }
24251
+ return "";
24252
+ }
24253
+ function collectLiveMeshSessionRecords(args) {
24254
+ const matches = args.liveSessionRecords.filter((record) => {
24255
+ const nodeWorkspace = readStringValue(args.node?.workspace);
24256
+ if (liveSessionRecordMatchesMeshNode(record, args.meshId, args.nodeId)) return true;
24257
+ return !!nodeWorkspace && liveSessionRecordMatchesMeshWorkspace(record, args.meshId, nodeWorkspace);
24258
+ });
24259
+ if (args.allowCoordinatorSession) {
24260
+ for (const record of args.liveSessionRecords) {
24261
+ if (readStringValue(record?.meta?.meshCoordinatorFor) !== args.meshId) continue;
24262
+ const sessionId = readStringValue(record?.sessionId);
24263
+ if (sessionId && matches.some((entry) => readStringValue(entry?.sessionId) === sessionId)) continue;
24264
+ matches.push(record);
24265
+ }
24266
+ }
24267
+ return matches;
24268
+ }
24269
+ function applyCachedInlineMeshNodeStatus(status, node, options) {
24270
+ const cachedStatus = readObjectRecord(node?.cachedStatus);
24271
+ const liveGit = buildInlineMeshTransitGitStatus(node);
24272
+ const git = options?.skipGit ? void 0 : liveGit ?? buildCachedInlineMeshGitStatus(node);
24273
+ const error = options?.skipError ? void 0 : liveGit ? void 0 : readStringValue(cachedStatus.error, node?.error);
24274
+ const health = options?.skipHealth ? void 0 : liveGit ? void 0 : readStringValue(cachedStatus.health, node?.health);
23678
24275
  const machineStatus = readStringValue(cachedStatus.machineStatus, node?.machineStatus);
23679
- if (!git && !error && !health) return false;
23680
- if (!machineStatus && !git && !error) return false;
24276
+ const lastSeenAt = toIsoTimestamp(cachedStatus.lastSeenAt ?? cachedStatus.last_seen_at ?? node?.lastSeenAt ?? node?.last_seen_at);
24277
+ const updatedAt = toIsoTimestamp(cachedStatus.updatedAt ?? cachedStatus.updated_at ?? node?.updatedAt ?? node?.updated_at);
24278
+ const activeSessions = readCachedInlineMeshActiveSessions(node);
24279
+ const activeSessionDetails = readCachedInlineMeshActiveSessionDetails(node);
24280
+ if (!git && !error && !health && !machineStatus && !lastSeenAt && !updatedAt && activeSessions.length === 0) return false;
23681
24281
  if (git) status.git = git;
23682
24282
  if (error) status.error = error;
24283
+ if (machineStatus) status.machineStatus = machineStatus;
24284
+ if (lastSeenAt) status.lastSeenAt = lastSeenAt;
24285
+ if (updatedAt) status.updatedAt = updatedAt;
24286
+ if (activeSessions.length > 0) status.activeSessions = activeSessions;
24287
+ if (activeSessionDetails.length > 0) status.activeSessionDetails = activeSessionDetails;
23683
24288
  if (health) {
23684
24289
  status.health = health;
23685
24290
  return true;
23686
24291
  }
23687
24292
  if (git) {
23688
- const dirty = Number(git.staged || 0) + Number(git.modified || 0) + Number(git.untracked || 0) + Number(git.deleted || 0) + Number(git.renamed || 0) > 0;
23689
- status.health = git.isGitRepo === false ? "degraded" : dirty ? "dirty" : "online";
24293
+ status.health = deriveMeshNodeHealthFromGit(git);
23690
24294
  return true;
23691
24295
  }
23692
- return false;
24296
+ return activeSessions.length > 0 || !!machineStatus || !!lastSeenAt || !!updatedAt;
23693
24297
  }
23694
24298
  async function resolveProviderTypeFromPriority(args) {
23695
24299
  if (!args.providerPriority.length) {
@@ -24087,25 +24691,40 @@ var DaemonCommandRouter = class {
24087
24691
  }
24088
24692
  getCachedInlineMesh(meshId, inlineMesh) {
24089
24693
  if (inlineMesh && typeof inlineMesh === "object") {
24090
- this.inlineMeshCache.set(meshId, inlineMesh);
24091
- return inlineMesh;
24694
+ return this.warmInlineMeshCache(meshId, inlineMesh);
24092
24695
  }
24093
24696
  return this.inlineMeshCache.get(meshId);
24094
24697
  }
24698
+ warmInlineMeshCache(meshId, inlineMesh) {
24699
+ if (!inlineMesh || typeof inlineMesh !== "object") return void 0;
24700
+ const sanitizedInlineMesh = sanitizeInlineMesh(inlineMesh);
24701
+ const cached = this.inlineMeshCache.get(meshId);
24702
+ if (cached) {
24703
+ const merged = reconcileInlineMeshCache(cached, sanitizedInlineMesh);
24704
+ this.inlineMeshCache.set(meshId, merged);
24705
+ return merged;
24706
+ }
24707
+ this.inlineMeshCache.set(meshId, sanitizedInlineMesh);
24708
+ return sanitizedInlineMesh;
24709
+ }
24095
24710
  async getMeshForCommand(meshId, inlineMesh, options) {
24096
24711
  const preferInline = options?.preferInline === true;
24097
24712
  if (preferInline) {
24098
- const cached2 = this.getCachedInlineMesh(meshId, inlineMesh);
24099
- if (cached2) return { mesh: cached2, inline: true };
24713
+ const cached2 = this.getCachedInlineMesh(meshId);
24714
+ if (cached2) return { mesh: cached2, inline: true, source: "inline_cache" };
24715
+ const warmedInline2 = this.warmInlineMeshCache(meshId, inlineMesh);
24716
+ if (warmedInline2) return { mesh: warmedInline2, inline: true, source: "inline_bootstrap" };
24100
24717
  }
24101
24718
  try {
24102
24719
  const { getMesh: getMesh3 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
24103
24720
  const mesh = getMesh3(meshId);
24104
- if (mesh) return { mesh, inline: false };
24721
+ if (mesh) return { mesh, inline: false, source: "local_config" };
24105
24722
  } catch {
24106
24723
  }
24107
- const cached = this.getCachedInlineMesh(meshId, inlineMesh);
24108
- return cached ? { mesh: cached, inline: true } : null;
24724
+ const cached = this.getCachedInlineMesh(meshId);
24725
+ if (cached) return { mesh: cached, inline: true, source: "inline_cache" };
24726
+ const warmedInline = this.warmInlineMeshCache(meshId, inlineMesh);
24727
+ return warmedInline ? { mesh: warmedInline, inline: true, source: "inline_bootstrap" } : null;
24109
24728
  }
24110
24729
  updateInlineMeshNode(meshId, mesh, node) {
24111
24730
  if (!mesh || !Array.isArray(mesh.nodes) || !node?.id) return;
@@ -24334,6 +24953,7 @@ var DaemonCommandRouter = class {
24334
24953
  const deletedSessionIds = [];
24335
24954
  const skippedSessionIds = [];
24336
24955
  const skippedLiveSessionIds = [];
24956
+ const skippedCoordinatorSessionIds = [];
24337
24957
  const deleteUnsupportedSessionIds = [];
24338
24958
  const recordsRemainSessionIds = [];
24339
24959
  const errors = [];
@@ -24366,6 +24986,12 @@ var DaemonCommandRouter = class {
24366
24986
  const completed = this.isCompletedHostedSession(record);
24367
24987
  const surfaceKind = getSessionHostSurfaceKind(record);
24368
24988
  const liveRuntime = surfaceKind === "live_runtime";
24989
+ const coordinatorSession = readStringValue(record?.meta?.meshCoordinatorFor) === args.meshId;
24990
+ if (!hasExplicitSessionIds && coordinatorSession) {
24991
+ skippedSessionIds.push(sessionId);
24992
+ skippedCoordinatorSessionIds.push(sessionId);
24993
+ continue;
24994
+ }
24369
24995
  if (!hasExplicitSessionIds && liveRuntime) {
24370
24996
  skippedSessionIds.push(sessionId);
24371
24997
  skippedLiveSessionIds.push(sessionId);
@@ -24431,6 +25057,7 @@ var DaemonCommandRouter = class {
24431
25057
  deletedSessionIds,
24432
25058
  skippedSessionIds,
24433
25059
  skippedLiveSessionIds,
25060
+ skippedCoordinatorSessionIds,
24434
25061
  ...deleteUnsupported ? {
24435
25062
  deleteUnsupported: true,
24436
25063
  effectiveCleanup: args.mode === "stop_and_delete" ? "stopped_only_records_remain" : "delete_unsupported_records_remain",
@@ -24563,7 +25190,8 @@ var DaemonCommandRouter = class {
24563
25190
  return handleMeshForwardEvent({ instanceManager: this.deps.instanceManager }, args);
24564
25191
  }
24565
25192
  case "get_pending_mesh_events": {
24566
- const events = drainPendingMeshCoordinatorEvents();
25193
+ const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
25194
+ const events = drainPendingMeshCoordinatorEvents(meshId || void 0);
24567
25195
  return { success: true, events };
24568
25196
  }
24569
25197
  case "launch_cli":
@@ -25092,15 +25720,39 @@ var DaemonCommandRouter = class {
25092
25720
  case "get_mesh": {
25093
25721
  const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
25094
25722
  if (!meshId) return { success: false, error: "meshId required" };
25095
- try {
25096
- const { getMesh: getMesh3 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
25097
- const mesh = getMesh3(meshId);
25098
- if (mesh) return { success: true, mesh };
25099
- } catch {
25723
+ const meshRecord = await this.getMeshForCommand(meshId, args?.inlineMesh, { preferInline: true });
25724
+ if (!meshRecord?.mesh) return { success: false, error: "Mesh not found" };
25725
+ const requireDirectPeerTruth = args?.requireDirectPeerTruth === true;
25726
+ const directTruth = await hydrateInlineMeshDirectTruth({
25727
+ mesh: meshRecord.mesh,
25728
+ meshSource: meshRecord.source,
25729
+ dispatchMeshCommand: this.deps.dispatchMeshCommand,
25730
+ statusInstanceId: this.deps.statusInstanceId,
25731
+ localMachineId: loadConfig().machineId || ""
25732
+ });
25733
+ const directTruthSatisfied = meshRecord.source !== "inline_bootstrap" || directTruth.directEvidenceCount > 0;
25734
+ const sourceOfTruth = {
25735
+ membership: meshRecord.source === "inline_cache" ? "coordinator_inline_mesh_cache" : meshRecord.source === "local_config" ? "local_mesh_config" : "inline_bootstrap_snapshot",
25736
+ coordinatorOwnsLiveTruth: directTruthSatisfied,
25737
+ directPeerTruth: {
25738
+ required: requireDirectPeerTruth,
25739
+ satisfied: directTruthSatisfied,
25740
+ directEvidenceCount: directTruth.directEvidenceCount,
25741
+ localConfirmedCount: directTruth.localConfirmedCount,
25742
+ peerAttemptedCount: directTruth.peerAttemptedCount,
25743
+ peerConfirmedCount: directTruth.peerConfirmedCount,
25744
+ unavailableNodeIds: directTruth.unavailableNodeIds
25745
+ }
25746
+ };
25747
+ if (requireDirectPeerTruth && !directTruthSatisfied) {
25748
+ return {
25749
+ success: false,
25750
+ code: "mesh_direct_peer_truth_unavailable",
25751
+ error: "Selected coordinator could not confirm direct mesh truth yet. Bootstrap inventory stays unavailable until direct get_mesh probes succeed.",
25752
+ sourceOfTruth
25753
+ };
25100
25754
  }
25101
- const cached = this.inlineMeshCache.get(meshId);
25102
- if (cached) return { success: true, mesh: cached };
25103
- return { success: false, error: "Mesh not found" };
25755
+ return { success: true, mesh: meshRecord.mesh, sourceOfTruth };
25104
25756
  }
25105
25757
  case "create_mesh": {
25106
25758
  const name = typeof args?.name === "string" ? args.name.trim() : "";
@@ -25621,7 +26273,14 @@ var DaemonCommandRouter = class {
25621
26273
  cliType
25622
26274
  };
25623
26275
  }
25624
- const workspace = typeof coordinatorNode.workspace === "string" ? coordinatorNode.workspace.trim() : "";
26276
+ const sessionHostRecords = this.deps.sessionHostControl?.listSessions ? await this.deps.sessionHostControl.listSessions().catch(() => []) : [];
26277
+ const liveMeshSessions = partitionSessionHostRecords(Array.isArray(sessionHostRecords) ? sessionHostRecords : []).liveRuntimes;
26278
+ const workspace = readLiveMeshNodeWorkspace({
26279
+ meshId,
26280
+ nodeId: String(coordinatorNode.id || coordinatorNode.nodeId || preferredCoordinatorNodeId || ""),
26281
+ liveSessionRecords: liveMeshSessions,
26282
+ allowCoordinatorSession: true
26283
+ }) || (typeof coordinatorNode.workspace === "string" ? coordinatorNode.workspace.trim() : "");
25625
26284
  if (!workspace) return { success: false, error: "Coordinator node workspace required", meshId, cliType };
25626
26285
  if (!cliType) {
25627
26286
  const resolved = await resolveProviderTypeFromPriority({
@@ -25783,7 +26442,7 @@ ${block}`);
25783
26442
  workspace
25784
26443
  };
25785
26444
  }
25786
- const { existsSync: existsSync25, readFileSync: readFileSync17, writeFileSync: writeFileSync15, copyFileSync: copyFileSync4, mkdirSync: mkdirSync17 } = await import("fs");
26445
+ const { existsSync: existsSync26, readFileSync: readFileSync18, writeFileSync: writeFileSync15, copyFileSync: copyFileSync4, mkdirSync: mkdirSync17 } = await import("fs");
25787
26446
  const { dirname: dirname9 } = await import("path");
25788
26447
  const mcpConfigPath = coordinatorSetup.configPath;
25789
26448
  const hermesManualFallback = cliType === "hermes-cli" && configFormat === "hermes_config_yaml" ? createHermesManualMeshCoordinatorSetup(meshId, workspace) : null;
@@ -25826,14 +26485,14 @@ ${block}`);
25826
26485
  if (hermesManualFallback) return returnManualFallback(message);
25827
26486
  return { success: false, code: "mesh_coordinator_config_write_failed", error: message, meshId, cliType, workspace };
25828
26487
  }
25829
- const hadExistingMcpConfig = existsSync25(mcpConfigPath);
26488
+ const hadExistingMcpConfig = existsSync26(mcpConfigPath);
25830
26489
  let existingMcpConfig = hermesBaseConfig?.config || {};
25831
26490
  if (hermesBaseConfig) {
25832
26491
  copyHermesCoordinatorCredentialFiles(hermesBaseConfig.sourceHome, dirname9(mcpConfigPath));
25833
26492
  }
25834
26493
  if (hadExistingMcpConfig) {
25835
26494
  try {
25836
- const parsedExistingMcpConfig = parseMeshCoordinatorMcpConfig(readFileSync17(mcpConfigPath, "utf-8"), configFormat);
26495
+ const parsedExistingMcpConfig = parseMeshCoordinatorMcpConfig(readFileSync18(mcpConfigPath, "utf-8"), configFormat);
25837
26496
  const existingCoordinatorConfig = hermesManualFallback ? stripHermesCoordinatorTempModelProviderOverrides(parsedExistingMcpConfig) : parsedExistingMcpConfig;
25838
26497
  existingMcpConfig = { ...existingMcpConfig, ...existingCoordinatorConfig };
25839
26498
  copyFileSync4(mcpConfigPath, mcpConfigPath + ".backup");
@@ -25929,92 +26588,184 @@ ${block}`);
25929
26588
  const { readLedgerEntries: readLedgerEntries2, getLedgerSummary: getLedgerSummary2 } = await Promise.resolve().then(() => (init_mesh_ledger(), mesh_ledger_exports));
25930
26589
  const ledgerEntries = readLedgerEntries2(meshId, { tail: 20 });
25931
26590
  const ledgerSummary = getLedgerSummary2(meshId);
26591
+ const sessionHostRecords = this.deps.sessionHostControl?.listSessions ? await this.deps.sessionHostControl.listSessions().catch(() => []) : [];
26592
+ const liveMeshSessions = partitionSessionHostRecords(Array.isArray(sessionHostRecords) ? sessionHostRecords : []).liveRuntimes;
26593
+ const localMachineId = loadConfig().machineId || "";
26594
+ const selectedCoordinatorNodeId = readStringValue(
26595
+ mesh.coordinator?.preferredNodeId,
26596
+ mesh.nodes?.[0]?.id,
26597
+ mesh.nodes?.[0]?.nodeId
26598
+ );
26599
+ const inlineCoordinatorNodeId = meshRecord?.inline && Array.isArray(mesh.nodes) ? selectedCoordinatorNodeId : void 0;
26600
+ const refreshedAt = (/* @__PURE__ */ new Date()).toISOString();
25932
26601
  const nodeStatuses = [];
25933
- for (const node of mesh.nodes || []) {
26602
+ for (const [nodeIndex, node] of (mesh.nodes || []).entries()) {
26603
+ const nodeId = String(node.id || node.nodeId || "");
26604
+ const daemonId = readStringValue(node.daemonId);
26605
+ const providerPriority = readProviderPriorityFromPolicy(node.policy);
26606
+ const isSelfNode = Boolean(
26607
+ nodeId && inlineCoordinatorNodeId && nodeId === inlineCoordinatorNodeId
26608
+ ) || Boolean(
26609
+ daemonId && (daemonId === localMachineId || daemonId === this.deps.statusInstanceId)
26610
+ ) || Boolean(meshRecord?.inline && nodeIndex === 0);
25934
26611
  const status = {
25935
- nodeId: node.id || node.nodeId,
26612
+ nodeId,
25936
26613
  machineLabel: node.machineLabel || node.id || node.nodeId,
25937
26614
  workspace: node.workspace,
25938
26615
  repoRoot: node.repoRoot,
25939
26616
  isLocalWorktree: node.isLocalWorktree,
25940
26617
  worktreeBranch: node.worktreeBranch,
25941
- daemonId: node.daemonId,
26618
+ daemonId,
25942
26619
  machineId: node.machineId,
26620
+ machineStatus: node.machineStatus,
25943
26621
  health: "unknown",
25944
26622
  providers: node.providers || [],
25945
- activeSessions: []
26623
+ providerPriority,
26624
+ activeSessions: [],
26625
+ activeSessionDetails: [],
26626
+ launchReady: false
25946
26627
  };
25947
- if (node.workspace && typeof node.workspace === "string") {
25948
- if (!fs10.existsSync(node.workspace) && applyCachedInlineMeshNodeStatus(status, node)) {
25949
- nodeStatuses.push(status);
25950
- continue;
26628
+ if (isSelfNode) {
26629
+ status.connection = {
26630
+ perspective: "selected_coordinator",
26631
+ source: "mesh_peer_status",
26632
+ state: "self",
26633
+ transport: "local",
26634
+ reported: true,
26635
+ reason: "Selected coordinator daemon",
26636
+ lastStateChangeAt: refreshedAt
26637
+ };
26638
+ } else if (daemonId) {
26639
+ const connection = this.deps.getMeshPeerConnectionStatus?.(daemonId);
26640
+ status.connection = connection ?? {
26641
+ perspective: "selected_coordinator",
26642
+ source: "not_reported",
26643
+ state: "unknown",
26644
+ transport: "unknown",
26645
+ reported: false,
26646
+ reason: "No live mesh peer telemetry reported by the selected coordinator yet."
26647
+ };
26648
+ } else {
26649
+ status.connection = {
26650
+ perspective: "selected_coordinator",
26651
+ source: "not_reported",
26652
+ state: "unknown",
26653
+ transport: "unknown",
26654
+ reported: false,
26655
+ reason: "Node has no daemon id, so mesh transport cannot be reported from the selected coordinator."
26656
+ };
26657
+ }
26658
+ const matchedLiveSessionRecords = collectLiveMeshSessionRecords({
26659
+ meshId,
26660
+ node,
26661
+ nodeId,
26662
+ liveSessionRecords: liveMeshSessions,
26663
+ allowCoordinatorSession: nodeId === selectedCoordinatorNodeId
26664
+ });
26665
+ const workspace = readLiveMeshNodeWorkspace({
26666
+ meshId,
26667
+ nodeId,
26668
+ liveSessionRecords: matchedLiveSessionRecords,
26669
+ allowCoordinatorSession: nodeId === selectedCoordinatorNodeId
26670
+ }) || (typeof node.workspace === "string" ? node.workspace : "");
26671
+ status.workspace = workspace || node.workspace;
26672
+ if (matchedLiveSessionRecords.length > 0) {
26673
+ const sessionIds = matchedLiveSessionRecords.map((record) => typeof record?.sessionId === "string" ? record.sessionId : "").filter(Boolean);
26674
+ const providerTypes = matchedLiveSessionRecords.map((record) => readStringValue(record?.providerType)).filter(Boolean);
26675
+ status.activeSessions = sessionIds;
26676
+ status.activeSessionDetails = matchedLiveSessionRecords.map(summarizeMeshSessionRecord);
26677
+ if (providerTypes.length > 0) {
26678
+ status.providers = Array.from(/* @__PURE__ */ new Set([...Array.isArray(status.providers) ? status.providers : [], ...providerTypes]));
25951
26679
  }
25952
- try {
25953
- const { execFile: execFile3 } = await import("child_process");
25954
- const { promisify: promisify3 } = await import("util");
25955
- const execFileAsync3 = promisify3(execFile3);
25956
- const runGit2 = async (args2) => {
25957
- const result = await execFileAsync3("git", ["-C", node.workspace, ...args2], {
25958
- encoding: "utf8",
25959
- timeout: 1e4
25960
- });
25961
- return result.stdout.trim();
25962
- };
25963
- const branch = await runGit2(["branch", "--show-current"]).catch(() => "");
25964
- const porc = await runGit2(["status", "--porcelain"]).catch(() => "");
25965
- const headCommit = await runGit2(["rev-parse", "--short", "HEAD"]).catch(() => null);
25966
- const headMessage = await runGit2(["log", "-1", "--format=%s"]).catch(() => null);
25967
- const upstream = await runGit2(["rev-parse", "--abbrev-ref", "@{upstream}"]).catch(() => null);
25968
- const aheadBehind = await runGit2(["rev-list", "--left-right", "--count", "@{upstream}...HEAD"]).catch(() => "");
25969
- const stashCount = await runGit2(["stash", "list"]).catch(() => "");
25970
- let ahead = 0, behind = 0;
25971
- if (aheadBehind) {
25972
- const parts = aheadBehind.split(/\s+/);
25973
- if (parts.length >= 2) {
25974
- behind = parseInt(parts[0], 10) || 0;
25975
- ahead = parseInt(parts[1], 10) || 0;
26680
+ }
26681
+ if (workspace) {
26682
+ if (!fs10.existsSync(workspace)) {
26683
+ const inlineTransitGit = buildInlineMeshTransitGitStatus(node);
26684
+ let remoteProbeApplied = false;
26685
+ if (inlineTransitGit) {
26686
+ status.git = inlineTransitGit;
26687
+ status.health = inlineTransitGit.isGitRepo ? deriveMeshNodeHealthFromGit(inlineTransitGit) : "degraded";
26688
+ remoteProbeApplied = true;
26689
+ } else if (!isSelfNode && daemonId && this.deps.dispatchMeshCommand) {
26690
+ try {
26691
+ const remoteGit = await probeRemoteMeshGitStatus({
26692
+ dispatchMeshCommand: this.deps.dispatchMeshCommand,
26693
+ daemonId,
26694
+ workspace,
26695
+ timeoutMs: 8e3
26696
+ });
26697
+ if (remoteGit) {
26698
+ status.git = remoteGit;
26699
+ status.health = remoteGit.isGitRepo ? deriveMeshNodeHealthFromGit(remoteGit) : "degraded";
26700
+ recordInlineMeshDirectGitTruth(node, remoteGit, "selected_coordinator_mesh_p2p_git");
26701
+ remoteProbeApplied = true;
26702
+ }
26703
+ } catch {
26704
+ const refreshedConnection = this.deps.getMeshPeerConnectionStatus?.(daemonId);
26705
+ const refreshedConnectionState = readStringValue(refreshedConnection?.state);
26706
+ if (refreshedConnection && refreshedConnectionState === "connected") {
26707
+ status.connection = refreshedConnection;
26708
+ try {
26709
+ const remoteGit = await probeRemoteMeshGitStatus({
26710
+ dispatchMeshCommand: this.deps.dispatchMeshCommand,
26711
+ daemonId,
26712
+ workspace,
26713
+ timeoutMs: 12e3
26714
+ });
26715
+ if (remoteGit) {
26716
+ status.git = remoteGit;
26717
+ status.health = remoteGit.isGitRepo ? deriveMeshNodeHealthFromGit(remoteGit) : "degraded";
26718
+ recordInlineMeshDirectGitTruth(node, remoteGit, "selected_coordinator_mesh_p2p_git");
26719
+ remoteProbeApplied = true;
26720
+ }
26721
+ } catch {
26722
+ }
26723
+ }
25976
26724
  }
25977
26725
  }
25978
- const dirty = porc.length > 0;
25979
- const lines = porc ? porc.split("\n").filter(Boolean) : [];
25980
- let staged = 0, modified = 0, untracked = 0, deleted = 0, renamed = 0;
25981
- for (const line of lines) {
25982
- const xy = line.slice(0, 2);
25983
- if (xy[0] !== " " && xy[0] !== "?") staged++;
25984
- if (xy[1] === "M") modified++;
25985
- if (xy[1] === "D") deleted++;
25986
- if (xy[0] === "R" || xy[1] === "R") renamed++;
25987
- if (xy === "??") untracked++;
26726
+ if (!remoteProbeApplied) {
26727
+ const connectionState = readStringValue(status.connection?.state);
26728
+ const pendingPeerGitProbe = !inlineTransitGit && !isSelfNode && !!daemonId && (readStringValue(status.machineStatus) === "online" || readStringValue(status.health) === "online" || connectionState === "connecting" || connectionState === "connected" || connectionState === "unknown");
26729
+ if (pendingPeerGitProbe) {
26730
+ status.gitProbePending = true;
26731
+ status.health = "unknown";
26732
+ }
26733
+ if (applyCachedInlineMeshNodeStatus(
26734
+ status,
26735
+ node,
26736
+ pendingPeerGitProbe ? { skipGit: true, skipError: true, skipHealth: true } : void 0
26737
+ )) {
26738
+ finalizeMeshNodeStatus({ status, node, daemonId, isSelfNode });
26739
+ nodeStatuses.push(status);
26740
+ continue;
26741
+ }
26742
+ if (meshRecord?.source === "inline_cache" && !isSelfNode) {
26743
+ finalizeMeshNodeStatus({ status, node, daemonId, isSelfNode });
26744
+ nodeStatuses.push(status);
26745
+ continue;
26746
+ }
25988
26747
  }
25989
- status.git = {
25990
- workspace: node.workspace,
25991
- repoRoot: node.workspace,
25992
- isGitRepo: true,
25993
- branch: branch || null,
25994
- headCommit,
25995
- headMessage,
25996
- upstream,
25997
- ahead,
25998
- behind,
25999
- staged,
26000
- modified,
26001
- untracked,
26002
- deleted,
26003
- renamed,
26004
- hasConflicts: false,
26005
- conflictFiles: [],
26006
- stashCount: stashCount ? stashCount.split("\n").filter(Boolean).length : 0,
26007
- lastCheckedAt: Date.now()
26008
- };
26009
- status.health = branch ? dirty ? "dirty" : "online" : "degraded";
26010
- } catch {
26011
- if (!applyCachedInlineMeshNodeStatus(status, node)) {
26012
- status.health = "degraded";
26748
+ } else {
26749
+ try {
26750
+ const gitStatus = await getGitRepoStatus(workspace, { timeoutMs: 1e4, refreshUpstream: true });
26751
+ status.git = gitStatus;
26752
+ recordInlineMeshDirectGitTruth(node, gitStatus, "selected_coordinator_local_git");
26753
+ if (gitStatus.isGitRepo) {
26754
+ status.health = deriveMeshNodeHealthFromGit(gitStatus);
26755
+ } else {
26756
+ status.health = "degraded";
26757
+ if (gitStatus.error && !status.error) status.error = gitStatus.error;
26758
+ }
26759
+ } catch {
26760
+ if (!applyCachedInlineMeshNodeStatus(status, node)) {
26761
+ status.health = "degraded";
26762
+ }
26013
26763
  }
26014
26764
  }
26015
26765
  } else {
26016
26766
  applyCachedInlineMeshNodeStatus(status, node);
26017
26767
  }
26768
+ finalizeMeshNodeStatus({ status, node, daemonId, isSelfNode });
26018
26769
  nodeStatuses.push(status);
26019
26770
  }
26020
26771
  return {
@@ -26023,6 +26774,12 @@ ${block}`);
26023
26774
  meshName: mesh.name,
26024
26775
  repoIdentity: mesh.repoIdentity,
26025
26776
  defaultBranch: mesh.defaultBranch,
26777
+ refreshedAt: (/* @__PURE__ */ new Date()).toISOString(),
26778
+ sourceOfTruth: {
26779
+ membership: meshRecord?.source === "inline_cache" ? "coordinator_inline_mesh_cache" : meshRecord?.source === "local_config" ? "local_mesh_config" : "inline_bootstrap_snapshot",
26780
+ coordinatorOwnsLiveTruth: meshRecord?.source !== "inline_bootstrap",
26781
+ historicalEvidenceOnly: ["recoveryHints", "ledger.summary", "queue.summary"]
26782
+ },
26026
26783
  nodes: nodeStatuses,
26027
26784
  queue: { tasks: queue, summary: queueSummary },
26028
26785
  ledger: { entries: ledgerEntries, summary: ledgerSummary }
@@ -33957,6 +34714,7 @@ async function initDaemonComponents(config) {
33957
34714
  sessionHostControl: config.sessionHostControl,
33958
34715
  statusInstanceId: config.statusInstanceId,
33959
34716
  statusVersion: config.statusVersion,
34717
+ getMeshPeerConnectionStatus: config.getMeshPeerConnectionStatus,
33960
34718
  getCdpLogFn: config.getCdpLogFn || ((ideType) => LOG.forComponent(`CDP:${ideType}`).asLogFn())
33961
34719
  });
33962
34720
  poller = new AgentStreamPoller({
@@ -34231,6 +34989,7 @@ export {
34231
34989
  prepareSessionChatTailUpdate,
34232
34990
  prepareSessionModalUpdate,
34233
34991
  probeCdpPort,
34992
+ queuePendingMeshCoordinatorEvent,
34234
34993
  readChatHistory,
34235
34994
  readLedgerEntries,
34236
34995
  readLedgerSlice,