@adhdev/daemon-core 0.9.82-rc.381 → 0.9.82-rc.383

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
@@ -378,10 +378,10 @@ function readInjected(value) {
378
378
  }
379
379
  function getDaemonBuildInfo() {
380
380
  if (cached) return cached;
381
- const commit = readInjected(true ? "18afac213951f79c502feb6b25b7399fe4d709b3" : void 0) ?? "unknown";
382
- const commitShort = readInjected(true ? "18afac21" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
383
- const version = readInjected(true ? "0.9.82-rc.381" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
384
- const builtAt = readInjected(true ? "2026-06-25T11:44:40.598Z" : void 0);
381
+ const commit = readInjected(true ? "6cca365bcea9757dd350c6bac460ca5a169a9280" : void 0) ?? "unknown";
382
+ const commitShort = readInjected(true ? "6cca365b" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
383
+ const version = readInjected(true ? "0.9.82-rc.383" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
384
+ const builtAt = readInjected(true ? "2026-06-25T15:14:41.579Z" : void 0);
385
385
  cached = builtAt ? { commit, commitShort, version, builtAt } : { commit, commitShort, version };
386
386
  return cached;
387
387
  }
@@ -8574,6 +8574,109 @@ var init_mesh_active_work = __esm({
8574
8574
  }
8575
8575
  });
8576
8576
 
8577
+ // src/mesh/mesh-scheduling-runtime.ts
8578
+ var mesh_scheduling_runtime_exports = {};
8579
+ __export(mesh_scheduling_runtime_exports, {
8580
+ buildMeshSchedulingRuntime: () => buildMeshSchedulingRuntime
8581
+ });
8582
+ function isReadonly(task) {
8583
+ return task.taskMode === "live_debug_readonly";
8584
+ }
8585
+ function isAssigned(task) {
8586
+ return task.status === "assigned";
8587
+ }
8588
+ function buildMeshSchedulingRuntime(mesh, queue) {
8589
+ const strategy = normalizeMeshSchedulingStrategy(mesh?.policy?.schedulingStrategy);
8590
+ const maxParallelTasks = resolveMaxParallelTasks(mesh?.policy?.maxParallelTasks);
8591
+ const maxReadonlyParallelTasks = Math.max(2, maxParallelTasks * 2);
8592
+ const assignedTasks = (Array.isArray(queue) ? queue : []).filter(isAssigned);
8593
+ const activeWriteAssigned = assignedTasks.filter((t) => !isReadonly(t)).length;
8594
+ const activeReadonlyAssigned = assignedTasks.filter(isReadonly).length;
8595
+ const globalWriteCapReached = activeWriteAssigned >= maxParallelTasks;
8596
+ const globalReadonlyCapReached = activeReadonlyAssigned >= maxReadonlyParallelTasks;
8597
+ const writeAssignedByNode = /* @__PURE__ */ new Map();
8598
+ const assignedByNode = /* @__PURE__ */ new Map();
8599
+ const providerCountByNode = /* @__PURE__ */ new Map();
8600
+ for (const task of assignedTasks) {
8601
+ const nodeId = typeof task.assignedNodeId === "string" ? task.assignedNodeId.trim() : "";
8602
+ if (!nodeId) continue;
8603
+ assignedByNode.set(nodeId, (assignedByNode.get(nodeId) ?? 0) + 1);
8604
+ if (!isReadonly(task)) {
8605
+ writeAssignedByNode.set(nodeId, (writeAssignedByNode.get(nodeId) ?? 0) + 1);
8606
+ }
8607
+ const provider = typeof task.assignedProviderType === "string" ? task.assignedProviderType : "";
8608
+ if (provider) {
8609
+ let byProvider = providerCountByNode.get(nodeId);
8610
+ if (!byProvider) {
8611
+ byProvider = /* @__PURE__ */ new Map();
8612
+ providerCountByNode.set(nodeId, byProvider);
8613
+ }
8614
+ byProvider.set(provider, (byProvider.get(provider) ?? 0) + 1);
8615
+ }
8616
+ }
8617
+ const nodes = [];
8618
+ for (const rawNode of Array.isArray(mesh?.nodes) ? mesh.nodes : []) {
8619
+ const nodeId = normalizeMeshNodeId(rawNode);
8620
+ if (!nodeId) continue;
8621
+ const policy = rawNode?.policy || void 0;
8622
+ const load4 = assignedByNode.get(nodeId) ?? 0;
8623
+ const schedulingPriority = resolveNodeSchedulingPriority(policy);
8624
+ const capReasons = [];
8625
+ if (globalWriteCapReached) capReasons.push("global_max_parallel_tasks_reached");
8626
+ if ((writeAssignedByNode.get(nodeId) ?? 0) > 0) capReasons.push("node_has_active_assignment");
8627
+ let providerRoles;
8628
+ const declaredRoles = Array.isArray(policy?.providerRoles) ? policy.providerRoles : [];
8629
+ if (declaredRoles.length) {
8630
+ const byProvider = providerCountByNode.get(nodeId);
8631
+ providerRoles = [];
8632
+ for (const role of declaredRoles) {
8633
+ if (!role || typeof role !== "object") continue;
8634
+ const providerType = typeof role.providerType === "string" ? role.providerType.trim() : "";
8635
+ if (!providerType) continue;
8636
+ const maxParallel = resolveProviderMaxParallel(policy, providerType);
8637
+ const activeAssigned = byProvider?.get(providerType) ?? 0;
8638
+ const capReached = maxParallel !== void 0 && activeAssigned >= maxParallel;
8639
+ providerRoles.push({
8640
+ providerType,
8641
+ ...maxParallel !== void 0 ? { maxParallel } : {},
8642
+ activeAssigned,
8643
+ capReached
8644
+ });
8645
+ if (capReached) capReasons.push(`max_provider_parallel_reached:${providerType}`);
8646
+ }
8647
+ if (!providerRoles.length) providerRoles = void 0;
8648
+ }
8649
+ const maxConcurrentSessions = Number(policy?.maxConcurrentSessions);
8650
+ const hasSessionCap = Number.isFinite(maxConcurrentSessions) && maxConcurrentSessions >= 0;
8651
+ nodes.push({
8652
+ nodeId,
8653
+ load: load4,
8654
+ schedulingPriority,
8655
+ ...hasSessionCap ? { maxConcurrentSessions: Math.floor(maxConcurrentSessions) } : {},
8656
+ ...providerRoles ? { providerRoles } : {},
8657
+ capReached: capReasons.length > 0,
8658
+ capReasons
8659
+ });
8660
+ }
8661
+ return {
8662
+ strategy,
8663
+ maxParallelTasks,
8664
+ maxReadonlyParallelTasks,
8665
+ activeWriteAssigned,
8666
+ activeReadonlyAssigned,
8667
+ globalWriteCapReached,
8668
+ globalReadonlyCapReached,
8669
+ nodes
8670
+ };
8671
+ }
8672
+ var init_mesh_scheduling_runtime = __esm({
8673
+ "src/mesh/mesh-scheduling-runtime.ts"() {
8674
+ "use strict";
8675
+ init_repo_mesh_types();
8676
+ init_dist();
8677
+ }
8678
+ });
8679
+
8577
8680
  // src/mesh/mesh-events-utils.ts
8578
8681
  function readNonEmptyString2(value) {
8579
8682
  return typeof value === "string" && value.trim() ? value.trim() : "";
@@ -13805,6 +13908,20 @@ function recoverMeshIdByNodeId(nodeId) {
13805
13908
  }
13806
13909
  return "";
13807
13910
  }
13911
+ function recoverMeshIdByCoordinatorAndNode(coordinatorDaemonId, nodeId) {
13912
+ if (!coordinatorDaemonId) return "";
13913
+ const hosted = listMeshes().filter((mesh) => {
13914
+ const host = resolveMeshHostStatus(mesh);
13915
+ return host.role === "host" && (!host.hostDaemonId || daemonIdsEquivalent(host.hostDaemonId, coordinatorDaemonId));
13916
+ });
13917
+ if (hosted.length === 0) return "";
13918
+ if (nodeId) {
13919
+ const byNode = hosted.find((mesh) => Array.isArray(mesh.nodes) && mesh.nodes.some((n) => meshNodeIdMatches(n, nodeId)));
13920
+ if (byNode) return readNonEmptyString2(byNode.id);
13921
+ return "";
13922
+ }
13923
+ return hosted.length === 1 ? readNonEmptyString2(hosted[0].id) : "";
13924
+ }
13808
13925
  function resolveForwardEventMeshId(components, payload) {
13809
13926
  const direct = readNonEmptyString2(payload.meshId);
13810
13927
  if (direct) return direct;
@@ -14551,7 +14668,10 @@ function handleMeshForwardEvent(components, payload) {
14551
14668
  }
14552
14669
  const nodeId = readNonEmptyString2(payload.nodeId);
14553
14670
  const workspace = readNonEmptyString2(payload.workspace);
14554
- const meshId = readNonEmptyString2(payload.meshId) || (workspace ? readNonEmptyString2(getCachedMeshByWorkspace(workspace)?.id) : "") || recoverMeshIdByNodeId(nodeId);
14671
+ const meshId = readNonEmptyString2(payload.meshId) || (workspace ? readNonEmptyString2(getCachedMeshByWorkspace(workspace)?.id) : "") || recoverMeshIdByNodeId(nodeId) || recoverMeshIdByCoordinatorAndNode(
14672
+ readNonEmptyString2(payload.meshCoordinatorDaemonId) || readNonEmptyString2(payload.coordinatorDaemonId),
14673
+ nodeId
14674
+ );
14555
14675
  if (!meshId) {
14556
14676
  traceMeshEventDrop("meshId_required", {
14557
14677
  taskId: payload.taskId,
@@ -14606,7 +14726,12 @@ function forwardUnresolvedDelegateEvent(components, routing, event) {
14606
14726
  ...event,
14607
14727
  event: eventName,
14608
14728
  nodeId: readNonEmptyString2(routing.nodeId) || readNonEmptyString2(event.meshNodeId) || void 0,
14609
- workspace: readNonEmptyString2(routing.workspace) || readNonEmptyString2(event.workspace) || void 0
14729
+ workspace: readNonEmptyString2(routing.workspace) || readNonEmptyString2(event.workspace) || void 0,
14730
+ // Fix B: carry the resolved coordinator anchor so the coordinator's receive-side
14731
+ // recovery (recoverMeshIdByCoordinatorAndNode) can match this forward to one of the
14732
+ // meshes it hosts when workspace + nodeId both miss. routing.coordinatorDaemonId is
14733
+ // the same anchor this forward is addressed to (coordinatorDaemonId below).
14734
+ meshCoordinatorDaemonId: coordinatorDaemonId
14610
14735
  };
14611
14736
  const resolvedMeshId = resolveForwardEventMeshId(components, payload);
14612
14737
  if (resolvedMeshId) payload.meshId = resolvedMeshId;
@@ -14735,6 +14860,7 @@ var init_mesh_event_forwarding = __esm({
14735
14860
  init_mesh_runtime_store();
14736
14861
  init_mesh_events_pending();
14737
14862
  init_mesh_routing();
14863
+ init_mesh_host_ownership();
14738
14864
  init_mesh_unresolved_forward_outbox();
14739
14865
  init_mesh_event_trace();
14740
14866
  init_snapshot();
@@ -15026,8 +15152,7 @@ async function runMeshReconcileTick(components) {
15026
15152
  const idleCoordinators = meshCoordinators.filter((c) => c.idle);
15027
15153
  const generatingCoordinators = meshCoordinators.filter((c) => !c.idle && !c.modalParked);
15028
15154
  const modalParkedCoordinators = meshCoordinators.filter((c) => !c.idle && c.modalParked);
15029
- const targetCoordinators = idleCoordinators.length > 0 ? idleCoordinators : generatingCoordinators;
15030
- const forceOnly = idleCoordinators.length === 0;
15155
+ const targetCoordinators = idleCoordinators;
15031
15156
  if (targetCoordinators.length === 0) {
15032
15157
  if (modalParkedCoordinators.length > 0) {
15033
15158
  const liveSessionIds = new Set(
@@ -15094,6 +15219,23 @@ async function runMeshReconcileTick(components) {
15094
15219
  modalParkedCoordinators.length
15095
15220
  );
15096
15221
  }
15222
+ } else if (generatingCoordinators.length > 0) {
15223
+ let hasPending = true;
15224
+ if (store) {
15225
+ try {
15226
+ hasPending = store.pendingEventCount(meshId) > 0;
15227
+ } catch {
15228
+ }
15229
+ }
15230
+ if (hasPending) {
15231
+ LOG.info("MeshReconcile", `Reconcile skip \u2192 generating: holding pending event(s) for mesh ${meshId} (${generatingCoordinators.length} coordinator(s) busy; events left queued for the next idle tick)`);
15232
+ recordHeldTerminalEventsToLedger(
15233
+ meshId,
15234
+ drainDaemonIds.length > 0 ? drainDaemonIds : localDaemonId ? [localDaemonId] : [],
15235
+ "generating_no_idle_coordinator",
15236
+ generatingCoordinators.length
15237
+ );
15238
+ }
15097
15239
  }
15098
15240
  continue;
15099
15241
  }
@@ -15107,16 +15249,14 @@ async function runMeshReconcileTick(components) {
15107
15249
  try {
15108
15250
  pendingEvents = drainPendingMeshCoordinatorEvents(
15109
15251
  meshId,
15110
- drainDaemonIds.length > 0 ? drainDaemonIds : localDaemonId,
15111
- forceOnly ? { onlyEvents: MESH_FORCE_INJECT_EVENTS } : void 0
15252
+ drainDaemonIds.length > 0 ? drainDaemonIds : localDaemonId
15112
15253
  );
15113
15254
  } catch (e) {
15114
15255
  LOG.warn("MeshReconcile", `Drain failed for mesh ${meshId}: ${e?.message || e}`);
15115
15256
  continue;
15116
15257
  }
15117
15258
  if (pendingEvents.length === 0) continue;
15118
- const mode = forceOnly ? "force-drain \u2192 generating" : "inject \u2192 idle";
15119
- LOG.info("MeshReconcile", `Reconcile ${mode}: ${pendingEvents.length} pending event(s) \u2192 ${targetCoordinators.length} coordinator(s) for mesh ${meshId}`);
15259
+ LOG.info("MeshReconcile", `Reconcile inject \u2192 idle: ${pendingEvents.length} pending event(s) \u2192 ${targetCoordinators.length} coordinator(s) for mesh ${meshId}`);
15120
15260
  for (const pending of pendingEvents) {
15121
15261
  const wantSession = readNonEmptyString2(pending.targetCoordinatorSessionId);
15122
15262
  if (wantSession) {
@@ -22974,102 +23114,7 @@ function buildMeshLedgerReconciliationEvidence(meshId, replicas) {
22974
23114
  init_mesh_work_queue();
22975
23115
  init_mesh_active_work();
22976
23116
  init_mesh_refine_status();
22977
-
22978
- // src/mesh/mesh-scheduling-runtime.ts
22979
- init_repo_mesh_types();
22980
- init_dist();
22981
- function isReadonly(task) {
22982
- return task.taskMode === "live_debug_readonly";
22983
- }
22984
- function isAssigned(task) {
22985
- return task.status === "assigned";
22986
- }
22987
- function buildMeshSchedulingRuntime(mesh, queue) {
22988
- const strategy = normalizeMeshSchedulingStrategy(mesh?.policy?.schedulingStrategy);
22989
- const maxParallelTasks = resolveMaxParallelTasks(mesh?.policy?.maxParallelTasks);
22990
- const maxReadonlyParallelTasks = Math.max(2, maxParallelTasks * 2);
22991
- const assignedTasks = (Array.isArray(queue) ? queue : []).filter(isAssigned);
22992
- const activeWriteAssigned = assignedTasks.filter((t) => !isReadonly(t)).length;
22993
- const activeReadonlyAssigned = assignedTasks.filter(isReadonly).length;
22994
- const globalWriteCapReached = activeWriteAssigned >= maxParallelTasks;
22995
- const globalReadonlyCapReached = activeReadonlyAssigned >= maxReadonlyParallelTasks;
22996
- const writeAssignedByNode = /* @__PURE__ */ new Map();
22997
- const assignedByNode = /* @__PURE__ */ new Map();
22998
- const providerCountByNode = /* @__PURE__ */ new Map();
22999
- for (const task of assignedTasks) {
23000
- const nodeId = typeof task.assignedNodeId === "string" ? task.assignedNodeId.trim() : "";
23001
- if (!nodeId) continue;
23002
- assignedByNode.set(nodeId, (assignedByNode.get(nodeId) ?? 0) + 1);
23003
- if (!isReadonly(task)) {
23004
- writeAssignedByNode.set(nodeId, (writeAssignedByNode.get(nodeId) ?? 0) + 1);
23005
- }
23006
- const provider = typeof task.assignedProviderType === "string" ? task.assignedProviderType : "";
23007
- if (provider) {
23008
- let byProvider = providerCountByNode.get(nodeId);
23009
- if (!byProvider) {
23010
- byProvider = /* @__PURE__ */ new Map();
23011
- providerCountByNode.set(nodeId, byProvider);
23012
- }
23013
- byProvider.set(provider, (byProvider.get(provider) ?? 0) + 1);
23014
- }
23015
- }
23016
- const nodes = [];
23017
- for (const rawNode of Array.isArray(mesh?.nodes) ? mesh.nodes : []) {
23018
- const nodeId = normalizeMeshNodeId(rawNode);
23019
- if (!nodeId) continue;
23020
- const policy = rawNode?.policy || void 0;
23021
- const load4 = assignedByNode.get(nodeId) ?? 0;
23022
- const schedulingPriority = resolveNodeSchedulingPriority(policy);
23023
- const capReasons = [];
23024
- if (globalWriteCapReached) capReasons.push("global_max_parallel_tasks_reached");
23025
- if ((writeAssignedByNode.get(nodeId) ?? 0) > 0) capReasons.push("node_has_active_assignment");
23026
- let providerRoles;
23027
- const declaredRoles = Array.isArray(policy?.providerRoles) ? policy.providerRoles : [];
23028
- if (declaredRoles.length) {
23029
- const byProvider = providerCountByNode.get(nodeId);
23030
- providerRoles = [];
23031
- for (const role of declaredRoles) {
23032
- if (!role || typeof role !== "object") continue;
23033
- const providerType = typeof role.providerType === "string" ? role.providerType.trim() : "";
23034
- if (!providerType) continue;
23035
- const maxParallel = resolveProviderMaxParallel(policy, providerType);
23036
- const activeAssigned = byProvider?.get(providerType) ?? 0;
23037
- const capReached = maxParallel !== void 0 && activeAssigned >= maxParallel;
23038
- providerRoles.push({
23039
- providerType,
23040
- ...maxParallel !== void 0 ? { maxParallel } : {},
23041
- activeAssigned,
23042
- capReached
23043
- });
23044
- if (capReached) capReasons.push(`max_provider_parallel_reached:${providerType}`);
23045
- }
23046
- if (!providerRoles.length) providerRoles = void 0;
23047
- }
23048
- const maxConcurrentSessions = Number(policy?.maxConcurrentSessions);
23049
- const hasSessionCap = Number.isFinite(maxConcurrentSessions) && maxConcurrentSessions >= 0;
23050
- nodes.push({
23051
- nodeId,
23052
- load: load4,
23053
- schedulingPriority,
23054
- ...hasSessionCap ? { maxConcurrentSessions: Math.floor(maxConcurrentSessions) } : {},
23055
- ...providerRoles ? { providerRoles } : {},
23056
- capReached: capReasons.length > 0,
23057
- capReasons
23058
- });
23059
- }
23060
- return {
23061
- strategy,
23062
- maxParallelTasks,
23063
- maxReadonlyParallelTasks,
23064
- activeWriteAssigned,
23065
- activeReadonlyAssigned,
23066
- globalWriteCapReached,
23067
- globalReadonlyCapReached,
23068
- nodes
23069
- };
23070
- }
23071
-
23072
- // src/index.ts
23117
+ init_mesh_scheduling_runtime();
23073
23118
  init_mesh_host_ownership();
23074
23119
  init_mesh_events();
23075
23120
  init_mesh_events_utils();
@@ -38852,9 +38897,35 @@ var CliProviderInstance = class _CliProviderInstance {
38852
38897
  * terminal state. Leaving meshNodeFor pinned would route this session's
38853
38898
  * subsequent unrelated turns (e.g. ad-hoc dashboard chats) to the
38854
38899
  * coordinator as if they were task completions.
38900
+ *
38901
+ * MESHID-DROP-ON-DETACH (Fix C): a coordinator-LAUNCHED worker session
38902
+ * (launchedByCoordinator) holds its mesh membership (meshNodeFor / meshNodeId /
38903
+ * meshCoordinatorDaemonId) at the SESSION level — set once at launch
38904
+ * (mesh_launch_session / queue auto-launch), independent of any single task.
38905
+ * The original detach wiped meshNodeFor + meshNodeId together with the
38906
+ * task-level meshActiveTaskId, so the FIRST task completion stripped the
38907
+ * membership and EVERY subsequent completion forwarded with meshId absent —
38908
+ * resolveWorkerDelegateRouting fell to mesh_unresolved and the coordinator
38909
+ * rejected the forward "meshId required". For a launched member we therefore
38910
+ * clear ONLY the task-level marker (meshActiveTaskId) and preserve the
38911
+ * session-level membership so its next task's completion still resolves.
38912
+ * A task-less ad-hoc turn on a preserved-membership session is NOT misrouted:
38913
+ * its completion carries no taskId and the session holds no active assignment,
38914
+ * so the forwarder's WARMUPGAP guard skips the dispatch-row flip (it only
38915
+ * injects a benign task-less notification). A NON-launched session (a plain CLI
38916
+ * session adopted by mesh_send_task --direct, launchedByCoordinator falsy)
38917
+ * keeps the original full clear so an ad-hoc session is never left pinned.
38855
38918
  */
38856
38919
  detachMeshAssignment() {
38857
38920
  if (!this.settings.meshNodeFor && !this.settings.meshActiveTaskId && !this.settings.meshNodeId) return;
38921
+ if (this.settings.launchedByCoordinator === true) {
38922
+ if (!this.settings.meshActiveTaskId) return;
38923
+ const { meshActiveTaskId: meshActiveTaskId2, ...rest2 } = this.settings;
38924
+ void meshActiveTaskId2;
38925
+ this.settings = rest2;
38926
+ this.adapter.updateRuntimeSettings?.(this.settings);
38927
+ return;
38928
+ }
38858
38929
  const { meshNodeFor, meshNodeId, meshActiveTaskId, ...rest } = this.settings;
38859
38930
  void meshNodeFor;
38860
38931
  void meshActiveTaskId;
@@ -48728,6 +48799,9 @@ var meshStatusHandlers = {
48728
48799
  const { getMeshQueueStats: getMeshQueueStats2, getQueue: getQueue2 } = await Promise.resolve().then(() => (init_mesh_work_queue(), mesh_work_queue_exports));
48729
48800
  const queue = getQueue2(meshId);
48730
48801
  const queueSummary = getMeshQueueStats2(meshId);
48802
+ const { buildMeshSchedulingRuntime: buildMeshSchedulingRuntime2 } = await Promise.resolve().then(() => (init_mesh_scheduling_runtime(), mesh_scheduling_runtime_exports));
48803
+ const schedulingRuntime = buildMeshSchedulingRuntime2(mesh, queue);
48804
+ const schedulingByNode = new Map(schedulingRuntime.nodes.map((n) => [n.nodeId, n]));
48731
48805
  const { readLedgerEntries: readLedgerEntries2, getLedgerSummary: getLedgerSummary2 } = await Promise.resolve().then(() => (init_mesh_ledger(), mesh_ledger_exports));
48732
48806
  const ledgerEntries = readLedgerEntries2(meshId, { tail: 20 });
48733
48807
  const asyncRefineLedgerEntries = readLedgerEntries2(meshId, { tail: 100 });
@@ -48842,6 +48916,11 @@ var meshStatusHandlers = {
48842
48916
  activeSessionDetails: [],
48843
48917
  launchReady: false
48844
48918
  };
48919
+ const nodeScheduling = schedulingByNode.get(nodeId);
48920
+ if (nodeScheduling) {
48921
+ const { nodeId: _omitNodeId, ...nodeSchedulingRest } = nodeScheduling;
48922
+ status.scheduling = nodeSchedulingRest;
48923
+ }
48845
48924
  if (isSelfNode) {
48846
48925
  status.connection = {
48847
48926
  perspective: "selected_coordinator",
@@ -49042,6 +49121,19 @@ var meshStatusHandlers = {
49042
49121
  branchConvergenceSummary: summarizeInlineMeshBranchConvergence(nodeStatuses),
49043
49122
  ...previewFreshness ? { previewFreshness, deployFreshness: previewFreshness } : {},
49044
49123
  nodes: nodeStatuses,
49124
+ // Mesh-level scheduling rollup (strategy + global cap consumption). Mirrors
49125
+ // the MCP `mesh_status` tool's `scheduling` block field-for-field so both
49126
+ // surfaces read the same runtime; per-node detail lives on each
49127
+ // nodes[].scheduling above.
49128
+ scheduling: {
49129
+ strategy: schedulingRuntime.strategy,
49130
+ maxParallelTasks: schedulingRuntime.maxParallelTasks,
49131
+ maxReadonlyParallelTasks: schedulingRuntime.maxReadonlyParallelTasks,
49132
+ activeWriteAssigned: schedulingRuntime.activeWriteAssigned,
49133
+ activeReadonlyAssigned: schedulingRuntime.activeReadonlyAssigned,
49134
+ globalWriteCapReached: schedulingRuntime.globalWriteCapReached,
49135
+ globalReadonlyCapReached: schedulingRuntime.globalReadonlyCapReached
49136
+ },
49045
49137
  queue: { tasks: queue, summary: queueSummary },
49046
49138
  ledger: { entries: ledgerEntries, summary: ledgerSummary },
49047
49139
  ...missions.length > 0 ? { missions } : {},
@@ -51986,17 +52078,40 @@ var DaemonCommandRouter = class {
51986
52078
  * the wider plural-shape scan so a controlbar/modal command targeting a non-primary remote
51987
52079
  * session still resolves its owner — the singular readCachedInlineMeshActiveSessions semantics
51988
52080
  * other consumers depend on stay untouched.
52081
+ *
52082
+ * CANCEL-STOP-RELAY: the session-id cache scan above only matches when the coordinator's
52083
+ * cached status snapshot already lists the worker's session id in a recognized active-sessions
52084
+ * shape. A worktree-clone worker session whose id form/timing differs from the cached snapshot
52085
+ * (or is simply not yet reflected) misses the scan, so a stop that carries the authoritative
52086
+ * owning nodeId (mesh_queue_cancel knows assignedNodeId) used to silently fail to forward.
52087
+ * `ownerNodeIdHint` adds a deterministic fallback: when the session-id scan misses, resolve the
52088
+ * owner daemonId by matching the node by id (meshNodeIdMatches — same form-tolerant compare the
52089
+ * rest of the router uses, no new raw compare). The same self-loopback guard applies to both
52090
+ * paths, so a coordinator-hosted node is still never force-forwarded to a remote form of itself.
51989
52091
  */
51990
- resolveRemoteMeshSessionOwnerDaemonId(sessionId) {
52092
+ resolveRemoteMeshSessionOwnerDaemonId(sessionId, ownerNodeIdHint) {
51991
52093
  const trimmed = typeof sessionId === "string" ? sessionId.trim() : "";
51992
- if (!trimmed) return void 0;
52094
+ const nodeHint = typeof ownerNodeIdHint === "string" ? ownerNodeIdHint.trim() : "";
52095
+ if (!trimmed && !nodeHint) return void 0;
51993
52096
  const selfDaemonId = this.deps.statusInstanceId;
51994
- for (const node of this.collectMeshSessionOwnerCandidateNodes()) {
51995
- if (!collectMeshNodeHostedSessionIds(node).has(trimmed)) continue;
51996
- const nodeDaemonId = readMeshNodeDaemonId(readObjectRecord(node));
51997
- if (!nodeDaemonId) continue;
51998
- if (selfDaemonId && daemonIdsEquivalent(nodeDaemonId, selfDaemonId)) return void 0;
51999
- return nodeDaemonId;
52097
+ const candidates = this.collectMeshSessionOwnerCandidateNodes();
52098
+ if (trimmed) {
52099
+ for (const node of candidates) {
52100
+ if (!collectMeshNodeHostedSessionIds(node).has(trimmed)) continue;
52101
+ const nodeDaemonId = readMeshNodeDaemonId(readObjectRecord(node));
52102
+ if (!nodeDaemonId) continue;
52103
+ if (selfDaemonId && daemonIdsEquivalent(nodeDaemonId, selfDaemonId)) return void 0;
52104
+ return nodeDaemonId;
52105
+ }
52106
+ }
52107
+ if (nodeHint) {
52108
+ for (const node of candidates) {
52109
+ if (!meshNodeIdMatches(node, nodeHint)) continue;
52110
+ const nodeDaemonId = readMeshNodeDaemonId(readObjectRecord(node));
52111
+ if (!nodeDaemonId) continue;
52112
+ if (selfDaemonId && daemonIdsEquivalent(nodeDaemonId, selfDaemonId)) return void 0;
52113
+ return nodeDaemonId;
52114
+ }
52000
52115
  }
52001
52116
  return void 0;
52002
52117
  }
@@ -54130,7 +54245,9 @@ ${hintLines.join("\n")}` : "",
54130
54245
  const localInstance = this.deps.instanceManager?.getInstance(targetSessionId);
54131
54246
  const localRegistry = this.deps.sessionRegistry?.get?.(targetSessionId);
54132
54247
  if (!localInstance && !localRegistry) {
54133
- const ownerDaemonId = this.resolveRemoteMeshSessionOwnerDaemonId(targetSessionId);
54248
+ const meshContext = readObjectRecord(args?.meshContext);
54249
+ const ownerNodeIdHint = readStringValue(meshContext.nodeId);
54250
+ const ownerDaemonId = this.resolveRemoteMeshSessionOwnerDaemonId(targetSessionId, ownerNodeIdHint);
54134
54251
  if (ownerDaemonId) {
54135
54252
  LOG.info("Mesh", `[Mesh] Forwarding session-scoped '${cmd}' for remote worker session ${targetSessionId.split("_")[0]} \u2192 daemon ${ownerDaemonId.slice(0, 12)}`);
54136
54253
  const forwarded = await this.deps.dispatchMeshCommand(ownerDaemonId, cmd, {