@adhdev/daemon-standalone 0.9.82-rc.9 → 0.9.82-rc.90

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.
@@ -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,
@@ -235,6 +270,30 @@ var meshSessionProviderMetadata = /* @__PURE__ */ new Map();
235
270
  function readString(value) {
236
271
  return typeof value === "string" && value.trim() ? value.trim() : void 0;
237
272
  }
273
+ function summarizeTaskMessage(message) {
274
+ const taskSummary = message.replace(/\s+/g, " ").trim();
275
+ const taskTitle = taskSummary.length > 96 ? `${taskSummary.slice(0, 93)}...` : taskSummary;
276
+ return { taskTitle: taskTitle || "(untitled task)", taskSummary };
277
+ }
278
+ function buildDirectTaskPayload(message, via, opts) {
279
+ const descriptor = summarizeTaskMessage(message);
280
+ return {
281
+ source: "direct",
282
+ via,
283
+ taskId: opts.taskId,
284
+ message,
285
+ taskTitle: descriptor.taskTitle,
286
+ taskSummary: descriptor.taskSummary,
287
+ ...opts.taskMode ? { taskMode: opts.taskMode } : {},
288
+ ...opts.providerType ? { providerType: opts.providerType } : {},
289
+ ...opts.targetSessionId ? { targetSessionId: opts.targetSessionId } : {}
290
+ };
291
+ }
292
+ function findNode(mesh, nodeId) {
293
+ const node = mesh.nodes.find((n) => n.id === nodeId);
294
+ if (!node) throw new Error(`Node '${nodeId}' is not a member of mesh '${mesh.name}'`);
295
+ return node;
296
+ }
238
297
  var DUPLICATE_DISPATCH_WINDOW_MS = 6e4;
239
298
  var STALE_ASSIGNED_QUEUE_MS = 30 * 6e4;
240
299
  var OLD_HISTORICAL_QUEUE_RECORD_MS = 7 * 24 * 60 * 6e4;
@@ -246,15 +305,24 @@ async function refreshMeshFromDaemon(ctx) {
246
305
  const result = await ctx.transport.command("get_mesh", { meshId: ctx.mesh.id });
247
306
  if (!result?.success || !Array.isArray(result.mesh?.nodes)) return;
248
307
  const refreshedNodes = result.mesh.nodes.filter((n) => n?.id).map((n) => n);
249
- if (!refreshedNodes.length) return;
250
308
  ctx.mesh.nodes.splice(0, ctx.mesh.nodes.length, ...refreshedNodes);
251
309
  ctx.mesh.updatedAt = result.mesh.updatedAt ?? ctx.mesh.updatedAt;
252
310
  } catch {
253
311
  }
254
312
  }
313
+ async function syncCoordinatorDaemonMeshCache(ctx) {
314
+ if (!(ctx.transport instanceof IpcTransport)) return;
315
+ try {
316
+ await ctx.transport.command("get_mesh", {
317
+ meshId: ctx.mesh.id,
318
+ inlineMesh: ctx.mesh
319
+ });
320
+ } catch {
321
+ }
322
+ }
255
323
  async function findNodeWithRefresh(ctx, nodeId) {
256
324
  const hit = ctx.mesh.nodes.find((n) => n.id === nodeId);
257
- if (hit) return hit;
325
+ if (hit && !hit.isLocalWorktree) return hit;
258
326
  await refreshMeshFromDaemon(ctx);
259
327
  const refreshed = ctx.mesh.nodes.find((n) => n.id === nodeId);
260
328
  if (!refreshed) throw new Error(`Node '${nodeId}' is not a member of mesh '${ctx.mesh.name}'`);
@@ -262,7 +330,7 @@ async function findNodeWithRefresh(ctx, nodeId) {
262
330
  }
263
331
  async function findOptionalNodeWithRefresh(ctx, nodeId) {
264
332
  const hit = ctx.mesh.nodes.find((n) => n.id === nodeId);
265
- if (hit) return hit;
333
+ if (hit && !hit.isLocalWorktree) return hit;
266
334
  await refreshMeshFromDaemon(ctx);
267
335
  return ctx.mesh.nodes.find((n) => n.id === nodeId) ?? null;
268
336
  }
@@ -314,9 +382,26 @@ function buildMissingNodeReadChatRecovery(ctx, args) {
314
382
  readDebugLocator: readString(lastTerminal?.payload?.readDebugLocator) || readString(lastTerminal?.payload?.debugBundlePath)
315
383
  };
316
384
  if (finalSummary) {
385
+ if (args.compact === true) {
386
+ return {
387
+ ...compactChatPayload({
388
+ success: true,
389
+ status: "idle",
390
+ providerSessionId,
391
+ summary: finalSummary,
392
+ messages: [{ role: "assistant", content: finalSummary, isHistorical: true }]
393
+ }, {
394
+ nodeId: args.node_id,
395
+ sessionId: args.session_id,
396
+ limit: args.tail ?? 10
397
+ }),
398
+ recoveredFromLedger: true,
399
+ ledger
400
+ };
401
+ }
317
402
  return {
318
403
  success: true,
319
- compact: args.compact === true,
404
+ compact: false,
320
405
  recoveredFromLedger: true,
321
406
  nodeId: args.node_id,
322
407
  sessionId: args.session_id,
@@ -368,6 +453,14 @@ function buildMissingNodeReadChatRecovery(ctx, args) {
368
453
  function readSessionRecordId(session) {
369
454
  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
455
  }
456
+ function extractStatusMetadataSessions(value) {
457
+ const payload = unwrapCommandPayload(value);
458
+ const status = payload?.status && typeof payload.status === "object" ? payload.status : payload;
459
+ return Array.isArray(status?.sessions) ? status.sessions : [];
460
+ }
461
+ function resolveSessionProviderType(session) {
462
+ return readString(session?.providerType) || readString(session?.cliType) || readString(session?.agentType) || "";
463
+ }
371
464
  function addSessionRecord(target, session) {
372
465
  if (!session || typeof session !== "object" || isTerminalSessionRecord(session)) return;
373
466
  const sessionId = readSessionRecordId(session);
@@ -436,18 +529,26 @@ function queueAssignmentStaleReason(task, liveness) {
436
529
  }
437
530
  function buildQueueStatusSummary(queue) {
438
531
  const counts = { pending: 0, assigned: 0, completed: 0, failed: 0, cancelled: 0 };
532
+ let staleAssigned = 0;
439
533
  for (const task of queue) {
440
534
  const status = typeof task?.status === "string" ? task.status : void 0;
441
535
  if (status && Object.prototype.hasOwnProperty.call(counts, status)) {
442
536
  counts[status] += 1;
443
537
  }
538
+ if (status === "assigned" && task?.staleAssigned === true) staleAssigned += 1;
444
539
  }
540
+ const liveAssigned = Math.max(0, counts.assigned - staleAssigned);
445
541
  return {
446
542
  totalCount: queue.length,
447
- activeCount: counts.pending + counts.assigned,
543
+ activeCount: counts.pending + liveAssigned,
448
544
  historicalCount: counts.completed + counts.failed + counts.cancelled,
449
545
  counts,
450
546
  activeCounts: {
547
+ pending: counts.pending,
548
+ assigned: liveAssigned
549
+ },
550
+ staleAssignedCount: staleAssigned,
551
+ rawActiveCounts: {
451
552
  pending: counts.pending,
452
553
  assigned: counts.assigned
453
554
  },
@@ -475,6 +576,18 @@ function filterQueueForView(queue, view, statuses) {
475
576
  if (view === "historical") return queue.filter((task) => HISTORICAL_QUEUE_STATUSES.has(String(task?.status || "")));
476
577
  return queue;
477
578
  }
579
+ function prioritizeActiveQueueRows(queue) {
580
+ const active = [];
581
+ const historical = [];
582
+ const other = [];
583
+ for (const task of queue) {
584
+ const status = String(task?.status || "");
585
+ if (ACTIVE_QUEUE_STATUSES.has(status)) active.push(task);
586
+ else if (HISTORICAL_QUEUE_STATUSES.has(status)) historical.push(task);
587
+ else other.push(task);
588
+ }
589
+ return [...active, ...other, ...historical];
590
+ }
478
591
  function slimQueueTask(task) {
479
592
  return {
480
593
  id: task?.id,
@@ -580,22 +693,59 @@ function isIdleSessionRecord(session) {
580
693
  const chatStatus = typeof session?.activeChat?.status === "string" ? session.activeChat.status.toLowerCase() : "";
581
694
  return status === "idle" || chatStatus === "waiting_input";
582
695
  }
696
+ function isMeshOwnedDelegateSession(session, meshId, nodeId) {
697
+ const settings = session?.settings;
698
+ const sessionMeshId = typeof settings?.meshNodeFor === "string" ? settings.meshNodeFor.trim() : "";
699
+ const coordinatorDaemonId = typeof settings?.meshCoordinatorDaemonId === "string" ? settings.meshCoordinatorDaemonId.trim() : "";
700
+ const sessionNodeId = typeof settings?.meshNodeId === "string" ? settings.meshNodeId.trim() : "";
701
+ if (sessionMeshId !== meshId || !coordinatorDaemonId) return false;
702
+ return !sessionNodeId || sessionNodeId === nodeId;
703
+ }
583
704
  function chooseDispatchableSession(sessions, providerType, meshId, nodeId) {
584
705
  const live = sessions.filter((session) => !isTerminalSessionRecord(session));
585
706
  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
707
  const meshSessions = live.filter(
595
- (session) => isMeshOwnedDelegateSession(session)
708
+ (session) => isMeshOwnedDelegateSession(session, meshId, nodeId)
596
709
  );
597
710
  return meshSessions.find((session) => isIdleSessionRecord(session) && matchingProvider(session)) || meshSessions.find(matchingProvider) || void 0;
598
711
  }
712
+ function buildRelayUnsafeRemoteSessionFailure(ctx, node, sessionId, providerType) {
713
+ return {
714
+ success: false,
715
+ recoverable: true,
716
+ code: "mesh_delegate_session_missing_relay_metadata",
717
+ reason: "mesh_delegate_session_missing_relay_metadata",
718
+ transport: "mesh_transport",
719
+ retryRecommended: true,
720
+ meshId: ctx.mesh.id,
721
+ nodeId: node.id,
722
+ daemonId: node.daemonId,
723
+ workspace: node.workspace,
724
+ sessionId,
725
+ ...providerType ? { resolvedProviderType: providerType } : {},
726
+ 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.`,
727
+ 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.`,
728
+ noFallbackReason: "Blindly reusing a remote session without mesh relay metadata would silently drop task_completed / generating_completed events."
729
+ };
730
+ }
731
+ function buildMissingCoordinatorDaemonIdFailure(ctx, node, providerType) {
732
+ return {
733
+ success: false,
734
+ recoverable: true,
735
+ code: "mesh_coordinator_daemon_unknown",
736
+ reason: "mesh_coordinator_daemon_unknown",
737
+ transport: "mesh_transport",
738
+ retryRecommended: true,
739
+ meshId: ctx.mesh.id,
740
+ nodeId: node.id,
741
+ daemonId: node.daemonId,
742
+ workspace: node.workspace,
743
+ ...providerType ? { resolvedProviderType: providerType } : {},
744
+ 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.`,
745
+ 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.",
746
+ noFallbackReason: "Launching without meshCoordinatorDaemonId would create a worker session that can finish work but cannot emit task_completed / generating_completed back to the coordinator."
747
+ };
748
+ }
599
749
  function findNestedPayload(value, predicate) {
600
750
  const seen = /* @__PURE__ */ new Set();
601
751
  const stack = [{ payload: value, depth: 0 }];
@@ -623,12 +773,16 @@ function extractGitDiff(value) {
623
773
  }
624
774
  function extractSubmodules(value, ignorePaths) {
625
775
  const payload = unwrapCommandPayload(value);
626
- const subs = payload?.submodules ?? value?.submodules;
776
+ const subs = payload?.status?.submodules ?? payload?.submodules ?? value?.status?.submodules ?? value?.submodules;
627
777
  if (!Array.isArray(subs)) return void 0;
628
778
  if (ignorePaths.length === 0) return subs;
629
779
  const ignoreSet = new Set(ignorePaths);
630
780
  return subs.filter((s) => s?.path && !ignoreSet.has(s.path));
631
781
  }
782
+ function assignFullGitSnapshot(entry, status) {
783
+ if (!status || typeof status !== "object" || Array.isArray(status)) return;
784
+ entry.git = status;
785
+ }
632
786
  function extractLaunchPayload(value) {
633
787
  return findNestedPayload(value, (payload) => Boolean(payload?.sessionId || payload?.id || payload?.runtimeSessionId));
634
788
  }
@@ -753,20 +907,63 @@ async function ipcDispatchToRemoteAgent(ctx, node, args) {
753
907
  let sessionId = args.session_id?.trim() || "";
754
908
  const providerPriorityList = Array.isArray(node.policy?.providerPriority) ? node.policy.providerPriority : [];
755
909
  let resolvedProviderType = args.providerType?.trim() || providerPriorityList[0] || "";
756
- if (!sessionId) {
910
+ if (!sessionId || args.session_id) {
757
911
  try {
758
912
  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;
913
+ const sessions = extractStatusMetadataSessions(relayResult);
914
+ if (sessionId) {
915
+ const explicitSession = sessions.find((session) => readSessionRecordId(session) === sessionId);
916
+ if (!explicitSession) {
917
+ return {
918
+ success: false,
919
+ recoverable: true,
920
+ code: "mesh_target_session_not_found",
921
+ reason: "mesh_target_session_not_found",
922
+ transport: "mesh_transport",
923
+ retryRecommended: true,
924
+ meshId: ctx.mesh.id,
925
+ nodeId: node.id,
926
+ daemonId,
927
+ workspace: node.workspace,
928
+ sessionId,
929
+ ...resolvedProviderType ? { resolvedProviderType } : {},
930
+ error: `Remote session '${sessionId}' is not present in the live status for node '${node.id}'.`,
931
+ 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.`
932
+ };
933
+ }
934
+ if (!isMeshOwnedDelegateSession(explicitSession, ctx.mesh.id, node.id)) {
935
+ return buildRelayUnsafeRemoteSessionFailure(
936
+ ctx,
937
+ node,
938
+ sessionId,
939
+ resolvedProviderType || resolveSessionProviderType(explicitSession) || void 0
940
+ );
941
+ }
765
942
  if (!resolvedProviderType) {
766
- resolvedProviderType = targetSession.providerType || targetSession.cliType || "";
943
+ resolvedProviderType = resolveSessionProviderType(explicitSession);
944
+ }
945
+ } else {
946
+ const targetSession = chooseDispatchableSession(sessions, resolvedProviderType, ctx.mesh.id, node.id);
947
+ if (targetSession?.id || targetSession?.sessionId) {
948
+ sessionId = targetSession.id || targetSession.sessionId;
949
+ if (!resolvedProviderType) {
950
+ resolvedProviderType = resolveSessionProviderType(targetSession);
951
+ }
767
952
  }
768
953
  }
769
954
  } catch (e) {
955
+ if (sessionId) {
956
+ return {
957
+ ...buildCoordinatorP2pRelayFailure(e, {
958
+ command: "get_status_metadata",
959
+ targetDaemonId: daemonId,
960
+ nodeId: node.id,
961
+ sessionId
962
+ }),
963
+ success: false,
964
+ error: `Cannot verify remote session '${sessionId}' before dispatch: ${e?.message || String(e)}`
965
+ };
966
+ }
770
967
  }
771
968
  }
772
969
  if (!resolvedProviderType) {
@@ -796,7 +993,7 @@ async function ipcDispatchToRemoteAgent(ctx, node, args) {
796
993
  error: `P2P dispatch failed: ${errorMessage}`
797
994
  };
798
995
  }
799
- return { success: true, dispatched: true, sessionId: sessionId || resolvedProviderType };
996
+ return { success: true, dispatched: true, sessionId: sessionId || resolvedProviderType, providerType: resolvedProviderType };
800
997
  } catch (e) {
801
998
  const errorMessage = e?.message || String(e);
802
999
  return {
@@ -831,6 +1028,34 @@ function readNodeMachineId(node) {
831
1028
  function readNodeDaemonId(node) {
832
1029
  return readString(node.daemonId) || readString(node.daemon_id);
833
1030
  }
1031
+ function normalizeHostname(value) {
1032
+ const hostname = readString(value);
1033
+ if (!hostname) return void 0;
1034
+ return hostname.toLowerCase().replace(/\.$/, "");
1035
+ }
1036
+ function readNodeHostname(node) {
1037
+ return readString(node.hostname) || readString(node.machineHostname) || readString(node.machine_hostname) || readString(node.machineName) || readString(node.machine_name) || readString(node.lastProbe?.hostname) || readString(node.last_probe?.hostname) || readString(node.lastProbe?.machine?.hostname) || readString(node.last_probe?.machine?.hostname);
1038
+ }
1039
+ function buildNodeMachineIdentity(ctx, node) {
1040
+ const machineId = readNodeMachineId(node);
1041
+ const daemonId = readNodeDaemonId(node);
1042
+ const hostname = readNodeHostname(node);
1043
+ const coordinatorHostname = readString(ctx.coordinatorHostname);
1044
+ const hostnameMatches = Boolean(
1045
+ normalizeHostname(hostname) && normalizeHostname(coordinatorHostname) && normalizeHostname(hostname) === normalizeHostname(coordinatorHostname)
1046
+ );
1047
+ const sameMachine = isLocalControlPlaneNode(ctx, node) || hostnameMatches;
1048
+ return {
1049
+ daemonId,
1050
+ machineId,
1051
+ hostname,
1052
+ machineName: hostname,
1053
+ coordinatorHostname,
1054
+ sameMachine,
1055
+ locality: sameMachine ? "same_machine" : "remote_or_unknown",
1056
+ localityReason: sameMachine ? isLocalControlPlaneNode(ctx, node) ? "matched coordinator daemon or machine id" : "matched coordinator hostname" : "no coordinator daemon, machine id, or hostname match"
1057
+ };
1058
+ }
834
1059
  function isDirectLocalNode(ctx, node) {
835
1060
  const machineId = readNodeMachineId(node);
836
1061
  const daemonId = readNodeDaemonId(node);
@@ -938,6 +1163,14 @@ function getNodeLaunchReadiness(node) {
938
1163
  launchBlockedMessage: missingProviderPriorityMessage(node.id)
939
1164
  };
940
1165
  }
1166
+ async function collectLiveStatusSessions(ctx, node) {
1167
+ try {
1168
+ const statusResult = await commandForNode(ctx, node, "get_status_metadata", {});
1169
+ return extractStatusMetadataSessions(statusResult);
1170
+ } catch {
1171
+ return [];
1172
+ }
1173
+ }
941
1174
  function readNumeric(value, fallback = 0) {
942
1175
  const parsed = Number(value);
943
1176
  return Number.isFinite(parsed) ? parsed : fallback;
@@ -1073,7 +1306,81 @@ async function commandForNode(ctx, node, command, args = {}) {
1073
1306
  if (isLocalTransport(ctx.transport)) {
1074
1307
  return ctx.transport.command(command, args);
1075
1308
  }
1076
- throw new Error(`Command '${command}' requires daemon IPC/local transport for node '${node.id}'`);
1309
+ const identity = buildNodeMachineIdentity(ctx, node);
1310
+ 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})`);
1311
+ }
1312
+ function normalizePendingMeshCoordinatorEvents(value) {
1313
+ const payload = unwrapCommandPayload(value);
1314
+ const events = Array.isArray(payload?.events) ? payload.events : Array.isArray(value?.events) ? value.events : [];
1315
+ return events.filter((event) => event && typeof event === "object");
1316
+ }
1317
+ function buildMeshForwardPayloadFromPendingEvent(event) {
1318
+ const metadataEvent = event?.metadataEvent && typeof event.metadataEvent === "object" ? event.metadataEvent : {};
1319
+ return {
1320
+ event: readString(event?.event),
1321
+ meshId: readString(event?.meshId),
1322
+ nodeId: readString(event?.nodeId) || readString(metadataEvent.meshNodeId),
1323
+ workspace: readString(event?.workspace) || readString(metadataEvent.workspace),
1324
+ targetSessionId: readString(metadataEvent.targetSessionId) || readString(metadataEvent.sessionId) || readString(metadataEvent.instanceId),
1325
+ providerType: readString(metadataEvent.providerType),
1326
+ providerSessionId: readString(metadataEvent.providerSessionId),
1327
+ finalSummary: readString(metadataEvent.finalSummary) || readString(metadataEvent.summary),
1328
+ jobId: readString(metadataEvent.jobId),
1329
+ interactionId: readString(metadataEvent.interactionId),
1330
+ status: readString(metadataEvent.status),
1331
+ targetDaemonId: readString(metadataEvent.targetDaemonId),
1332
+ startedAt: readString(metadataEvent.startedAt),
1333
+ completedAt: readString(metadataEvent.completedAt),
1334
+ retryOfJobId: readString(metadataEvent.retryOfJobId),
1335
+ ...metadataEvent.result && typeof metadataEvent.result === "object" && !Array.isArray(metadataEvent.result) ? { result: metadataEvent.result } : {},
1336
+ ...metadataEvent.intentional === true ? { intentional: true } : {},
1337
+ ...metadataEvent.intentionalStop === true ? { intentionalStop: true } : {},
1338
+ ...metadataEvent.operatorCleanup === true ? { operatorCleanup: true } : {},
1339
+ ...readString(metadataEvent.reason) ? { reason: readString(metadataEvent.reason) } : {},
1340
+ ...readString(metadataEvent.stopReason) ? { stopReason: readString(metadataEvent.stopReason) } : {},
1341
+ ...readString(metadataEvent.cleanupReason) ? { cleanupReason: readString(metadataEvent.cleanupReason) } : {},
1342
+ ...readString(metadataEvent.source) ? { source: readString(metadataEvent.source) } : {}
1343
+ };
1344
+ }
1345
+ async function drainCoordinatorPendingEvents(ctx, opts) {
1346
+ const requestedNodeIds = opts?.nodeIds?.length ? new Set(opts.nodeIds) : null;
1347
+ const matchesCurrentMesh = (event) => readString(event?.meshId) === ctx.mesh.id;
1348
+ if (ctx.transport instanceof IpcTransport) {
1349
+ const surfacedEvents = [];
1350
+ try {
1351
+ surfacedEvents.push(
1352
+ ...normalizePendingMeshCoordinatorEvents(await ctx.transport.command("get_pending_mesh_events", { meshId: ctx.mesh.id })).filter(matchesCurrentMesh)
1353
+ );
1354
+ } catch {
1355
+ }
1356
+ for (const node of ctx.mesh.nodes) {
1357
+ if (!node.daemonId || isLocalControlPlaneNode(ctx, node)) continue;
1358
+ if (requestedNodeIds && !requestedNodeIds.has(node.id)) continue;
1359
+ try {
1360
+ const remoteEvents = normalizePendingMeshCoordinatorEvents(
1361
+ await ctx.transport.meshCommand(node.daemonId, "get_pending_mesh_events", { meshId: ctx.mesh.id })
1362
+ ).filter(matchesCurrentMesh);
1363
+ if (remoteEvents.length === 0) continue;
1364
+ for (const event of remoteEvents) {
1365
+ const payload = buildMeshForwardPayloadFromPendingEvent(event);
1366
+ if (!payload.event || !payload.meshId) continue;
1367
+ await ctx.transport.command("mesh_forward_event", payload);
1368
+ }
1369
+ } catch {
1370
+ }
1371
+ }
1372
+ try {
1373
+ surfacedEvents.push(
1374
+ ...normalizePendingMeshCoordinatorEvents(await ctx.transport.command("get_pending_mesh_events", { meshId: ctx.mesh.id })).filter(matchesCurrentMesh)
1375
+ );
1376
+ } catch {
1377
+ }
1378
+ return surfacedEvents;
1379
+ }
1380
+ if (isLocalTransport(ctx.transport)) {
1381
+ return (0, import_daemon_core.drainPendingMeshCoordinatorEvents)(ctx.mesh.id).filter(matchesCurrentMesh);
1382
+ }
1383
+ return [];
1077
1384
  }
1078
1385
  function isP2pTransportUnavailableError(error) {
1079
1386
  return (0, import_daemon_core.isP2pRelayTransportFailure)(error);
@@ -1112,7 +1419,9 @@ var MESH_ENQUEUE_TASK_TOOL = {
1112
1419
  inputSchema: {
1113
1420
  type: "object",
1114
1421
  properties: {
1115
- message: { type: "string", description: "The task instruction for the agent." }
1422
+ message: { type: "string", description: "The task instruction for the agent." },
1423
+ 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." },
1424
+ taskMode: { type: "string", enum: ["code_change", "validation", "live_debug_readonly", "launch_app", "convergence"], description: "CamelCase alias for task_mode." }
1116
1425
  },
1117
1426
  required: ["message"]
1118
1427
  }
@@ -1172,7 +1481,9 @@ var MESH_SEND_TASK_TOOL = {
1172
1481
  properties: {
1173
1482
  node_id: { type: "string", description: "Target node ID (from mesh_list_nodes)." },
1174
1483
  session_id: { type: "string", description: "Agent session ID on the target node." },
1175
- message: { type: "string", description: "Natural-language task to send to the agent." }
1484
+ message: { type: "string", description: "Natural-language task to send to the agent." },
1485
+ 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." },
1486
+ taskMode: { type: "string", enum: ["code_change", "validation", "live_debug_readonly", "launch_app", "convergence"], description: "CamelCase alias for task_mode." }
1176
1487
  },
1177
1488
  required: ["node_id", "session_id", "message"]
1178
1489
  }
@@ -1230,6 +1541,21 @@ var MESH_GIT_STATUS_TOOL = {
1230
1541
  required: ["node_id"]
1231
1542
  }
1232
1543
  };
1544
+ var MESH_FAST_FORWARD_NODE_TOOL = {
1545
+ name: "mesh_fast_forward_node",
1546
+ 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.",
1547
+ inputSchema: {
1548
+ type: "object",
1549
+ properties: {
1550
+ node_id: { type: "string", description: "Target node ID." },
1551
+ branch: { type: "string", description: "Optional guard: require the node's current branch to match this branch before planning/executing." },
1552
+ execute: { type: "boolean", description: "When true, apply the fast-forward if all safety gates pass. Defaults false/dry-run." },
1553
+ dry_run: { type: "boolean", description: "Preview only. Defaults true unless execute=true; dry_run=true overrides execute." },
1554
+ 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." }
1555
+ },
1556
+ required: ["node_id"]
1557
+ }
1558
+ };
1233
1559
  var MESH_CHECKPOINT_TOOL = {
1234
1560
  name: "mesh_checkpoint",
1235
1561
  description: "Create a git checkpoint (commit) on a mesh node workspace.",
@@ -1313,7 +1639,7 @@ var MESH_TASK_HISTORY_TOOL = {
1313
1639
  type: "object",
1314
1640
  properties: {
1315
1641
  tail: { type: "number", description: "Number of recent entries to return (default: 20)." },
1316
- kind: { type: "string", description: "Filter by entry kind: task_dispatched, task_completed, task_failed, task_stalled, session_launched, checkpoint_created, node_cloned, node_removed." }
1642
+ 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." }
1317
1643
  }
1318
1644
  }
1319
1645
  };
@@ -1333,7 +1659,7 @@ var MESH_RECONCILE_LEDGER_TOOL = {
1333
1659
  };
1334
1660
  var MESH_REFINE_NODE_TOOL = {
1335
1661
  name: "mesh_refine_node",
1336
- 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.",
1662
+ 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.",
1337
1663
  inputSchema: {
1338
1664
  type: "object",
1339
1665
  properties: {
@@ -1342,6 +1668,43 @@ var MESH_REFINE_NODE_TOOL = {
1342
1668
  required: ["node_id"]
1343
1669
  }
1344
1670
  };
1671
+ var MESH_REFINE_CONFIG_SCHEMA_TOOL = {
1672
+ name: "mesh_refine_config_schema",
1673
+ 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.",
1674
+ inputSchema: { type: "object", properties: {} }
1675
+ };
1676
+ var MESH_VALIDATE_REFINE_CONFIG_TOOL = {
1677
+ name: "mesh_validate_refine_config",
1678
+ description: "Validate the repo mesh/refine config for a node/workspace without running validation commands or merging.",
1679
+ inputSchema: {
1680
+ type: "object",
1681
+ properties: {
1682
+ node_id: { type: "string", description: "Optional node/workspace whose refine config should be loaded. Defaults to the first mesh node." },
1683
+ config: { type: "object", description: "Optional inline config object to validate instead of loading from the repo." }
1684
+ }
1685
+ }
1686
+ };
1687
+ var MESH_SUGGEST_REFINE_CONFIG_TOOL = {
1688
+ name: "mesh_suggest_refine_config",
1689
+ description: "Suggest a repo mesh/refine config scaffold from project context/package scripts. Suggestions are never executed until saved as explicit refine config.",
1690
+ inputSchema: {
1691
+ type: "object",
1692
+ properties: {
1693
+ node_id: { type: "string", description: "Optional node/workspace used for suggestions. Defaults to the first mesh node." }
1694
+ }
1695
+ }
1696
+ };
1697
+ var MESH_REFINE_PLAN_TOOL = {
1698
+ name: "mesh_refine_plan",
1699
+ 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.",
1700
+ inputSchema: {
1701
+ type: "object",
1702
+ properties: {
1703
+ node_id: { type: "string", description: "Node ID of the worktree node to plan." }
1704
+ },
1705
+ required: ["node_id"]
1706
+ }
1707
+ };
1345
1708
  var ALL_MESH_TOOLS = [
1346
1709
  MESH_STATUS_TOOL,
1347
1710
  MESH_LIST_NODES_TOOL,
@@ -1354,11 +1717,16 @@ var ALL_MESH_TOOLS = [
1354
1717
  MESH_READ_DEBUG_TOOL,
1355
1718
  MESH_LAUNCH_SESSION_TOOL,
1356
1719
  MESH_GIT_STATUS_TOOL,
1720
+ MESH_FAST_FORWARD_NODE_TOOL,
1357
1721
  MESH_CHECKPOINT_TOOL,
1358
1722
  MESH_APPROVE_TOOL,
1359
1723
  MESH_CLONE_NODE_TOOL,
1360
1724
  MESH_REMOVE_NODE_TOOL,
1361
1725
  MESH_REFINE_NODE_TOOL,
1726
+ MESH_REFINE_CONFIG_SCHEMA_TOOL,
1727
+ MESH_VALIDATE_REFINE_CONFIG_TOOL,
1728
+ MESH_SUGGEST_REFINE_CONFIG_TOOL,
1729
+ MESH_REFINE_PLAN_TOOL,
1362
1730
  MESH_CLEANUP_SESSIONS_TOOL,
1363
1731
  MESH_TASK_HISTORY_TOOL,
1364
1732
  MESH_RECONCILE_LEDGER_TOOL
@@ -1372,6 +1740,9 @@ async function meshStatus(ctx) {
1372
1740
  const entry = {
1373
1741
  nodeId: node.id,
1374
1742
  workspace: node.workspace,
1743
+ machine: buildNodeMachineIdentity(ctx, node),
1744
+ daemonId: readNodeDaemonId(node),
1745
+ machineId: readNodeMachineId(node),
1375
1746
  ...getNodeLaunchReadiness(node)
1376
1747
  };
1377
1748
  try {
@@ -1381,6 +1752,7 @@ async function meshStatus(ctx) {
1381
1752
  const uncommittedChanges = countUncommittedChanges(status);
1382
1753
  const dirty = isGitStatusDirty(status);
1383
1754
  entry.health = status?.isGitRepo ? dirty ? "dirty" : "online" : "degraded";
1755
+ assignFullGitSnapshot(entry, status);
1384
1756
  entry.branch = status?.branch;
1385
1757
  entry.isDirty = dirty;
1386
1758
  entry.uncommittedChanges = uncommittedChanges;
@@ -1402,6 +1774,7 @@ async function meshStatus(ctx) {
1402
1774
  const uncommittedChanges = countUncommittedChanges(status);
1403
1775
  const dirty = isGitStatusDirty(status);
1404
1776
  entry.health = status?.isGitRepo ? dirty ? "dirty" : "online" : "degraded";
1777
+ assignFullGitSnapshot(entry, status);
1405
1778
  entry.branch = status?.branch;
1406
1779
  entry.isDirty = dirty;
1407
1780
  entry.uncommittedChanges = uncommittedChanges;
@@ -1477,15 +1850,35 @@ async function meshStatus(ctx) {
1477
1850
  }
1478
1851
  const relatedRepos = await collectRelatedRepoStatuses(ctx, node);
1479
1852
  if (relatedRepos.length) entry.relatedRepos = relatedRepos;
1853
+ const liveSessions = await collectLiveStatusSessions(ctx, node);
1854
+ if (liveSessions.length > 0) {
1855
+ entry.sessions = liveSessions;
1856
+ }
1480
1857
  results.push(entry);
1481
1858
  }
1859
+ const activeWorkEvidence = (0, import_daemon_core.buildMeshActiveWork)({
1860
+ meshId: mesh.id,
1861
+ queue: (0, import_daemon_core.getQueue)(mesh.id),
1862
+ ledgerEntries: (0, import_daemon_core.readLedgerEntries)(mesh.id, { tail: 500 }),
1863
+ nodes: results
1864
+ });
1482
1865
  const response = {
1483
1866
  meshId: mesh.id,
1484
1867
  meshName: mesh.name,
1485
1868
  repoIdentity: mesh.repoIdentity,
1486
1869
  policy: mesh.policy,
1487
1870
  refreshedAt: (/* @__PURE__ */ new Date()).toISOString(),
1871
+ sourceOfTruth: {
1872
+ membership: "coordinator_daemon_live_mesh",
1873
+ currentStatus: "live_git_and_session_probes",
1874
+ activeWork: "mesh_queue_file_and_local_ledger",
1875
+ historicalEvidenceOnly: ["recoveryHints", "ledgerSummary"]
1876
+ },
1488
1877
  nodes: results,
1878
+ activeWork: activeWorkEvidence.activeWork,
1879
+ staleDirectWork: activeWorkEvidence.staleDirectWork,
1880
+ terminalDirectWork: activeWorkEvidence.terminalDirectWork,
1881
+ activeWorkSummary: activeWorkEvidence.summary,
1489
1882
  branchConvergenceSummary: summarizeBranchConvergence(results)
1490
1883
  };
1491
1884
  try {
@@ -1493,13 +1886,7 @@ async function meshStatus(ctx) {
1493
1886
  } catch {
1494
1887
  }
1495
1888
  try {
1496
- let pendingEvents = [];
1497
- if (ctx.transport instanceof IpcTransport) {
1498
- const eventsResult = await ctx.transport.command("get_pending_mesh_events", {});
1499
- pendingEvents = Array.isArray(eventsResult?.events) ? eventsResult.events : [];
1500
- } else if (isLocalTransport(ctx.transport)) {
1501
- pendingEvents = (0, import_daemon_core.drainPendingMeshCoordinatorEvents)();
1502
- }
1889
+ const pendingEvents = await drainCoordinatorPendingEvents(ctx);
1503
1890
  if (pendingEvents.length > 0) {
1504
1891
  response.pendingCoordinatorEvents = pendingEvents;
1505
1892
  }
@@ -1509,11 +1896,17 @@ async function meshStatus(ctx) {
1509
1896
  }
1510
1897
  async function meshTaskHistory(ctx, args) {
1511
1898
  const { mesh } = ctx;
1899
+ const pendingEvents = await drainCoordinatorPendingEvents(ctx);
1512
1900
  const tail = typeof args.tail === "number" && args.tail > 0 ? args.tail : 20;
1513
1901
  const kind = typeof args.kind === "string" && args.kind.trim() ? [args.kind.trim()] : void 0;
1514
1902
  const entries = (0, import_daemon_core.readLedgerEntries)(mesh.id, { tail, kind });
1515
1903
  const summary = (0, import_daemon_core.getLedgerSummary)(mesh.id);
1516
- return JSON.stringify({ meshId: mesh.id, entries, summary }, null, 2);
1904
+ return JSON.stringify({
1905
+ meshId: mesh.id,
1906
+ entries,
1907
+ summary,
1908
+ ...pendingEvents.length > 0 ? { pendingCoordinatorEvents: pendingEvents } : {}
1909
+ }, null, 2);
1517
1910
  }
1518
1911
  async function meshReconcileLedger(ctx, args) {
1519
1912
  await refreshMeshFromDaemon(ctx);
@@ -1603,6 +1996,9 @@ async function meshListNodes(ctx) {
1603
1996
  nodeId: n.id,
1604
1997
  workspace: n.workspace,
1605
1998
  repoRoot: n.repoRoot,
1999
+ daemonId: readNodeDaemonId(n),
2000
+ machineId: readNodeMachineId(n),
2001
+ machine: buildNodeMachineIdentity(ctx, n),
1606
2002
  isLocalWorktree: n.isLocalWorktree,
1607
2003
  policy: n.policy,
1608
2004
  relatedRepos: readRelatedRepos(n),
@@ -1612,12 +2008,13 @@ async function meshListNodes(ctx) {
1612
2008
  }, null, 2);
1613
2009
  }
1614
2010
  async function meshEnqueueTask(ctx, args) {
2011
+ const taskMode = readString(args.task_mode) || readString(args.taskMode);
1615
2012
  try {
1616
- const task = (0, import_daemon_core.enqueueTask)(ctx.mesh.id, args.message);
2013
+ const task = (0, import_daemon_core.enqueueTask)(ctx.mesh.id, args.message, { taskMode });
1617
2014
  if (isLocalTransport(ctx.transport) && !(ctx.transport instanceof IpcTransport)) {
1618
2015
  ctx.transport.command("trigger_mesh_queue", { meshId: ctx.mesh.id }).catch(() => {
1619
2016
  });
1620
- return JSON.stringify({ success: true, taskId: task.id, status: task.status });
2017
+ return JSON.stringify({ success: true, source: "queue", taskId: task.id, status: task.status, taskMode: task.taskMode });
1621
2018
  }
1622
2019
  if (ctx.transport instanceof IpcTransport) {
1623
2020
  ctx.transport.command("trigger_mesh_queue", { meshId: ctx.mesh.id }).catch(() => {
@@ -1630,11 +2027,24 @@ async function meshEnqueueTask(ctx, args) {
1630
2027
  ipcDispatchToRemoteAgent(ctx, node, { message: args.message }).then((result) => {
1631
2028
  if (result.success) {
1632
2029
  try {
2030
+ const providerType = result.providerType;
2031
+ const descriptor = summarizeTaskMessage(args.message);
1633
2032
  (0, import_daemon_core.appendLedgerEntry)(ctx.mesh.id, {
1634
2033
  kind: "task_dispatched",
1635
2034
  nodeId: node.id,
1636
2035
  sessionId: result.sessionId,
1637
- payload: { message: args.message, via: "p2p_direct", taskId: task.id }
2036
+ providerType,
2037
+ payload: {
2038
+ source: "queue",
2039
+ via: "p2p_direct",
2040
+ taskId: task.id,
2041
+ message: args.message,
2042
+ taskTitle: descriptor.taskTitle,
2043
+ taskSummary: descriptor.taskSummary,
2044
+ ...task.taskMode ? { taskMode: task.taskMode } : {},
2045
+ ...providerType ? { providerType } : {},
2046
+ targetSessionId: result.sessionId
2047
+ }
1638
2048
  });
1639
2049
  } catch {
1640
2050
  }
@@ -1645,22 +2055,33 @@ async function meshEnqueueTask(ctx, args) {
1645
2055
  }
1646
2056
  Promise.all(dispatchPromises).catch(() => {
1647
2057
  });
1648
- return JSON.stringify({ success: true, taskId: task.id, status: task.status });
2058
+ return JSON.stringify({ success: true, source: "queue", taskId: task.id, status: task.status, taskMode: task.taskMode });
1649
2059
  }
1650
- return JSON.stringify({ success: true, taskId: task.id, status: task.status });
2060
+ return JSON.stringify({ success: true, source: "queue", taskId: task.id, status: task.status, taskMode: task.taskMode });
1651
2061
  } catch (e) {
1652
- return JSON.stringify({ success: false, error: e.message });
2062
+ const message = e?.message || String(e);
2063
+ if (message.includes("live_debug_readonly_guardrail_violation")) {
2064
+ return JSON.stringify({ success: false, code: "live_debug_readonly_guardrail_violation", taskMode, error: message });
2065
+ }
2066
+ return JSON.stringify({ success: false, error: message });
1653
2067
  }
1654
2068
  }
1655
2069
  async function meshViewQueue(ctx, args) {
1656
2070
  try {
2071
+ await refreshMeshFromDaemon(ctx);
1657
2072
  const statusFilter = sanitizeQueueStatusFilter(args.status);
1658
2073
  const view = normalizeQueueViewMode(args.view);
1659
- const fullQueue = annotateQueueStaleness((0, import_daemon_core.getQueue)(ctx.mesh.id), ctx.mesh);
2074
+ const fullQueue = prioritizeActiveQueueRows(annotateQueueStaleness((0, import_daemon_core.getQueue)(ctx.mesh.id), ctx.mesh));
1660
2075
  const queue = filterQueueForView(fullQueue, view, statusFilter);
1661
2076
  const summary = buildQueueStatusSummary(fullQueue);
1662
2077
  const visibleSummary = buildQueueStatusSummary(queue);
1663
2078
  const maintenance = buildQueueMaintenanceReport(fullQueue);
2079
+ const activeWorkEvidence = (0, import_daemon_core.buildMeshActiveWork)({
2080
+ meshId: ctx.mesh.id,
2081
+ queue: fullQueue,
2082
+ ledgerEntries: (0, import_daemon_core.readLedgerEntries)(ctx.mesh.id, { tail: 500 }),
2083
+ nodes: ctx.mesh.nodes
2084
+ });
1664
2085
  const staleAssignedTasks = maintenance.staleAssignedTasks || [];
1665
2086
  const requestedHistoricalRows = queue.some((task) => HISTORICAL_QUEUE_STATUSES.has(String(task?.status || "")));
1666
2087
  return JSON.stringify({
@@ -1678,6 +2099,9 @@ async function meshViewQueue(ctx, args) {
1678
2099
  },
1679
2100
  queue,
1680
2101
  visibleQueue: queue,
2102
+ activeWork: activeWorkEvidence.activeWork,
2103
+ staleDirectWork: activeWorkEvidence.staleDirectWork,
2104
+ activeWorkSummary: activeWorkEvidence.summary,
1681
2105
  visibleSummary,
1682
2106
  summary,
1683
2107
  activeCounts: summary.activeCounts,
@@ -1711,6 +2135,10 @@ async function meshQueueCancel(ctx, args) {
1711
2135
  if (!taskId) return JSON.stringify({ success: false, error: "task_id required" });
1712
2136
  const task = (0, import_daemon_core.cancelTask)(ctx.mesh.id, taskId, { reason: args.reason });
1713
2137
  if (!task) return JSON.stringify({ success: false, error: `Queue task '${taskId}' not found` });
2138
+ if (isLocalTransport(ctx.transport)) {
2139
+ ctx.transport.command("trigger_mesh_queue", { meshId: ctx.mesh.id }).catch(() => {
2140
+ });
2141
+ }
1714
2142
  return JSON.stringify({ success: true, task }, null, 2);
1715
2143
  } catch (e) {
1716
2144
  return JSON.stringify({ success: false, error: e.message });
@@ -1741,6 +2169,19 @@ async function meshQueueRequeue(ctx, args) {
1741
2169
  }
1742
2170
  }
1743
2171
  async function meshSendTask(ctx, args) {
2172
+ const requestedTaskMode = readString(args.task_mode) || readString(args.taskMode);
2173
+ const modeValidation = (0, import_daemon_core.validateMeshTaskModeRequest)(requestedTaskMode, args.message);
2174
+ if (!modeValidation.valid) {
2175
+ return JSON.stringify({
2176
+ success: false,
2177
+ code: "live_debug_readonly_guardrail_violation",
2178
+ taskMode: modeValidation.taskMode || requestedTaskMode,
2179
+ violations: modeValidation.violations,
2180
+ allowedOperations: modeValidation.allowedOperations,
2181
+ error: `live_debug_readonly_guardrail_violation: forbidden operations (${modeValidation.violations.join(", ")})`
2182
+ });
2183
+ }
2184
+ const taskMode = modeValidation.taskMode;
1744
2185
  const node = await findNodeWithRefresh(ctx, args.node_id);
1745
2186
  if (node.policy?.readOnly) {
1746
2187
  return JSON.stringify({ error: `Node '${args.node_id}' is read-only` });
@@ -1768,13 +2209,15 @@ async function meshSendTask(ctx, args) {
1768
2209
  const res = await ctx.transport.meshEnqueueTask(node.daemonId, {
1769
2210
  meshId: ctx.mesh.id,
1770
2211
  message: args.message,
1771
- targetNodeId: args.node_id
2212
+ targetNodeId: args.node_id,
2213
+ ...taskMode ? { taskMode } : {}
1772
2214
  });
1773
2215
  return JSON.stringify(res);
1774
2216
  }
1775
2217
  const isLocalNode = isLocalControlPlaneNode(ctx, node);
1776
2218
  if (ctx.transport instanceof IpcTransport && node.daemonId && !isLocalNode) {
1777
2219
  const cached = meshSessionProviderMetadata.get(meshSessionCacheKey(args.node_id, args.session_id || ""));
2220
+ const taskId = (0, import_node_crypto.randomUUID)();
1778
2221
  const result2 = await ipcDispatchToRemoteAgent(ctx, node, {
1779
2222
  session_id: args.session_id,
1780
2223
  message: args.message,
@@ -1783,60 +2226,123 @@ async function meshSendTask(ctx, args) {
1783
2226
  if (result2.success) {
1784
2227
  const dispatchedSessionId = args.session_id || result2.sessionId;
1785
2228
  try {
2229
+ const providerType = result2.providerType || cached?.providerType;
1786
2230
  (0, import_daemon_core.appendLedgerEntry)(ctx.mesh.id, {
1787
2231
  kind: "task_dispatched",
1788
2232
  nodeId: args.node_id,
1789
2233
  sessionId: dispatchedSessionId,
1790
- payload: {
1791
- message: args.message,
1792
- via: "p2p_direct",
1793
- ...dispatchedSessionId ? { targetSessionId: dispatchedSessionId } : {}
1794
- }
2234
+ providerType,
2235
+ payload: buildDirectTaskPayload(args.message, "p2p_direct", {
2236
+ taskId,
2237
+ taskMode,
2238
+ providerType,
2239
+ targetSessionId: dispatchedSessionId
2240
+ })
1795
2241
  });
1796
2242
  } catch {
1797
2243
  }
1798
2244
  }
1799
- return JSON.stringify({ ...result2, nodeId: args.node_id, dispatched: result2.success === true });
2245
+ return JSON.stringify({
2246
+ ...result2,
2247
+ nodeId: args.node_id,
2248
+ sessionId: result2.success ? args.session_id || result2.sessionId : args.session_id,
2249
+ ...result2.success ? { source: "direct", taskId } : {},
2250
+ taskMode,
2251
+ ...result2.success && result2.providerType ? { providerType: result2.providerType } : {},
2252
+ dispatched: result2.success === true
2253
+ });
1800
2254
  }
1801
2255
  if (args.session_id && isLocalTransport(ctx.transport)) {
1802
2256
  const cached = meshSessionProviderMetadata.get(meshSessionCacheKey(args.node_id, args.session_id));
2257
+ let resolvedProviderType = cached?.providerType || "";
2258
+ if (!resolvedProviderType) {
2259
+ const statusResult = await commandForNode(ctx, node, "get_status_metadata", {});
2260
+ const sessions = extractStatusMetadataSessions(statusResult);
2261
+ const explicitSession = sessions.find((session) => readSessionRecordId(session) === args.session_id);
2262
+ if (!explicitSession) {
2263
+ return JSON.stringify({
2264
+ success: false,
2265
+ recoverable: true,
2266
+ code: "mesh_target_session_not_found",
2267
+ reason: "mesh_target_session_not_found",
2268
+ transport: "local_ipc",
2269
+ retryRecommended: true,
2270
+ nodeId: args.node_id,
2271
+ sessionId: args.session_id,
2272
+ error: `Local session '${args.session_id}' is not present in live status for node '${args.node_id}'.`,
2273
+ 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.`
2274
+ });
2275
+ }
2276
+ resolvedProviderType = resolveSessionProviderType(explicitSession);
2277
+ if (resolvedProviderType) {
2278
+ meshSessionProviderMetadata.set(meshSessionCacheKey(args.node_id, args.session_id), {
2279
+ providerType: resolvedProviderType,
2280
+ providerSessionId: readString(explicitSession?.providerSessionId) || void 0
2281
+ });
2282
+ }
2283
+ }
2284
+ if (!resolvedProviderType) {
2285
+ return JSON.stringify({
2286
+ success: false,
2287
+ recoverable: true,
2288
+ code: "mesh_target_session_provider_unknown",
2289
+ reason: "mesh_target_session_provider_unknown",
2290
+ transport: "local_ipc",
2291
+ retryRecommended: false,
2292
+ nodeId: args.node_id,
2293
+ sessionId: args.session_id,
2294
+ error: `Local session '${args.session_id}' is live but does not expose providerType/cliType, so agent_command cannot be routed safely.`,
2295
+ 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.`
2296
+ });
2297
+ }
1803
2298
  const dispatchResult = await commandForNode(ctx, node, "agent_command", {
1804
2299
  targetSessionId: args.session_id,
1805
- ...cached?.providerType ? { agentType: cached.providerType, cliType: cached.providerType, providerType: cached.providerType } : {},
2300
+ agentType: resolvedProviderType,
2301
+ cliType: resolvedProviderType,
2302
+ providerType: resolvedProviderType,
1806
2303
  action: "send_chat",
1807
2304
  message: args.message
1808
2305
  });
1809
2306
  const dispatchPayload = unwrapCommandPayload(dispatchResult);
1810
2307
  if (dispatchPayload?.success === false || dispatchResult?.success === false) {
2308
+ const source = dispatchPayload?.success === false ? dispatchPayload : dispatchResult;
1811
2309
  return JSON.stringify({
2310
+ ...source && typeof source === "object" ? source : {},
1812
2311
  success: false,
1813
2312
  nodeId: args.node_id,
1814
2313
  sessionId: args.session_id,
1815
2314
  error: dispatchPayload?.error || dispatchResult?.error || "agent_command rejected the task"
1816
2315
  });
1817
2316
  }
2317
+ const taskId = (0, import_node_crypto.randomUUID)();
1818
2318
  try {
1819
2319
  (0, import_daemon_core.appendLedgerEntry)(ctx.mesh.id, {
1820
2320
  kind: "task_dispatched",
1821
2321
  nodeId: args.node_id,
1822
2322
  sessionId: args.session_id,
1823
- providerType: cached?.providerType,
1824
- payload: { message: args.message, via: "local_direct" }
2323
+ providerType: resolvedProviderType,
2324
+ payload: buildDirectTaskPayload(args.message, "local_direct", {
2325
+ taskId,
2326
+ taskMode,
2327
+ providerType: resolvedProviderType,
2328
+ targetSessionId: args.session_id
2329
+ })
1825
2330
  });
1826
2331
  } catch {
1827
2332
  }
1828
- return JSON.stringify({ success: true, dispatched: true, nodeId: args.node_id, sessionId: args.session_id });
2333
+ return JSON.stringify({ success: true, dispatched: true, source: "direct", taskId, taskMode, providerType: resolvedProviderType, nodeId: args.node_id, sessionId: args.session_id });
1829
2334
  }
1830
2335
  const task = (0, import_daemon_core.enqueueTask)(ctx.mesh.id, args.message, {
1831
2336
  targetNodeId: args.node_id,
1832
- targetSessionId: args.session_id
2337
+ targetSessionId: args.session_id,
2338
+ taskMode
1833
2339
  });
1834
2340
  if (isLocalTransport(ctx.transport) || ctx.transport instanceof IpcTransport) {
1835
2341
  ctx.transport.command("trigger_mesh_queue", { meshId: ctx.mesh.id }).catch(() => {
1836
2342
  });
1837
2343
  }
1838
- const pendingEvents = isLocalTransport(ctx.transport) ? (0, import_daemon_core.drainPendingMeshCoordinatorEvents)() : [];
1839
- const result = { success: true, nodeId: args.node_id, taskId: task.id, status: task.status };
2344
+ const pendingEvents = isLocalTransport(ctx.transport) ? (0, import_daemon_core.drainPendingMeshCoordinatorEvents)(ctx.mesh.id) : [];
2345
+ const result = { success: true, source: "queue", nodeId: args.node_id, taskId: task.id, status: task.status, taskMode: task.taskMode };
1840
2346
  if (pendingEvents.length > 0) {
1841
2347
  result.pendingCoordinatorEvents = pendingEvents;
1842
2348
  }
@@ -1856,6 +2362,9 @@ async function meshReadChat(ctx, args) {
1856
2362
  if (!node) {
1857
2363
  return JSON.stringify(buildMissingNodeReadChatRecovery(ctx, args), null, 2);
1858
2364
  }
2365
+ if (ctx.transport instanceof IpcTransport || isLocalTransport(ctx.transport)) {
2366
+ await drainCoordinatorPendingEvents(ctx, { nodeIds: [args.node_id] });
2367
+ }
1859
2368
  if (isLocalTransport(ctx.transport)) {
1860
2369
  const cached = meshSessionProviderMetadata.get(meshSessionCacheKey(args.node_id, args.session_id));
1861
2370
  const providerSessionId = typeof args.provider_session_id === "string" && args.provider_session_id.trim() ? args.provider_session_id.trim() : cached?.providerSessionId;
@@ -1958,6 +2467,10 @@ async function meshLaunchSession(ctx, args) {
1958
2467
  const coordinatorNode = resolveCoordinatorNode(ctx);
1959
2468
  const coordinatorDaemonId = coordinatorNode?.daemonId || ctx.localDaemonId;
1960
2469
  const spawnedSessionVisibility = readSpawnedSessionVisibility(ctx.mesh.policy);
2470
+ const isLocalNode = isLocalControlPlaneNode(ctx, node);
2471
+ if (node.daemonId && !isLocalNode && !coordinatorDaemonId) {
2472
+ return JSON.stringify(buildMissingCoordinatorDaemonIdFailure(ctx, node, resolvedProviderType), null, 2);
2473
+ }
1961
2474
  let result;
1962
2475
  try {
1963
2476
  result = await commandForNode(ctx, node, "launch_cli", {
@@ -1998,7 +2511,6 @@ async function meshLaunchSession(ctx, args) {
1998
2511
  });
1999
2512
  } catch {
2000
2513
  }
2001
- const isLocalNode = isLocalControlPlaneNode(ctx, node);
2002
2514
  if (ctx.transport instanceof IpcTransport && node.daemonId && !isLocalNode) {
2003
2515
  ctx.transport.meshCommand(node.daemonId, "trigger_mesh_queue", { meshId: ctx.mesh.id }).catch(() => {
2004
2516
  });
@@ -2023,6 +2535,9 @@ async function meshLaunchSession(ctx, args) {
2023
2535
  const coordinatorNode = resolveCoordinatorNode(ctx);
2024
2536
  const coordinatorDaemonId = coordinatorNode?.daemonId || ctx.localDaemonId;
2025
2537
  const spawnedSessionVisibility = readSpawnedSessionVisibility(ctx.mesh.policy);
2538
+ if (!coordinatorDaemonId) {
2539
+ return JSON.stringify(buildMissingCoordinatorDaemonIdFailure(ctx, node, resolvedProviderType), null, 2);
2540
+ }
2026
2541
  try {
2027
2542
  const res = await ctx.transport.launch(node.daemonId, {
2028
2543
  type: resolvedProviderType,
@@ -2103,6 +2618,51 @@ async function meshGitStatus(ctx, args) {
2103
2618
  }, null, 2);
2104
2619
  }
2105
2620
  }
2621
+ async function meshFastForwardNode(ctx, args) {
2622
+ await refreshMeshFromDaemon(ctx);
2623
+ const node = await findNodeWithRefresh(ctx, args.node_id);
2624
+ const submoduleIgnorePaths = node.policy?.submoduleIgnorePaths || [];
2625
+ if (node.policy?.readOnly) {
2626
+ return JSON.stringify({
2627
+ success: false,
2628
+ code: "node_read_only",
2629
+ nodeId: args.node_id,
2630
+ workspace: node.workspace,
2631
+ allowed: false,
2632
+ willRun: false,
2633
+ executed: false,
2634
+ blockingReasons: ["node_read_only"]
2635
+ }, null, 2);
2636
+ }
2637
+ try {
2638
+ const dryRun = args.dry_run === true || args.execute !== true;
2639
+ const result = await commandForNode(ctx, node, "fast_forward_mesh_node", {
2640
+ meshId: ctx.mesh.id,
2641
+ nodeId: node.id,
2642
+ workspace: node.workspace,
2643
+ branch: typeof args.branch === "string" ? args.branch : void 0,
2644
+ execute: args.execute === true && args.dry_run !== true,
2645
+ dryRun,
2646
+ updateSubmodules: args.update_submodules === true,
2647
+ submoduleIgnorePaths: submoduleIgnorePaths.length > 0 ? submoduleIgnorePaths : void 0
2648
+ });
2649
+ return JSON.stringify(unwrapCommandPayload(result), null, 2);
2650
+ } catch (e) {
2651
+ const failure = buildCoordinatorP2pRelayFailure(e, {
2652
+ command: "fast_forward_mesh_node",
2653
+ targetDaemonId: node.daemonId,
2654
+ nodeId: args.node_id
2655
+ });
2656
+ return JSON.stringify({
2657
+ ...failure,
2658
+ workspace: node.workspace,
2659
+ allowed: false,
2660
+ willRun: false,
2661
+ executed: false,
2662
+ blockingReasons: [failure.code || "mesh_fast_forward_unavailable"]
2663
+ }, null, 2);
2664
+ }
2665
+ }
2106
2666
  async function meshCheckpoint(ctx, args) {
2107
2667
  const node = await findNodeWithRefresh(ctx, args.node_id);
2108
2668
  if (node.policy?.readOnly) {
@@ -2188,6 +2748,7 @@ async function meshCloneNode(ctx, args) {
2188
2748
  if (existingIndex >= 0) ctx.mesh.nodes[existingIndex] = clonePayload.node;
2189
2749
  else ctx.mesh.nodes.push(clonePayload.node);
2190
2750
  ctx.mesh.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
2751
+ await syncCoordinatorDaemonMeshCache(ctx);
2191
2752
  }
2192
2753
  return JSON.stringify(result, null, 2);
2193
2754
  } else if (!isLocalTransport(ctx.transport) && sourceNode.daemonId) {
@@ -2205,6 +2766,7 @@ async function meshCloneNode(ctx, args) {
2205
2766
  if (existingIndex >= 0) ctx.mesh.nodes[existingIndex] = clonePayload.node;
2206
2767
  else ctx.mesh.nodes.push(clonePayload.node);
2207
2768
  ctx.mesh.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
2769
+ await syncCoordinatorDaemonMeshCache(ctx);
2208
2770
  }
2209
2771
  return JSON.stringify(res, null, 2);
2210
2772
  } catch (e) {
@@ -2300,6 +2862,43 @@ async function meshRemoveNode(ctx, args) {
2300
2862
  return JSON.stringify({ error: "Cloud mesh remove_node requires node daemonId" });
2301
2863
  }
2302
2864
  }
2865
+ function resolveRefineConfigNode(ctx, nodeId) {
2866
+ if (nodeId) return findNode(ctx.mesh, nodeId);
2867
+ const node = ctx.mesh.nodes.find((entry) => !!entry.workspace);
2868
+ if (!node) throw new Error("No mesh node with a workspace is available");
2869
+ return node;
2870
+ }
2871
+ async function meshRefineConfigSchema(ctx) {
2872
+ const node = resolveRefineConfigNode(ctx);
2873
+ const result = await commandForNode(ctx, node, "get_mesh_refine_config_schema", {});
2874
+ return JSON.stringify(result, null, 2);
2875
+ }
2876
+ async function meshValidateRefineConfig(ctx, args) {
2877
+ const node = resolveRefineConfigNode(ctx, args.node_id);
2878
+ const result = await commandForNode(ctx, node, "validate_mesh_refine_config", {
2879
+ workspace: node.workspace,
2880
+ inlineMesh: ctx.mesh,
2881
+ ...args.config ? { config: args.config } : {}
2882
+ });
2883
+ return JSON.stringify(result, null, 2);
2884
+ }
2885
+ async function meshSuggestRefineConfig(ctx, args) {
2886
+ const node = resolveRefineConfigNode(ctx, args.node_id);
2887
+ const result = await commandForNode(ctx, node, "suggest_mesh_refine_config", {
2888
+ workspace: node.workspace,
2889
+ inlineMesh: ctx.mesh
2890
+ });
2891
+ return JSON.stringify(result, null, 2);
2892
+ }
2893
+ async function meshRefinePlan(ctx, args) {
2894
+ const node = await findNodeWithRefresh(ctx, args.node_id);
2895
+ const result = await commandForNode(ctx, node, "plan_mesh_refine_node", {
2896
+ meshId: ctx.mesh.id,
2897
+ nodeId: args.node_id,
2898
+ inlineMesh: ctx.mesh
2899
+ });
2900
+ return JSON.stringify(result, null, 2);
2901
+ }
2303
2902
  async function meshRefineNode(ctx, args) {
2304
2903
  const node = await findNodeWithRefresh(ctx, args.node_id);
2305
2904
  if (isLocalTransport(ctx.transport)) {
@@ -2308,7 +2907,7 @@ async function meshRefineNode(ctx, args) {
2308
2907
  nodeId: args.node_id,
2309
2908
  inlineMesh: ctx.mesh
2310
2909
  });
2311
- if (result?.success && result.removeResult?.removed !== false) {
2910
+ if (result?.success && result.async !== true && result.removeResult?.removed !== false) {
2312
2911
  const idx = ctx.mesh.nodes.findIndex((n) => n.id === args.node_id);
2313
2912
  if (idx >= 0) {
2314
2913
  ctx.mesh.nodes.splice(idx, 1);
@@ -2323,7 +2922,7 @@ async function meshRefineNode(ctx, args) {
2323
2922
  nodeId: args.node_id,
2324
2923
  inlineMesh: ctx.mesh
2325
2924
  });
2326
- if (res?.success && res.removeResult?.removed !== false) {
2925
+ if (res?.success && res.async !== true && res.removeResult?.removed !== false) {
2327
2926
  const idx = ctx.mesh.nodes.findIndex((n) => n.id === args.node_id);
2328
2927
  if (idx >= 0) {
2329
2928
  ctx.mesh.nodes.splice(idx, 1);
@@ -2360,13 +2959,13 @@ var STANDARD_TOOLS = [
2360
2959
  function buildMcpHelpText() {
2361
2960
  const meshTools = ALL_MESH_TOOLS.map((tool) => tool.name);
2362
2961
  return `
2363
- adhdev-mcp \u2014 ADHDev MCP Server
2962
+ ADHDev MCP Server
2364
2963
 
2365
2964
  Usage:
2366
- adhdev-mcp Local mode (requires standalone daemon)
2367
- adhdev-mcp --api-key <key> Cloud mode (ADHDev cloud API)
2368
- adhdev-mcp --mode ipc --repo-mesh <mesh_id> Cloud daemon IPC mesh mode
2369
- adhdev-mcp --repo-mesh <mesh_id> Mesh mode (coordinator-scoped tools)
2965
+ adhdev mcp Local mode (requires standalone daemon)
2966
+ adhdev mcp --api-key <key> Cloud mode (ADHDev cloud API)
2967
+ adhdev mcp --mode ipc --repo-mesh <mesh_id> Cloud daemon IPC mesh mode
2968
+ adhdev-mcp --help Compatibility bin (same server, legacy package entrypoint)
2370
2969
 
2371
2970
  Options:
2372
2971
  --mode <mode> Transport: local, cloud, or ipc
@@ -2391,6 +2990,7 @@ Mesh tools: ${meshTools.join(", ")}
2391
2990
  // src/server.ts
2392
2991
  var import_server = require("@modelcontextprotocol/sdk/server/index.js");
2393
2992
  var import_stdio = require("@modelcontextprotocol/sdk/server/stdio.js");
2993
+ var import_node_os = __toESM(require("os"));
2394
2994
  var import_types = require("@modelcontextprotocol/sdk/types.js");
2395
2995
 
2396
2996
  // src/transports/local.ts
@@ -2941,6 +3541,22 @@ function formatChatResult(result, sessionId, format, limit = 50, compact = false
2941
3541
  }))
2942
3542
  }, null, 2);
2943
3543
  }
3544
+ if ((format === "text" || format === void 0) && compact && compactPayload) {
3545
+ const lines2 = outputMessages.slice(-limit).map((m) => {
3546
+ const role = m.role === "user" ? "User" : m.role === "assistant" ? "Agent" : m.role;
3547
+ const content = messageContent(m);
3548
+ const truncated = content.length > 500 ? `${content.slice(0, 500)}\u2026` : content;
3549
+ return `[${role}] ${truncated}`;
3550
+ });
3551
+ if (compactPayload.summary) {
3552
+ const truncatedSummary = compactPayload.summary.length > 500 ? `${compactPayload.summary.slice(0, 500)}\u2026` : compactPayload.summary;
3553
+ lines2.push(`[Summary] ${truncatedSummary}`);
3554
+ }
3555
+ if (result?.pollingAdvisory) {
3556
+ lines2.push(`Advisory: ${result.pollingAdvisory.message}`);
3557
+ }
3558
+ return lines2.length > 0 ? lines2.join("\n\n") : "No messages in chat.";
3559
+ }
2944
3560
  if (outputMessages.length === 0) {
2945
3561
  return result?.pollingAdvisory ? `No messages in chat.
2946
3562
 
@@ -3908,6 +4524,7 @@ async function startMcpServer(opts) {
3908
4524
  requirePreTaskCheckpoint: false,
3909
4525
  requirePostTaskCheckpoint: true,
3910
4526
  requireApprovalForPush: true,
4527
+ allowAutoPublishSubmoduleMainCommits: false,
3911
4528
  requireApprovalForDestructiveGit: true,
3912
4529
  dirtyWorkspaceBehavior: "warn",
3913
4530
  maxParallelTasks: 2,
@@ -3964,6 +4581,7 @@ async function startMcpServer(opts) {
3964
4581
  }
3965
4582
  let localDaemonId;
3966
4583
  let localMachineId;
4584
+ let coordinatorHostname = import_node_os.default.hostname();
3967
4585
  if (transport instanceof LocalTransport || transport instanceof IpcTransport) {
3968
4586
  try {
3969
4587
  const { loadConfig } = await import("@adhdev/daemon-core");
@@ -3976,11 +4594,13 @@ async function startMcpServer(opts) {
3976
4594
  try {
3977
4595
  const statusResult = await transport.getStatus();
3978
4596
  const instanceId = typeof statusResult?.status?.instanceId === "string" ? statusResult.status.instanceId.trim() : "";
4597
+ const hostname = typeof statusResult?.status?.hostname === "string" ? statusResult.status.hostname.trim() : typeof statusResult?.status?.machine?.hostname === "string" ? statusResult.status.machine.hostname.trim() : "";
3979
4598
  if (instanceId) localDaemonId = instanceId;
4599
+ if (hostname) coordinatorHostname = hostname;
3980
4600
  } catch {
3981
4601
  }
3982
4602
  }
3983
- const meshCtx = { mesh, transport, ...localDaemonId ? { localDaemonId } : {}, ...localMachineId ? { localMachineId } : {} };
4603
+ const meshCtx = { mesh, transport, ...localDaemonId ? { localDaemonId } : {}, ...localMachineId ? { localMachineId } : {}, ...coordinatorHostname ? { coordinatorHostname } : {} };
3984
4604
  const coordinatorPrompt = await buildMeshModeCoordinatorPrompt(mesh);
3985
4605
  const server2 = new import_server.Server(
3986
4606
  { name: "adhdev-mcp-server", version: "0.9.81" },
@@ -4041,6 +4661,9 @@ async function startMcpServer(opts) {
4041
4661
  case "mesh_git_status":
4042
4662
  text = await meshGitStatus(meshCtx, a);
4043
4663
  break;
4664
+ case "mesh_fast_forward_node":
4665
+ text = await meshFastForwardNode(meshCtx, a);
4666
+ break;
4044
4667
  case "mesh_checkpoint":
4045
4668
  text = await meshCheckpoint(meshCtx, a);
4046
4669
  break;
@@ -4056,6 +4679,18 @@ async function startMcpServer(opts) {
4056
4679
  case "mesh_refine_node":
4057
4680
  text = await meshRefineNode(meshCtx, a);
4058
4681
  break;
4682
+ case "mesh_refine_config_schema":
4683
+ text = await meshRefineConfigSchema(meshCtx);
4684
+ break;
4685
+ case "mesh_validate_refine_config":
4686
+ text = await meshValidateRefineConfig(meshCtx, a);
4687
+ break;
4688
+ case "mesh_suggest_refine_config":
4689
+ text = await meshSuggestRefineConfig(meshCtx, a);
4690
+ break;
4691
+ case "mesh_refine_plan":
4692
+ text = await meshRefinePlan(meshCtx, a);
4693
+ break;
4059
4694
  case "mesh_cleanup_sessions":
4060
4695
  text = await meshCleanupSessions(meshCtx, a);
4061
4696
  break;