@adhdev/daemon-core 0.9.82-rc.461 → 0.9.82-rc.463

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
@@ -409,10 +409,10 @@ function readInjected(value) {
409
409
  }
410
410
  function getDaemonBuildInfo() {
411
411
  if (cached) return cached;
412
- const commit = readInjected(true ? "ed8842e811aa362a2b4cc530498bc1fc7e1a7e4a" : void 0) ?? "unknown";
413
- const commitShort = readInjected(true ? "ed8842e8" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
414
- const version = readInjected(true ? "0.9.82-rc.461" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
415
- const builtAt = readInjected(true ? "2026-07-04T15:00:03.344Z" : void 0);
412
+ const commit = readInjected(true ? "3441855fe9c04e158a4dc94eed196b7bcba1647e" : void 0) ?? "unknown";
413
+ const commitShort = readInjected(true ? "3441855f" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
414
+ const version = readInjected(true ? "0.9.82-rc.463" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
415
+ const builtAt = readInjected(true ? "2026-07-05T02:56:26.902Z" : void 0);
416
416
  cached = builtAt ? { commit, commitShort, version, builtAt } : { commit, commitShort, version };
417
417
  return cached;
418
418
  }
@@ -11479,6 +11479,37 @@ var init_mesh_events_utils = __esm({
11479
11479
  function normalizeCoordinatorDaemonIds(coordinatorDaemonId) {
11480
11480
  return expandDaemonIdForms(coordinatorDaemonId);
11481
11481
  }
11482
+ function isMeshProtocolV2EnforceEnabled() {
11483
+ const raw = readNonEmptyString2(process.env.MESH_PROTOCOL_V2_ENFORCE);
11484
+ if (!raw) return false;
11485
+ const v = raw.trim().toLowerCase();
11486
+ return v === "1" || v === "true" || v === "on" || v === "yes";
11487
+ }
11488
+ function ledgerRecordQuarantinedEvent(event, reason) {
11489
+ try {
11490
+ const finalSummary = readMeshCompletionSummary(event.metadataEvent || {});
11491
+ appendLedgerEntry(event.meshId, {
11492
+ kind: "event_held",
11493
+ ...event.nodeId ? { nodeId: event.nodeId } : {},
11494
+ payload: {
11495
+ event: event.event,
11496
+ reason,
11497
+ recoverable: true,
11498
+ nodeLabel: event.nodeLabel,
11499
+ ...event.workspace ? { workspace: event.workspace } : {},
11500
+ targetCoordinatorDaemonId: event.targetCoordinatorDaemonId ?? null,
11501
+ ...readNonEmptyString2(event.eventId) ? { eventId: event.eventId } : {},
11502
+ queuedAt: event.queuedAt,
11503
+ ...finalSummary ? { finalSummary } : {}
11504
+ }
11505
+ });
11506
+ } catch (e) {
11507
+ LOG.warn("MeshEventsV2", `Failed to ledger-record v2-quarantined ${event.event} for mesh ${event.meshId}: ${e?.message || e}`);
11508
+ }
11509
+ }
11510
+ function getMeshV2DrainCounters() {
11511
+ return { ...meshV2DrainCounters };
11512
+ }
11482
11513
  function warnV2Once(key2, message) {
11483
11514
  if (warnedV2Violations.has(key2)) return;
11484
11515
  warnedV2Violations.add(key2);
@@ -11510,12 +11541,22 @@ function identityDeliversTo(intendedFor, drainer) {
11510
11541
  }
11511
11542
  function routeV2EventsForDrainer(events, drainer, ctx) {
11512
11543
  if (!drainer) return events;
11544
+ const enforce = isMeshProtocolV2EnforceEnabled();
11513
11545
  const bump = (k) => {
11514
11546
  if (ctx.countMetrics) meshV2DrainCounters[k]++;
11515
11547
  };
11516
11548
  const kept = [];
11517
11549
  for (const event of events) {
11518
11550
  if (!isV2Event(event)) {
11551
+ if (enforce) {
11552
+ bump("v1UnversionedQuarantined");
11553
+ if (ctx.countMetrics) ledgerRecordQuarantinedEvent(event, "v2_enforce_unversioned_quarantined");
11554
+ warnV2Once(
11555
+ `${event.meshId}::${event.eventId ?? event.event}::v1-quarantined`,
11556
+ `v2 ENFORCE: unversioned ${event.event} on mesh ${event.meshId} QUARANTINED (no v2 envelope \u2014 held back, not delivered; ledger-recorded recoverable). A producer path still emits v1.`
11557
+ );
11558
+ continue;
11559
+ }
11519
11560
  bump("v1BroadcastAccepted");
11520
11561
  kept.push(event);
11521
11562
  continue;
@@ -11524,6 +11565,15 @@ function routeV2EventsForDrainer(events, drainer, ctx) {
11524
11565
  try {
11525
11566
  validated = assertPendingMeshCoordinatorEventV2(event);
11526
11567
  } catch (e) {
11568
+ if (enforce) {
11569
+ bump("v2ValidationFailedQuarantined");
11570
+ if (ctx.countMetrics) ledgerRecordQuarantinedEvent(event, "v2_enforce_validation_failed_quarantined");
11571
+ warnV2Once(
11572
+ `${event.meshId}::${event.eventId ?? event.event}::invalid-quarantined`,
11573
+ `v2 ENFORCE: envelope validation failed for ${event.event} on mesh ${event.meshId} \u2014 QUARANTINED (held back, not delivered; ledger-recorded recoverable): ${e?.message || e}`
11574
+ );
11575
+ continue;
11576
+ }
11527
11577
  bump("v2ValidationFailedAccepted");
11528
11578
  warnV2Once(
11529
11579
  `${event.meshId}::${event.eventId ?? event.event}::invalid`,
@@ -12108,7 +12158,15 @@ var init_mesh_events_pending = __esm({
12108
12158
  * coordinatorRunId change orphaned them). */
12109
12159
  v2ReattributedToDrainer: 0,
12110
12160
  /** v1 (unversioned) events passed through as broadcast (rollout baseline). */
12111
- v1BroadcastAccepted: 0
12161
+ v1BroadcastAccepted: 0,
12162
+ /** T6 enforce: v2 events that FAILED validation and were QUARANTINED (held back
12163
+ * from delivery, not dropped). Non-zero here means a producer is still emitting a
12164
+ * malformed envelope after enforce was turned on. */
12165
+ v2ValidationFailedQuarantined: 0,
12166
+ /** T6 enforce: v1 (unversioned) events QUARANTINED because no v2 envelope could be
12167
+ * derived at emit time. Non-zero here means a producer path still emits v1 after
12168
+ * enforce — it should reach 0 once every node is on a v2-stamping build. */
12169
+ v1UnversionedQuarantined: 0
12112
12170
  };
12113
12171
  warnedV2Violations = /* @__PURE__ */ new Set();
12114
12172
  TERMINAL_COMPLETION_EVENTS = /* @__PURE__ */ new Set(["agent:generating_completed", "agent:stopped"]);
@@ -18312,6 +18370,21 @@ function resolveAckedDeathDeadlineMs() {
18312
18370
  function resolveAckedTranscriptFastTrackGraceMs() {
18313
18371
  return resolveTunedReconcileMs("MESH_INFLIGHT_ACKED_TRANSCRIPT_FASTTRACK_GRACE_MS", 4e4, 0, 5 * 6e4);
18314
18372
  }
18373
+ function getMeshV2BackstopCounters() {
18374
+ return { ...meshV2BackstopCounters };
18375
+ }
18376
+ function meshProtocolV2EnforceOn() {
18377
+ const raw = process.env.MESH_PROTOCOL_V2_ENFORCE;
18378
+ if (typeof raw !== "string") return false;
18379
+ const v = raw.trim().toLowerCase();
18380
+ return v === "1" || v === "true" || v === "on" || v === "yes";
18381
+ }
18382
+ function recordBackstopFire(kind, detail) {
18383
+ meshV2BackstopCounters[kind]++;
18384
+ if (meshProtocolV2EnforceOn()) {
18385
+ LOG.warn("MeshReconcileV2", `v2 ENFORCE last-resort backstop fired (${kind}): ${detail}. Under a healthy v2 completion contract this should be 0 \u2014 a worker's real terminal emit was lost/late.`);
18386
+ }
18387
+ }
18315
18388
  function inFlightSynthKey(meshId, taskId) {
18316
18389
  return `${meshId}::${taskId}`;
18317
18390
  }
@@ -19226,6 +19299,7 @@ async function reconcileUnterminatedDirectDispatches(components, mesh, selfIds,
19226
19299
  };
19227
19300
  const synthKey = inFlightSynthKey(mesh.id, taskId);
19228
19301
  const isAcked = dispatch.status === "acked";
19302
+ let backstopKind;
19229
19303
  let payload = null;
19230
19304
  let readFailed = false;
19231
19305
  try {
@@ -19290,6 +19364,7 @@ async function reconcileUnterminatedDirectDispatches(components, mesh, selfIds,
19290
19364
  const idleHeldMs = nowMs - idleSinceMs;
19291
19365
  if (idleHeldMs >= fastTrackGraceMs) {
19292
19366
  fastTrackReady = true;
19367
+ backstopKind = "ackedHoldFastTrackFired";
19293
19368
  LOG.info("MeshReconcile", `Acked-hold transcript fast-track: task ${taskId} on node ${nodeId} (mesh ${mesh.id}) read idle WITH a final assistant message for ${Math.round(idleHeldMs / 1e3)}s continuous (grace ${Math.round(fastTrackGraceMs / 1e3)}s) \u2014 promoting the synth ahead of the ${Math.round(deathDeadlineMs / 1e3)}s death backstop; the worker's real emit was lost/late and a later one no-ops idempotently.`);
19294
19369
  }
19295
19370
  } else if (holdState?.transcriptIdleSinceMs !== void 0) {
@@ -19300,6 +19375,7 @@ async function reconcileUnterminatedDirectDispatches(components, mesh, selfIds,
19300
19375
  continue;
19301
19376
  }
19302
19377
  if (!fastTrackReady) {
19378
+ backstopKind = "ackedHoldDeathDeadlineFired";
19303
19379
  LOG.warn("MeshReconcile", `Acked-hold death deadline reached: task ${taskId} on node ${nodeId} (mesh ${mesh.id}) still idle ${Math.round(sinceAckMs / 1e3)}s after the ack (deadline ${Math.round(deathDeadlineMs / 1e3)}s) \u2014 synthesizing the missing completion as a notification-loss net (a real emit, if it ever lands, no-ops idempotently).`);
19304
19380
  }
19305
19381
  }
@@ -19344,6 +19420,7 @@ async function reconcileUnterminatedDirectDispatches(components, mesh, selfIds,
19344
19420
  source: "daemon_reconcile_transcript_completion"
19345
19421
  });
19346
19422
  if (result.reconciled) {
19423
+ recordBackstopFire(backstopKind ?? "phase4SynthesisFired", `task ${taskId} on node ${nodeId} (mesh ${mesh.id}), kind=${result.kind}`);
19347
19424
  LOG.info("MeshReconcile", `Synthesized missing completion (${result.kind}) for task ${taskId} on node ${nodeId} (mesh ${mesh.id})`);
19348
19425
  }
19349
19426
  } catch (e) {
@@ -19473,7 +19550,7 @@ function setupMeshReconcileLoop(components) {
19473
19550
  }
19474
19551
  };
19475
19552
  }
19476
- var DEFAULT_RECONCILE_INTERVAL_MS, DEFAULT_AUTO_PRUNE_MIN_AGE_MS, DEFAULT_PENDING_HELD_DRAIN_ESCALATE_MS, ACKED_DEATH_CONSECUTIVE_READ_FAILURES, inFlightAckedHoldState, rehydratedHoldMeshes, coordinatorModalParkState, heldEventLedgerRecorded, ASSIGNED_STRANDED_DEADLINE_MS, DELIVERED_NO_TURN_DEADLINE_MS, RECLAIM_UNKNOWN_GRACE_TICKS, deliveredNoTurnUnknownStreak, STRICT_SESSION_MATCH_TTL_MS, unresolvedForwardRejectionCounts, MAX_FORWARD_REJECTIONS;
19553
+ var DEFAULT_RECONCILE_INTERVAL_MS, DEFAULT_AUTO_PRUNE_MIN_AGE_MS, DEFAULT_PENDING_HELD_DRAIN_ESCALATE_MS, ACKED_DEATH_CONSECUTIVE_READ_FAILURES, inFlightAckedHoldState, rehydratedHoldMeshes, meshV2BackstopCounters, coordinatorModalParkState, heldEventLedgerRecorded, ASSIGNED_STRANDED_DEADLINE_MS, DELIVERED_NO_TURN_DEADLINE_MS, RECLAIM_UNKNOWN_GRACE_TICKS, deliveredNoTurnUnknownStreak, STRICT_SESSION_MATCH_TTL_MS, unresolvedForwardRejectionCounts, MAX_FORWARD_REJECTIONS;
19477
19554
  var init_mesh_reconcile_loop = __esm({
19478
19555
  "src/mesh/mesh-reconcile-loop.ts"() {
19479
19556
  "use strict";
@@ -19501,6 +19578,14 @@ var init_mesh_reconcile_loop = __esm({
19501
19578
  ACKED_DEATH_CONSECUTIVE_READ_FAILURES = 3;
19502
19579
  inFlightAckedHoldState = /* @__PURE__ */ new Map();
19503
19580
  rehydratedHoldMeshes = /* @__PURE__ */ new Set();
19581
+ meshV2BackstopCounters = {
19582
+ /** PHASE-4 transcript synthesis actually reconciled a missing completion. */
19583
+ phase4SynthesisFired: 0,
19584
+ /** Acked-hold transcript fast-track promoted a synth ahead of the death deadline. */
19585
+ ackedHoldFastTrackFired: 0,
19586
+ /** Acked-hold death-deadline backstop released a held synth (the 8-min net). */
19587
+ ackedHoldDeathDeadlineFired: 0
19588
+ };
19504
19589
  coordinatorModalParkState = /* @__PURE__ */ new Map();
19505
19590
  heldEventLedgerRecorded = /* @__PURE__ */ new Set();
19506
19591
  ASSIGNED_STRANDED_DEADLINE_MS = 5 * 6e4;
@@ -19520,9 +19605,12 @@ __export(mesh_events_exports, {
19520
19605
  __resetMeshWorkspaceCacheForTests: () => __resetMeshWorkspaceCacheForTests,
19521
19606
  clearPendingMeshCoordinatorEvents: () => clearPendingMeshCoordinatorEvents,
19522
19607
  drainPendingMeshCoordinatorEvents: () => drainPendingMeshCoordinatorEvents,
19608
+ getMeshV2BackstopCounters: () => getMeshV2BackstopCounters,
19609
+ getMeshV2DrainCounters: () => getMeshV2DrainCounters,
19523
19610
  getPendingMeshCoordinatorEvents: () => getPendingMeshCoordinatorEvents,
19524
19611
  handleMeshForwardEvent: () => handleMeshForwardEvent,
19525
19612
  isMeshCoordinatorEvent: () => isMeshCoordinatorEvent,
19613
+ isMeshProtocolV2EnforceEnabled: () => isMeshProtocolV2EnforceEnabled,
19526
19614
  isSessionActivelyGenerating: () => isSessionActivelyGenerating,
19527
19615
  queuePendingMeshCoordinatorEvent: () => queuePendingMeshCoordinatorEvent,
19528
19616
  readV2EnvelopeFromWire: () => readV2EnvelopeFromWire,
@@ -40601,15 +40689,37 @@ function executeSqlite(src, input) {
40601
40689
  }
40602
40690
  try {
40603
40691
  const requested = input.providerSessionId || "";
40604
- const resolveMessagesFor = (sessionId2) => {
40605
- if (!sessionId2) return null;
40606
- let rows;
40607
- try {
40608
- rows = db.prepare(src.message_query).all(sessionId2);
40609
- } catch {
40610
- return null;
40692
+ const resolveClusterIds = (anchorId) => {
40693
+ const ids = /* @__PURE__ */ new Set();
40694
+ if (anchorId) ids.add(anchorId);
40695
+ if (src.session_cluster_query && anchorId) {
40696
+ try {
40697
+ const rows = db.prepare(src.session_cluster_query).all(anchorId);
40698
+ for (const row of rows) {
40699
+ const idRaw = Object.values(row)[0];
40700
+ if (idRaw != null && String(idRaw)) ids.add(String(idRaw));
40701
+ }
40702
+ } catch {
40703
+ }
40611
40704
  }
40612
- return rows && rows.length > 0 ? rows : null;
40705
+ return Array.from(ids);
40706
+ };
40707
+ const resolveMessagesFor = (anchorId) => {
40708
+ if (!anchorId) return null;
40709
+ const clusterIds = resolveClusterIds(anchorId);
40710
+ const merged = [];
40711
+ for (const id of clusterIds) {
40712
+ let rows;
40713
+ try {
40714
+ rows = db.prepare(src.message_query).all(id);
40715
+ } catch {
40716
+ continue;
40717
+ }
40718
+ if (rows && rows.length > 0) merged.push(...rows);
40719
+ }
40720
+ if (merged.length === 0) return null;
40721
+ if (clusterIds.length > 1) sortRowsByMappedTimestamp(merged, src.message_map);
40722
+ return merged;
40613
40723
  };
40614
40724
  const resolveNewestSessionId = () => {
40615
40725
  let sessionRow;
@@ -40666,6 +40776,20 @@ function executeSqlite(src, input) {
40666
40776
  }
40667
40777
  }
40668
40778
  }
40779
+ function sortRowsByMappedTimestamp(rows, map) {
40780
+ if (!map.timestamp_ms) return;
40781
+ const keyed = rows.map((row, index) => {
40782
+ const parsed = parseTimestamp(jsonPathGet(row, map.timestamp_ms));
40783
+ return { row, index, ts: parsed == null ? Number.NaN : parsed };
40784
+ });
40785
+ keyed.sort((a, b) => {
40786
+ const aHas = !Number.isNaN(a.ts);
40787
+ const bHas = !Number.isNaN(b.ts);
40788
+ if (aHas && bHas && a.ts !== b.ts) return a.ts - b.ts;
40789
+ return a.index - b.index;
40790
+ });
40791
+ for (let i = 0; i < keyed.length; i += 1) rows[i] = keyed[i].row;
40792
+ }
40669
40793
  function expandPath2(template, input, opts) {
40670
40794
  if (!template) return null;
40671
40795
  let out = template;
@@ -43290,6 +43414,19 @@ var CliProviderInstance = class _CliProviderInstance {
43290
43414
  }
43291
43415
  return probe;
43292
43416
  }
43417
+ /**
43418
+ * The spawned CLI's env overrides (e.g. the mesh coordinator points hermes
43419
+ * at a per-coordinator HERMES_HOME so its state.db lives in a tmpdir instead
43420
+ * of ~/.hermes). The native-history executor expands `${HERMES_HOME:-~/.hermes}`
43421
+ * from this map, so the completion gate MUST pass it through — otherwise the
43422
+ * gate reads ~/.hermes, finds no coordinator-session transcript, and
43423
+ * false-fires missing_final_assistant on every coordinator turn.
43424
+ */
43425
+ spawnedEnvOverrides() {
43426
+ const meta = typeof this.adapter?.getRuntimeMetadata === "function" ? this.adapter.getRuntimeMetadata() : void 0;
43427
+ const env = meta && typeof meta === "object" ? meta.spawnedEnv : void 0;
43428
+ return env && typeof env === "object" ? env : void 0;
43429
+ }
43293
43430
  readExternalCompletionMessages() {
43294
43431
  const adapterOwnsMessagesElsewhere = this.adapter?.chatMessagesOwnedExternally === true;
43295
43432
  if (!adapterOwnsMessagesElsewhere) return null;
@@ -43310,6 +43447,7 @@ var CliProviderInstance = class _CliProviderInstance {
43310
43447
  historyBehavior: this.provider.historyBehavior,
43311
43448
  scripts: this.provider.scripts,
43312
43449
  sessionStartedAtMs: this.startedAt,
43450
+ envOverrides: this.spawnedEnvOverrides(),
43313
43451
  forceRefresh: true
43314
43452
  });
43315
43453
  if (restoredHistory.source !== "provider-native") {
@@ -43835,10 +43973,10 @@ var CliProviderInstance = class _CliProviderInstance {
43835
43973
  if (buttonIndex < 0 || !hasReliableConsentAnchor) {
43836
43974
  return autoApproveActive;
43837
43975
  }
43976
+ const affirmativeAnchor = normalizeApprovalLabel(buttonLabel);
43838
43977
  const modalSignature = [
43839
43978
  typeof modal?.message === "string" ? modal.message.trim() : "",
43840
- buttons.join("|"),
43841
- buttonIndex
43979
+ affirmativeAnchor
43842
43980
  ].join("::");
43843
43981
  const approvalEntrySeq = typeof adapterStatus?.approvalEntrySeq === "number" ? adapterStatus.approvalEntrySeq : 0;
43844
43982
  const busySignature = `${approvalEntrySeq}::${modalSignature}`;
@@ -48882,14 +49020,44 @@ function openDb() {
48882
49020
  return null;
48883
49021
  }
48884
49022
  }
49023
+ function resolveClusterSessionIds(db, anchorId) {
49024
+ if (!anchorId) return [];
49025
+ try {
49026
+ const rows = db.prepare(
49027
+ `WITH RECURSIVE
49028
+ up(id) AS (
49029
+ SELECT id FROM sessions WHERE id = ?
49030
+ UNION
49031
+ SELECT s.parent_session_id FROM sessions s JOIN up ON s.id = up.id
49032
+ WHERE s.parent_session_id IS NOT NULL
49033
+ ),
49034
+ cluster(id) AS (
49035
+ SELECT id FROM up
49036
+ UNION
49037
+ SELECT s.id FROM sessions s JOIN cluster ON s.parent_session_id = cluster.id
49038
+ )
49039
+ SELECT id FROM cluster`
49040
+ ).all(anchorId);
49041
+ const ids = /* @__PURE__ */ new Set([anchorId]);
49042
+ for (const r of rows) {
49043
+ if (r && r.id != null && String(r.id)) ids.add(String(r.id));
49044
+ }
49045
+ return Array.from(ids);
49046
+ } catch {
49047
+ return [anchorId];
49048
+ }
49049
+ }
48885
49050
  function loadMessagesForSession(db, sessionId) {
49051
+ const clusterIds = resolveClusterSessionIds(db, sessionId);
49052
+ if (clusterIds.length === 0) return [];
49053
+ const placeholders = clusterIds.map(() => "?").join(", ");
48886
49054
  const rows = db.prepare(
48887
49055
  `SELECT id, role, COALESCE(NULLIF(content, ''), tool_calls) AS content, timestamp
48888
49056
  FROM messages
48889
- WHERE session_id = ?
49057
+ WHERE session_id IN (${placeholders})
48890
49058
  AND ((content IS NOT NULL AND content != '') OR (tool_calls IS NOT NULL AND tool_calls != ''))
48891
49059
  ORDER BY timestamp ASC, id ASC`
48892
- ).all(sessionId);
49060
+ ).all(...clusterIds);
48893
49061
  const out = [];
48894
49062
  for (const r of rows) {
48895
49063
  const role = normalizeHermesRole(r.role);
@@ -53445,7 +53613,12 @@ var meshEventsHandlers = {
53445
53613
  return { success: true, events: [], heldForBusyLocalCoordinator: true, hasLiveCliCoordinator };
53446
53614
  }
53447
53615
  const events = drainPendingMeshCoordinatorEvents(meshId || void 0, coordinatorDaemonId);
53448
- return { success: true, events, hasLiveCliCoordinator, ...selfCoordinatorInboxRead ? { surfacedForSelfCoordinator: true } : {} };
53616
+ const meshProtocolV2Counters = {
53617
+ enforce: isMeshProtocolV2EnforceEnabled(),
53618
+ drain: { ...getMeshV2DrainCounters() },
53619
+ backstop: { ...getMeshV2BackstopCounters() }
53620
+ };
53621
+ return { success: true, events, hasLiveCliCoordinator, meshProtocolV2Counters, ...selfCoordinatorInboxRead ? { surfacedForSelfCoordinator: true } : {} };
53449
53622
  },
53450
53623
  interactive_prompt_response: async (ctx, args) => {
53451
53624
  const sessionId = typeof args?.targetSessionId === "string" && args.targetSessionId.trim() ? args.targetSessionId.trim() : typeof args?.sessionId === "string" && args.sessionId.trim() ? args.sessionId.trim() : "";
@@ -54471,6 +54644,11 @@ var meshStatusHandlers = {
54471
54644
  const callerCoordinatorDaemonId = typeof args?.coordinatorDaemonId === "string" && args.coordinatorDaemonId.trim() ? args.coordinatorDaemonId.trim() : ctx.deps.statusInstanceId || void 0;
54472
54645
  const pendingCoordinatorEvents = getPendingMeshCoordinatorEvents(meshId, callerCoordinatorDaemonId);
54473
54646
  const unroutableDeliveries = getRecentUnroutableDeliveries();
54647
+ const meshProtocolV2Counters = {
54648
+ enforce: isMeshProtocolV2EnforceEnabled(),
54649
+ drain: { ...getMeshV2DrainCounters() },
54650
+ backstop: { ...getMeshV2BackstopCounters() }
54651
+ };
54474
54652
  const previewFreshness = (() => {
54475
54653
  const localRepoRoot = nodeStatuses.map((node) => readStringValue(node?.git?.repoRoot, node?.repoRoot, node?.workspace)).find((candidate) => !!candidate && fs27.existsSync(candidate));
54476
54654
  return localRepoRoot ? buildPreviewFreshness(localRepoRoot) : void 0;
@@ -54560,6 +54738,7 @@ var meshStatusHandlers = {
54560
54738
  ...historicalSessions ? { historicalSessions } : {},
54561
54739
  ...pendingCoordinatorEvents.length > 0 ? { pendingCoordinatorEvents } : {},
54562
54740
  ...unroutableDeliveries.length > 0 ? { unroutableDeliveries } : {},
54741
+ meshProtocolV2Counters,
54563
54742
  activeRefineJobs: Array.from(ctx.runningRefineJobs.values()).filter((job) => job.meshId === meshId).map((job) => ({
54564
54743
  jobId: job.jobId,
54565
54744
  nodeId: job.targetNodeId,
@@ -54569,12 +54748,13 @@ var meshStatusHandlers = {
54569
54748
  targetCoordinatorDaemonId: job.targetCoordinatorDaemonId
54570
54749
  }))
54571
54750
  };
54572
- const { pendingCoordinatorEvents: _pendingCoordinatorEvents, unroutableDeliveries: _unroutableDeliveries, ...cacheableStatusResult } = statusResult;
54751
+ const { pendingCoordinatorEvents: _pendingCoordinatorEvents, unroutableDeliveries: _unroutableDeliveries, meshProtocolV2Counters: _meshProtocolV2Counters, ...cacheableStatusResult } = statusResult;
54573
54752
  const rememberedStatus = verboseMissions ? cacheableStatusResult : ctx.rememberAggregateMeshStatus(meshId, cacheableStatusResult, refreshReason);
54574
54753
  const returnedStatus = {
54575
54754
  ...rememberedStatus,
54576
54755
  ...pendingCoordinatorEvents.length > 0 ? { pendingCoordinatorEvents } : {},
54577
- ...unroutableDeliveries.length > 0 ? { unroutableDeliveries } : {}
54756
+ ...unroutableDeliveries.length > 0 ? { unroutableDeliveries } : {},
54757
+ meshProtocolV2Counters
54578
54758
  };
54579
54759
  logRepoMeshStatusDebug("return_live", {
54580
54760
  meshId,
@@ -54817,7 +54997,6 @@ cleanOldFiles();
54817
54997
  // src/commands/router.ts
54818
54998
  init_debug_trace();
54819
54999
  init_mesh_host_ownership();
54820
- init_mesh_work_queue();
54821
55000
  var fs33 = __toESM(require("fs"));
54822
55001
 
54823
55002
  // src/mesh/mesh-node-identity.ts
@@ -59211,6 +59390,177 @@ async function cleanupMeshSessions(self, args) {
59211
59390
  };
59212
59391
  }
59213
59392
 
59393
+ // src/commands/router-aggregate-status.ts
59394
+ init_dist();
59395
+ init_mesh_work_queue();
59396
+ function cloneJsonValue(value) {
59397
+ if (typeof structuredClone === "function") return structuredClone(value);
59398
+ return JSON.parse(JSON.stringify(value));
59399
+ }
59400
+ function hydrateCachedAggregateMeshStatusFromInline(self, snapshot, mesh, options) {
59401
+ if (!mesh || typeof mesh !== "object" || !Array.isArray(mesh.nodes) || !Array.isArray(snapshot?.nodes)) return snapshot;
59402
+ const inlineNodesById = /* @__PURE__ */ new Map();
59403
+ for (const node of mesh.nodes) {
59404
+ const nodeId = readInlineMeshNodeId(node);
59405
+ if (nodeId) inlineNodesById.set(nodeId, node);
59406
+ }
59407
+ if (!inlineNodesById.size) return snapshot;
59408
+ let changed = false;
59409
+ const unavailableNodeIds = /* @__PURE__ */ new Set();
59410
+ const sourceOfTruth = readObjectRecord(snapshot.sourceOfTruth);
59411
+ const directPeerTruth = readObjectRecord(sourceOfTruth.directPeerTruth);
59412
+ const deadNodeIds = /* @__PURE__ */ new Set();
59413
+ for (const node of mesh.nodes) {
59414
+ if (!isDeadLocalWorktreeNode(node)) continue;
59415
+ const deadId = readInlineMeshNodeId(node);
59416
+ if (deadId) deadNodeIds.add(deadId);
59417
+ }
59418
+ let droppedDeadUnavailable = false;
59419
+ for (const entry of Array.isArray(directPeerTruth.unavailableNodeIds) ? directPeerTruth.unavailableNodeIds : []) {
59420
+ const nodeId = readStringValue(entry);
59421
+ if (!nodeId) continue;
59422
+ if (deadNodeIds.has(nodeId)) {
59423
+ droppedDeadUnavailable = true;
59424
+ continue;
59425
+ }
59426
+ unavailableNodeIds.add(nodeId);
59427
+ }
59428
+ if (droppedDeadUnavailable) changed = true;
59429
+ const nodes = snapshot.nodes.map((statusNode) => {
59430
+ const nodeId = normalizeMeshNodeId(statusNode);
59431
+ const inlineNode = nodeId ? inlineNodesById.get(nodeId) : void 0;
59432
+ if (!inlineNode) return statusNode;
59433
+ const liveGit = buildInlineMeshTransitGitStatus(inlineNode);
59434
+ if (!liveGit) return statusNode;
59435
+ const nextStatus = { ...statusNode };
59436
+ nextStatus.git = liveGit;
59437
+ nextStatus.health = deriveMeshNodeHealthFromGit(liveGit);
59438
+ applyInlineMeshBranchConvergence(mesh, inlineNode, nextStatus);
59439
+ nextStatus.launchReady = readBooleanValue(nextStatus.launchReady) ?? true;
59440
+ const connection = readObjectRecord(nextStatus.connection);
59441
+ const connectionState = readStringValue(connection.state);
59442
+ const connectionReported = readBooleanValue(connection.reported) ?? false;
59443
+ if (!connectionReported || connectionState === "unknown") {
59444
+ nextStatus.connection = buildLivePeerGitConnection(connection);
59445
+ }
59446
+ delete nextStatus.gitProbePending;
59447
+ const error = readStringValue(nextStatus.error);
59448
+ if (error && /pending_git|git probe|live peer git snapshot|no peer git snapshot/i.test(error)) delete nextStatus.error;
59449
+ if (!readStringValue(nextStatus.machineStatus)) nextStatus.machineStatus = "online";
59450
+ if (nodeId) unavailableNodeIds.delete(nodeId);
59451
+ changed = true;
59452
+ return nextStatus;
59453
+ });
59454
+ const aggregateDirectTruthSatisfied = sourceOfTruth.coordinatorOwnsLiveTruth === true || directPeerTruth.satisfied === true;
59455
+ if (!changed && !(options?.requireDirectPeerTruth && unavailableNodeIds.size > 0 && !aggregateDirectTruthSatisfied)) return snapshot;
59456
+ const nextSourceOfTruth = {
59457
+ ...sourceOfTruth,
59458
+ ...Object.keys(directPeerTruth).length ? {
59459
+ directPeerTruth: {
59460
+ ...directPeerTruth,
59461
+ satisfied: options?.requireDirectPeerTruth === true ? aggregateDirectTruthSatisfied || unavailableNodeIds.size === 0 : directPeerTruth.satisfied,
59462
+ unavailableNodeIds: [...unavailableNodeIds]
59463
+ },
59464
+ ...options?.requireDirectPeerTruth === true ? {
59465
+ coordinatorOwnsLiveTruth: aggregateDirectTruthSatisfied || unavailableNodeIds.size === 0,
59466
+ currentStatus: aggregateDirectTruthSatisfied || unavailableNodeIds.size === 0 ? "live_git_and_session_probes" : "direct_peer_truth_unavailable"
59467
+ } : {}
59468
+ } : {}
59469
+ };
59470
+ return {
59471
+ ...snapshot,
59472
+ ...options?.requireDirectPeerTruth === true && unavailableNodeIds.size > 0 && !aggregateDirectTruthSatisfied ? {
59473
+ success: false,
59474
+ code: "mesh_direct_peer_truth_unavailable",
59475
+ error: "Selected coordinator could not confirm direct mesh truth for every remote node yet."
59476
+ } : {},
59477
+ sourceOfTruth: nextSourceOfTruth,
59478
+ branchConvergenceSummary: summarizeInlineMeshBranchConvergence(nodes),
59479
+ nodes
59480
+ };
59481
+ }
59482
+ function getCachedAggregateMeshStatus(self, meshId, mesh, options) {
59483
+ const cached3 = self.aggregateMeshStatusCache.get(meshId);
59484
+ if (!cached3?.snapshot || cached3.snapshot.success !== true || !Array.isArray(cached3.snapshot.nodes)) return null;
59485
+ if (cached3.queueRevision !== getMeshQueueRevision(meshId)) return null;
59486
+ let snapshot = cloneJsonValue(cached3.snapshot);
59487
+ snapshot = hydrateCachedAggregateMeshStatusFromInline(self, snapshot, mesh, options);
59488
+ if (!options?.allowStalePending && shouldRefreshStalePendingAggregate(snapshot, options)) return null;
59489
+ const ageMs = Math.max(0, Date.now() - cached3.builtAt);
59490
+ const sourceOfTruth = snapshot.sourceOfTruth && typeof snapshot.sourceOfTruth === "object" ? snapshot.sourceOfTruth : {};
59491
+ snapshot.sourceOfTruth = {
59492
+ ...sourceOfTruth,
59493
+ aggregateSnapshot: {
59494
+ ...sourceOfTruth.aggregateSnapshot && typeof sourceOfTruth.aggregateSnapshot === "object" ? sourceOfTruth.aggregateSnapshot : {},
59495
+ owner: "coordinator_daemon_memory",
59496
+ cached: true,
59497
+ source: "memory",
59498
+ refreshReason: "memory_cache_hit",
59499
+ ageMs,
59500
+ cachedAt: new Date(cached3.builtAt).toISOString(),
59501
+ returnedAt: (/* @__PURE__ */ new Date()).toISOString()
59502
+ }
59503
+ };
59504
+ return snapshot;
59505
+ }
59506
+ function rememberAggregateMeshStatus(self, meshId, snapshot, refreshReason) {
59507
+ if (!snapshot || typeof snapshot !== "object" || snapshot.success !== true || !Array.isArray(snapshot.nodes)) return snapshot;
59508
+ const builtAt = Date.now();
59509
+ const next = cloneJsonValue(snapshot);
59510
+ const sourceOfTruth = next.sourceOfTruth && typeof next.sourceOfTruth === "object" ? next.sourceOfTruth : {};
59511
+ next.sourceOfTruth = {
59512
+ ...sourceOfTruth,
59513
+ aggregateSnapshot: {
59514
+ owner: "coordinator_daemon_memory",
59515
+ cached: false,
59516
+ source: "live_refresh",
59517
+ refreshReason,
59518
+ ageMs: 0,
59519
+ cachedAt: new Date(builtAt).toISOString(),
59520
+ returnedAt: new Date(builtAt).toISOString()
59521
+ }
59522
+ };
59523
+ self.aggregateMeshStatusCache.set(meshId, { builtAt, snapshot: cloneJsonValue(next), queueRevision: getMeshQueueRevision(meshId) });
59524
+ return next;
59525
+ }
59526
+
59527
+ // src/commands/router-mesh-session-owner.ts
59528
+ init_dist();
59529
+ function resolveRemoteMeshSessionOwnerDaemonId(self, sessionId, ownerNodeIdHint) {
59530
+ const trimmed = typeof sessionId === "string" ? sessionId.trim() : "";
59531
+ const nodeHint = typeof ownerNodeIdHint === "string" ? ownerNodeIdHint.trim() : "";
59532
+ if (!trimmed && !nodeHint) return void 0;
59533
+ const selfDaemonId = self.deps.statusInstanceId;
59534
+ const candidates = collectMeshSessionOwnerCandidateNodes(self);
59535
+ if (trimmed) {
59536
+ for (const node of candidates) {
59537
+ if (!collectMeshNodeHostedSessionIds(node).has(trimmed)) continue;
59538
+ const nodeDaemonId = readMeshNodeDaemonId(readObjectRecord(node));
59539
+ if (!nodeDaemonId) continue;
59540
+ if (selfDaemonId && daemonIdsEquivalent(nodeDaemonId, selfDaemonId)) return void 0;
59541
+ return nodeDaemonId;
59542
+ }
59543
+ }
59544
+ if (nodeHint) {
59545
+ for (const node of candidates) {
59546
+ if (!meshNodeIdMatches(node, nodeHint)) continue;
59547
+ const nodeDaemonId = readMeshNodeDaemonId(readObjectRecord(node));
59548
+ if (!nodeDaemonId) continue;
59549
+ if (selfDaemonId && daemonIdsEquivalent(nodeDaemonId, selfDaemonId)) return void 0;
59550
+ return nodeDaemonId;
59551
+ }
59552
+ }
59553
+ return void 0;
59554
+ }
59555
+ function collectMeshSessionOwnerCandidateNodes(self) {
59556
+ const nodes = self.getCachedInlineMeshNodes();
59557
+ for (const cached3 of self.aggregateMeshStatusCache.values()) {
59558
+ const snapshotNodes = cached3?.snapshot?.nodes;
59559
+ if (Array.isArray(snapshotNodes)) nodes.push(...snapshotNodes);
59560
+ }
59561
+ return nodes;
59562
+ }
59563
+
59214
59564
  // src/mesh/mesh-coordinator-config.ts
59215
59565
  init_logger();
59216
59566
  var yaml5 = __toESM(require("js-yaml"));
@@ -59379,7 +59729,8 @@ var DaemonCommandRouter = class {
59379
59729
  * on disk) clears the tombstone and merges normally, preserving clone
59380
59730
  * worktree visibility and legitimate node re-creation. */
59381
59731
  removedInlineMeshNodeIds = /* @__PURE__ */ new Map();
59382
- /** Coordinator-owned whole-mesh aggregate status snapshots. Browser callers read this by default. */
59732
+ /** Coordinator-owned whole-mesh aggregate status snapshots. Browser callers read this by default.
59733
+ * Public (not private) so the extracted ./router-aggregate-status.ts orchestration can reach it via `self`. */
59383
59734
  aggregateMeshStatusCache = /* @__PURE__ */ new Map();
59384
59735
  /** Shared per-peer git_status probe dedup + recently-probed reuse gate.
59385
59736
  * Spans separate mesh_status/get_mesh calls so the dashboard auto-retry
@@ -59401,135 +59752,19 @@ var DaemonCommandRouter = class {
59401
59752
  constructor(deps) {
59402
59753
  this.deps = deps;
59403
59754
  }
59404
- cloneJsonValue(value) {
59405
- if (typeof structuredClone === "function") return structuredClone(value);
59406
- return JSON.parse(JSON.stringify(value));
59407
- }
59755
+ // ─── Aggregate mesh-status cache ────────────────────────────────────
59756
+ // Implementation lives in ./router-aggregate-status.ts (behavior-preserving
59757
+ // code move). Kept here as thin delegators: getCachedAggregateMeshStatus /
59758
+ // rememberAggregateMeshStatus are bound into HighFamilyContext, so callers
59759
+ // reach these via `self.` for correct instance dispatch.
59408
59760
  hydrateCachedAggregateMeshStatusFromInline(snapshot, mesh, options) {
59409
- if (!mesh || typeof mesh !== "object" || !Array.isArray(mesh.nodes) || !Array.isArray(snapshot?.nodes)) return snapshot;
59410
- const inlineNodesById = /* @__PURE__ */ new Map();
59411
- for (const node of mesh.nodes) {
59412
- const nodeId = readInlineMeshNodeId(node);
59413
- if (nodeId) inlineNodesById.set(nodeId, node);
59414
- }
59415
- if (!inlineNodesById.size) return snapshot;
59416
- let changed = false;
59417
- const unavailableNodeIds = /* @__PURE__ */ new Set();
59418
- const sourceOfTruth = readObjectRecord(snapshot.sourceOfTruth);
59419
- const directPeerTruth = readObjectRecord(sourceOfTruth.directPeerTruth);
59420
- const deadNodeIds = /* @__PURE__ */ new Set();
59421
- for (const node of mesh.nodes) {
59422
- if (!isDeadLocalWorktreeNode(node)) continue;
59423
- const deadId = readInlineMeshNodeId(node);
59424
- if (deadId) deadNodeIds.add(deadId);
59425
- }
59426
- let droppedDeadUnavailable = false;
59427
- for (const entry of Array.isArray(directPeerTruth.unavailableNodeIds) ? directPeerTruth.unavailableNodeIds : []) {
59428
- const nodeId = readStringValue(entry);
59429
- if (!nodeId) continue;
59430
- if (deadNodeIds.has(nodeId)) {
59431
- droppedDeadUnavailable = true;
59432
- continue;
59433
- }
59434
- unavailableNodeIds.add(nodeId);
59435
- }
59436
- if (droppedDeadUnavailable) changed = true;
59437
- const nodes = snapshot.nodes.map((statusNode) => {
59438
- const nodeId = normalizeMeshNodeId(statusNode);
59439
- const inlineNode = nodeId ? inlineNodesById.get(nodeId) : void 0;
59440
- if (!inlineNode) return statusNode;
59441
- const liveGit = buildInlineMeshTransitGitStatus(inlineNode);
59442
- if (!liveGit) return statusNode;
59443
- const nextStatus = { ...statusNode };
59444
- nextStatus.git = liveGit;
59445
- nextStatus.health = deriveMeshNodeHealthFromGit(liveGit);
59446
- applyInlineMeshBranchConvergence(mesh, inlineNode, nextStatus);
59447
- nextStatus.launchReady = readBooleanValue(nextStatus.launchReady) ?? true;
59448
- const connection = readObjectRecord(nextStatus.connection);
59449
- const connectionState = readStringValue(connection.state);
59450
- const connectionReported = readBooleanValue(connection.reported) ?? false;
59451
- if (!connectionReported || connectionState === "unknown") {
59452
- nextStatus.connection = buildLivePeerGitConnection(connection);
59453
- }
59454
- delete nextStatus.gitProbePending;
59455
- const error = readStringValue(nextStatus.error);
59456
- if (error && /pending_git|git probe|live peer git snapshot|no peer git snapshot/i.test(error)) delete nextStatus.error;
59457
- if (!readStringValue(nextStatus.machineStatus)) nextStatus.machineStatus = "online";
59458
- if (nodeId) unavailableNodeIds.delete(nodeId);
59459
- changed = true;
59460
- return nextStatus;
59461
- });
59462
- const aggregateDirectTruthSatisfied = sourceOfTruth.coordinatorOwnsLiveTruth === true || directPeerTruth.satisfied === true;
59463
- if (!changed && !(options?.requireDirectPeerTruth && unavailableNodeIds.size > 0 && !aggregateDirectTruthSatisfied)) return snapshot;
59464
- const nextSourceOfTruth = {
59465
- ...sourceOfTruth,
59466
- ...Object.keys(directPeerTruth).length ? {
59467
- directPeerTruth: {
59468
- ...directPeerTruth,
59469
- satisfied: options?.requireDirectPeerTruth === true ? aggregateDirectTruthSatisfied || unavailableNodeIds.size === 0 : directPeerTruth.satisfied,
59470
- unavailableNodeIds: [...unavailableNodeIds]
59471
- },
59472
- ...options?.requireDirectPeerTruth === true ? {
59473
- coordinatorOwnsLiveTruth: aggregateDirectTruthSatisfied || unavailableNodeIds.size === 0,
59474
- currentStatus: aggregateDirectTruthSatisfied || unavailableNodeIds.size === 0 ? "live_git_and_session_probes" : "direct_peer_truth_unavailable"
59475
- } : {}
59476
- } : {}
59477
- };
59478
- return {
59479
- ...snapshot,
59480
- ...options?.requireDirectPeerTruth === true && unavailableNodeIds.size > 0 && !aggregateDirectTruthSatisfied ? {
59481
- success: false,
59482
- code: "mesh_direct_peer_truth_unavailable",
59483
- error: "Selected coordinator could not confirm direct mesh truth for every remote node yet."
59484
- } : {},
59485
- sourceOfTruth: nextSourceOfTruth,
59486
- branchConvergenceSummary: summarizeInlineMeshBranchConvergence(nodes),
59487
- nodes
59488
- };
59761
+ return hydrateCachedAggregateMeshStatusFromInline(this, snapshot, mesh, options);
59489
59762
  }
59490
59763
  getCachedAggregateMeshStatus(meshId, mesh, options) {
59491
- const cached3 = this.aggregateMeshStatusCache.get(meshId);
59492
- if (!cached3?.snapshot || cached3.snapshot.success !== true || !Array.isArray(cached3.snapshot.nodes)) return null;
59493
- if (cached3.queueRevision !== getMeshQueueRevision(meshId)) return null;
59494
- let snapshot = this.cloneJsonValue(cached3.snapshot);
59495
- snapshot = this.hydrateCachedAggregateMeshStatusFromInline(snapshot, mesh, options);
59496
- if (!options?.allowStalePending && shouldRefreshStalePendingAggregate(snapshot, options)) return null;
59497
- const ageMs = Math.max(0, Date.now() - cached3.builtAt);
59498
- const sourceOfTruth = snapshot.sourceOfTruth && typeof snapshot.sourceOfTruth === "object" ? snapshot.sourceOfTruth : {};
59499
- snapshot.sourceOfTruth = {
59500
- ...sourceOfTruth,
59501
- aggregateSnapshot: {
59502
- ...sourceOfTruth.aggregateSnapshot && typeof sourceOfTruth.aggregateSnapshot === "object" ? sourceOfTruth.aggregateSnapshot : {},
59503
- owner: "coordinator_daemon_memory",
59504
- cached: true,
59505
- source: "memory",
59506
- refreshReason: "memory_cache_hit",
59507
- ageMs,
59508
- cachedAt: new Date(cached3.builtAt).toISOString(),
59509
- returnedAt: (/* @__PURE__ */ new Date()).toISOString()
59510
- }
59511
- };
59512
- return snapshot;
59764
+ return getCachedAggregateMeshStatus(this, meshId, mesh, options);
59513
59765
  }
59514
59766
  rememberAggregateMeshStatus(meshId, snapshot, refreshReason) {
59515
- if (!snapshot || typeof snapshot !== "object" || snapshot.success !== true || !Array.isArray(snapshot.nodes)) return snapshot;
59516
- const builtAt = Date.now();
59517
- const next = this.cloneJsonValue(snapshot);
59518
- const sourceOfTruth = next.sourceOfTruth && typeof next.sourceOfTruth === "object" ? next.sourceOfTruth : {};
59519
- next.sourceOfTruth = {
59520
- ...sourceOfTruth,
59521
- aggregateSnapshot: {
59522
- owner: "coordinator_daemon_memory",
59523
- cached: false,
59524
- source: "live_refresh",
59525
- refreshReason,
59526
- ageMs: 0,
59527
- cachedAt: new Date(builtAt).toISOString(),
59528
- returnedAt: new Date(builtAt).toISOString()
59529
- }
59530
- };
59531
- this.aggregateMeshStatusCache.set(meshId, { builtAt, snapshot: this.cloneJsonValue(next), queueRevision: getMeshQueueRevision(meshId) });
59532
- return next;
59767
+ return rememberAggregateMeshStatus(this, meshId, snapshot, refreshReason);
59533
59768
  }
59534
59769
  getCachedInlineMeshNodes() {
59535
59770
  const nodes = [];
@@ -59540,82 +59775,13 @@ var DaemonCommandRouter = class {
59540
59775
  }
59541
59776
  return nodes;
59542
59777
  }
59543
- /**
59544
- * Resolve the REMOTE worker daemonId that owns a given session, when the session
59545
- * belongs to a mesh node hosted on a DIFFERENT daemon than this coordinator.
59546
- *
59547
- * The coordinator does not host remote-worker session instances in its own
59548
- * instanceManager/sessionRegistry — only their cached mesh-node metadata. A
59549
- * dashboard-issued session-scoped command (invoke_provider_script / resolve_action /
59550
- * set_mode / …) lands on the coordinator with a targetSessionId the coordinator can't
59551
- * find locally, and without forwarding it dies as "Live session not found". send_chat
59552
- * happens to survive (its target resolves to the worker by another route), but the
59553
- * controlbar commands do not — so the controlbar buttons appear to do nothing.
59554
- *
59555
- * Mirror the existing node-level remote-forward pattern (fast_forward_mesh_node etc.):
59556
- * scan the candidate mesh nodes for the one hosting the targetSessionId, and return its
59557
- * daemonId when that daemonId is a remote daemon (i.e. not this coordinator's own
59558
- * statusInstanceId). Returns undefined for a locally-hosted session (no forward — execute
59559
- * locally as before) or when ownership can't be resolved.
59560
- *
59561
- * The candidate set spans BOTH the cached inline-mesh nodes and the live aggregate
59562
- * mesh-status snapshots. The inline cache reliably carries only each node's single primary
59563
- * session (cachedStatus.activeSession), so a worker hosting more than one session exposes its
59564
- * non-primary sessions only on the aggregate snapshot nodes (status.activeSessions /
59565
- * activeSessionDetails, built from live session records). collectMeshNodeHostedSessionIds does
59566
- * the wider plural-shape scan so a controlbar/modal command targeting a non-primary remote
59567
- * session still resolves its owner — the singular readCachedInlineMeshActiveSessions semantics
59568
- * other consumers depend on stay untouched.
59569
- *
59570
- * CANCEL-STOP-RELAY: the session-id cache scan above only matches when the coordinator's
59571
- * cached status snapshot already lists the worker's session id in a recognized active-sessions
59572
- * shape. A worktree-clone worker session whose id form/timing differs from the cached snapshot
59573
- * (or is simply not yet reflected) misses the scan, so a stop that carries the authoritative
59574
- * owning nodeId (mesh_queue_cancel knows assignedNodeId) used to silently fail to forward.
59575
- * `ownerNodeIdHint` adds a deterministic fallback: when the session-id scan misses, resolve the
59576
- * owner daemonId by matching the node by id (meshNodeIdMatches — same form-tolerant compare the
59577
- * rest of the router uses, no new raw compare). The same self-loopback guard applies to both
59578
- * paths, so a coordinator-hosted node is still never force-forwarded to a remote form of itself.
59579
- */
59778
+ // ─── Remote mesh-session owner resolution ───────────────────────────
59779
+ // Implementation lives in ./router-mesh-session-owner.ts (behavior-preserving
59780
+ // code move). resolveRemoteMeshSessionOwnerDaemonId stays public (the [Z]
59781
+ // session-scoped forward in executeDaemonCommand and a unit test call it), so
59782
+ // it's kept here as a thin delegator.
59580
59783
  resolveRemoteMeshSessionOwnerDaemonId(sessionId, ownerNodeIdHint) {
59581
- const trimmed = typeof sessionId === "string" ? sessionId.trim() : "";
59582
- const nodeHint = typeof ownerNodeIdHint === "string" ? ownerNodeIdHint.trim() : "";
59583
- if (!trimmed && !nodeHint) return void 0;
59584
- const selfDaemonId = this.deps.statusInstanceId;
59585
- const candidates = this.collectMeshSessionOwnerCandidateNodes();
59586
- if (trimmed) {
59587
- for (const node of candidates) {
59588
- if (!collectMeshNodeHostedSessionIds(node).has(trimmed)) continue;
59589
- const nodeDaemonId = readMeshNodeDaemonId(readObjectRecord(node));
59590
- if (!nodeDaemonId) continue;
59591
- if (selfDaemonId && daemonIdsEquivalent(nodeDaemonId, selfDaemonId)) return void 0;
59592
- return nodeDaemonId;
59593
- }
59594
- }
59595
- if (nodeHint) {
59596
- for (const node of candidates) {
59597
- if (!meshNodeIdMatches(node, nodeHint)) continue;
59598
- const nodeDaemonId = readMeshNodeDaemonId(readObjectRecord(node));
59599
- if (!nodeDaemonId) continue;
59600
- if (selfDaemonId && daemonIdsEquivalent(nodeDaemonId, selfDaemonId)) return void 0;
59601
- return nodeDaemonId;
59602
- }
59603
- }
59604
- return void 0;
59605
- }
59606
- /**
59607
- * Candidate nodes for remote-session owner resolution: the cached inline-mesh nodes (which
59608
- * carry each node's primary session) plus the nodes from every cached aggregate mesh-status
59609
- * snapshot (which carry each node's full live session list). getCachedInlineMeshNodes()
59610
- * returns a fresh array, so appending the aggregate nodes never mutates cached state.
59611
- */
59612
- collectMeshSessionOwnerCandidateNodes() {
59613
- const nodes = this.getCachedInlineMeshNodes();
59614
- for (const cached3 of this.aggregateMeshStatusCache.values()) {
59615
- const snapshotNodes = cached3?.snapshot?.nodes;
59616
- if (Array.isArray(snapshotNodes)) nodes.push(...snapshotNodes);
59617
- }
59618
- return nodes;
59784
+ return resolveRemoteMeshSessionOwnerDaemonId(this, sessionId, ownerNodeIdHint);
59619
59785
  }
59620
59786
  getCachedInlineMesh(meshId, inlineMesh) {
59621
59787
  if (inlineMesh && typeof inlineMesh === "object") {