@adhdev/daemon-standalone 0.9.82-rc.12 → 0.9.82-rc.121

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.
Files changed (36) hide show
  1. package/dist/index.js +26981 -21358
  2. package/dist/index.js.map +1 -1
  3. package/package.json +1 -1
  4. package/public/assets/index-BJ05ceSl.js +98 -0
  5. package/public/assets/index-BKsjvBcH.js +100 -0
  6. package/public/assets/index-BNKDsz6G.css +1 -0
  7. package/public/assets/index-BfLqOvWH.js +98 -0
  8. package/public/assets/index-BggZArlj.js +99 -0
  9. package/public/assets/index-Bso1b8Lh.css +1 -0
  10. package/public/assets/index-BzfqwAXl.js +98 -0
  11. package/public/assets/index-CAip3He8.js +100 -0
  12. package/public/assets/index-CCQPbtl4.css +1 -0
  13. package/public/assets/index-CYwXUKol.js +98 -0
  14. package/public/assets/index-CiB8XPwO.css +1 -0
  15. package/public/assets/index-CsEmn20l.css +1 -0
  16. package/public/assets/index-CsR4qRd4.js +98 -0
  17. package/public/assets/index-DDB8O9lr.js +100 -0
  18. package/public/assets/index-DJmCzwTk.js +98 -0
  19. package/public/assets/index-DW3PmABW.js +99 -0
  20. package/public/assets/index-DaIkPFUd.js +99 -0
  21. package/public/assets/index-Dc9o_onl.js +98 -0
  22. package/public/assets/index-DcAeIiVq.css +1 -0
  23. package/public/assets/index-Deb1Bk0M.js +98 -0
  24. package/public/assets/index-DhQzhjNN.js +98 -0
  25. package/public/assets/index-Dt2Xvr87.js +98 -0
  26. package/public/assets/index-R9GDvGJ8.js +98 -0
  27. package/public/assets/index-kt4CV7OM.js +100 -0
  28. package/public/assets/index-phY3RKNC.js +98 -0
  29. package/public/assets/index-xSlc1ntZ.css +1 -0
  30. package/public/assets/index-yF4m-swI.js +100 -0
  31. package/public/assets/terminal-D46M5EWH.js +143 -0
  32. package/public/assets/terminal-NZFQPQy6.js +143 -0
  33. package/public/assets/vendor-C7br1-G2.js +2745 -0
  34. package/public/index.html +2 -2
  35. package/vendor/mcp-server/index.js +921 -88
  36. package/vendor/mcp-server/index.js.map +1 -1
@@ -35,9 +35,21 @@ __export(index_exports, {
35
35
  });
36
36
  module.exports = __toCommonJS(index_exports);
37
37
 
38
+ // src/tools/mesh-tools.ts
39
+ var import_node_crypto = require("crypto");
40
+
38
41
  // src/transports/ipc.ts
39
42
  var DEFAULT_IPC_PORT = 19222;
40
43
  var DEFAULT_IPC_PATH = "/ipc";
44
+ var DEFAULT_IPC_COMMAND_TIMEOUT_MS = 15e3;
45
+ var IPC_COMMAND_TIMEOUTS_MS = {
46
+ mesh_relay_command: 12e4,
47
+ agent_command: 3e4,
48
+ git_status: 45e3,
49
+ git_diff_summary: 45e3,
50
+ fast_forward_mesh_node: 12e4,
51
+ mesh_status: 12e4
52
+ };
41
53
  var IpcTransport = class {
42
54
  port;
43
55
  path;
@@ -85,9 +97,22 @@ var IpcTransport = class {
85
97
  }
86
98
  fn();
87
99
  };
88
- const timeoutMs = type === "mesh_relay_command" ? 6e4 : 15e3;
100
+ const nestedCommand = typeof args?.command === "string" ? args.command : "";
101
+ const targetDaemonId = typeof args?.targetDaemonId === "string" ? args.targetDaemonId : "";
102
+ const effectiveType = type === "mesh_relay_command" && nestedCommand ? nestedCommand : type;
103
+ const timeoutMs = Math.max(
104
+ IPC_COMMAND_TIMEOUTS_MS[type] ?? DEFAULT_IPC_COMMAND_TIMEOUT_MS,
105
+ IPC_COMMAND_TIMEOUTS_MS[effectiveType] ?? DEFAULT_IPC_COMMAND_TIMEOUT_MS
106
+ );
107
+ const diagnosticParts = [
108
+ `command='${type}'`,
109
+ ...nestedCommand ? [`relayedCommand='${nestedCommand}'`] : [],
110
+ ...targetDaemonId ? [`targetDaemonId='${targetDaemonId.slice(0, 12)}'`] : [],
111
+ ...typeof args?.nodeId === "string" ? [`nodeId='${args.nodeId}'`] : [],
112
+ ...typeof args?.workspace === "string" ? [`workspace='${args.workspace}'`] : []
113
+ ];
89
114
  const timeout = setTimeout(() => {
90
- finish(() => reject(new Error(`Daemon IPC command '${type}' timed out after ${Math.round(timeoutMs / 1e3)}s`)));
115
+ finish(() => reject(new Error(`Daemon IPC ${diagnosticParts.join(" ")} timed out after ${Math.round(timeoutMs / 1e3)}s (requestId=${requestId})`)));
91
116
  }, timeoutMs);
92
117
  let commandSent = false;
93
118
  const send = () => {
@@ -143,6 +168,10 @@ function isLocalTransport(transport) {
143
168
  }
144
169
 
145
170
  // src/tools/chat-compact.ts
171
+ function isAssistantLike(message) {
172
+ const role = String(message?.role ?? "").toLowerCase();
173
+ return role === "assistant" || role === "agent";
174
+ }
146
175
  function messageContent(message) {
147
176
  const content = message?.content;
148
177
  if (typeof content === "string") return content;
@@ -161,16 +190,22 @@ function isCoordinatorVisibleMessage(message) {
161
190
  if (meta?.internal === true || meta?.debug === true || meta?.control === true || meta?.userVisible === false || meta?.user_visible === false) return false;
162
191
  return role === "user" || role === "assistant" || role === "agent";
163
192
  }
193
+ function buildCompactMessageTail(visibleMessages, opts) {
194
+ const summary = typeof opts.summary === "string" ? opts.summary.trim() : "";
195
+ const shouldOmitSummaryMessage = !!summary && !!opts.finalAssistant && isAssistantLike(opts.finalAssistant) && messageContent(opts.finalAssistant).trim() === summary;
196
+ const sourceMessages = shouldOmitSummaryMessage ? visibleMessages.filter((message) => message !== opts.finalAssistant) : visibleMessages;
197
+ return sourceMessages.slice(-opts.limit);
198
+ }
164
199
  function compactChatPayload(payload, opts = {}) {
165
200
  const rawMessages = Array.isArray(payload?.messages) ? payload.messages : [];
166
201
  const visible = rawMessages.filter(isCoordinatorVisibleMessage);
167
202
  const limit = Math.max(1, Math.min(opts.limit ?? 10, 10));
168
- const messages = visible.slice(-limit);
169
203
  const finalAssistant = [...visible].reverse().find((message) => {
170
204
  const role = String(message?.role ?? "").toLowerCase();
171
205
  return (role === "assistant" || role === "agent") && messageContent(message).trim();
172
206
  });
173
207
  const summary = typeof payload?.summary === "string" && payload.summary.trim() ? payload.summary.trim() : messageContent(finalAssistant).trim();
208
+ const messages = buildCompactMessageTail(visible, { summary, finalAssistant, limit });
174
209
  return {
175
210
  success: payload?.success !== false,
176
211
  compact: true,
@@ -232,9 +267,45 @@ function annotateRapidReadChatAdvisory(payload, options) {
232
267
  // src/tools/mesh-tools.ts
233
268
  var import_daemon_core = require("@adhdev/daemon-core");
234
269
  var meshSessionProviderMetadata = /* @__PURE__ */ new Map();
270
+ var ACTIVE_WORK_POLLING_BACKOFF_MS = 6e4;
271
+ function buildActiveWorkPollingGuidance(summary, now = Date.now()) {
272
+ if (!summary || summary.generatingCount <= 0) return void 0;
273
+ return {
274
+ activeGeneratingWork: true,
275
+ generatingCount: summary.generatingCount,
276
+ doNotPollBefore: new Date(now + ACTIVE_WORK_POLLING_BACKOFF_MS).toISOString(),
277
+ eventSurface: "pendingCoordinatorEvents",
278
+ nextRecommendedAction: "Wait for pendingCoordinatorEvents/completion events or an explicit user status request. After a terminal signal, call mesh_read_chat once with compact=true, then verify git state if repository changes were expected.",
279
+ message: "Do not repeatedly poll mesh_status/mesh_view_queue/mesh_read_chat while delegated work is generating; these snapshots rarely change until the worker emits a completion/status event."
280
+ };
281
+ }
235
282
  function readString(value) {
236
283
  return typeof value === "string" && value.trim() ? value.trim() : void 0;
237
284
  }
285
+ function summarizeTaskMessage(message) {
286
+ const taskSummary = message.replace(/\s+/g, " ").trim();
287
+ const taskTitle = taskSummary.length > 96 ? `${taskSummary.slice(0, 93)}...` : taskSummary;
288
+ return { taskTitle: taskTitle || "(untitled task)", taskSummary };
289
+ }
290
+ function buildDirectTaskPayload(message, via, opts) {
291
+ const descriptor = summarizeTaskMessage(message);
292
+ return {
293
+ source: "direct",
294
+ via,
295
+ taskId: opts.taskId,
296
+ message,
297
+ taskTitle: descriptor.taskTitle,
298
+ taskSummary: descriptor.taskSummary,
299
+ ...opts.taskMode ? { taskMode: opts.taskMode } : {},
300
+ ...opts.providerType ? { providerType: opts.providerType } : {},
301
+ ...opts.targetSessionId ? { targetSessionId: opts.targetSessionId } : {}
302
+ };
303
+ }
304
+ function findNode(mesh, nodeId) {
305
+ const node = mesh.nodes.find((n) => n.id === nodeId);
306
+ if (!node) throw new Error(`Node '${nodeId}' is not a member of mesh '${mesh.name}'`);
307
+ return node;
308
+ }
238
309
  var DUPLICATE_DISPATCH_WINDOW_MS = 6e4;
239
310
  var STALE_ASSIGNED_QUEUE_MS = 30 * 6e4;
240
311
  var OLD_HISTORICAL_QUEUE_RECORD_MS = 7 * 24 * 60 * 6e4;
@@ -246,15 +317,24 @@ async function refreshMeshFromDaemon(ctx) {
246
317
  const result = await ctx.transport.command("get_mesh", { meshId: ctx.mesh.id });
247
318
  if (!result?.success || !Array.isArray(result.mesh?.nodes)) return;
248
319
  const refreshedNodes = result.mesh.nodes.filter((n) => n?.id).map((n) => n);
249
- if (!refreshedNodes.length) return;
250
320
  ctx.mesh.nodes.splice(0, ctx.mesh.nodes.length, ...refreshedNodes);
251
321
  ctx.mesh.updatedAt = result.mesh.updatedAt ?? ctx.mesh.updatedAt;
252
322
  } catch {
253
323
  }
254
324
  }
325
+ async function syncCoordinatorDaemonMeshCache(ctx) {
326
+ if (!(ctx.transport instanceof IpcTransport)) return;
327
+ try {
328
+ await ctx.transport.command("get_mesh", {
329
+ meshId: ctx.mesh.id,
330
+ inlineMesh: ctx.mesh
331
+ });
332
+ } catch {
333
+ }
334
+ }
255
335
  async function findNodeWithRefresh(ctx, nodeId) {
256
336
  const hit = ctx.mesh.nodes.find((n) => n.id === nodeId);
257
- if (hit) return hit;
337
+ if (hit && !hit.isLocalWorktree) return hit;
258
338
  await refreshMeshFromDaemon(ctx);
259
339
  const refreshed = ctx.mesh.nodes.find((n) => n.id === nodeId);
260
340
  if (!refreshed) throw new Error(`Node '${nodeId}' is not a member of mesh '${ctx.mesh.name}'`);
@@ -262,7 +342,7 @@ async function findNodeWithRefresh(ctx, nodeId) {
262
342
  }
263
343
  async function findOptionalNodeWithRefresh(ctx, nodeId) {
264
344
  const hit = ctx.mesh.nodes.find((n) => n.id === nodeId);
265
- if (hit) return hit;
345
+ if (hit && !hit.isLocalWorktree) return hit;
266
346
  await refreshMeshFromDaemon(ctx);
267
347
  return ctx.mesh.nodes.find((n) => n.id === nodeId) ?? null;
268
348
  }
@@ -314,9 +394,26 @@ function buildMissingNodeReadChatRecovery(ctx, args) {
314
394
  readDebugLocator: readString(lastTerminal?.payload?.readDebugLocator) || readString(lastTerminal?.payload?.debugBundlePath)
315
395
  };
316
396
  if (finalSummary) {
397
+ if (args.compact === true) {
398
+ return {
399
+ ...compactChatPayload({
400
+ success: true,
401
+ status: "idle",
402
+ providerSessionId,
403
+ summary: finalSummary,
404
+ messages: [{ role: "assistant", content: finalSummary, isHistorical: true }]
405
+ }, {
406
+ nodeId: args.node_id,
407
+ sessionId: args.session_id,
408
+ limit: args.tail ?? 10
409
+ }),
410
+ recoveredFromLedger: true,
411
+ ledger
412
+ };
413
+ }
317
414
  return {
318
415
  success: true,
319
- compact: args.compact === true,
416
+ compact: false,
320
417
  recoveredFromLedger: true,
321
418
  nodeId: args.node_id,
322
419
  sessionId: args.session_id,
@@ -368,6 +465,22 @@ function buildMissingNodeReadChatRecovery(ctx, args) {
368
465
  function readSessionRecordId(session) {
369
466
  return readString(session?.id) || readString(session?.sessionId) || readString(session?.session_id) || readString(session?.runtimeSessionId) || readString(session?.runtime_session_id) || readString(session?.instanceId) || readString(session?.instance_id);
370
467
  }
468
+ function extractStatusMetadataSessions(value) {
469
+ const payload = unwrapCommandPayload(value);
470
+ const status = payload?.status && typeof payload.status === "object" ? payload.status : payload;
471
+ return Array.isArray(status?.sessions) ? status.sessions : [];
472
+ }
473
+ function resolveSessionProviderType(session) {
474
+ return readString(session?.providerType) || readString(session?.cliType) || readString(session?.agentType) || "";
475
+ }
476
+ function isMeshCoordinatorSessionRecord(session) {
477
+ return Boolean(
478
+ readString(session?.settings?.meshCoordinatorFor) || readString(session?.meta?.meshCoordinatorFor) || readString(session?.metadata?.meshCoordinatorFor) || readString(session?.meshCoordinatorFor)
479
+ );
480
+ }
481
+ function isWorkerTaskMode(taskMode) {
482
+ return taskMode !== "live_debug_readonly";
483
+ }
371
484
  function addSessionRecord(target, session) {
372
485
  if (!session || typeof session !== "object" || isTerminalSessionRecord(session)) return;
373
486
  const sessionId = readSessionRecordId(session);
@@ -436,18 +549,26 @@ function queueAssignmentStaleReason(task, liveness) {
436
549
  }
437
550
  function buildQueueStatusSummary(queue) {
438
551
  const counts = { pending: 0, assigned: 0, completed: 0, failed: 0, cancelled: 0 };
552
+ let staleAssigned = 0;
439
553
  for (const task of queue) {
440
554
  const status = typeof task?.status === "string" ? task.status : void 0;
441
555
  if (status && Object.prototype.hasOwnProperty.call(counts, status)) {
442
556
  counts[status] += 1;
443
557
  }
558
+ if (status === "assigned" && task?.staleAssigned === true) staleAssigned += 1;
444
559
  }
560
+ const liveAssigned = Math.max(0, counts.assigned - staleAssigned);
445
561
  return {
446
562
  totalCount: queue.length,
447
- activeCount: counts.pending + counts.assigned,
563
+ activeCount: counts.pending + liveAssigned,
448
564
  historicalCount: counts.completed + counts.failed + counts.cancelled,
449
565
  counts,
450
566
  activeCounts: {
567
+ pending: counts.pending,
568
+ assigned: liveAssigned
569
+ },
570
+ staleAssignedCount: staleAssigned,
571
+ rawActiveCounts: {
451
572
  pending: counts.pending,
452
573
  assigned: counts.assigned
453
574
  },
@@ -475,6 +596,18 @@ function filterQueueForView(queue, view, statuses) {
475
596
  if (view === "historical") return queue.filter((task) => HISTORICAL_QUEUE_STATUSES.has(String(task?.status || "")));
476
597
  return queue;
477
598
  }
599
+ function prioritizeActiveQueueRows(queue) {
600
+ const active = [];
601
+ const historical = [];
602
+ const other = [];
603
+ for (const task of queue) {
604
+ const status = String(task?.status || "");
605
+ if (ACTIVE_QUEUE_STATUSES.has(status)) active.push(task);
606
+ else if (HISTORICAL_QUEUE_STATUSES.has(status)) historical.push(task);
607
+ else other.push(task);
608
+ }
609
+ return [...active, ...other, ...historical];
610
+ }
478
611
  function slimQueueTask(task) {
479
612
  return {
480
613
  id: task?.id,
@@ -580,22 +713,59 @@ function isIdleSessionRecord(session) {
580
713
  const chatStatus = typeof session?.activeChat?.status === "string" ? session.activeChat.status.toLowerCase() : "";
581
714
  return status === "idle" || chatStatus === "waiting_input";
582
715
  }
716
+ function isMeshOwnedDelegateSession(session, meshId, nodeId) {
717
+ const settings = session?.settings;
718
+ const sessionMeshId = typeof settings?.meshNodeFor === "string" ? settings.meshNodeFor.trim() : "";
719
+ const coordinatorDaemonId = typeof settings?.meshCoordinatorDaemonId === "string" ? settings.meshCoordinatorDaemonId.trim() : "";
720
+ const sessionNodeId = typeof settings?.meshNodeId === "string" ? settings.meshNodeId.trim() : "";
721
+ if (sessionMeshId !== meshId || !coordinatorDaemonId) return false;
722
+ return !sessionNodeId || sessionNodeId === nodeId;
723
+ }
583
724
  function chooseDispatchableSession(sessions, providerType, meshId, nodeId) {
584
725
  const live = sessions.filter((session) => !isTerminalSessionRecord(session));
585
726
  const matchingProvider = (session) => !providerType || session?.providerType === providerType || session?.cliType === providerType;
586
- const isMeshOwnedDelegateSession = (session) => {
587
- const settings = session?.settings;
588
- const sessionMeshId = typeof settings?.meshNodeFor === "string" ? settings.meshNodeFor.trim() : "";
589
- const coordinatorDaemonId = typeof settings?.meshCoordinatorDaemonId === "string" ? settings.meshCoordinatorDaemonId.trim() : "";
590
- const sessionNodeId = typeof settings?.meshNodeId === "string" ? settings.meshNodeId.trim() : "";
591
- if (sessionMeshId !== meshId || !coordinatorDaemonId) return false;
592
- return !sessionNodeId || sessionNodeId === nodeId;
593
- };
594
727
  const meshSessions = live.filter(
595
- (session) => isMeshOwnedDelegateSession(session)
728
+ (session) => isMeshOwnedDelegateSession(session, meshId, nodeId)
596
729
  );
597
730
  return meshSessions.find((session) => isIdleSessionRecord(session) && matchingProvider(session)) || meshSessions.find(matchingProvider) || void 0;
598
731
  }
732
+ function buildRelayUnsafeRemoteSessionFailure(ctx, node, sessionId, providerType) {
733
+ return {
734
+ success: false,
735
+ recoverable: true,
736
+ code: "mesh_delegate_session_missing_relay_metadata",
737
+ reason: "mesh_delegate_session_missing_relay_metadata",
738
+ transport: "mesh_transport",
739
+ retryRecommended: true,
740
+ meshId: ctx.mesh.id,
741
+ nodeId: node.id,
742
+ daemonId: node.daemonId,
743
+ workspace: node.workspace,
744
+ sessionId,
745
+ ...providerType ? { resolvedProviderType: providerType } : {},
746
+ error: `Remote session '${sessionId}' is not relay-safe for mesh '${ctx.mesh.id}': missing meshNodeFor/meshCoordinatorDaemonId metadata, so completion events would not reach the coordinator ledger.`,
747
+ nextAction: `Launch a fresh relay-safe session with mesh_launch_session(node_id: '${node.id}'${providerType ? `, type: '${providerType}'` : ""}) or dispatch without session_id so Repo Mesh can choose a valid delegate session.`,
748
+ noFallbackReason: "Blindly reusing a remote session without mesh relay metadata would silently drop task_completed / generating_completed events."
749
+ };
750
+ }
751
+ function buildMissingCoordinatorDaemonIdFailure(ctx, node, providerType) {
752
+ return {
753
+ success: false,
754
+ recoverable: true,
755
+ code: "mesh_coordinator_daemon_unknown",
756
+ reason: "mesh_coordinator_daemon_unknown",
757
+ transport: "mesh_transport",
758
+ retryRecommended: true,
759
+ meshId: ctx.mesh.id,
760
+ nodeId: node.id,
761
+ daemonId: node.daemonId,
762
+ workspace: node.workspace,
763
+ ...providerType ? { resolvedProviderType: providerType } : {},
764
+ error: `Cannot launch a remote mesh delegate for node '${node.id}': coordinator daemon identity is unavailable, so the worker would be unable to relay completion events back to the coordinator.`,
765
+ nextAction: "Retry after the coordinator daemon identity is available (for example from an attached daemon-backed MCP session) so meshCoordinatorDaemonId can be stamped on the worker session.",
766
+ noFallbackReason: "Launching without meshCoordinatorDaemonId would create a worker session that can finish work but cannot emit task_completed / generating_completed back to the coordinator."
767
+ };
768
+ }
599
769
  function findNestedPayload(value, predicate) {
600
770
  const seen = /* @__PURE__ */ new Set();
601
771
  const stack = [{ payload: value, depth: 0 }];
@@ -623,12 +793,16 @@ function extractGitDiff(value) {
623
793
  }
624
794
  function extractSubmodules(value, ignorePaths) {
625
795
  const payload = unwrapCommandPayload(value);
626
- const subs = payload?.submodules ?? value?.submodules;
796
+ const subs = payload?.status?.submodules ?? payload?.submodules ?? value?.status?.submodules ?? value?.submodules;
627
797
  if (!Array.isArray(subs)) return void 0;
628
798
  if (ignorePaths.length === 0) return subs;
629
799
  const ignoreSet = new Set(ignorePaths);
630
800
  return subs.filter((s) => s?.path && !ignoreSet.has(s.path));
631
801
  }
802
+ function assignFullGitSnapshot(entry, status) {
803
+ if (!status || typeof status !== "object" || Array.isArray(status)) return;
804
+ entry.git = status;
805
+ }
632
806
  function extractLaunchPayload(value) {
633
807
  return findNestedPayload(value, (payload) => Boolean(payload?.sessionId || payload?.id || payload?.runtimeSessionId));
634
808
  }
@@ -753,20 +927,76 @@ async function ipcDispatchToRemoteAgent(ctx, node, args) {
753
927
  let sessionId = args.session_id?.trim() || "";
754
928
  const providerPriorityList = Array.isArray(node.policy?.providerPriority) ? node.policy.providerPriority : [];
755
929
  let resolvedProviderType = args.providerType?.trim() || providerPriorityList[0] || "";
756
- if (!sessionId) {
930
+ if (sessionId && args.verifiedSession) {
931
+ const explicitSession = args.verifiedSession;
932
+ if (!isMeshOwnedDelegateSession(explicitSession, ctx.mesh.id, node.id)) {
933
+ return buildRelayUnsafeRemoteSessionFailure(
934
+ ctx,
935
+ node,
936
+ sessionId,
937
+ resolvedProviderType || resolveSessionProviderType(explicitSession) || void 0
938
+ );
939
+ }
940
+ if (!resolvedProviderType) {
941
+ resolvedProviderType = resolveSessionProviderType(explicitSession);
942
+ }
943
+ } else if (!sessionId || args.session_id) {
757
944
  try {
758
945
  const relayResult = await transport.meshCommand(daemonId, "get_status_metadata", {});
759
- const innerResult = relayResult?.result ?? relayResult;
760
- const statusObj = innerResult?.status ?? innerResult;
761
- const sessions = Array.isArray(statusObj?.sessions) ? statusObj.sessions : [];
762
- const targetSession = chooseDispatchableSession(sessions, resolvedProviderType, ctx.mesh.id, node.id);
763
- if (targetSession?.id || targetSession?.sessionId) {
764
- sessionId = targetSession.id || targetSession.sessionId;
946
+ const sessions = extractStatusMetadataSessions(relayResult);
947
+ if (sessionId) {
948
+ const explicitSession = sessions.find((session) => readSessionRecordId(session) === sessionId);
949
+ if (!explicitSession) {
950
+ return {
951
+ success: false,
952
+ recoverable: true,
953
+ code: "mesh_target_session_not_found",
954
+ reason: "mesh_target_session_not_found",
955
+ transport: "mesh_transport",
956
+ retryRecommended: true,
957
+ meshId: ctx.mesh.id,
958
+ nodeId: node.id,
959
+ daemonId,
960
+ workspace: node.workspace,
961
+ sessionId,
962
+ ...resolvedProviderType ? { resolvedProviderType } : {},
963
+ error: `Remote session '${sessionId}' is not present in the live status for node '${node.id}'.`,
964
+ nextAction: `Launch a fresh session with mesh_launch_session(node_id: '${node.id}'${resolvedProviderType ? `, type: '${resolvedProviderType}'` : ""}) or retry without session_id so Repo Mesh can target a live delegate session.`
965
+ };
966
+ }
967
+ if (!isMeshOwnedDelegateSession(explicitSession, ctx.mesh.id, node.id)) {
968
+ return buildRelayUnsafeRemoteSessionFailure(
969
+ ctx,
970
+ node,
971
+ sessionId,
972
+ resolvedProviderType || resolveSessionProviderType(explicitSession) || void 0
973
+ );
974
+ }
765
975
  if (!resolvedProviderType) {
766
- resolvedProviderType = targetSession.providerType || targetSession.cliType || "";
976
+ resolvedProviderType = resolveSessionProviderType(explicitSession);
977
+ }
978
+ } else {
979
+ const targetSession = chooseDispatchableSession(sessions, resolvedProviderType, ctx.mesh.id, node.id);
980
+ if (targetSession?.id || targetSession?.sessionId) {
981
+ sessionId = targetSession.id || targetSession.sessionId;
982
+ if (!resolvedProviderType) {
983
+ resolvedProviderType = resolveSessionProviderType(targetSession);
984
+ }
767
985
  }
768
986
  }
769
987
  } catch (e) {
988
+ if (sessionId) {
989
+ return {
990
+ ...buildCoordinatorP2pRelayFailure(e, {
991
+ command: "get_status_metadata",
992
+ targetDaemonId: daemonId,
993
+ nodeId: node.id,
994
+ sessionId
995
+ }),
996
+ success: false,
997
+ error: `Cannot verify remote session '${sessionId}' before dispatch: ${e?.message || String(e)}`
998
+ };
999
+ }
770
1000
  }
771
1001
  }
772
1002
  if (!resolvedProviderType) {
@@ -796,7 +1026,7 @@ async function ipcDispatchToRemoteAgent(ctx, node, args) {
796
1026
  error: `P2P dispatch failed: ${errorMessage}`
797
1027
  };
798
1028
  }
799
- return { success: true, dispatched: true, sessionId: sessionId || resolvedProviderType };
1029
+ return { success: true, dispatched: true, sessionId: sessionId || resolvedProviderType, providerType: resolvedProviderType };
800
1030
  } catch (e) {
801
1031
  const errorMessage = e?.message || String(e);
802
1032
  return {
@@ -826,34 +1056,194 @@ function resolveCoordinatorNode(ctx) {
826
1056
  return void 0;
827
1057
  }
828
1058
  function readNodeMachineId(node) {
829
- return readString(node.machineId) || readString(node.machine_id);
1059
+ return readString(node.machineId) || readString(node.machine_id) || readString(node.machine?.id) || readString(node.machine?.machineId) || readString(node.lastProbe?.machineId) || readString(node.last_probe?.machine_id) || readString(node.lastProbe?.machine?.id) || readString(node.lastProbe?.machine?.machineId) || readString(node.last_probe?.machine?.id) || readString(node.last_probe?.machine?.machine_id);
830
1060
  }
831
1061
  function readNodeDaemonId(node) {
832
- return readString(node.daemonId) || readString(node.daemon_id);
1062
+ return readString(node.daemonId) || readString(node.daemon_id) || readString(node.machine?.daemonId) || readString(node.machine?.daemon_id) || readString(node.lastProbe?.daemonId) || readString(node.last_probe?.daemon_id) || readString(node.lastProbe?.machine?.daemonId) || readString(node.lastProbe?.machine?.daemon_id) || readString(node.last_probe?.machine?.daemonId) || readString(node.last_probe?.machine?.daemon_id);
1063
+ }
1064
+ function normalizeHostname(value) {
1065
+ const hostname = readString(value);
1066
+ if (!hostname) return void 0;
1067
+ return hostname.toLowerCase().replace(/\.$/, "");
1068
+ }
1069
+ function readNodeHostname(node) {
1070
+ return readString(node.hostname) || readString(node.host) || readString(node.machineHostname) || readString(node.machine_hostname) || readString(node.machine?.hostname) || readString(node.machine?.host) || readString(node.lastProbe?.hostname) || readString(node.last_probe?.hostname) || readString(node.lastProbe?.machine?.hostname) || readString(node.last_probe?.machine?.hostname);
1071
+ }
1072
+ function readNodeDisplayMachineName(node) {
1073
+ return readString(node.machineName) || readString(node.machine_name) || readString(node.machineLabel) || readString(node.machine_label) || readString(node.machineNickname) || readString(node.machine_nickname) || readString(node.alias) || readString(node.machine?.name) || readString(node.machine?.displayName) || readString(node.machine?.display_name) || readString(node.lastProbe?.machineName) || readString(node.last_probe?.machine_name) || readString(node.lastProbe?.machine?.name) || readString(node.last_probe?.machine?.name) || readNodeHostname(node);
1074
+ }
1075
+ function compactIdentityEvidence(value) {
1076
+ if (!value) return void 0;
1077
+ return value.length > 24 ? `${value.slice(0, 12)}\u2026${value.slice(-8)}` : value;
1078
+ }
1079
+ function pushIdentityEvidence(evidence, label, value) {
1080
+ const compact = compactIdentityEvidence(value);
1081
+ if (compact) evidence.push(`${label}:${compact}`);
1082
+ }
1083
+ function buildNodeMachineIdentity(ctx, node) {
1084
+ const machineId = readNodeMachineId(node);
1085
+ const daemonId = readNodeDaemonId(node);
1086
+ const hostname = readNodeHostname(node);
1087
+ const machineName = readNodeDisplayMachineName(node);
1088
+ const coordinatorHostname = readString(ctx.coordinatorHostname);
1089
+ const localControlPlaneReason = getLocalControlPlaneMatchReason(ctx, node);
1090
+ const directLocal = !!localControlPlaneReason;
1091
+ const hostnameMatches = Boolean(
1092
+ normalizeHostname(hostname) && normalizeHostname(coordinatorHostname) && normalizeHostname(hostname) === normalizeHostname(coordinatorHostname)
1093
+ );
1094
+ const sameMachine = directLocal || hostnameMatches;
1095
+ const evidence = [];
1096
+ pushIdentityEvidence(evidence, "machineName", machineName);
1097
+ pushIdentityEvidence(evidence, "hostname", hostname);
1098
+ pushIdentityEvidence(evidence, "machineId", machineId);
1099
+ pushIdentityEvidence(evidence, "daemonId", daemonId);
1100
+ if (localControlPlaneReason) {
1101
+ pushIdentityEvidence(evidence, "localMatch", localControlPlaneReason);
1102
+ pushIdentityEvidence(evidence, "localMachineId", ctx.localMachineId);
1103
+ pushIdentityEvidence(evidence, "localDaemonId", ctx.localDaemonId);
1104
+ }
1105
+ const locality = sameMachine ? "same_machine" : evidence.length > 0 ? "remote_known" : "remote_or_unknown";
1106
+ const localityReason = sameMachine ? localControlPlaneReason || "matched coordinator hostname" : evidence.length > 0 ? `known remote/other machine identity; no local coordinator match (${evidence.join(", ")})` : "no useful machine identity evidence available";
1107
+ return {
1108
+ daemonId,
1109
+ machineId,
1110
+ hostname,
1111
+ machineName,
1112
+ displayName: machineName || hostname || daemonId || machineId,
1113
+ coordinatorHostname,
1114
+ sameMachine,
1115
+ locality,
1116
+ localityReason,
1117
+ identityEvidence: evidence
1118
+ };
1119
+ }
1120
+ function nodeHasLocalDaemonEvidence(ctx, node) {
1121
+ const isLocal = (session) => {
1122
+ if (!session || typeof session !== "object") return false;
1123
+ if (ctx.localDaemonId && session.settings?.meshCoordinatorDaemonId === ctx.localDaemonId) return true;
1124
+ if (session.launchedByCoordinator === true) return true;
1125
+ if (ctx.localDaemonId && session.runtime?.owner === ctx.localDaemonId) return true;
1126
+ if (ctx.localDaemonId && session.daemonClient?.daemonId === ctx.localDaemonId) return true;
1127
+ return false;
1128
+ };
1129
+ const sessionArrays = [
1130
+ node?.sessions,
1131
+ node?.activeSessions,
1132
+ node?.active_sessions,
1133
+ node?.lastProbe?.sessions,
1134
+ node?.last_probe?.sessions,
1135
+ node?.lastProbe?.status?.sessions,
1136
+ node?.last_probe?.status?.sessions
1137
+ ];
1138
+ for (const arr of sessionArrays) {
1139
+ if (Array.isArray(arr) && arr.some(isLocal)) return true;
1140
+ }
1141
+ const sessionRecords = [
1142
+ node?.activeSession,
1143
+ node?.active_session,
1144
+ node?.currentSession,
1145
+ node?.current_session,
1146
+ node?.runtimeSession,
1147
+ node?.runtime_session,
1148
+ node?.session,
1149
+ node?.lastProbe?.activeSession,
1150
+ node?.last_probe?.active_session,
1151
+ node?.lastProbe?.currentSession,
1152
+ node?.last_probe?.current_session,
1153
+ node?.lastProbe?.session,
1154
+ node?.last_probe?.session
1155
+ ];
1156
+ for (const session of sessionRecords) {
1157
+ if (isLocal(session)) return true;
1158
+ }
1159
+ return false;
833
1160
  }
834
1161
  function isDirectLocalNode(ctx, node) {
835
1162
  const machineId = readNodeMachineId(node);
836
1163
  const daemonId = readNodeDaemonId(node);
837
1164
  return Boolean(
838
- ctx.localMachineId && machineId === ctx.localMachineId || ctx.localDaemonId && daemonId === ctx.localDaemonId
1165
+ ctx.localMachineId && machineId === ctx.localMachineId || ctx.localDaemonId && daemonId === ctx.localDaemonId || nodeHasLocalDaemonEvidence(ctx, node)
839
1166
  );
840
1167
  }
1168
+ function isConfiguredCoordinatorNode(ctx, node) {
1169
+ if (!ctx.localMachineId && !ctx.localDaemonId) return false;
1170
+ const nodeId = readString(node.id) || readString(node.nodeId) || readString(node.node_id);
1171
+ if (!nodeId) return false;
1172
+ const preferredNodeId = readString(ctx.mesh.coordinator?.preferredNodeId) || readString(ctx.mesh.coordinator?.preferred_node_id);
1173
+ if (preferredNodeId) return nodeId === preferredNodeId;
1174
+ const first = ctx.mesh.nodes?.[0];
1175
+ const firstNodeId = readString(first?.id) || readString(first?.nodeId) || readString(first?.node_id);
1176
+ return !!firstNodeId && nodeId === firstNodeId;
1177
+ }
1178
+ function getLocalControlPlaneMatchReason(ctx, node) {
1179
+ if (isDirectLocalNode(ctx, node)) return "matched coordinator daemon or machine id";
1180
+ if (isConfiguredCoordinatorNode(ctx, node)) return "matched configured coordinator node";
1181
+ if (node.isLocalWorktree === true) {
1182
+ const sourceNode = findClonedFromNode(ctx, node);
1183
+ if (sourceNode && isDirectLocalNode(ctx, sourceNode)) return "matched local cloned-from node";
1184
+ if (sourceNode && isConfiguredCoordinatorNode(ctx, sourceNode)) return "matched configured coordinator source node";
1185
+ }
1186
+ return void 0;
1187
+ }
841
1188
  function findClonedFromNode(ctx, node) {
842
1189
  const clonedFromNodeId = readString(node.clonedFromNodeId) || readString(node.cloned_from_node_id);
843
1190
  if (!clonedFromNodeId) return void 0;
844
1191
  return ctx.mesh.nodes.find((n) => n.id === clonedFromNodeId || n.nodeId === clonedFromNodeId || n.node_id === clonedFromNodeId);
845
1192
  }
846
1193
  function isLocalControlPlaneNode(ctx, node) {
847
- if (isDirectLocalNode(ctx, node)) return true;
848
- if (node.isLocalWorktree === true) {
849
- const sourceNode = findClonedFromNode(ctx, node);
850
- if (sourceNode && isDirectLocalNode(ctx, sourceNode)) return true;
851
- }
852
- return false;
1194
+ return !!getLocalControlPlaneMatchReason(ctx, node);
853
1195
  }
854
1196
  function meshSessionCacheKey(nodeId, runtimeSessionId) {
855
1197
  return `${nodeId}:${runtimeSessionId}`;
856
1198
  }
1199
+ function rememberMeshSessionProviderMetadata(nodeId, runtimeSessionId, metadata) {
1200
+ const keyNodeId = readString(nodeId);
1201
+ const keySessionId = readString(runtimeSessionId);
1202
+ if (!keyNodeId || !keySessionId) return;
1203
+ const providerType = readString(metadata.providerType);
1204
+ const providerSessionId = readString(metadata.providerSessionId);
1205
+ if (!providerType && !providerSessionId) return;
1206
+ const existing = meshSessionProviderMetadata.get(meshSessionCacheKey(keyNodeId, keySessionId)) || { providerType: "" };
1207
+ meshSessionProviderMetadata.set(meshSessionCacheKey(keyNodeId, keySessionId), {
1208
+ providerType: providerType || existing.providerType,
1209
+ providerSessionId: providerSessionId || existing.providerSessionId
1210
+ });
1211
+ }
1212
+ function rememberMeshSessionProviderMetadataFromEvent(event) {
1213
+ const metadataEvent = event?.metadataEvent && typeof event.metadataEvent === "object" ? event.metadataEvent : event && typeof event === "object" ? event : {};
1214
+ const nodeId = readString(event?.nodeId) || readString(metadataEvent.nodeId) || readString(metadataEvent.meshNodeId);
1215
+ const sessionId = readString(metadataEvent.targetSessionId) || readString(metadataEvent.sessionId) || readString(metadataEvent.instanceId) || readString(event?.sessionId);
1216
+ rememberMeshSessionProviderMetadata(nodeId, sessionId, {
1217
+ providerType: readString(metadataEvent.providerType) || readString(event?.providerType) || "",
1218
+ providerSessionId: readString(metadataEvent.providerSessionId) || readString(event?.providerSessionId)
1219
+ });
1220
+ }
1221
+ function resolveMeshSessionProviderMetadataFromLedger(ctx, nodeId, runtimeSessionId) {
1222
+ const entries = (0, import_daemon_core.readLedgerEntries)(ctx.mesh.id, { tail: 500 });
1223
+ for (let i = entries.length - 1; i >= 0; i -= 1) {
1224
+ const entry = entries[i];
1225
+ const payload = entry.payload && typeof entry.payload === "object" && !Array.isArray(entry.payload) ? entry.payload : {};
1226
+ const entryNodeId = readString(entry.nodeId) || readString(payload.nodeId) || readString(payload.meshNodeId);
1227
+ if (entryNodeId && entryNodeId !== nodeId) continue;
1228
+ const entrySessionId = readString(entry.sessionId) || readString(payload.targetSessionId) || readString(payload.sessionId) || readString(payload.instanceId);
1229
+ if (entrySessionId !== runtimeSessionId) continue;
1230
+ const providerType = readString(entry.providerType) || readString(payload.providerType);
1231
+ const completionDiagnostic = payload.completionDiagnostic && typeof payload.completionDiagnostic === "object" && !Array.isArray(payload.completionDiagnostic) ? payload.completionDiagnostic : {};
1232
+ const metadataEvent = payload.metadataEvent && typeof payload.metadataEvent === "object" && !Array.isArray(payload.metadataEvent) ? payload.metadataEvent : {};
1233
+ const providerSessionId = readString(payload.providerSessionId) || readString(completionDiagnostic.providerSessionId) || readString(metadataEvent.providerSessionId);
1234
+ if (providerType || providerSessionId) {
1235
+ return { providerType: providerType || "", providerSessionId };
1236
+ }
1237
+ }
1238
+ return void 0;
1239
+ }
1240
+ function resolveMeshSessionProviderMetadata(ctx, nodeId, runtimeSessionId) {
1241
+ const cached = meshSessionProviderMetadata.get(meshSessionCacheKey(nodeId, runtimeSessionId));
1242
+ if (cached?.providerType || cached?.providerSessionId) return cached;
1243
+ const fromLedger = resolveMeshSessionProviderMetadataFromLedger(ctx, nodeId, runtimeSessionId);
1244
+ if (fromLedger) rememberMeshSessionProviderMetadata(nodeId, runtimeSessionId, fromLedger);
1245
+ return fromLedger;
1246
+ }
857
1247
  function countUncommittedChanges(status) {
858
1248
  if (typeof status?.uncommittedChanges === "number") return status.uncommittedChanges;
859
1249
  const keys = ["staged", "modified", "untracked", "deleted", "renamed"];
@@ -924,6 +1314,16 @@ function missingProviderPriorityMessage(nodeId) {
924
1314
  return `Node '${nodeId}' has no providerPriority policy; pass type explicitly or configure node.policy.providerPriority`;
925
1315
  }
926
1316
  function getNodeLaunchReadiness(node) {
1317
+ const bootstrap = node.worktreeBootstrap;
1318
+ if (node.isLocalWorktree && bootstrap?.status === "failed" && bootstrap?.required !== false) {
1319
+ return {
1320
+ providerPriority: readProviderPriority(node.policy),
1321
+ launchReady: false,
1322
+ launchBlockedReason: "worktree_bootstrap_failed",
1323
+ launchBlockedMessage: typeof bootstrap.error === "string" && bootstrap.error.trim() ? bootstrap.error.trim() : "Required worktree bootstrap failed; resolve it before launching an agent into this node.",
1324
+ worktreeBootstrap: bootstrap
1325
+ };
1326
+ }
927
1327
  const providerPriority = readProviderPriority(node.policy);
928
1328
  if (providerPriority.length) {
929
1329
  return {
@@ -938,6 +1338,33 @@ function getNodeLaunchReadiness(node) {
938
1338
  launchBlockedMessage: missingProviderPriorityMessage(node.id)
939
1339
  };
940
1340
  }
1341
+ function getWorktreeBootstrapLaunchBlock(node) {
1342
+ const bootstrap = node.worktreeBootstrap;
1343
+ if (!node.isLocalWorktree || bootstrap?.status !== "failed" || bootstrap?.required === false) return void 0;
1344
+ return {
1345
+ success: false,
1346
+ code: "worktree_bootstrap_failed",
1347
+ error: typeof bootstrap.error === "string" && bootstrap.error.trim() ? bootstrap.error.trim() : `Node '${node.id}' has a failed required worktree bootstrap.`,
1348
+ nodeId: node.id,
1349
+ worktreeBootstrap: bootstrap,
1350
+ recoveryHint: "Fix the configured worktree bootstrap command or remove/recreate the worktree node before launching an agent."
1351
+ };
1352
+ }
1353
+ async function collectLiveStatusSessions(ctx, node) {
1354
+ try {
1355
+ const statusResult = await commandForNode(ctx, node, "get_status_metadata", {});
1356
+ return extractStatusMetadataSessions(statusResult);
1357
+ } catch {
1358
+ return [];
1359
+ }
1360
+ }
1361
+ async function collectMeshViewQueueNodesWithLiveSessions(ctx) {
1362
+ const nodes = await Promise.all(ctx.mesh.nodes.map(async (node) => {
1363
+ const liveSessions = await collectLiveStatusSessions(ctx, node);
1364
+ return liveSessions.length > 0 ? { ...node, sessions: liveSessions } : node;
1365
+ }));
1366
+ return nodes;
1367
+ }
941
1368
  function readNumeric(value, fallback = 0) {
942
1369
  const parsed = Number(value);
943
1370
  return Number.isFinite(parsed) ? parsed : fallback;
@@ -1073,7 +1500,8 @@ async function commandForNode(ctx, node, command, args = {}) {
1073
1500
  if (isLocalTransport(ctx.transport)) {
1074
1501
  return ctx.transport.command(command, args);
1075
1502
  }
1076
- throw new Error(`Command '${command}' requires daemon IPC/local transport for node '${node.id}'`);
1503
+ const identity = buildNodeMachineIdentity(ctx, node);
1504
+ throw new Error(`Command '${command}' requires daemon IPC/local transport for node '${node.id}' (hostname=${identity.hostname || "unknown"}, coordinatorHostname=${identity.coordinatorHostname || "unknown"}, sameMachine=${identity.sameMachine})`);
1077
1505
  }
1078
1506
  function normalizePendingMeshCoordinatorEvents(value) {
1079
1507
  const payload = unwrapCommandPayload(value);
@@ -1091,6 +1519,14 @@ function buildMeshForwardPayloadFromPendingEvent(event) {
1091
1519
  providerType: readString(metadataEvent.providerType),
1092
1520
  providerSessionId: readString(metadataEvent.providerSessionId),
1093
1521
  finalSummary: readString(metadataEvent.finalSummary) || readString(metadataEvent.summary),
1522
+ jobId: readString(metadataEvent.jobId),
1523
+ interactionId: readString(metadataEvent.interactionId),
1524
+ status: readString(metadataEvent.status),
1525
+ targetDaemonId: readString(metadataEvent.targetDaemonId),
1526
+ startedAt: readString(metadataEvent.startedAt),
1527
+ completedAt: readString(metadataEvent.completedAt),
1528
+ retryOfJobId: readString(metadataEvent.retryOfJobId),
1529
+ ...metadataEvent.result && typeof metadataEvent.result === "object" && !Array.isArray(metadataEvent.result) ? { result: metadataEvent.result } : {},
1094
1530
  ...metadataEvent.intentional === true ? { intentional: true } : {},
1095
1531
  ...metadataEvent.intentionalStop === true ? { intentionalStop: true } : {},
1096
1532
  ...metadataEvent.operatorCleanup === true ? { operatorCleanup: true } : {},
@@ -1107,8 +1543,9 @@ async function drainCoordinatorPendingEvents(ctx, opts) {
1107
1543
  const surfacedEvents = [];
1108
1544
  try {
1109
1545
  surfacedEvents.push(
1110
- ...normalizePendingMeshCoordinatorEvents(await ctx.transport.command("get_pending_mesh_events", {})).filter(matchesCurrentMesh)
1546
+ ...normalizePendingMeshCoordinatorEvents(await ctx.transport.command("get_pending_mesh_events", { meshId: ctx.mesh.id })).filter(matchesCurrentMesh)
1111
1547
  );
1548
+ surfacedEvents.forEach(rememberMeshSessionProviderMetadataFromEvent);
1112
1549
  } catch {
1113
1550
  }
1114
1551
  for (const node of ctx.mesh.nodes) {
@@ -1116,27 +1553,31 @@ async function drainCoordinatorPendingEvents(ctx, opts) {
1116
1553
  if (requestedNodeIds && !requestedNodeIds.has(node.id)) continue;
1117
1554
  try {
1118
1555
  const remoteEvents = normalizePendingMeshCoordinatorEvents(
1119
- await ctx.transport.meshCommand(node.daemonId, "get_pending_mesh_events", {})
1556
+ await ctx.transport.meshCommand(node.daemonId, "get_pending_mesh_events", { meshId: ctx.mesh.id })
1120
1557
  ).filter(matchesCurrentMesh);
1121
1558
  if (remoteEvents.length === 0) continue;
1122
1559
  for (const event of remoteEvents) {
1123
1560
  const payload = buildMeshForwardPayloadFromPendingEvent(event);
1124
1561
  if (!payload.event || !payload.meshId) continue;
1125
1562
  await ctx.transport.command("mesh_forward_event", payload);
1563
+ rememberMeshSessionProviderMetadataFromEvent({ ...event, metadataEvent: payload });
1126
1564
  }
1127
1565
  } catch {
1128
1566
  }
1129
1567
  }
1130
1568
  try {
1131
1569
  surfacedEvents.push(
1132
- ...normalizePendingMeshCoordinatorEvents(await ctx.transport.command("get_pending_mesh_events", {})).filter(matchesCurrentMesh)
1570
+ ...normalizePendingMeshCoordinatorEvents(await ctx.transport.command("get_pending_mesh_events", { meshId: ctx.mesh.id })).filter(matchesCurrentMesh)
1133
1571
  );
1572
+ surfacedEvents.forEach(rememberMeshSessionProviderMetadataFromEvent);
1134
1573
  } catch {
1135
1574
  }
1136
1575
  return surfacedEvents;
1137
1576
  }
1138
1577
  if (isLocalTransport(ctx.transport)) {
1139
- return (0, import_daemon_core.drainPendingMeshCoordinatorEvents)().filter(matchesCurrentMesh);
1578
+ const events = (0, import_daemon_core.drainPendingMeshCoordinatorEvents)(ctx.mesh.id).filter(matchesCurrentMesh);
1579
+ events.forEach(rememberMeshSessionProviderMetadataFromEvent);
1580
+ return events;
1140
1581
  }
1141
1582
  return [];
1142
1583
  }
@@ -1153,11 +1594,12 @@ function buildRemoveNodeArgs(ctx, nodeId, sessionCleanupMode) {
1153
1594
  }
1154
1595
  var MESH_STATUS_TOOL = {
1155
1596
  name: "mesh_status",
1156
- description: "Get the current status of all nodes in the repo mesh \u2014 health, git state, active sessions, recovery hints, and recommended next steps. Use this to decide which node to send work to or how to recover from failures.",
1597
+ description: "Get the current status of all nodes in the repo mesh \u2014 health, git state, active sessions, recovery hints, and recommended next steps. Use this to decide which node to send work to or how to recover from failures. Do not repeatedly call this to wait for generating delegated work; wait for pendingCoordinatorEvents/completion events or an explicit user status request.",
1157
1598
  inputSchema: {
1158
1599
  type: "object",
1159
1600
  properties: {
1160
- _gemini_compat: { type: "string", description: "Dummy property for Gemini compatibility. Ignore this." }
1601
+ _gemini_compat: { type: "string", description: "Dummy property for Gemini compatibility. Ignore this." },
1602
+ includeStaleDirectWorkDetails: { type: "boolean", description: "Opt in to the full staleDirectWork array. Defaults false; normal status returns compact staleDirectWorkSummary only." }
1161
1603
  }
1162
1604
  }
1163
1605
  };
@@ -1177,14 +1619,16 @@ var MESH_ENQUEUE_TASK_TOOL = {
1177
1619
  inputSchema: {
1178
1620
  type: "object",
1179
1621
  properties: {
1180
- message: { type: "string", description: "The task instruction for the agent." }
1622
+ message: { type: "string", description: "The task instruction for the agent." },
1623
+ task_mode: { type: "string", enum: ["code_change", "validation", "live_debug_readonly", "launch_app", "convergence"], description: "Optional task-mode contract. live_debug_readonly rejects obvious write/commit/push/deploy/destructive instructions before dispatch." },
1624
+ taskMode: { type: "string", enum: ["code_change", "validation", "live_debug_readonly", "launch_app", "convergence"], description: "CamelCase alias for task_mode." }
1181
1625
  },
1182
1626
  required: ["message"]
1183
1627
  }
1184
1628
  };
1185
1629
  var MESH_VIEW_QUEUE_TOOL = {
1186
1630
  name: "mesh_view_queue",
1187
- description: "View the mesh work queue with source-of-truth active counts separated from historical completed/failed/cancelled records.",
1631
+ description: "View the mesh work queue with source-of-truth active counts separated from historical completed/failed/cancelled records. Do not repeatedly call this to wait for generating assigned work; wait for pendingCoordinatorEvents/completion events or an explicit user status request.",
1188
1632
  inputSchema: {
1189
1633
  type: "object",
1190
1634
  properties: {
@@ -1237,7 +1681,9 @@ var MESH_SEND_TASK_TOOL = {
1237
1681
  properties: {
1238
1682
  node_id: { type: "string", description: "Target node ID (from mesh_list_nodes)." },
1239
1683
  session_id: { type: "string", description: "Agent session ID on the target node." },
1240
- message: { type: "string", description: "Natural-language task to send to the agent." }
1684
+ message: { type: "string", description: "Natural-language task to send to the agent." },
1685
+ task_mode: { type: "string", enum: ["code_change", "validation", "live_debug_readonly", "launch_app", "convergence"], description: "Optional task-mode contract. live_debug_readonly rejects obvious write/commit/push/deploy/destructive instructions before local or remote direct dispatch." },
1686
+ taskMode: { type: "string", enum: ["code_change", "validation", "live_debug_readonly", "launch_app", "convergence"], description: "CamelCase alias for task_mode." }
1241
1687
  },
1242
1688
  required: ["node_id", "session_id", "message"]
1243
1689
  }
@@ -1295,6 +1741,21 @@ var MESH_GIT_STATUS_TOOL = {
1295
1741
  required: ["node_id"]
1296
1742
  }
1297
1743
  };
1744
+ var MESH_FAST_FORWARD_NODE_TOOL = {
1745
+ name: "mesh_fast_forward_node",
1746
+ description: "Safely dry-run or execute an obvious direct fast-forward for a mesh node without launching an agent session. Defaults to dry-run; execution requires execute=true. Never pushes, rebases, resets, cleans, or checks out arbitrary revisions.",
1747
+ inputSchema: {
1748
+ type: "object",
1749
+ properties: {
1750
+ node_id: { type: "string", description: "Target node ID." },
1751
+ branch: { type: "string", description: "Optional guard: require the node's current branch to match this branch before planning/executing." },
1752
+ execute: { type: "boolean", description: "When true, apply the fast-forward if all safety gates pass. Defaults false/dry-run." },
1753
+ dry_run: { type: "boolean", description: "Preview only. Defaults true unless execute=true; dry_run=true overrides execute." },
1754
+ update_submodules: { type: "boolean", description: "When true, if the root fast-forward changes gitlinks, run only git submodule update --init --recursive and verify submodules clean." }
1755
+ },
1756
+ required: ["node_id"]
1757
+ }
1758
+ };
1298
1759
  var MESH_CHECKPOINT_TOOL = {
1299
1760
  name: "mesh_checkpoint",
1300
1761
  description: "Create a git checkpoint (commit) on a mesh node workspace.",
@@ -1378,7 +1839,7 @@ var MESH_TASK_HISTORY_TOOL = {
1378
1839
  type: "object",
1379
1840
  properties: {
1380
1841
  tail: { type: "number", description: "Number of recent entries to return (default: 20)." },
1381
- kind: { type: "string", description: "Filter by entry kind: task_dispatched, task_completed, task_failed, task_stalled, session_launched, checkpoint_created, node_cloned, node_removed." }
1842
+ kind: { type: "string", description: "Filter by entry kind: task_dispatched, task_completed, task_failed, task_stalled, session_launched, checkpoint_created, node_cloned, node_removed, direct_fast_forward." }
1382
1843
  }
1383
1844
  }
1384
1845
  };
@@ -1398,7 +1859,7 @@ var MESH_RECONCILE_LEDGER_TOOL = {
1398
1859
  };
1399
1860
  var MESH_REFINE_NODE_TOOL = {
1400
1861
  name: "mesh_refine_node",
1401
- description: "The Refinery: Automatically validate and merge a completed worktree node back into its base branch. This tool automates the validation gate and merge queue step. It will merge the node's branch into its base branch and cleanly remove the worktree node and its sessions.",
1862
+ description: "The Refinery: Accept an async validation/merge/cleanup job for a completed worktree node. The immediate response includes async:true, status:'accepted', jobId, interactionId, target node, and startedAt; completion/failure evidence is delivered through pending mesh events and the mesh task ledger.",
1402
1863
  inputSchema: {
1403
1864
  type: "object",
1404
1865
  properties: {
@@ -1407,6 +1868,43 @@ var MESH_REFINE_NODE_TOOL = {
1407
1868
  required: ["node_id"]
1408
1869
  }
1409
1870
  };
1871
+ var MESH_REFINE_CONFIG_SCHEMA_TOOL = {
1872
+ name: "mesh_refine_config_schema",
1873
+ description: "Return the Repo Mesh Refinery config JSON schema and supported repo-local config locations. This is the validation source of truth; heuristic command detection is suggestions-only.",
1874
+ inputSchema: { type: "object", properties: {} }
1875
+ };
1876
+ var MESH_VALIDATE_REFINE_CONFIG_TOOL = {
1877
+ name: "mesh_validate_refine_config",
1878
+ description: "Validate the repo mesh/refine config for a node/workspace without running validation commands or merging.",
1879
+ inputSchema: {
1880
+ type: "object",
1881
+ properties: {
1882
+ node_id: { type: "string", description: "Optional node/workspace whose refine config should be loaded. Defaults to the first mesh node." },
1883
+ config: { type: "object", description: "Optional inline config object to validate instead of loading from the repo." }
1884
+ }
1885
+ }
1886
+ };
1887
+ var MESH_SUGGEST_REFINE_CONFIG_TOOL = {
1888
+ name: "mesh_suggest_refine_config",
1889
+ description: "Suggest a repo mesh/refine config scaffold from project context/package scripts. Suggestions are never executed until saved as explicit refine config.",
1890
+ inputSchema: {
1891
+ type: "object",
1892
+ properties: {
1893
+ node_id: { type: "string", description: "Optional node/workspace used for suggestions. Defaults to the first mesh node." }
1894
+ }
1895
+ }
1896
+ };
1897
+ var MESH_REFINE_PLAN_TOOL = {
1898
+ name: "mesh_refine_plan",
1899
+ description: "Dry-run Refinery plan for a worktree node: reports config source, validation commands, suggestions/unavailable reason, and merge/cleanup intent without executing validation or git merge.",
1900
+ inputSchema: {
1901
+ type: "object",
1902
+ properties: {
1903
+ node_id: { type: "string", description: "Node ID of the worktree node to plan." }
1904
+ },
1905
+ required: ["node_id"]
1906
+ }
1907
+ };
1410
1908
  var ALL_MESH_TOOLS = [
1411
1909
  MESH_STATUS_TOOL,
1412
1910
  MESH_LIST_NODES_TOOL,
@@ -1419,16 +1917,21 @@ var ALL_MESH_TOOLS = [
1419
1917
  MESH_READ_DEBUG_TOOL,
1420
1918
  MESH_LAUNCH_SESSION_TOOL,
1421
1919
  MESH_GIT_STATUS_TOOL,
1920
+ MESH_FAST_FORWARD_NODE_TOOL,
1422
1921
  MESH_CHECKPOINT_TOOL,
1423
1922
  MESH_APPROVE_TOOL,
1424
1923
  MESH_CLONE_NODE_TOOL,
1425
1924
  MESH_REMOVE_NODE_TOOL,
1426
1925
  MESH_REFINE_NODE_TOOL,
1926
+ MESH_REFINE_CONFIG_SCHEMA_TOOL,
1927
+ MESH_VALIDATE_REFINE_CONFIG_TOOL,
1928
+ MESH_SUGGEST_REFINE_CONFIG_TOOL,
1929
+ MESH_REFINE_PLAN_TOOL,
1427
1930
  MESH_CLEANUP_SESSIONS_TOOL,
1428
1931
  MESH_TASK_HISTORY_TOOL,
1429
1932
  MESH_RECONCILE_LEDGER_TOOL
1430
1933
  ];
1431
- async function meshStatus(ctx) {
1934
+ async function meshStatus(ctx, args = {}) {
1432
1935
  await refreshMeshFromDaemon(ctx);
1433
1936
  const { mesh, transport } = ctx;
1434
1937
  const results = [];
@@ -1437,6 +1940,9 @@ async function meshStatus(ctx) {
1437
1940
  const entry = {
1438
1941
  nodeId: node.id,
1439
1942
  workspace: node.workspace,
1943
+ machine: buildNodeMachineIdentity(ctx, node),
1944
+ daemonId: readNodeDaemonId(node),
1945
+ machineId: readNodeMachineId(node),
1440
1946
  ...getNodeLaunchReadiness(node)
1441
1947
  };
1442
1948
  try {
@@ -1446,6 +1952,7 @@ async function meshStatus(ctx) {
1446
1952
  const uncommittedChanges = countUncommittedChanges(status);
1447
1953
  const dirty = isGitStatusDirty(status);
1448
1954
  entry.health = status?.isGitRepo ? dirty ? "dirty" : "online" : "degraded";
1955
+ assignFullGitSnapshot(entry, status);
1449
1956
  entry.branch = status?.branch;
1450
1957
  entry.isDirty = dirty;
1451
1958
  entry.uncommittedChanges = uncommittedChanges;
@@ -1467,6 +1974,7 @@ async function meshStatus(ctx) {
1467
1974
  const uncommittedChanges = countUncommittedChanges(status);
1468
1975
  const dirty = isGitStatusDirty(status);
1469
1976
  entry.health = status?.isGitRepo ? dirty ? "dirty" : "online" : "degraded";
1977
+ assignFullGitSnapshot(entry, status);
1470
1978
  entry.branch = status?.branch;
1471
1979
  entry.isDirty = dirty;
1472
1980
  entry.uncommittedChanges = uncommittedChanges;
@@ -1542,15 +2050,43 @@ async function meshStatus(ctx) {
1542
2050
  }
1543
2051
  const relatedRepos = await collectRelatedRepoStatuses(ctx, node);
1544
2052
  if (relatedRepos.length) entry.relatedRepos = relatedRepos;
2053
+ const liveSessions = await collectLiveStatusSessions(ctx, node);
2054
+ if (liveSessions.length > 0) {
2055
+ entry.sessions = liveSessions;
2056
+ }
1545
2057
  results.push(entry);
1546
2058
  }
2059
+ const ledgerEntries = (0, import_daemon_core.readLedgerEntries)(mesh.id, { tail: 500 });
2060
+ const activeWorkEvidence = (0, import_daemon_core.buildMeshActiveWork)({
2061
+ meshId: mesh.id,
2062
+ queue: (0, import_daemon_core.getQueue)(mesh.id),
2063
+ ledgerEntries,
2064
+ nodes: results
2065
+ });
2066
+ const pollingGuidance = buildActiveWorkPollingGuidance(activeWorkEvidence.summary);
2067
+ const staleDirectWorkSummary = (0, import_daemon_core.buildCompactStaleDirectWorkSummary)(activeWorkEvidence.staleDirectWork, {
2068
+ note: activeWorkEvidence.staleDirectWorkNote,
2069
+ detailHint: "Full stale direct entries are omitted from mesh_status by default. Call mesh_status with includeStaleDirectWorkDetails=true or inspect mesh_task_history for ledger detail."
2070
+ });
1547
2071
  const response = {
1548
2072
  meshId: mesh.id,
1549
2073
  meshName: mesh.name,
1550
2074
  repoIdentity: mesh.repoIdentity,
1551
2075
  policy: mesh.policy,
1552
2076
  refreshedAt: (/* @__PURE__ */ new Date()).toISOString(),
2077
+ sourceOfTruth: {
2078
+ membership: "coordinator_daemon_live_mesh",
2079
+ currentStatus: "live_git_and_session_probes",
2080
+ activeWork: "mesh_queue_file_and_local_ledger",
2081
+ historicalEvidenceOnly: ["recoveryHints", "ledgerSummary"]
2082
+ },
1553
2083
  nodes: results,
2084
+ activeWork: activeWorkEvidence.activeWork,
2085
+ staleDirectWorkSummary,
2086
+ ...args.includeStaleDirectWorkDetails === true ? { staleDirectWork: activeWorkEvidence.staleDirectWork } : {},
2087
+ terminalDirectWork: activeWorkEvidence.terminalDirectWork,
2088
+ activeWorkSummary: activeWorkEvidence.summary,
2089
+ ...pollingGuidance ? { pollingGuidance } : {},
1554
2090
  branchConvergenceSummary: summarizeBranchConvergence(results)
1555
2091
  };
1556
2092
  try {
@@ -1559,6 +2095,14 @@ async function meshStatus(ctx) {
1559
2095
  }
1560
2096
  try {
1561
2097
  const pendingEvents = await drainCoordinatorPendingEvents(ctx);
2098
+ const asyncRefineJobs = (0, import_daemon_core.buildMeshAsyncRefineJobs)({
2099
+ meshId: mesh.id,
2100
+ ledgerEntries,
2101
+ pendingEvents
2102
+ });
2103
+ if (asyncRefineJobs.length > 0) {
2104
+ response.asyncRefineJobs = asyncRefineJobs;
2105
+ }
1562
2106
  if (pendingEvents.length > 0) {
1563
2107
  response.pendingCoordinatorEvents = pendingEvents;
1564
2108
  }
@@ -1568,12 +2112,17 @@ async function meshStatus(ctx) {
1568
2112
  }
1569
2113
  async function meshTaskHistory(ctx, args) {
1570
2114
  const { mesh } = ctx;
1571
- await drainCoordinatorPendingEvents(ctx);
2115
+ const pendingEvents = await drainCoordinatorPendingEvents(ctx);
1572
2116
  const tail = typeof args.tail === "number" && args.tail > 0 ? args.tail : 20;
1573
2117
  const kind = typeof args.kind === "string" && args.kind.trim() ? [args.kind.trim()] : void 0;
1574
2118
  const entries = (0, import_daemon_core.readLedgerEntries)(mesh.id, { tail, kind });
1575
2119
  const summary = (0, import_daemon_core.getLedgerSummary)(mesh.id);
1576
- return JSON.stringify({ meshId: mesh.id, entries, summary }, null, 2);
2120
+ return JSON.stringify({
2121
+ meshId: mesh.id,
2122
+ entries,
2123
+ summary,
2124
+ ...pendingEvents.length > 0 ? { pendingCoordinatorEvents: pendingEvents } : {}
2125
+ }, null, 2);
1577
2126
  }
1578
2127
  async function meshReconcileLedger(ctx, args) {
1579
2128
  await refreshMeshFromDaemon(ctx);
@@ -1663,6 +2212,9 @@ async function meshListNodes(ctx) {
1663
2212
  nodeId: n.id,
1664
2213
  workspace: n.workspace,
1665
2214
  repoRoot: n.repoRoot,
2215
+ daemonId: readNodeDaemonId(n),
2216
+ machineId: readNodeMachineId(n),
2217
+ machine: buildNodeMachineIdentity(ctx, n),
1666
2218
  isLocalWorktree: n.isLocalWorktree,
1667
2219
  policy: n.policy,
1668
2220
  relatedRepos: readRelatedRepos(n),
@@ -1672,12 +2224,13 @@ async function meshListNodes(ctx) {
1672
2224
  }, null, 2);
1673
2225
  }
1674
2226
  async function meshEnqueueTask(ctx, args) {
2227
+ const taskMode = readString(args.task_mode) || readString(args.taskMode);
1675
2228
  try {
1676
- const task = (0, import_daemon_core.enqueueTask)(ctx.mesh.id, args.message);
2229
+ const task = (0, import_daemon_core.enqueueTask)(ctx.mesh.id, args.message, { taskMode });
1677
2230
  if (isLocalTransport(ctx.transport) && !(ctx.transport instanceof IpcTransport)) {
1678
2231
  ctx.transport.command("trigger_mesh_queue", { meshId: ctx.mesh.id }).catch(() => {
1679
2232
  });
1680
- return JSON.stringify({ success: true, taskId: task.id, status: task.status });
2233
+ return JSON.stringify({ success: true, source: "queue", taskId: task.id, status: task.status, taskMode: task.taskMode });
1681
2234
  }
1682
2235
  if (ctx.transport instanceof IpcTransport) {
1683
2236
  ctx.transport.command("trigger_mesh_queue", { meshId: ctx.mesh.id }).catch(() => {
@@ -1690,11 +2243,24 @@ async function meshEnqueueTask(ctx, args) {
1690
2243
  ipcDispatchToRemoteAgent(ctx, node, { message: args.message }).then((result) => {
1691
2244
  if (result.success) {
1692
2245
  try {
2246
+ const providerType = result.providerType;
2247
+ const descriptor = summarizeTaskMessage(args.message);
1693
2248
  (0, import_daemon_core.appendLedgerEntry)(ctx.mesh.id, {
1694
2249
  kind: "task_dispatched",
1695
2250
  nodeId: node.id,
1696
2251
  sessionId: result.sessionId,
1697
- payload: { message: args.message, via: "p2p_direct", taskId: task.id }
2252
+ providerType,
2253
+ payload: {
2254
+ source: "queue",
2255
+ via: "p2p_direct",
2256
+ taskId: task.id,
2257
+ message: args.message,
2258
+ taskTitle: descriptor.taskTitle,
2259
+ taskSummary: descriptor.taskSummary,
2260
+ ...task.taskMode ? { taskMode: task.taskMode } : {},
2261
+ ...providerType ? { providerType } : {},
2262
+ targetSessionId: result.sessionId
2263
+ }
1698
2264
  });
1699
2265
  } catch {
1700
2266
  }
@@ -1705,24 +2271,37 @@ async function meshEnqueueTask(ctx, args) {
1705
2271
  }
1706
2272
  Promise.all(dispatchPromises).catch(() => {
1707
2273
  });
1708
- return JSON.stringify({ success: true, taskId: task.id, status: task.status });
2274
+ return JSON.stringify({ success: true, source: "queue", taskId: task.id, status: task.status, taskMode: task.taskMode });
1709
2275
  }
1710
- return JSON.stringify({ success: true, taskId: task.id, status: task.status });
2276
+ return JSON.stringify({ success: true, source: "queue", taskId: task.id, status: task.status, taskMode: task.taskMode });
1711
2277
  } catch (e) {
1712
- return JSON.stringify({ success: false, error: e.message });
2278
+ const message = e?.message || String(e);
2279
+ if (message.includes("live_debug_readonly_guardrail_violation")) {
2280
+ return JSON.stringify({ success: false, code: "live_debug_readonly_guardrail_violation", taskMode, error: message });
2281
+ }
2282
+ return JSON.stringify({ success: false, error: message });
1713
2283
  }
1714
2284
  }
1715
2285
  async function meshViewQueue(ctx, args) {
1716
2286
  try {
2287
+ await refreshMeshFromDaemon(ctx);
1717
2288
  const statusFilter = sanitizeQueueStatusFilter(args.status);
1718
2289
  const view = normalizeQueueViewMode(args.view);
1719
- const fullQueue = annotateQueueStaleness((0, import_daemon_core.getQueue)(ctx.mesh.id), ctx.mesh);
2290
+ const fullQueue = prioritizeActiveQueueRows(annotateQueueStaleness((0, import_daemon_core.getQueue)(ctx.mesh.id), ctx.mesh));
1720
2291
  const queue = filterQueueForView(fullQueue, view, statusFilter);
1721
2292
  const summary = buildQueueStatusSummary(fullQueue);
1722
2293
  const visibleSummary = buildQueueStatusSummary(queue);
1723
2294
  const maintenance = buildQueueMaintenanceReport(fullQueue);
2295
+ const liveNodes = await collectMeshViewQueueNodesWithLiveSessions(ctx);
2296
+ const activeWorkEvidence = (0, import_daemon_core.buildMeshActiveWork)({
2297
+ meshId: ctx.mesh.id,
2298
+ queue: fullQueue,
2299
+ ledgerEntries: (0, import_daemon_core.readLedgerEntries)(ctx.mesh.id, { tail: 500 }),
2300
+ nodes: liveNodes
2301
+ });
1724
2302
  const staleAssignedTasks = maintenance.staleAssignedTasks || [];
1725
2303
  const requestedHistoricalRows = queue.some((task) => HISTORICAL_QUEUE_STATUSES.has(String(task?.status || "")));
2304
+ const pollingGuidance = buildActiveWorkPollingGuidance(activeWorkEvidence.summary);
1726
2305
  return JSON.stringify({
1727
2306
  success: true,
1728
2307
  sourceOfTruth: {
@@ -1738,6 +2317,10 @@ async function meshViewQueue(ctx, args) {
1738
2317
  },
1739
2318
  queue,
1740
2319
  visibleQueue: queue,
2320
+ activeWork: activeWorkEvidence.activeWork,
2321
+ staleDirectWork: activeWorkEvidence.staleDirectWork,
2322
+ activeWorkSummary: activeWorkEvidence.summary,
2323
+ ...pollingGuidance ? { pollingGuidance } : {},
1741
2324
  visibleSummary,
1742
2325
  summary,
1743
2326
  activeCounts: summary.activeCounts,
@@ -1771,6 +2354,10 @@ async function meshQueueCancel(ctx, args) {
1771
2354
  if (!taskId) return JSON.stringify({ success: false, error: "task_id required" });
1772
2355
  const task = (0, import_daemon_core.cancelTask)(ctx.mesh.id, taskId, { reason: args.reason });
1773
2356
  if (!task) return JSON.stringify({ success: false, error: `Queue task '${taskId}' not found` });
2357
+ if (isLocalTransport(ctx.transport)) {
2358
+ ctx.transport.command("trigger_mesh_queue", { meshId: ctx.mesh.id }).catch(() => {
2359
+ });
2360
+ }
1774
2361
  return JSON.stringify({ success: true, task }, null, 2);
1775
2362
  } catch (e) {
1776
2363
  return JSON.stringify({ success: false, error: e.message });
@@ -1801,10 +2388,46 @@ async function meshQueueRequeue(ctx, args) {
1801
2388
  }
1802
2389
  }
1803
2390
  async function meshSendTask(ctx, args) {
2391
+ const requestedTaskMode = readString(args.task_mode) || readString(args.taskMode);
2392
+ const modeValidation = (0, import_daemon_core.validateMeshTaskModeRequest)(requestedTaskMode, args.message);
2393
+ if (!modeValidation.valid) {
2394
+ return JSON.stringify({
2395
+ success: false,
2396
+ code: "live_debug_readonly_guardrail_violation",
2397
+ taskMode: modeValidation.taskMode || requestedTaskMode,
2398
+ violations: modeValidation.violations,
2399
+ allowedOperations: modeValidation.allowedOperations,
2400
+ error: `live_debug_readonly_guardrail_violation: forbidden operations (${modeValidation.violations.join(", ")})`
2401
+ });
2402
+ }
2403
+ const taskMode = modeValidation.taskMode;
1804
2404
  const node = await findNodeWithRefresh(ctx, args.node_id);
1805
2405
  if (node.policy?.readOnly) {
1806
2406
  return JSON.stringify({ error: `Node '${args.node_id}' is read-only` });
1807
2407
  }
2408
+ let explicitTargetSession;
2409
+ if (args.session_id && isWorkerTaskMode(taskMode) && (ctx.transport instanceof IpcTransport || isLocalTransport(ctx.transport))) {
2410
+ try {
2411
+ const statusResult = await commandForNode(ctx, node, "get_status_metadata", {});
2412
+ const sessions = extractStatusMetadataSessions(statusResult);
2413
+ explicitTargetSession = sessions.find((session) => readSessionRecordId(session) === args.session_id);
2414
+ if (explicitTargetSession && isMeshCoordinatorSessionRecord(explicitTargetSession)) {
2415
+ return JSON.stringify({
2416
+ success: false,
2417
+ recoverable: true,
2418
+ code: "mesh_target_session_is_coordinator",
2419
+ reason: "mesh_target_session_is_coordinator",
2420
+ nodeId: args.node_id,
2421
+ sessionId: args.session_id,
2422
+ taskMode: taskMode || "unspecified",
2423
+ error: `Session '${args.session_id}' is a Repo Mesh coordinator session, not a visible worker session. Launch or use a visible worker session before dispatching this task.`,
2424
+ nextAction: `Call mesh_launch_session for node '${args.node_id}' and then retry mesh_send_task with that worker session_id, or use mesh_enqueue_task for queue-based worker assignment.`
2425
+ });
2426
+ }
2427
+ } catch {
2428
+ explicitTargetSession = void 0;
2429
+ }
2430
+ }
1808
2431
  const duplicate = hasRecentDuplicateDispatch(ctx, args);
1809
2432
  if (duplicate.duplicate) {
1810
2433
  return JSON.stringify({
@@ -1828,75 +2451,144 @@ async function meshSendTask(ctx, args) {
1828
2451
  const res = await ctx.transport.meshEnqueueTask(node.daemonId, {
1829
2452
  meshId: ctx.mesh.id,
1830
2453
  message: args.message,
1831
- targetNodeId: args.node_id
2454
+ targetNodeId: args.node_id,
2455
+ ...taskMode ? { taskMode } : {}
1832
2456
  });
1833
2457
  return JSON.stringify(res);
1834
2458
  }
1835
2459
  const isLocalNode = isLocalControlPlaneNode(ctx, node);
1836
2460
  if (ctx.transport instanceof IpcTransport && node.daemonId && !isLocalNode) {
1837
2461
  const cached = meshSessionProviderMetadata.get(meshSessionCacheKey(args.node_id, args.session_id || ""));
2462
+ const taskId = (0, import_node_crypto.randomUUID)();
1838
2463
  const result2 = await ipcDispatchToRemoteAgent(ctx, node, {
1839
2464
  session_id: args.session_id,
1840
2465
  message: args.message,
1841
- providerType: cached?.providerType
2466
+ providerType: cached?.providerType,
2467
+ verifiedSession: explicitTargetSession
1842
2468
  });
1843
2469
  if (result2.success) {
1844
2470
  const dispatchedSessionId = args.session_id || result2.sessionId;
1845
2471
  try {
2472
+ const providerType = result2.providerType || cached?.providerType;
1846
2473
  (0, import_daemon_core.appendLedgerEntry)(ctx.mesh.id, {
1847
2474
  kind: "task_dispatched",
1848
2475
  nodeId: args.node_id,
1849
2476
  sessionId: dispatchedSessionId,
1850
- payload: {
1851
- message: args.message,
1852
- via: "p2p_direct",
1853
- ...dispatchedSessionId ? { targetSessionId: dispatchedSessionId } : {}
1854
- }
2477
+ providerType,
2478
+ payload: buildDirectTaskPayload(args.message, "p2p_direct", {
2479
+ taskId,
2480
+ taskMode,
2481
+ providerType,
2482
+ targetSessionId: dispatchedSessionId
2483
+ })
1855
2484
  });
1856
2485
  } catch {
1857
2486
  }
1858
2487
  }
1859
- return JSON.stringify({ ...result2, nodeId: args.node_id, dispatched: result2.success === true });
2488
+ return JSON.stringify({
2489
+ ...result2,
2490
+ nodeId: args.node_id,
2491
+ sessionId: result2.success ? args.session_id || result2.sessionId : args.session_id,
2492
+ ...result2.success ? { source: "direct", taskId } : {},
2493
+ taskMode,
2494
+ ...result2.success && result2.providerType ? { providerType: result2.providerType } : {},
2495
+ dispatched: result2.success === true
2496
+ });
1860
2497
  }
1861
2498
  if (args.session_id && isLocalTransport(ctx.transport)) {
1862
2499
  const cached = meshSessionProviderMetadata.get(meshSessionCacheKey(args.node_id, args.session_id));
2500
+ let resolvedProviderType = cached?.providerType || "";
2501
+ if (!resolvedProviderType) {
2502
+ let explicitSession = explicitTargetSession;
2503
+ if (!explicitSession) {
2504
+ const statusResult = await commandForNode(ctx, node, "get_status_metadata", {});
2505
+ const sessions = extractStatusMetadataSessions(statusResult);
2506
+ explicitSession = sessions.find((session) => readSessionRecordId(session) === args.session_id);
2507
+ }
2508
+ if (!explicitSession) {
2509
+ return JSON.stringify({
2510
+ success: false,
2511
+ recoverable: true,
2512
+ code: "mesh_target_session_not_found",
2513
+ reason: "mesh_target_session_not_found",
2514
+ transport: "local_ipc",
2515
+ retryRecommended: true,
2516
+ nodeId: args.node_id,
2517
+ sessionId: args.session_id,
2518
+ error: `Local session '${args.session_id}' is not present in live status for node '${args.node_id}'.`,
2519
+ nextAction: `Launch a fresh session with mesh_launch_session(node_id: '${args.node_id}') or retry without session_id so Repo Mesh can target a live delegate session.`
2520
+ });
2521
+ }
2522
+ resolvedProviderType = resolveSessionProviderType(explicitSession);
2523
+ if (resolvedProviderType) {
2524
+ meshSessionProviderMetadata.set(meshSessionCacheKey(args.node_id, args.session_id), {
2525
+ providerType: resolvedProviderType,
2526
+ providerSessionId: readString(explicitSession?.providerSessionId) || void 0
2527
+ });
2528
+ }
2529
+ }
2530
+ if (!resolvedProviderType) {
2531
+ return JSON.stringify({
2532
+ success: false,
2533
+ recoverable: true,
2534
+ code: "mesh_target_session_provider_unknown",
2535
+ reason: "mesh_target_session_provider_unknown",
2536
+ transport: "local_ipc",
2537
+ retryRecommended: false,
2538
+ nodeId: args.node_id,
2539
+ sessionId: args.session_id,
2540
+ error: `Local session '${args.session_id}' is live but does not expose providerType/cliType, so agent_command cannot be routed safely.`,
2541
+ nextAction: `Relaunch the target session on node '${args.node_id}' or retry without session_id so Repo Mesh can pick a session with provider metadata.`
2542
+ });
2543
+ }
1863
2544
  const dispatchResult = await commandForNode(ctx, node, "agent_command", {
1864
2545
  targetSessionId: args.session_id,
1865
- ...cached?.providerType ? { agentType: cached.providerType, cliType: cached.providerType, providerType: cached.providerType } : {},
2546
+ agentType: resolvedProviderType,
2547
+ cliType: resolvedProviderType,
2548
+ providerType: resolvedProviderType,
1866
2549
  action: "send_chat",
1867
2550
  message: args.message
1868
2551
  });
1869
2552
  const dispatchPayload = unwrapCommandPayload(dispatchResult);
1870
2553
  if (dispatchPayload?.success === false || dispatchResult?.success === false) {
2554
+ const source = dispatchPayload?.success === false ? dispatchPayload : dispatchResult;
1871
2555
  return JSON.stringify({
2556
+ ...source && typeof source === "object" ? source : {},
1872
2557
  success: false,
1873
2558
  nodeId: args.node_id,
1874
2559
  sessionId: args.session_id,
1875
2560
  error: dispatchPayload?.error || dispatchResult?.error || "agent_command rejected the task"
1876
2561
  });
1877
2562
  }
2563
+ const taskId = (0, import_node_crypto.randomUUID)();
1878
2564
  try {
1879
2565
  (0, import_daemon_core.appendLedgerEntry)(ctx.mesh.id, {
1880
2566
  kind: "task_dispatched",
1881
2567
  nodeId: args.node_id,
1882
2568
  sessionId: args.session_id,
1883
- providerType: cached?.providerType,
1884
- payload: { message: args.message, via: "local_direct" }
2569
+ providerType: resolvedProviderType,
2570
+ payload: buildDirectTaskPayload(args.message, "local_direct", {
2571
+ taskId,
2572
+ taskMode,
2573
+ providerType: resolvedProviderType,
2574
+ targetSessionId: args.session_id
2575
+ })
1885
2576
  });
1886
2577
  } catch {
1887
2578
  }
1888
- return JSON.stringify({ success: true, dispatched: true, nodeId: args.node_id, sessionId: args.session_id });
2579
+ return JSON.stringify({ success: true, dispatched: true, source: "direct", taskId, taskMode, providerType: resolvedProviderType, nodeId: args.node_id, sessionId: args.session_id });
1889
2580
  }
1890
2581
  const task = (0, import_daemon_core.enqueueTask)(ctx.mesh.id, args.message, {
1891
2582
  targetNodeId: args.node_id,
1892
- targetSessionId: args.session_id
2583
+ targetSessionId: args.session_id,
2584
+ taskMode
1893
2585
  });
1894
2586
  if (isLocalTransport(ctx.transport) || ctx.transport instanceof IpcTransport) {
1895
2587
  ctx.transport.command("trigger_mesh_queue", { meshId: ctx.mesh.id }).catch(() => {
1896
2588
  });
1897
2589
  }
1898
- const pendingEvents = isLocalTransport(ctx.transport) ? (0, import_daemon_core.drainPendingMeshCoordinatorEvents)() : [];
1899
- const result = { success: true, nodeId: args.node_id, taskId: task.id, status: task.status };
2590
+ const pendingEvents = isLocalTransport(ctx.transport) ? (0, import_daemon_core.drainPendingMeshCoordinatorEvents)(ctx.mesh.id) : [];
2591
+ const result = { success: true, source: "queue", nodeId: args.node_id, taskId: task.id, status: task.status, taskMode: task.taskMode };
1900
2592
  if (pendingEvents.length > 0) {
1901
2593
  result.pendingCoordinatorEvents = pendingEvents;
1902
2594
  }
@@ -1920,7 +2612,7 @@ async function meshReadChat(ctx, args) {
1920
2612
  await drainCoordinatorPendingEvents(ctx, { nodeIds: [args.node_id] });
1921
2613
  }
1922
2614
  if (isLocalTransport(ctx.transport)) {
1923
- const cached = meshSessionProviderMetadata.get(meshSessionCacheKey(args.node_id, args.session_id));
2615
+ const cached = resolveMeshSessionProviderMetadata(ctx, args.node_id, args.session_id);
1924
2616
  const providerSessionId = typeof args.provider_session_id === "string" && args.provider_session_id.trim() ? args.provider_session_id.trim() : cached?.providerSessionId;
1925
2617
  const result = await commandForNode(ctx, node, "read_chat", {
1926
2618
  sessionId: args.session_id,
@@ -1966,7 +2658,7 @@ async function meshReadChat(ctx, args) {
1966
2658
  async function meshReadDebug(ctx, args) {
1967
2659
  const node = await findNodeWithRefresh(ctx, args.node_id);
1968
2660
  if (isLocalTransport(ctx.transport)) {
1969
- const cached = meshSessionProviderMetadata.get(meshSessionCacheKey(args.node_id, args.session_id));
2661
+ const cached = resolveMeshSessionProviderMetadata(ctx, args.node_id, args.session_id);
1970
2662
  const providerSessionId = typeof args.provider_session_id === "string" && args.provider_session_id.trim() ? args.provider_session_id.trim() : cached?.providerSessionId;
1971
2663
  const delivery = args.delivery === "inline" ? void 0 : "daemon_file";
1972
2664
  const result = await commandForNode(ctx, node, "get_chat_debug_bundle", {
@@ -1997,6 +2689,8 @@ async function meshReadDebug(ctx, args) {
1997
2689
  }
1998
2690
  async function meshLaunchSession(ctx, args) {
1999
2691
  const node = await findNodeWithRefresh(ctx, args.node_id);
2692
+ const bootstrapBlock = getWorktreeBootstrapLaunchBlock(node);
2693
+ if (bootstrapBlock) return JSON.stringify(bootstrapBlock, null, 2);
2000
2694
  if (isLocalTransport(ctx.transport)) {
2001
2695
  let resolvedProviderType = typeof args.type === "string" && args.type.trim() ? args.type : "";
2002
2696
  if (!resolvedProviderType) {
@@ -2021,6 +2715,10 @@ async function meshLaunchSession(ctx, args) {
2021
2715
  const coordinatorNode = resolveCoordinatorNode(ctx);
2022
2716
  const coordinatorDaemonId = coordinatorNode?.daemonId || ctx.localDaemonId;
2023
2717
  const spawnedSessionVisibility = readSpawnedSessionVisibility(ctx.mesh.policy);
2718
+ const isLocalNode = isLocalControlPlaneNode(ctx, node);
2719
+ if (node.daemonId && !isLocalNode && !coordinatorDaemonId) {
2720
+ return JSON.stringify(buildMissingCoordinatorDaemonIdFailure(ctx, node, resolvedProviderType), null, 2);
2721
+ }
2024
2722
  let result;
2025
2723
  try {
2026
2724
  result = await commandForNode(ctx, node, "launch_cli", {
@@ -2061,7 +2759,6 @@ async function meshLaunchSession(ctx, args) {
2061
2759
  });
2062
2760
  } catch {
2063
2761
  }
2064
- const isLocalNode = isLocalControlPlaneNode(ctx, node);
2065
2762
  if (ctx.transport instanceof IpcTransport && node.daemonId && !isLocalNode) {
2066
2763
  ctx.transport.meshCommand(node.daemonId, "trigger_mesh_queue", { meshId: ctx.mesh.id }).catch(() => {
2067
2764
  });
@@ -2086,6 +2783,9 @@ async function meshLaunchSession(ctx, args) {
2086
2783
  const coordinatorNode = resolveCoordinatorNode(ctx);
2087
2784
  const coordinatorDaemonId = coordinatorNode?.daemonId || ctx.localDaemonId;
2088
2785
  const spawnedSessionVisibility = readSpawnedSessionVisibility(ctx.mesh.policy);
2786
+ if (!coordinatorDaemonId) {
2787
+ return JSON.stringify(buildMissingCoordinatorDaemonIdFailure(ctx, node, resolvedProviderType), null, 2);
2788
+ }
2089
2789
  try {
2090
2790
  const res = await ctx.transport.launch(node.daemonId, {
2091
2791
  type: resolvedProviderType,
@@ -2166,6 +2866,51 @@ async function meshGitStatus(ctx, args) {
2166
2866
  }, null, 2);
2167
2867
  }
2168
2868
  }
2869
+ async function meshFastForwardNode(ctx, args) {
2870
+ await refreshMeshFromDaemon(ctx);
2871
+ const node = await findNodeWithRefresh(ctx, args.node_id);
2872
+ const submoduleIgnorePaths = node.policy?.submoduleIgnorePaths || [];
2873
+ if (node.policy?.readOnly) {
2874
+ return JSON.stringify({
2875
+ success: false,
2876
+ code: "node_read_only",
2877
+ nodeId: args.node_id,
2878
+ workspace: node.workspace,
2879
+ allowed: false,
2880
+ willRun: false,
2881
+ executed: false,
2882
+ blockingReasons: ["node_read_only"]
2883
+ }, null, 2);
2884
+ }
2885
+ try {
2886
+ const dryRun = args.dry_run === true || args.execute !== true;
2887
+ const result = await commandForNode(ctx, node, "fast_forward_mesh_node", {
2888
+ meshId: ctx.mesh.id,
2889
+ nodeId: node.id,
2890
+ workspace: node.workspace,
2891
+ branch: typeof args.branch === "string" ? args.branch : void 0,
2892
+ execute: args.execute === true && args.dry_run !== true,
2893
+ dryRun,
2894
+ updateSubmodules: args.update_submodules === true,
2895
+ submoduleIgnorePaths: submoduleIgnorePaths.length > 0 ? submoduleIgnorePaths : void 0
2896
+ });
2897
+ return JSON.stringify(unwrapCommandPayload(result), null, 2);
2898
+ } catch (e) {
2899
+ const failure = buildCoordinatorP2pRelayFailure(e, {
2900
+ command: "fast_forward_mesh_node",
2901
+ targetDaemonId: node.daemonId,
2902
+ nodeId: args.node_id
2903
+ });
2904
+ return JSON.stringify({
2905
+ ...failure,
2906
+ workspace: node.workspace,
2907
+ allowed: false,
2908
+ willRun: false,
2909
+ executed: false,
2910
+ blockingReasons: [failure.code || "mesh_fast_forward_unavailable"]
2911
+ }, null, 2);
2912
+ }
2913
+ }
2169
2914
  async function meshCheckpoint(ctx, args) {
2170
2915
  const node = await findNodeWithRefresh(ctx, args.node_id);
2171
2916
  if (node.policy?.readOnly) {
@@ -2181,7 +2926,13 @@ async function meshCheckpoint(ctx, args) {
2181
2926
  (0, import_daemon_core.appendLedgerEntry)(ctx.mesh.id, {
2182
2927
  kind: "checkpoint_created",
2183
2928
  nodeId: args.node_id,
2184
- payload: { message: args.message, commit: result?.checkpoint?.commit }
2929
+ payload: {
2930
+ message: args.message,
2931
+ commit: result?.checkpoint?.commit,
2932
+ outcome: result?.checkpoint?.status || (result?.checkpoint?.noop ? "skipped" : void 0),
2933
+ noop: result?.checkpoint?.noop === true,
2934
+ reason: result?.checkpoint?.reason
2935
+ }
2185
2936
  });
2186
2937
  } catch {
2187
2938
  }
@@ -2197,7 +2948,13 @@ async function meshCheckpoint(ctx, args) {
2197
2948
  (0, import_daemon_core.appendLedgerEntry)(ctx.mesh.id, {
2198
2949
  kind: "checkpoint_created",
2199
2950
  nodeId: args.node_id,
2200
- payload: { message: args.message, commit: res?.checkpoint?.commit }
2951
+ payload: {
2952
+ message: args.message,
2953
+ commit: res?.checkpoint?.commit,
2954
+ outcome: res?.checkpoint?.status || (res?.checkpoint?.noop ? "skipped" : void 0),
2955
+ noop: res?.checkpoint?.noop === true,
2956
+ reason: res?.checkpoint?.reason
2957
+ }
2201
2958
  });
2202
2959
  } catch {
2203
2960
  }
@@ -2251,6 +3008,7 @@ async function meshCloneNode(ctx, args) {
2251
3008
  if (existingIndex >= 0) ctx.mesh.nodes[existingIndex] = clonePayload.node;
2252
3009
  else ctx.mesh.nodes.push(clonePayload.node);
2253
3010
  ctx.mesh.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
3011
+ await syncCoordinatorDaemonMeshCache(ctx);
2254
3012
  }
2255
3013
  return JSON.stringify(result, null, 2);
2256
3014
  } else if (!isLocalTransport(ctx.transport) && sourceNode.daemonId) {
@@ -2268,6 +3026,7 @@ async function meshCloneNode(ctx, args) {
2268
3026
  if (existingIndex >= 0) ctx.mesh.nodes[existingIndex] = clonePayload.node;
2269
3027
  else ctx.mesh.nodes.push(clonePayload.node);
2270
3028
  ctx.mesh.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
3029
+ await syncCoordinatorDaemonMeshCache(ctx);
2271
3030
  }
2272
3031
  return JSON.stringify(res, null, 2);
2273
3032
  } catch (e) {
@@ -2363,6 +3122,43 @@ async function meshRemoveNode(ctx, args) {
2363
3122
  return JSON.stringify({ error: "Cloud mesh remove_node requires node daemonId" });
2364
3123
  }
2365
3124
  }
3125
+ function resolveRefineConfigNode(ctx, nodeId) {
3126
+ if (nodeId) return findNode(ctx.mesh, nodeId);
3127
+ const node = ctx.mesh.nodes.find((entry) => !!entry.workspace);
3128
+ if (!node) throw new Error("No mesh node with a workspace is available");
3129
+ return node;
3130
+ }
3131
+ async function meshRefineConfigSchema(ctx) {
3132
+ const node = resolveRefineConfigNode(ctx);
3133
+ const result = await commandForNode(ctx, node, "get_mesh_refine_config_schema", {});
3134
+ return JSON.stringify(result, null, 2);
3135
+ }
3136
+ async function meshValidateRefineConfig(ctx, args) {
3137
+ const node = resolveRefineConfigNode(ctx, args.node_id);
3138
+ const result = await commandForNode(ctx, node, "validate_mesh_refine_config", {
3139
+ workspace: node.workspace,
3140
+ inlineMesh: ctx.mesh,
3141
+ ...args.config ? { config: args.config } : {}
3142
+ });
3143
+ return JSON.stringify(result, null, 2);
3144
+ }
3145
+ async function meshSuggestRefineConfig(ctx, args) {
3146
+ const node = resolveRefineConfigNode(ctx, args.node_id);
3147
+ const result = await commandForNode(ctx, node, "suggest_mesh_refine_config", {
3148
+ workspace: node.workspace,
3149
+ inlineMesh: ctx.mesh
3150
+ });
3151
+ return JSON.stringify(result, null, 2);
3152
+ }
3153
+ async function meshRefinePlan(ctx, args) {
3154
+ const node = await findNodeWithRefresh(ctx, args.node_id);
3155
+ const result = await commandForNode(ctx, node, "plan_mesh_refine_node", {
3156
+ meshId: ctx.mesh.id,
3157
+ nodeId: args.node_id,
3158
+ inlineMesh: ctx.mesh
3159
+ });
3160
+ return JSON.stringify(result, null, 2);
3161
+ }
2366
3162
  async function meshRefineNode(ctx, args) {
2367
3163
  const node = await findNodeWithRefresh(ctx, args.node_id);
2368
3164
  if (isLocalTransport(ctx.transport)) {
@@ -2371,7 +3167,7 @@ async function meshRefineNode(ctx, args) {
2371
3167
  nodeId: args.node_id,
2372
3168
  inlineMesh: ctx.mesh
2373
3169
  });
2374
- if (result?.success && result.removeResult?.removed !== false) {
3170
+ if (result?.success && result.async !== true && result.removeResult?.removed !== false) {
2375
3171
  const idx = ctx.mesh.nodes.findIndex((n) => n.id === args.node_id);
2376
3172
  if (idx >= 0) {
2377
3173
  ctx.mesh.nodes.splice(idx, 1);
@@ -2386,7 +3182,7 @@ async function meshRefineNode(ctx, args) {
2386
3182
  nodeId: args.node_id,
2387
3183
  inlineMesh: ctx.mesh
2388
3184
  });
2389
- if (res?.success && res.removeResult?.removed !== false) {
3185
+ if (res?.success && res.async !== true && res.removeResult?.removed !== false) {
2390
3186
  const idx = ctx.mesh.nodes.findIndex((n) => n.id === args.node_id);
2391
3187
  if (idx >= 0) {
2392
3188
  ctx.mesh.nodes.splice(idx, 1);
@@ -2423,13 +3219,13 @@ var STANDARD_TOOLS = [
2423
3219
  function buildMcpHelpText() {
2424
3220
  const meshTools = ALL_MESH_TOOLS.map((tool) => tool.name);
2425
3221
  return `
2426
- adhdev-mcp \u2014 ADHDev MCP Server
3222
+ ADHDev MCP Server
2427
3223
 
2428
3224
  Usage:
2429
- adhdev-mcp Local mode (requires standalone daemon)
2430
- adhdev-mcp --api-key <key> Cloud mode (ADHDev cloud API)
2431
- adhdev-mcp --mode ipc --repo-mesh <mesh_id> Cloud daemon IPC mesh mode
2432
- adhdev-mcp --repo-mesh <mesh_id> Mesh mode (coordinator-scoped tools)
3225
+ adhdev mcp Local mode (requires standalone daemon)
3226
+ adhdev mcp --api-key <key> Cloud mode (ADHDev cloud API)
3227
+ adhdev mcp --mode ipc --repo-mesh <mesh_id> Cloud daemon IPC mesh mode
3228
+ adhdev-mcp --help Compatibility bin (same server, legacy package entrypoint)
2433
3229
 
2434
3230
  Options:
2435
3231
  --mode <mode> Transport: local, cloud, or ipc
@@ -2454,6 +3250,7 @@ Mesh tools: ${meshTools.join(", ")}
2454
3250
  // src/server.ts
2455
3251
  var import_server = require("@modelcontextprotocol/sdk/server/index.js");
2456
3252
  var import_stdio = require("@modelcontextprotocol/sdk/server/stdio.js");
3253
+ var import_node_os = __toESM(require("os"));
2457
3254
  var import_types = require("@modelcontextprotocol/sdk/types.js");
2458
3255
 
2459
3256
  // src/transports/local.ts
@@ -3004,6 +3801,22 @@ function formatChatResult(result, sessionId, format, limit = 50, compact = false
3004
3801
  }))
3005
3802
  }, null, 2);
3006
3803
  }
3804
+ if ((format === "text" || format === void 0) && compact && compactPayload) {
3805
+ const lines2 = outputMessages.slice(-limit).map((m) => {
3806
+ const role = m.role === "user" ? "User" : m.role === "assistant" ? "Agent" : m.role;
3807
+ const content = messageContent(m);
3808
+ const truncated = content.length > 500 ? `${content.slice(0, 500)}\u2026` : content;
3809
+ return `[${role}] ${truncated}`;
3810
+ });
3811
+ if (compactPayload.summary) {
3812
+ const truncatedSummary = compactPayload.summary.length > 500 ? `${compactPayload.summary.slice(0, 500)}\u2026` : compactPayload.summary;
3813
+ lines2.push(`[Summary] ${truncatedSummary}`);
3814
+ }
3815
+ if (result?.pollingAdvisory) {
3816
+ lines2.push(`Advisory: ${result.pollingAdvisory.message}`);
3817
+ }
3818
+ return lines2.length > 0 ? lines2.join("\n\n") : "No messages in chat.";
3819
+ }
3007
3820
  if (outputMessages.length === 0) {
3008
3821
  return result?.pollingAdvisory ? `No messages in chat.
3009
3822
 
@@ -3971,6 +4784,7 @@ async function startMcpServer(opts) {
3971
4784
  requirePreTaskCheckpoint: false,
3972
4785
  requirePostTaskCheckpoint: true,
3973
4786
  requireApprovalForPush: true,
4787
+ allowAutoPublishSubmoduleMainCommits: false,
3974
4788
  requireApprovalForDestructiveGit: true,
3975
4789
  dirtyWorkspaceBehavior: "warn",
3976
4790
  maxParallelTasks: 2,
@@ -4027,11 +4841,13 @@ async function startMcpServer(opts) {
4027
4841
  }
4028
4842
  let localDaemonId;
4029
4843
  let localMachineId;
4844
+ let coordinatorHostname = import_node_os.default.hostname();
4030
4845
  if (transport instanceof LocalTransport || transport instanceof IpcTransport) {
4031
4846
  try {
4032
4847
  const { loadConfig } = await import("@adhdev/daemon-core");
4033
4848
  const cfg = loadConfig();
4034
- if (cfg.registeredMachineId) localMachineId = cfg.registeredMachineId;
4849
+ if (cfg.machineId) localMachineId = cfg.machineId;
4850
+ else if (cfg.registeredMachineId) localMachineId = cfg.registeredMachineId;
4035
4851
  } catch {
4036
4852
  }
4037
4853
  }
@@ -4039,11 +4855,13 @@ async function startMcpServer(opts) {
4039
4855
  try {
4040
4856
  const statusResult = await transport.getStatus();
4041
4857
  const instanceId = typeof statusResult?.status?.instanceId === "string" ? statusResult.status.instanceId.trim() : "";
4858
+ const hostname = typeof statusResult?.status?.hostname === "string" ? statusResult.status.hostname.trim() : typeof statusResult?.status?.machine?.hostname === "string" ? statusResult.status.machine.hostname.trim() : "";
4042
4859
  if (instanceId) localDaemonId = instanceId;
4860
+ if (hostname) coordinatorHostname = hostname;
4043
4861
  } catch {
4044
4862
  }
4045
4863
  }
4046
- const meshCtx = { mesh, transport, ...localDaemonId ? { localDaemonId } : {}, ...localMachineId ? { localMachineId } : {} };
4864
+ const meshCtx = { mesh, transport, ...localDaemonId ? { localDaemonId } : {}, ...localMachineId ? { localMachineId } : {}, ...coordinatorHostname ? { coordinatorHostname } : {} };
4047
4865
  const coordinatorPrompt = await buildMeshModeCoordinatorPrompt(mesh);
4048
4866
  const server2 = new import_server.Server(
4049
4867
  { name: "adhdev-mcp-server", version: "0.9.81" },
@@ -4072,7 +4890,7 @@ async function startMcpServer(opts) {
4072
4890
  let text;
4073
4891
  switch (name) {
4074
4892
  case "mesh_status":
4075
- text = await meshStatus(meshCtx);
4893
+ text = await meshStatus(meshCtx, a);
4076
4894
  break;
4077
4895
  case "mesh_list_nodes":
4078
4896
  text = await meshListNodes(meshCtx);
@@ -4104,6 +4922,9 @@ async function startMcpServer(opts) {
4104
4922
  case "mesh_git_status":
4105
4923
  text = await meshGitStatus(meshCtx, a);
4106
4924
  break;
4925
+ case "mesh_fast_forward_node":
4926
+ text = await meshFastForwardNode(meshCtx, a);
4927
+ break;
4107
4928
  case "mesh_checkpoint":
4108
4929
  text = await meshCheckpoint(meshCtx, a);
4109
4930
  break;
@@ -4119,6 +4940,18 @@ async function startMcpServer(opts) {
4119
4940
  case "mesh_refine_node":
4120
4941
  text = await meshRefineNode(meshCtx, a);
4121
4942
  break;
4943
+ case "mesh_refine_config_schema":
4944
+ text = await meshRefineConfigSchema(meshCtx);
4945
+ break;
4946
+ case "mesh_validate_refine_config":
4947
+ text = await meshValidateRefineConfig(meshCtx, a);
4948
+ break;
4949
+ case "mesh_suggest_refine_config":
4950
+ text = await meshSuggestRefineConfig(meshCtx, a);
4951
+ break;
4952
+ case "mesh_refine_plan":
4953
+ text = await meshRefinePlan(meshCtx, a);
4954
+ break;
4122
4955
  case "mesh_cleanup_sessions":
4123
4956
  text = await meshCleanupSessions(meshCtx, a);
4124
4957
  break;