@adhdev/daemon-core 0.9.82-rc.380 → 0.9.82-rc.382

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
@@ -38,6 +38,56 @@ function resolveNodeSchedulingPriority(nodePolicy) {
38
38
  function resolveAutoConvergeCodeChange(policy) {
39
39
  return policy?.autoConvergeCodeChange === true;
40
40
  }
41
+ function resolveMaxParallelTasks(value) {
42
+ const n = Number(value);
43
+ if (!Number.isFinite(n)) return DEFAULT_MESH_POLICY.maxParallelTasks;
44
+ return Math.max(MESH_MAX_PARALLEL_TASKS_MIN, Math.min(MESH_MAX_PARALLEL_TASKS_MAX, Math.floor(n)));
45
+ }
46
+ function normalizeAutoFastForwardPolicy(value) {
47
+ const record = value && typeof value === "object" && !Array.isArray(value) ? value : {};
48
+ const maxBehind = Number(record.maxBehind);
49
+ return {
50
+ enabled: record.enabled !== false,
51
+ ...Number.isFinite(maxBehind) && maxBehind >= 0 ? { maxBehind: Math.floor(maxBehind) } : {},
52
+ requireCleanSubmodules: record.requireCleanSubmodules !== false
53
+ };
54
+ }
55
+ function mergeAndNormalizePolicy(base, patch) {
56
+ const autoFastForward = normalizeAutoFastForwardPolicy({
57
+ ...DEFAULT_MESH_POLICY.autoFastForward,
58
+ ...base?.autoFastForward && typeof base.autoFastForward === "object" ? base.autoFastForward : {},
59
+ ...patch?.autoFastForward && typeof patch.autoFastForward === "object" ? patch.autoFastForward : {}
60
+ });
61
+ const policy = {
62
+ ...DEFAULT_MESH_POLICY,
63
+ ...base || {},
64
+ ...patch || {},
65
+ autoFastForward
66
+ };
67
+ if (!DIRTY_WORKSPACE_BEHAVIORS.has(policy.dirtyWorkspaceBehavior)) {
68
+ policy.dirtyWorkspaceBehavior = "warn";
69
+ }
70
+ policy.maxParallelTasks = resolveMaxParallelTasks(policy.maxParallelTasks);
71
+ policy.allowAutoPublishSubmoduleMainCommits = policy.allowAutoPublishSubmoduleMainCommits === true;
72
+ if (!SESSION_CLEANUP_MODES.has(policy.sessionCleanupOnNodeRemove)) {
73
+ policy.sessionCleanupOnNodeRemove = "preserve";
74
+ }
75
+ if (!SPAWNED_SESSION_VISIBILITY_MODES.has(policy.spawnedSessionVisibility)) {
76
+ policy.spawnedSessionVisibility = DEFAULT_MESH_POLICY.spawnedSessionVisibility;
77
+ }
78
+ const normalizedStrategy = normalizeMeshSchedulingStrategy(policy.schedulingStrategy);
79
+ if (normalizedStrategy === "first_eligible") {
80
+ delete policy.schedulingStrategy;
81
+ } else {
82
+ policy.schedulingStrategy = normalizedStrategy;
83
+ }
84
+ if (policy.autoConvergeCodeChange === true) {
85
+ policy.autoConvergeCodeChange = true;
86
+ } else {
87
+ delete policy.autoConvergeCodeChange;
88
+ }
89
+ return policy;
90
+ }
41
91
  function resolveDelegatedWorkerAutoApprove(meshPolicy, nodePolicy) {
42
92
  if (typeof nodePolicy?.delegatedWorkerAutoApprove === "boolean") {
43
93
  return nodePolicy.delegatedWorkerAutoApprove;
@@ -62,7 +112,7 @@ function resolveProviderMaxParallel(nodePolicy, providerType) {
62
112
  }
63
113
  return void 0;
64
114
  }
65
- var MESH_SCHEDULING_STRATEGIES, DEFAULT_MESH_SCHEDULING_STRATEGY, MESH_CONVERGE_REFINE_TAG, MESH_CONVERGE_FAST_FORWARD_TAG, DEFAULT_MESH_POLICY;
115
+ var MESH_SCHEDULING_STRATEGIES, DEFAULT_MESH_SCHEDULING_STRATEGY, MESH_CONVERGE_REFINE_TAG, MESH_CONVERGE_FAST_FORWARD_TAG, DEFAULT_MESH_POLICY, SESSION_CLEANUP_MODES, SPAWNED_SESSION_VISIBILITY_MODES, DIRTY_WORKSPACE_BEHAVIORS, MESH_MAX_PARALLEL_TASKS_MIN, MESH_MAX_PARALLEL_TASKS_MAX;
66
116
  var init_repo_mesh_types = __esm({
67
117
  "src/repo-mesh-types.ts"() {
68
118
  "use strict";
@@ -92,6 +142,23 @@ var init_repo_mesh_types = __esm({
92
142
  autoFastForward: { enabled: true },
93
143
  maxTaskRetries: 1
94
144
  };
145
+ SESSION_CLEANUP_MODES = /* @__PURE__ */ new Set([
146
+ "preserve",
147
+ "stop",
148
+ "delete_stopped",
149
+ "stop_and_delete"
150
+ ]);
151
+ SPAWNED_SESSION_VISIBILITY_MODES = /* @__PURE__ */ new Set([
152
+ "visible",
153
+ "hidden"
154
+ ]);
155
+ DIRTY_WORKSPACE_BEHAVIORS = /* @__PURE__ */ new Set([
156
+ "block",
157
+ "warn",
158
+ "checkpoint_then_continue"
159
+ ]);
160
+ MESH_MAX_PARALLEL_TASKS_MIN = 1;
161
+ MESH_MAX_PARALLEL_TASKS_MAX = 8;
95
162
  }
96
163
  });
97
164
 
@@ -311,10 +378,10 @@ function readInjected(value) {
311
378
  }
312
379
  function getDaemonBuildInfo() {
313
380
  if (cached) return cached;
314
- const commit = readInjected(true ? "5fff0bee3f6a8e8f00989177c53d1d2a1cf607ad" : void 0) ?? "unknown";
315
- const commitShort = readInjected(true ? "5fff0bee" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
316
- const version = readInjected(true ? "0.9.82-rc.380" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
317
- const builtAt = readInjected(true ? "2026-06-25T10:07:36.562Z" : void 0);
381
+ const commit = readInjected(true ? "70741c4fe19c6f71bcef702e7e149d963d6fd916" : void 0) ?? "unknown";
382
+ const commitShort = readInjected(true ? "70741c4f" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
383
+ const version = readInjected(true ? "0.9.82-rc.382" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
384
+ const builtAt = readInjected(true ? "2026-06-25T13:31:28.133Z" : void 0);
318
385
  cached = builtAt ? { commit, commitShort, version, builtAt } : { commit, commitShort, version };
319
386
  return cached;
320
387
  }
@@ -2366,52 +2433,6 @@ function normalizeRepoIdentity(remoteUrl) {
2366
2433
  if (sshMatch) return `${sshMatch[1]}/${sshMatch[2]}`;
2367
2434
  return identity;
2368
2435
  }
2369
- function mergeMeshPolicy(base, patch) {
2370
- const autoFastForward = normalizeAutoFastForwardPolicy({
2371
- ...DEFAULT_MESH_POLICY.autoFastForward,
2372
- ...base?.autoFastForward && typeof base.autoFastForward === "object" ? base.autoFastForward : {},
2373
- ...patch?.autoFastForward && typeof patch.autoFastForward === "object" ? patch.autoFastForward : {}
2374
- });
2375
- const policy = {
2376
- ...DEFAULT_MESH_POLICY,
2377
- ...base || {},
2378
- ...patch || {},
2379
- autoFastForward
2380
- };
2381
- if (!["block", "warn", "checkpoint_then_continue"].includes(policy.dirtyWorkspaceBehavior)) {
2382
- policy.dirtyWorkspaceBehavior = "warn";
2383
- }
2384
- const maxParallelTasks = Number(policy.maxParallelTasks);
2385
- policy.maxParallelTasks = Number.isFinite(maxParallelTasks) ? Math.max(1, Math.min(8, Math.floor(maxParallelTasks))) : 2;
2386
- policy.allowAutoPublishSubmoduleMainCommits = policy.allowAutoPublishSubmoduleMainCommits === true;
2387
- if (!SESSION_CLEANUP_MODES.has(String(policy.sessionCleanupOnNodeRemove))) {
2388
- policy.sessionCleanupOnNodeRemove = "preserve";
2389
- }
2390
- if (!SPAWNED_SESSION_VISIBILITY_MODES.has(String(policy.spawnedSessionVisibility))) {
2391
- policy.spawnedSessionVisibility = DEFAULT_MESH_POLICY.spawnedSessionVisibility;
2392
- }
2393
- const normalizedStrategy = normalizeMeshSchedulingStrategy(policy.schedulingStrategy);
2394
- if (normalizedStrategy === "first_eligible") {
2395
- delete policy.schedulingStrategy;
2396
- } else {
2397
- policy.schedulingStrategy = normalizedStrategy;
2398
- }
2399
- if (policy.autoConvergeCodeChange === true) {
2400
- policy.autoConvergeCodeChange = true;
2401
- } else {
2402
- delete policy.autoConvergeCodeChange;
2403
- }
2404
- return policy;
2405
- }
2406
- function normalizeAutoFastForwardPolicy(value) {
2407
- const record = value && typeof value === "object" && !Array.isArray(value) ? value : {};
2408
- const maxBehind = Number(record.maxBehind);
2409
- return {
2410
- enabled: record.enabled !== false,
2411
- ...Number.isFinite(maxBehind) && maxBehind >= 0 ? { maxBehind: Math.floor(maxBehind) } : {},
2412
- requireCleanSubmodules: record.requireCleanSubmodules !== false
2413
- };
2414
- }
2415
2436
  function listMeshes() {
2416
2437
  return loadMeshConfig().meshes;
2417
2438
  }
@@ -2710,7 +2731,7 @@ function updateNode(meshId, nodeId, opts) {
2710
2731
  saveMeshConfig(config);
2711
2732
  return node;
2712
2733
  }
2713
- var SESSION_CLEANUP_MODES, SPAWNED_SESSION_VISIBILITY_MODES;
2734
+ var mergeMeshPolicy;
2714
2735
  var init_mesh_config = __esm({
2715
2736
  "src/config/mesh-config.ts"() {
2716
2737
  "use strict";
@@ -2718,8 +2739,7 @@ var init_mesh_config = __esm({
2718
2739
  init_config();
2719
2740
  init_repo_mesh_types();
2720
2741
  init_mesh_host_ownership();
2721
- SESSION_CLEANUP_MODES = /* @__PURE__ */ new Set(["preserve", "stop", "delete_stopped", "stop_and_delete"]);
2722
- SPAWNED_SESSION_VISIBILITY_MODES = /* @__PURE__ */ new Set(["visible", "hidden"]);
2742
+ mergeMeshPolicy = mergeAndNormalizePolicy;
2723
2743
  }
2724
2744
  });
2725
2745
 
@@ -3043,7 +3063,7 @@ Default branch: \`${mesh.defaultBranch}\`` : ""}`);
3043
3063
  if (recentActivity) sections.push(recentActivity);
3044
3064
  const operatingNotes = buildOperatingNotesSection(ctx.operatingNotes);
3045
3065
  if (operatingNotes) sections.push(operatingNotes);
3046
- sections.push(buildPolicySection({ ...DEFAULT_MESH_POLICY, ...mesh.policy || {} }));
3066
+ sections.push(buildPolicySection(mergeAndNormalizePolicy(void 0, mesh.policy)));
3047
3067
  sections.push(TOOLS_SECTION);
3048
3068
  sections.push(TOOL_EXPOSURE_PREFLIGHT_SECTION);
3049
3069
  sections.push(WORKFLOW_SECTION);
@@ -3076,7 +3096,7 @@ function expandPromptPlaceholders(template, ctx) {
3076
3096
  mission: ctx.missionSection?.trim() || "",
3077
3097
  recentActivity: buildRecentActivitySection(ctx.recentActivity) || "",
3078
3098
  operatingNotes: buildOperatingNotesSection(ctx.operatingNotes) || "",
3079
- policy: buildPolicySection({ ...DEFAULT_MESH_POLICY, ...mesh.policy || {} }),
3099
+ policy: buildPolicySection(mergeAndNormalizePolicy(void 0, mesh.policy)),
3080
3100
  tools: TOOLS_SECTION,
3081
3101
  workflow: WORKFLOW_SECTION,
3082
3102
  rules: buildRulesSection(coordinatorCliType),
@@ -5741,6 +5761,28 @@ var init_mesh_runtime_store = __esm({
5741
5761
  AND status NOT IN ('completed', 'failed')
5742
5762
  `).run({ status, meshId, sessionId, updatedAt: now });
5743
5763
  }
5764
+ /**
5765
+ * MESH-DISPATCH-MISROUTE (fix 3, consumer residual): resolve the task_id of the SINGLE
5766
+ * non-terminal direct dispatch a session owns. Returns the task_id only when the session
5767
+ * holds exactly ONE active ('dispatched'/'acked') row — the case where a taskId-less
5768
+ * lifecycle event (a legacy/relayed worker whose producer never stamped meshActiveTaskId)
5769
+ * unambiguously belongs to that one dispatch. With zero rows there is nothing to ack; with
5770
+ * two or more (a re-dispatch/nudge sibling) the firing event's owner is ambiguous, so we
5771
+ * return null and the caller MUST NOT fall back to the session_id sweep that would flip a
5772
+ * sibling row ("may flip a sibling dispatch row"). This narrows the legacy fallback to the
5773
+ * only safe case instead of removing the producer-side TASKIDLESS stamp's safety net.
5774
+ */
5775
+ getSoleActiveDirectDispatchTaskId(meshId, sessionId) {
5776
+ if (!sessionId) return null;
5777
+ const rows = this.db.prepare(`
5778
+ SELECT task_id FROM mesh_direct_dispatches
5779
+ WHERE mesh_id = ? AND session_id = ?
5780
+ AND status NOT IN ('completed', 'failed', 'stale')
5781
+ `).all(meshId, sessionId);
5782
+ if (rows.length !== 1) return null;
5783
+ const taskId = typeof rows[0]?.task_id === "string" ? rows[0].task_id.trim() : "";
5784
+ return taskId || null;
5785
+ }
5744
5786
  cleanupTerminalDirectDispatches(olderThanMs) {
5745
5787
  const cutoff = new Date(Date.now() - olderThanMs).toISOString();
5746
5788
  this.db.prepare(`
@@ -8532,6 +8574,109 @@ var init_mesh_active_work = __esm({
8532
8574
  }
8533
8575
  });
8534
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
+
8535
8680
  // src/mesh/mesh-events-utils.ts
8536
8681
  function readNonEmptyString2(value) {
8537
8682
  return typeof value === "string" && value.trim() ? value.trim() : "";
@@ -10815,8 +10960,8 @@ async function maybeAutoLaunchOneQueueSession(components, meshId, mesh) {
10815
10960
  const maxParallelTasks = Math.max(1, Math.floor(Number(mesh?.policy?.maxParallelTasks) || 2));
10816
10961
  const maxReadonlyParallelTasks = Math.max(2, maxParallelTasks * 2);
10817
10962
  for (const task of pending) {
10818
- const isReadonly = task.taskMode === "live_debug_readonly";
10819
- if (isReadonly) {
10963
+ const isReadonly2 = task.taskMode === "live_debug_readonly";
10964
+ if (isReadonly2) {
10820
10965
  if (activeReadonlyAssignedCount(meshId) >= maxReadonlyParallelTasks) {
10821
10966
  markAutoLaunch(meshId, task.id, { status: "skipped", reason: "max_readonly_parallel_tasks_reached" });
10822
10967
  continue;
@@ -13763,6 +13908,20 @@ function recoverMeshIdByNodeId(nodeId) {
13763
13908
  }
13764
13909
  return "";
13765
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
+ }
13766
13925
  function resolveForwardEventMeshId(components, payload) {
13767
13926
  const direct = readNonEmptyString2(payload.meshId);
13768
13927
  if (direct) return direct;
@@ -14244,8 +14403,19 @@ function injectMeshSystemMessage(components, args) {
14244
14403
  }
14245
14404
  if (sessionId) {
14246
14405
  const startedTaskId = readNonEmptyString2(args.metadataEvent.taskId) || void 0;
14247
- if (startedTaskId || sessionHasActiveAssignment(args.meshId, sessionId)) {
14406
+ if (startedTaskId) {
14248
14407
  updateDirectDispatchStatus(args.meshId, sessionId, "acked", startedTaskId);
14408
+ } else if (sessionHasActiveAssignment(args.meshId, sessionId)) {
14409
+ const soleTaskId = (() => {
14410
+ try {
14411
+ return MeshRuntimeStore.getInstance().getSoleActiveDirectDispatchTaskId(args.meshId, sessionId);
14412
+ } catch {
14413
+ return null;
14414
+ }
14415
+ })();
14416
+ if (soleTaskId) {
14417
+ updateDirectDispatchStatus(args.meshId, sessionId, "acked", soleTaskId);
14418
+ }
14249
14419
  }
14250
14420
  const activeDeliveries = (() => {
14251
14421
  try {
@@ -14498,7 +14668,10 @@ function handleMeshForwardEvent(components, payload) {
14498
14668
  }
14499
14669
  const nodeId = readNonEmptyString2(payload.nodeId);
14500
14670
  const workspace = readNonEmptyString2(payload.workspace);
14501
- 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
+ );
14502
14675
  if (!meshId) {
14503
14676
  traceMeshEventDrop("meshId_required", {
14504
14677
  taskId: payload.taskId,
@@ -14553,7 +14726,12 @@ function forwardUnresolvedDelegateEvent(components, routing, event) {
14553
14726
  ...event,
14554
14727
  event: eventName,
14555
14728
  nodeId: readNonEmptyString2(routing.nodeId) || readNonEmptyString2(event.meshNodeId) || void 0,
14556
- 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
14557
14735
  };
14558
14736
  const resolvedMeshId = resolveForwardEventMeshId(components, payload);
14559
14737
  if (resolvedMeshId) payload.meshId = resolvedMeshId;
@@ -14682,6 +14860,7 @@ var init_mesh_event_forwarding = __esm({
14682
14860
  init_mesh_runtime_store();
14683
14861
  init_mesh_events_pending();
14684
14862
  init_mesh_routing();
14863
+ init_mesh_host_ownership();
14685
14864
  init_mesh_unresolved_forward_outbox();
14686
14865
  init_mesh_event_trace();
14687
14866
  init_snapshot();
@@ -22921,6 +23100,7 @@ function buildMeshLedgerReconciliationEvidence(meshId, replicas) {
22921
23100
  init_mesh_work_queue();
22922
23101
  init_mesh_active_work();
22923
23102
  init_mesh_refine_status();
23103
+ init_mesh_scheduling_runtime();
22924
23104
  init_mesh_host_ownership();
22925
23105
  init_mesh_events();
22926
23106
  init_mesh_events_utils();
@@ -38703,9 +38883,35 @@ var CliProviderInstance = class _CliProviderInstance {
38703
38883
  * terminal state. Leaving meshNodeFor pinned would route this session's
38704
38884
  * subsequent unrelated turns (e.g. ad-hoc dashboard chats) to the
38705
38885
  * coordinator as if they were task completions.
38886
+ *
38887
+ * MESHID-DROP-ON-DETACH (Fix C): a coordinator-LAUNCHED worker session
38888
+ * (launchedByCoordinator) holds its mesh membership (meshNodeFor / meshNodeId /
38889
+ * meshCoordinatorDaemonId) at the SESSION level — set once at launch
38890
+ * (mesh_launch_session / queue auto-launch), independent of any single task.
38891
+ * The original detach wiped meshNodeFor + meshNodeId together with the
38892
+ * task-level meshActiveTaskId, so the FIRST task completion stripped the
38893
+ * membership and EVERY subsequent completion forwarded with meshId absent —
38894
+ * resolveWorkerDelegateRouting fell to mesh_unresolved and the coordinator
38895
+ * rejected the forward "meshId required". For a launched member we therefore
38896
+ * clear ONLY the task-level marker (meshActiveTaskId) and preserve the
38897
+ * session-level membership so its next task's completion still resolves.
38898
+ * A task-less ad-hoc turn on a preserved-membership session is NOT misrouted:
38899
+ * its completion carries no taskId and the session holds no active assignment,
38900
+ * so the forwarder's WARMUPGAP guard skips the dispatch-row flip (it only
38901
+ * injects a benign task-less notification). A NON-launched session (a plain CLI
38902
+ * session adopted by mesh_send_task --direct, launchedByCoordinator falsy)
38903
+ * keeps the original full clear so an ad-hoc session is never left pinned.
38706
38904
  */
38707
38905
  detachMeshAssignment() {
38708
38906
  if (!this.settings.meshNodeFor && !this.settings.meshActiveTaskId && !this.settings.meshNodeId) return;
38907
+ if (this.settings.launchedByCoordinator === true) {
38908
+ if (!this.settings.meshActiveTaskId) return;
38909
+ const { meshActiveTaskId: meshActiveTaskId2, ...rest2 } = this.settings;
38910
+ void meshActiveTaskId2;
38911
+ this.settings = rest2;
38912
+ this.adapter.updateRuntimeSettings?.(this.settings);
38913
+ return;
38914
+ }
38709
38915
  const { meshNodeFor, meshNodeId, meshActiveTaskId, ...rest } = this.settings;
38710
38916
  void meshNodeFor;
38711
38917
  void meshActiveTaskId;
@@ -48579,6 +48785,9 @@ var meshStatusHandlers = {
48579
48785
  const { getMeshQueueStats: getMeshQueueStats2, getQueue: getQueue2 } = await Promise.resolve().then(() => (init_mesh_work_queue(), mesh_work_queue_exports));
48580
48786
  const queue = getQueue2(meshId);
48581
48787
  const queueSummary = getMeshQueueStats2(meshId);
48788
+ const { buildMeshSchedulingRuntime: buildMeshSchedulingRuntime2 } = await Promise.resolve().then(() => (init_mesh_scheduling_runtime(), mesh_scheduling_runtime_exports));
48789
+ const schedulingRuntime = buildMeshSchedulingRuntime2(mesh, queue);
48790
+ const schedulingByNode = new Map(schedulingRuntime.nodes.map((n) => [n.nodeId, n]));
48582
48791
  const { readLedgerEntries: readLedgerEntries2, getLedgerSummary: getLedgerSummary2 } = await Promise.resolve().then(() => (init_mesh_ledger(), mesh_ledger_exports));
48583
48792
  const ledgerEntries = readLedgerEntries2(meshId, { tail: 20 });
48584
48793
  const asyncRefineLedgerEntries = readLedgerEntries2(meshId, { tail: 100 });
@@ -48693,6 +48902,11 @@ var meshStatusHandlers = {
48693
48902
  activeSessionDetails: [],
48694
48903
  launchReady: false
48695
48904
  };
48905
+ const nodeScheduling = schedulingByNode.get(nodeId);
48906
+ if (nodeScheduling) {
48907
+ const { nodeId: _omitNodeId, ...nodeSchedulingRest } = nodeScheduling;
48908
+ status.scheduling = nodeSchedulingRest;
48909
+ }
48696
48910
  if (isSelfNode) {
48697
48911
  status.connection = {
48698
48912
  perspective: "selected_coordinator",
@@ -48893,6 +49107,19 @@ var meshStatusHandlers = {
48893
49107
  branchConvergenceSummary: summarizeInlineMeshBranchConvergence(nodeStatuses),
48894
49108
  ...previewFreshness ? { previewFreshness, deployFreshness: previewFreshness } : {},
48895
49109
  nodes: nodeStatuses,
49110
+ // Mesh-level scheduling rollup (strategy + global cap consumption). Mirrors
49111
+ // the MCP `mesh_status` tool's `scheduling` block field-for-field so both
49112
+ // surfaces read the same runtime; per-node detail lives on each
49113
+ // nodes[].scheduling above.
49114
+ scheduling: {
49115
+ strategy: schedulingRuntime.strategy,
49116
+ maxParallelTasks: schedulingRuntime.maxParallelTasks,
49117
+ maxReadonlyParallelTasks: schedulingRuntime.maxReadonlyParallelTasks,
49118
+ activeWriteAssigned: schedulingRuntime.activeWriteAssigned,
49119
+ activeReadonlyAssigned: schedulingRuntime.activeReadonlyAssigned,
49120
+ globalWriteCapReached: schedulingRuntime.globalWriteCapReached,
49121
+ globalReadonlyCapReached: schedulingRuntime.globalReadonlyCapReached
49122
+ },
48896
49123
  queue: { tasks: queue, summary: queueSummary },
48897
49124
  ledger: { entries: ledgerEntries, summary: ledgerSummary },
48898
49125
  ...missions.length > 0 ? { missions } : {},
@@ -62209,6 +62436,8 @@ export {
62209
62436
  MAX_LEDGER_SLICE_LIMIT,
62210
62437
  MESH_CONVERGE_FAST_FORWARD_TAG,
62211
62438
  MESH_CONVERGE_REFINE_TAG,
62439
+ MESH_MAX_PARALLEL_TASKS_MAX,
62440
+ MESH_MAX_PARALLEL_TASKS_MIN,
62212
62441
  MESH_MISSION_STATUSES,
62213
62442
  MESH_NODE_LIVE_TRUTH_MARKER,
62214
62443
  MESH_REFINE_CONFIG_LOCATIONS,
@@ -62259,6 +62488,7 @@ export {
62259
62488
  buildMeshNodeCapabilityTags,
62260
62489
  buildMeshNodeDataFreshness,
62261
62490
  buildMeshNodeProbeFreshness,
62491
+ buildMeshSchedulingRuntime,
62262
62492
  buildMissionPromptSection,
62263
62493
  buildP2pRelayFailurePayload,
62264
62494
  buildPinnedGlobalInstallCommand,
@@ -62407,11 +62637,13 @@ export {
62407
62637
  markSetupComplete,
62408
62638
  markStaleDirectDispatches,
62409
62639
  maybeRunDaemonUpgradeHelperFromEnv,
62640
+ mergeAndNormalizePolicy,
62410
62641
  meshNodeIdMatches,
62411
62642
  namedKeyToAnsi,
62412
62643
  namedKeysToAnsi,
62413
62644
  nodeSatisfiesRequiredTags,
62414
62645
  normalizeActiveChatData,
62646
+ normalizeAutoFastForwardPolicy,
62415
62647
  normalizeChatMessage,
62416
62648
  normalizeChatMessageKind,
62417
62649
  normalizeChatMessages,
@@ -62473,11 +62705,13 @@ export {
62473
62705
  resolveDelegatedWorkerAutoApprove,
62474
62706
  resolveDeliveryDecision,
62475
62707
  resolveGitRepository,
62708
+ resolveMaxParallelTasks,
62476
62709
  resolveMeshHostStatus,
62477
62710
  resolveMeshNodeAttribution,
62478
62711
  resolveMeshRefineValidationPlan,
62479
62712
  resolveMeshSurfacedSessionPreview,
62480
62713
  resolveNodeSchedulingPriority,
62714
+ resolveProviderMaxParallel,
62481
62715
  resolveSessionHostAppName,
62482
62716
  resolveSessionHostAppNameResolution,
62483
62717
  resolveWorktreePath,