@adhdev/daemon-standalone 0.9.82-rc.373 → 0.9.82-rc.375

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -30036,10 +30036,10 @@ var require_dist3 = __commonJS({
30036
30036
  }
30037
30037
  function getDaemonBuildInfo() {
30038
30038
  if (cached2) return cached2;
30039
- const commit = readInjected(true ? "f16b5e6cdf653b4258f8f44cb11fb6ad8c13329f" : void 0) ?? "unknown";
30040
- const commitShort = readInjected(true ? "f16b5e6c" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
30041
- const version2 = readInjected(true ? "0.9.82-rc.373" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
30042
- const builtAt = readInjected(true ? "2026-06-24T16:29:42.060Z" : void 0);
30039
+ const commit = readInjected(true ? "b17fb9165bd52c9e2ab8cccf2ce80734e2165680" : void 0) ?? "unknown";
30040
+ const commitShort = readInjected(true ? "b17fb916" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
30041
+ const version2 = readInjected(true ? "0.9.82-rc.375" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
30042
+ const builtAt = readInjected(true ? "2026-06-25T02:22:25.633Z" : void 0);
30043
30043
  cached2 = builtAt ? { commit, commitShort, version: version2, builtAt } : { commit, commitShort, version: version2 };
30044
30044
  return cached2;
30045
30045
  }
@@ -32771,6 +32771,10 @@ Default branch: \`${mesh.defaultBranch}\`` : ""}`);
32771
32771
  if (ctx.missionSection?.trim()) {
32772
32772
  sections.push(ctx.missionSection.trim());
32773
32773
  }
32774
+ const recentActivity = buildRecentActivitySection(ctx.recentActivity);
32775
+ if (recentActivity) sections.push(recentActivity);
32776
+ const operatingNotes = buildOperatingNotesSection(ctx.operatingNotes);
32777
+ if (operatingNotes) sections.push(operatingNotes);
32774
32778
  sections.push(buildPolicySection({ ...DEFAULT_MESH_POLICY, ...mesh.policy || {} }));
32775
32779
  sections.push(TOOLS_SECTION);
32776
32780
  sections.push(TOOL_EXPOSURE_PREFLIGHT_SECTION);
@@ -32802,6 +32806,8 @@ Default branch: \`${mesh.defaultBranch}\`` : ""}`);
32802
32806
  cliType: coordinatorCliType || "",
32803
32807
  nodes: nodesSection,
32804
32808
  mission: ctx.missionSection?.trim() || "",
32809
+ recentActivity: buildRecentActivitySection(ctx.recentActivity) || "",
32810
+ operatingNotes: buildOperatingNotesSection(ctx.operatingNotes) || "",
32805
32811
  policy: buildPolicySection({ ...DEFAULT_MESH_POLICY, ...mesh.policy || {} }),
32806
32812
  tools: TOOLS_SECTION,
32807
32813
  workflow: WORKFLOW_SECTION,
@@ -32873,6 +32879,56 @@ Default branch: \`${mesh.defaultBranch}\`` : ""}`);
32873
32879
  if (lines.length === 1) return lines[0];
32874
32880
  return [lines[0], ...lines.slice(1).map((l) => pad + l)].join("\n");
32875
32881
  }
32882
+ function buildRecentActivitySection(activity) {
32883
+ if (!activity) return "";
32884
+ const failures = Array.isArray(activity.recentFailures) ? activity.recentFailures : [];
32885
+ const pending = Number.isFinite(activity.pendingTasks) ? Number(activity.pendingTasks) : 0;
32886
+ const assigned = Number.isFinite(activity.assignedTasks) ? Number(activity.assignedTasks) : 0;
32887
+ const stalled = Number.isFinite(activity.stalledTasks) ? Number(activity.stalledTasks) : 0;
32888
+ const recentFailureCount = Number.isFinite(activity.recentFailureCount) ? Number(activity.recentFailureCount) : failures.length;
32889
+ if (failures.length === 0 && pending === 0 && assigned === 0 && stalled === 0 && recentFailureCount === 0) {
32890
+ return "";
32891
+ }
32892
+ const lines = ["## Recent Activity", ""];
32893
+ lines.push("A snapshot of this mesh's recent ledger/queue state at launch. Use it to decide what needs attention first; call `mesh_task_history` / `mesh_view_queue` for full detail.");
32894
+ lines.push("");
32895
+ const counts = [];
32896
+ if (pending > 0) counts.push(`**${pending}** pending`);
32897
+ if (assigned > 0) counts.push(`**${assigned}** assigned`);
32898
+ if (stalled > 0) counts.push(`**${stalled}** stalled`);
32899
+ if (recentFailureCount > 0) counts.push(`**${recentFailureCount}** failed in the last 30 min`);
32900
+ if (counts.length) lines.push(`- Queue/ledger: ${counts.join(", ")}.`);
32901
+ if (activity.lastActivityAt) lines.push(`- Last ledger activity: ${activity.lastActivityAt}.`);
32902
+ if (failures.length > 0) {
32903
+ const recent = failures.slice(-5).reverse();
32904
+ lines.push("", "Recent failures (newest first):");
32905
+ for (const f of recent) {
32906
+ const when = f.timestamp ? `${f.timestamp} ` : "";
32907
+ const node = f.nodeId ? `node \`${f.nodeId}\`` : "unknown node";
32908
+ const summary = (f.summary || "").trim();
32909
+ lines.push(`- ${when}${node}${summary ? ` \u2014 ${summary}` : ""}`);
32910
+ }
32911
+ lines.push("", "_Check `mesh_task_history` before retrying; repeated failures on the same node mean reassign or escalate, not retry._");
32912
+ }
32913
+ return lines.join("\n");
32914
+ }
32915
+ function buildOperatingNotesSection(notes) {
32916
+ const valid = Array.isArray(notes) ? notes.filter((n) => n && typeof n.text === "string" && n.text.trim()) : [];
32917
+ if (valid.length === 0) return "";
32918
+ const categoryLabel = {
32919
+ provider_quirk: "provider quirk",
32920
+ pattern_to_avoid: "pattern to avoid",
32921
+ recovery_lesson: "recovery lesson"
32922
+ };
32923
+ const lines = ["## Operating Notes", ""];
32924
+ lines.push("Lessons earlier coordinators on this mesh recorded via `mesh_record_note`. Treat them as accumulated operating knowledge \u2014 apply them. When you learn a durable lesson (a provider quirk, a pattern to avoid, a recovery lesson), record it with `mesh_record_note` so future coordinators inherit it.");
32925
+ lines.push("");
32926
+ for (const n of valid) {
32927
+ const cat = n.category && categoryLabel[n.category] ? `[${categoryLabel[n.category]}] ` : "";
32928
+ lines.push(`- ${cat}${n.text.trim()}`);
32929
+ }
32930
+ return lines.join("\n");
32931
+ }
32876
32932
  function buildPolicySection(policy) {
32877
32933
  const rules = [];
32878
32934
  if (policy.requirePreTaskCheckpoint) rules.push("- Create a git checkpoint **before** starting each task");
@@ -32941,6 +32997,7 @@ ${rules.join("\n")}`;
32941
32997
  | \`mesh_read_chat\` | Read recent chat messages from a delegated agent session |
32942
32998
  | \`mesh_read_debug\` | Collect a daemon-side chat/parser debug bundle for a session |
32943
32999
  | \`mesh_task_history\` | Read the task ledger \u2014 dispatches, completions, failures. Use to understand what has been done before deciding next steps |
33000
+ | \`mesh_record_note\` | Record a durable, provider-neutral operating note (provider quirk / pattern to avoid / recovery lesson). Future coordinators see it under "## Operating Notes" at launch |
32944
33001
  | \`mesh_git_status\` | Check git status on a specific node |
32945
33002
  | \`mesh_read_node_logs\` | Fetch a remote node's daemon log tail directly over P2P (grep/since/byte-bounded, secrets redacted) \u2014 no session/PowerShell needed to debug a node's daemon |
32946
33003
  | \`mesh_fast_forward_node\` | Safely dry-run or explicitly execute an obvious clean fast-forward without launching an agent session |
@@ -38527,7 +38584,7 @@ Next step: ${nextStep}`;
38527
38584
  "src/mesh/mesh-events-utils.ts"() {
38528
38585
  "use strict";
38529
38586
  MESH_SURFACED_PREVIEW_MAX_CHARS = 512;
38530
- MESH_COMPLETION_SURFACE_MAX_CHARS = 4e3;
38587
+ MESH_COMPLETION_SURFACE_MAX_CHARS = 16e3;
38531
38588
  }
38532
38589
  });
38533
38590
  function normalizeCoordinatorDaemonIds(coordinatorDaemonId) {
@@ -39170,6 +39227,22 @@ Next step: ${nextStep}`;
39170
39227
  const diag = readRecord4(payload.completionDiagnostic);
39171
39228
  return diag?.finalAssistantPresent === false || diag?.blockReason === "missing_final_assistant";
39172
39229
  }
39230
+ function findTerminalLedgerEvidenceForTask(args) {
39231
+ const taskId = readNonEmptyString2(args.taskId);
39232
+ if (!taskId) return null;
39233
+ const entries = readLedgerEntries(args.meshId, { tail: args.tail ?? 500 });
39234
+ for (let i = entries.length - 1; i >= 0; i--) {
39235
+ const entry = entries[i];
39236
+ if (entry.kind !== "task_completed" && entry.kind !== "task_failed" && entry.kind !== "task_stalled") continue;
39237
+ const terminalTaskId = readNonEmptyString2(entry.payload?.taskId);
39238
+ if (terminalTaskId !== taskId) continue;
39239
+ if (entry.kind === "task_completed" && isWeakCompletionLedgerPayload(entry.payload)) continue;
39240
+ if (args.sessionId && entry.sessionId && entry.sessionId !== args.sessionId) continue;
39241
+ if (!args.sessionId && args.nodeId && entry.nodeId && !meshNodeIdMatches(entry, args.nodeId)) continue;
39242
+ return { id: entry.id, kind: entry.kind, payload: entry.payload || {}, timestamp: entry.timestamp };
39243
+ }
39244
+ return null;
39245
+ }
39173
39246
  function findDirectDispatchLedgerEntry(args) {
39174
39247
  const entries = readLedgerEntries(args.meshId, { tail: 500 });
39175
39248
  for (let i = entries.length - 1; i >= 0; i--) {
@@ -41308,7 +41381,7 @@ Next step: ${nextStep}`;
41308
41381
  "src/providers/chat-message-normalization.ts"() {
41309
41382
  "use strict";
41310
41383
  init_contracts();
41311
- DEFAULT_FINAL_SUMMARY_MAX_CHARS = 4e3;
41384
+ DEFAULT_FINAL_SUMMARY_MAX_CHARS = 16e3;
41312
41385
  BUILTIN_CHAT_MESSAGE_KINDS = ["standard", "thought", "tool", "terminal", "system"];
41313
41386
  CHAT_MESSAGE_VISIBILITIES = ["user", "debug", "internal", "hidden"];
41314
41387
  CHAT_MESSAGE_TRANSCRIPT_VISIBILITIES = ["visible", "chat", "user", "debug", "internal", "hidden"];
@@ -42708,6 +42781,18 @@ ${cleanBody}`;
42708
42781
  const diag = readRecord4(payload.completionDiagnostic);
42709
42782
  return diag?.finalAssistantPresent === false || diag?.blockReason === "missing_final_assistant";
42710
42783
  }
42784
+ function supersedesTruncatedTerminalSummary(args) {
42785
+ if (!args.terminalTaskId || !args.eventTaskId || args.terminalTaskId !== args.eventTaskId) return false;
42786
+ if (!isGenuineCompletionEvidence(args.metadataEvent)) return false;
42787
+ const terminalSummary = readNonEmptyString2(args.terminalPayload.finalSummary);
42788
+ const eventSummary = readNonEmptyString2(args.metadataEvent.finalSummary);
42789
+ if (!eventSummary) return false;
42790
+ if (terminalSummary === eventSummary) return false;
42791
+ if (isWeakTerminalLedgerPayload(args.terminalPayload)) return false;
42792
+ if (!terminalSummary) return true;
42793
+ if (eventSummary.startsWith(terminalSummary)) return true;
42794
+ return eventSummary.length > terminalSummary.length + 32;
42795
+ }
42711
42796
  function resolveActiveDirectDispatchTaskId(meshId, sessionId) {
42712
42797
  try {
42713
42798
  const matches = getActiveDirectDispatches(meshId).filter((d) => d.sessionId === sessionId);
@@ -42817,6 +42902,23 @@ ${cleanBody}`;
42817
42902
  if (!task) {
42818
42903
  return false;
42819
42904
  }
42905
+ const terminal = findTerminalLedgerEvidenceForTask({
42906
+ meshId,
42907
+ taskId: task.id
42908
+ });
42909
+ if (terminal) {
42910
+ const status = terminal.kind === "task_completed" ? "completed" : "failed";
42911
+ updateTaskStatus(meshId, task.id, status);
42912
+ LOG2.info("MeshQueue", `Skipped dispatch for terminal task ${task.id} on mesh ${meshId}; ${terminal.kind} ledger evidence already exists`);
42913
+ traceMeshEventDrop("dispatch_terminal_ledger", {
42914
+ taskId: task.id,
42915
+ sessionId,
42916
+ nodeId,
42917
+ meshId,
42918
+ event: "agent_command"
42919
+ }, terminal.kind);
42920
+ return false;
42921
+ }
42820
42922
  LOG2.info("MeshQueue", `Node ${nodeId} (${sessionId}) pulled task ${task.id}`);
42821
42923
  if (node?.daemonId && components.dispatchMeshCommand) {
42822
42924
  const isLocalNode = components.cliManager.adapters.has(sessionId);
@@ -43607,7 +43709,13 @@ ${cleanBody}`;
43607
43709
  const terminalTaskId = readNonEmptyString2(terminal.payload.taskId);
43608
43710
  const eventTaskId = readNonEmptyString2(args.metadataEvent.taskId);
43609
43711
  const distinctTaskCompletion = !!eventTaskId && !!terminalTaskId && eventTaskId !== terminalTaskId;
43610
- if (!newDispatchAfterTerminal && !supersedesWeakTerminal && !distinctTaskCompletion) {
43712
+ const supersedesTruncatedTerminal = supersedesTruncatedTerminalSummary({
43713
+ terminalPayload: terminal.payload,
43714
+ metadataEvent: args.metadataEvent,
43715
+ terminalTaskId,
43716
+ eventTaskId
43717
+ });
43718
+ if (!newDispatchAfterTerminal && !supersedesWeakTerminal && !distinctTaskCompletion && !supersedesTruncatedTerminal) {
43611
43719
  const terminalProviderSessionId = readNonEmptyString2(terminal.payload.providerSessionId);
43612
43720
  const terminalFinalSummary = readNonEmptyString2(terminal.payload.finalSummary);
43613
43721
  const eventProviderSessionId = readNonEmptyString2(args.metadataEvent.providerSessionId);
@@ -44372,20 +44480,24 @@ ${cleanBody}`;
44372
44480
  if (host.role && host.role !== "host") return false;
44373
44481
  const hostDaemonId = readNonEmptyString2(host.hostDaemonId);
44374
44482
  if (!hostDaemonId) return true;
44375
- return daemonIds.includes(hostDaemonId);
44483
+ return daemonIdListIncludes(daemonIds, hostDaemonId);
44484
+ }
44485
+ function daemonIdListIncludes(ids, id) {
44486
+ if (!id) return false;
44487
+ return ids.some((candidate) => candidate === id || daemonIdsEquivalent(candidate, id));
44376
44488
  }
44377
44489
  function resolveCoordinatorSelfIds(mesh, drainDaemonIds) {
44378
44490
  const ids = new Set(drainDaemonIds);
44379
44491
  for (const node of mesh.nodes) {
44380
44492
  const nodeDaemonId = readNonEmptyString2(node.daemonId);
44381
44493
  const nodeMachineId = readNonEmptyString2(node.machineId);
44382
- const isSelf = nodeDaemonId && drainDaemonIds.includes(nodeDaemonId) || nodeMachineId && drainDaemonIds.includes(nodeMachineId);
44494
+ const isSelf = nodeDaemonId && daemonIdListIncludes(drainDaemonIds, nodeDaemonId) || nodeMachineId && daemonIdListIncludes(drainDaemonIds, nodeMachineId);
44383
44495
  if (!isSelf) continue;
44384
44496
  if (nodeDaemonId) ids.add(nodeDaemonId);
44385
44497
  if (nodeMachineId) ids.add(nodeMachineId);
44386
44498
  }
44387
44499
  const hostDaemonId = readNonEmptyString2(mesh.meshHost?.hostDaemonId);
44388
- if (hostDaemonId && ids.has(hostDaemonId)) ids.add(hostDaemonId);
44500
+ if (hostDaemonId && daemonIdListIncludes([...ids], hostDaemonId)) ids.add(hostDaemonId);
44389
44501
  return [...ids];
44390
44502
  }
44391
44503
  function findLiveCoordinators(components) {
@@ -44398,6 +44510,16 @@ ${cleanBody}`;
44398
44510
  const status = readNonEmptyString2(state.status).toLowerCase();
44399
44511
  const modalParked = status === "waiting_choice" || status === "waiting_approval";
44400
44512
  const sessionId = readNonEmptyString2(state.instanceId);
44513
+ const stateKey = `${meshId}::${sessionId || "?"}`;
44514
+ const prevParked = coordinatorModalParkState.get(stateKey);
44515
+ if (prevParked !== modalParked) {
44516
+ coordinatorModalParkState.set(stateKey, modalParked);
44517
+ if (modalParked) {
44518
+ LOG2.info("MeshReconcile", `Coordinator ${sessionId || "?"} (mesh ${meshId}) entered modal-park (status=${status}) \u2014 terminal events for it will be held until the modal is answered`);
44519
+ } else if (prevParked === true) {
44520
+ LOG2.info("MeshReconcile", `Coordinator ${sessionId || "?"} (mesh ${meshId}) left modal-park (status=${status}) \u2014 held events will drain on this/next tick`);
44521
+ }
44522
+ }
44401
44523
  out.push({ meshId, instance: inst, sessionId, idle: status === "idle", modalParked });
44402
44524
  }
44403
44525
  return out;
@@ -44463,6 +44585,23 @@ ${cleanBody}`;
44463
44585
  const dispatchedAtMs = Date.parse(row.dispatchTimestamp ?? "");
44464
44586
  if (!Number.isFinite(dispatchedAtMs)) continue;
44465
44587
  if (nowMs - dispatchedAtMs < ASSIGNED_STRANDED_DEADLINE_MS) continue;
44588
+ const terminal = findTerminalLedgerEvidenceForTask({
44589
+ meshId,
44590
+ taskId: row.id
44591
+ });
44592
+ if (terminal) {
44593
+ const status = terminal.kind === "task_completed" ? "completed" : "failed";
44594
+ updateTaskStatus(meshId, row.id, status);
44595
+ LOG2.warn("MeshReconcile", `Skipped stranded reclaim redispatch for terminal task ${row.id} on mesh ${meshId}; ${terminal.kind} ledger evidence already exists`);
44596
+ traceMeshEventDrop("assigned_stranded_terminal_ledger", {
44597
+ taskId: row.id,
44598
+ sessionId: row.assignedSessionId,
44599
+ nodeId: row.assignedNodeId,
44600
+ meshId,
44601
+ event: "agent:generating_completed"
44602
+ }, terminal.kind);
44603
+ continue;
44604
+ }
44466
44605
  if (store.taskHasConfirmedDelivery(meshId, row.id)) continue;
44467
44606
  const reclaimed = reclaimStrandedAssignedTask(meshId, row.id, {
44468
44607
  reason: "assigned_stranded_dispatch_unconfirmed",
@@ -44574,7 +44713,55 @@ ${cleanBody}`;
44574
44713
  const forceOnly = idleCoordinators.length === 0;
44575
44714
  if (targetCoordinators.length === 0) {
44576
44715
  if (modalParkedCoordinators.length > 0) {
44577
- LOG2.info("MeshReconcile", `Reconcile skip \u2192 modal-parked: holding pending event(s) for mesh ${meshId} (${modalParkedCoordinators.length} coordinator(s) awaiting a modal answer; events left queued)`);
44716
+ const liveSessionIds = new Set(
44717
+ meshCoordinators.map((c) => readNonEmptyString2(c.sessionId)).filter(Boolean)
44718
+ );
44719
+ let orphanEscaped = 0;
44720
+ const hasPendingForOrphanPeek = !store || (() => {
44721
+ try {
44722
+ return store.pendingEventCount(meshId) > 0;
44723
+ } catch {
44724
+ return true;
44725
+ }
44726
+ })();
44727
+ if (hasPendingForOrphanPeek) {
44728
+ let peeked = [];
44729
+ try {
44730
+ peeked = getPendingMeshCoordinatorEvents(meshId, drainDaemonIds.length > 0 ? drainDaemonIds : void 0);
44731
+ } catch {
44732
+ peeked = [];
44733
+ }
44734
+ const isOrphan = (e) => {
44735
+ const want = readNonEmptyString2(e.targetCoordinatorSessionId);
44736
+ return !!want && !liveSessionIds.has(want);
44737
+ };
44738
+ const orphanEventNames = new Set(peeked.filter(isOrphan).map((e) => e.event));
44739
+ if (orphanEventNames.size > 0) {
44740
+ let drained = [];
44741
+ try {
44742
+ drained = drainPendingMeshCoordinatorEvents(
44743
+ meshId,
44744
+ drainDaemonIds.length > 0 ? drainDaemonIds : localDaemonId,
44745
+ { onlyEvents: orphanEventNames }
44746
+ );
44747
+ } catch (e) {
44748
+ LOG2.warn("MeshReconcile", `Orphan-escape drain failed for mesh ${meshId}: ${e?.message || e}`);
44749
+ drained = [];
44750
+ }
44751
+ for (const pending of drained) {
44752
+ if (isOrphan(pending)) {
44753
+ holdOrExpireStrictUnmatchedEvent(pending, readNonEmptyString2(pending.targetCoordinatorSessionId), meshId);
44754
+ orphanEscaped++;
44755
+ } else {
44756
+ try {
44757
+ queuePendingMeshCoordinatorEvent(pending);
44758
+ } catch {
44759
+ }
44760
+ }
44761
+ }
44762
+ }
44763
+ }
44764
+ LOG2.info("MeshReconcile", `Reconcile skip \u2192 modal-parked: holding pending event(s) for mesh ${meshId} (${modalParkedCoordinators.length} coordinator(s) awaiting a modal answer; events left queued${orphanEscaped > 0 ? `; ${orphanEscaped} orphan-targeted event(s) routed to strict-route TTL` : ""})`);
44578
44765
  let hasPending = true;
44579
44766
  if (store) {
44580
44767
  try {
@@ -44759,7 +44946,7 @@ ${cleanBody}`;
44759
44946
  const nodeDaemonId = readNonEmptyString2(node.daemonId);
44760
44947
  if (!nodeDaemonId) continue;
44761
44948
  if (daemonIdsEquivalent(nodeDaemonId, localDaemonId)) continue;
44762
- if (candidateDaemonIds.includes(nodeDaemonId)) continue;
44949
+ if (daemonIdListIncludes(candidateDaemonIds, nodeDaemonId)) continue;
44763
44950
  for (const pendingEventArgs of pulls) {
44764
44951
  let events;
44765
44952
  try {
@@ -44815,7 +45002,7 @@ ${cleanBody}`;
44815
45002
  if (!sessionId || !nodeId || !taskId) continue;
44816
45003
  const node = nodeById.get(nodeId);
44817
45004
  const nodeDaemonId = readNonEmptyString2(node?.daemonId);
44818
- const isLocalNode = !nodeDaemonId || selfIds.includes(nodeDaemonId) || daemonIdsEquivalent(nodeDaemonId, localDaemonId) || !!components.instanceManager.getInstance(sessionId);
45005
+ const isLocalNode = !nodeDaemonId || daemonIdListIncludes(selfIds, nodeDaemonId) || daemonIdsEquivalent(nodeDaemonId, localDaemonId) || !!components.instanceManager.getInstance(sessionId);
44819
45006
  const providerType = readNonEmptyString2(dispatch.providerType);
44820
45007
  const readArgs = {
44821
45008
  sessionId,
@@ -44845,6 +45032,19 @@ ${cleanBody}`;
44845
45032
  const messages = Array.isArray(payload.messages) ? payload.messages : [];
44846
45033
  const evidence = extractFinalAssistantSummaryEvidence(messages);
44847
45034
  if (!evidence.finalSummary) continue;
45035
+ const dispatchedAtMs = Date.parse(readNonEmptyString2(dispatch.dispatchedAt));
45036
+ const transcriptAtMs = Date.parse(evidence.transcriptMessageAt ?? "");
45037
+ if (Number.isFinite(dispatchedAtMs) && Number.isFinite(transcriptAtMs) && transcriptAtMs < dispatchedAtMs) {
45038
+ LOG2.info("MeshReconcile", `Stale-summary guard: skipping transcript reconcile for task ${taskId} on node ${nodeId} (mesh ${mesh.id}) \u2014 final assistant message (${evidence.transcriptMessageAt}) predates this task's dispatch (${dispatch.dispatchedAt}); it is a prior task's summary`);
45039
+ traceMeshEventDrop("reconcile_stale_summary_before_dispatch", {
45040
+ taskId,
45041
+ sessionId,
45042
+ nodeId,
45043
+ meshId: mesh.id,
45044
+ event: "agent:generating_completed"
45045
+ }, `transcriptAt=${evidence.transcriptMessageAt} < dispatchedAt=${dispatch.dispatchedAt}`);
45046
+ continue;
45047
+ }
44848
45048
  const providerSessionId = readNonEmptyString2(payload.providerSessionId);
44849
45049
  const coordinatorDaemonId = selfIds.find((id) => !!id);
44850
45050
  try {
@@ -44890,7 +45090,7 @@ ${cleanBody}`;
44890
45090
  const dispatchMeshCommand = components.dispatchMeshCommand;
44891
45091
  return Promise.all(mesh.nodes.map(async (node) => {
44892
45092
  const nodeDaemonId = readNonEmptyString2(node.daemonId);
44893
- const isLocalNode = !nodeDaemonId || selfIds.includes(nodeDaemonId) || daemonIdsEquivalent(nodeDaemonId, localDaemonId);
45093
+ const isLocalNode = !nodeDaemonId || daemonIdListIncludes(selfIds, nodeDaemonId) || daemonIdsEquivalent(nodeDaemonId, localDaemonId);
44894
45094
  let statusResult;
44895
45095
  try {
44896
45096
  if (isLocalNode) {
@@ -44974,6 +45174,7 @@ ${cleanBody}`;
44974
45174
  }
44975
45175
  var DEFAULT_RECONCILE_INTERVAL_MS;
44976
45176
  var DEFAULT_AUTO_PRUNE_MIN_AGE_MS;
45177
+ var coordinatorModalParkState;
44977
45178
  var heldEventLedgerRecorded;
44978
45179
  var ASSIGNED_STRANDED_DEADLINE_MS;
44979
45180
  var STRICT_SESSION_MATCH_TTL_MS;
@@ -45000,6 +45201,7 @@ ${cleanBody}`;
45000
45201
  init_chat_message_normalization();
45001
45202
  DEFAULT_RECONCILE_INTERVAL_MS = 4e3;
45002
45203
  DEFAULT_AUTO_PRUNE_MIN_AGE_MS = 24 * 60 * 6e4;
45204
+ coordinatorModalParkState = /* @__PURE__ */ new Map();
45003
45205
  heldEventLedgerRecorded = /* @__PURE__ */ new Set();
45004
45206
  ASSIGNED_STRANDED_DEADLINE_MS = 5 * 6e4;
45005
45207
  STRICT_SESSION_MATCH_TTL_MS = 6e4;
@@ -67746,6 +67948,8 @@ ${body}
67746
67948
  }
67747
67949
  var COMPLETED_FINALIZATION_RETRY_MS = 1e3;
67748
67950
  var COMPLETED_FINALIZATION_MAX_WAIT_MS = 3e4;
67951
+ var NATIVE_HISTORY_MESH_IDLE_SETTLE_MS = 1500;
67952
+ var USER_INPUT_ACK_DEDUP_WINDOW_MS = 6e4;
67749
67953
  var TERMINAL_MESH_EVENTS = /* @__PURE__ */ new Set([
67750
67954
  "agent:generating_completed",
67751
67955
  "agent:stopped",
@@ -68017,6 +68221,14 @@ ${body}
68017
68221
  runtimeMessages = [];
68018
68222
  lastPersistedHistoryMessages = [];
68019
68223
  lastAcknowledgedUserInputAt = 0;
68224
+ // TASKBUBBLE-DUP: per-content last-ack timestamps so the same dispatched
68225
+ // prompt acked twice in quick succession (the worker buffers the first
68226
+ // send during bootstrap/busy, then a redelivery — dispatch-confirm-timeout
68227
+ // requeue or a reconcile re-dispatch — fires a SECOND send_chat before the
68228
+ // outbound queue drains) collapses to ONE user bubble. Keyed on the trimmed
68229
+ // content; an entry older than USER_INPUT_ACK_DEDUP_WINDOW_MS is treated as
68230
+ // a fresh, intentional resend and is NOT suppressed.
68231
+ recentUserInputAcks = /* @__PURE__ */ new Map();
68020
68232
  lastNativeSourceCanonicalCheckAt = 0;
68021
68233
  lastNativeSourceCanonicalCacheKey = void 0;
68022
68234
  cachedSqliteDb = null;
@@ -68451,6 +68663,15 @@ ${body}
68451
68663
  const content = typeof input === "string" ? input.trim() : buildCliStructuredInputPrompt(input).trim();
68452
68664
  if (!content) return;
68453
68665
  const receivedAt = Date.now();
68666
+ const ackContentKey = shortHash(`${this.instanceId}:${content}`, 24);
68667
+ const lastAckAt = this.recentUserInputAcks.get(ackContentKey);
68668
+ if (lastAckAt !== void 0 && receivedAt - lastAckAt <= USER_INPUT_ACK_DEDUP_WINDOW_MS) {
68669
+ this.recentUserInputAcks.set(ackContentKey, receivedAt);
68670
+ this.pruneRecentUserInputAcks(receivedAt);
68671
+ return;
68672
+ }
68673
+ this.recentUserInputAcks.set(ackContentKey, receivedAt);
68674
+ this.pruneRecentUserInputAcks(receivedAt);
68454
68675
  this.lastAcknowledgedUserInputAt = receivedAt;
68455
68676
  const dedupKey = `user_input_ack:${shortHash(`${this.instanceId}:${content}:${receivedAt}`, 24)}`;
68456
68677
  this.appendRuntimeMessage(buildChatMessage({
@@ -68468,6 +68689,13 @@ ${body}
68468
68689
  }
68469
68690
  }), dedupKey);
68470
68691
  }
68692
+ /** Drop user-input ack entries older than the dedup window so the map can't grow unbounded. */
68693
+ pruneRecentUserInputAcks(now) {
68694
+ if (this.recentUserInputAcks.size <= 1) return;
68695
+ for (const [key, at] of this.recentUserInputAcks) {
68696
+ if (now - at > USER_INPUT_ACK_DEDUP_WINDOW_MS) this.recentUserInputAcks.delete(key);
68697
+ }
68698
+ }
68471
68699
  dispose() {
68472
68700
  this.adapter.shutdown();
68473
68701
  this.monitor.reset();
@@ -69157,8 +69385,9 @@ ${body}
69157
69385
  previousStatus: this.lastStatus
69158
69386
  };
69159
69387
  const ownsExternalHistory = !!this.adapter?.chatMessagesOwnedExternally;
69160
- const flushDelay = ownsExternalHistory ? 0 : 3e3;
69161
- LOG2.debug("CLI", `[${this.type}] set completedDebouncePending duration=${duration3}s ownsExternalHistory=${ownsExternalHistory} flushDelay=${flushDelay}ms generatingStartedAt=${this.generatingStartedAt}`);
69388
+ const meshWorkerSession = this.isMeshWorkerSession();
69389
+ const flushDelay = ownsExternalHistory ? meshWorkerSession ? NATIVE_HISTORY_MESH_IDLE_SETTLE_MS : 0 : 3e3;
69390
+ LOG2.debug("CLI", `[${this.type}] set completedDebouncePending duration=${duration3}s ownsExternalHistory=${ownsExternalHistory} meshWorker=${meshWorkerSession} flushDelay=${flushDelay}ms generatingStartedAt=${this.generatingStartedAt}`);
69162
69391
  this.scheduleCompletedDebounceFlush(flushDelay);
69163
69392
  }
69164
69393
  } else if (newStatus === "idle" && this.lastStatus === "starting") {
@@ -72203,11 +72432,11 @@ Run 'adhdev doctor' for detailed diagnostics.`
72203
72432
  }
72204
72433
  }
72205
72434
  }
72206
- const agentResult = await ctx.deps.cliManager.handleCliCommand("agent_command", args);
72207
72435
  const meshCtx = args?.meshContext;
72208
72436
  const dispatchNodeId = readStringValue(meshCtx?.nodeId);
72209
72437
  const dispatchMeshId = readStringValue(meshCtx?.meshId);
72210
- if (dispatchNodeId && dispatchMeshId && agentResult?.success !== false) {
72438
+ const isSendChat = args?.action === "send_chat";
72439
+ if (isSendChat && dispatchNodeId && dispatchMeshId) {
72211
72440
  try {
72212
72441
  const { getMesh: getMesh2 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
72213
72442
  const meshObj = getMesh2(dispatchMeshId) ?? ctx.getCachedInlineMesh(dispatchMeshId);
@@ -72215,17 +72444,22 @@ Run 'adhdev doctor' for detailed diagnostics.`
72215
72444
  const bootstrapStatus = readStringValue(nodeObj?.worktreeBootstrap?.status);
72216
72445
  if (bootstrapStatus === "running") {
72217
72446
  return {
72218
- success: true,
72219
- ...agentResult,
72220
- dispatchAcknowledgementRisk: true,
72221
- dispatchAcknowledgementRiskReason: "bootstrap_still_running",
72222
- nextAction: "Wait for worktree_bootstrap_complete event before dispatching work to this node."
72447
+ success: false,
72448
+ recoverable: true,
72449
+ dispatched: false,
72450
+ code: "mesh_node_bootstrap_pending",
72451
+ reason: "bootstrap_still_running",
72452
+ nodeId: dispatchNodeId,
72453
+ meshId: dispatchMeshId,
72454
+ ...readStringValue(meshCtx?.taskId) ? { taskId: readStringValue(meshCtx?.taskId) } : {},
72455
+ error: `Node '${dispatchNodeId}' worktree bootstrap is still running; a task injected now would land in the session input buffer before the provider is ready to consume it and be silently lost. Dispatch deferred.`,
72456
+ nextAction: "Wait for the worktree_bootstrap_complete event (or poll mesh_status until the node session is ready), then re-send the task with mesh_send_task. Alternatively use mesh_enqueue_task so the queue auto-assigns it once a ready session is available."
72223
72457
  };
72224
72458
  }
72225
72459
  } catch {
72226
72460
  }
72227
72461
  }
72228
- return agentResult;
72462
+ return ctx.deps.cliManager.handleCliCommand("agent_command", args);
72229
72463
  },
72230
72464
  // ─── Logs ───
72231
72465
  list_saved_sessions: async (ctx, args) => {
@@ -76447,7 +76681,7 @@ ${formatManifestValidationIssues2(validation2.issues)}`);
76447
76681
  return "";
76448
76682
  }
76449
76683
  })();
76450
- const isCoordinatorBaseNode = !!selfDaemonId && (nodeDaemonId === selfDaemonId || nodeMachineId === selfDaemonId) || !!selfMachineId && (nodeDaemonId === selfMachineId || nodeMachineId === selfMachineId);
76684
+ const isCoordinatorBaseNode = !!selfDaemonId && (daemonIdsEquivalent(nodeDaemonId, selfDaemonId) || daemonIdsEquivalent(nodeMachineId, selfDaemonId)) || !!selfMachineId && (daemonIdsEquivalent(nodeDaemonId, selfMachineId) || daemonIdsEquivalent(nodeMachineId, selfMachineId));
76451
76685
  if (isCoordinatorBaseNode) {
76452
76686
  return {
76453
76687
  success: false,
@@ -77307,49 +77541,72 @@ ${formatManifestValidationIssues2(validation2.issues)}`);
77307
77541
  };
77308
77542
  },
77309
77543
  fast_forward_mesh_node: async (ctx, args) => {
77310
- const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
77311
- const nodeId = typeof args?.nodeId === "string" ? args.nodeId.trim() : "";
77312
- let workspace = typeof args?.workspace === "string" ? args.workspace.trim() : "";
77313
- let submoduleIgnorePaths = Array.isArray(args?.submoduleIgnorePaths) ? args.submoduleIgnorePaths.filter((value) => typeof value === "string") : void 0;
77314
- let nodeDaemonId;
77315
- let allowAutoPublishSubmoduleMainCommits = false;
77316
- if (meshId && nodeId) {
77317
- const meshRecord = await ctx.getMeshForCommand(meshId, args?.inlineMesh, { preferInline: true });
77318
- const mesh = meshRecord?.mesh;
77319
- const node = mesh?.nodes?.find((n) => meshNodeIdMatches(n, nodeId));
77320
- if (!workspace) {
77321
- workspace = typeof node?.workspace === "string" ? node.workspace.trim() : "";
77544
+ const workspaceForError = typeof args?.workspace === "string" ? args.workspace.trim() : "";
77545
+ const meshIdForError = typeof args?.meshId === "string" ? args.meshId.trim() : "";
77546
+ const nodeIdForError = typeof args?.nodeId === "string" ? args.nodeId.trim() : "";
77547
+ try {
77548
+ const meshId = meshIdForError;
77549
+ const nodeId = nodeIdForError;
77550
+ let workspace = workspaceForError;
77551
+ let submoduleIgnorePaths = Array.isArray(args?.submoduleIgnorePaths) ? args.submoduleIgnorePaths.filter((value) => typeof value === "string") : void 0;
77552
+ let nodeDaemonId;
77553
+ let allowAutoPublishSubmoduleMainCommits = false;
77554
+ if (meshId && nodeId) {
77555
+ const meshRecord = await ctx.getMeshForCommand(meshId, args?.inlineMesh, { preferInline: true });
77556
+ const mesh = meshRecord?.mesh;
77557
+ const node = mesh?.nodes?.find((n) => meshNodeIdMatches(n, nodeId));
77558
+ if (!workspace) {
77559
+ workspace = typeof node?.workspace === "string" ? node.workspace.trim() : "";
77560
+ }
77561
+ if (!submoduleIgnorePaths && Array.isArray(node?.policy?.submoduleIgnorePaths)) {
77562
+ submoduleIgnorePaths = node.policy.submoduleIgnorePaths.filter((value) => typeof value === "string");
77563
+ }
77564
+ allowAutoPublishSubmoduleMainCommits = mesh?.policy?.allowAutoPublishSubmoduleMainCommits === true;
77565
+ nodeDaemonId = typeof node?.daemonId === "string" ? node.daemonId.trim() : void 0;
77322
77566
  }
77323
- if (!submoduleIgnorePaths && Array.isArray(node?.policy?.submoduleIgnorePaths)) {
77324
- submoduleIgnorePaths = node.policy.submoduleIgnorePaths.filter((value) => typeof value === "string");
77567
+ const selfDaemonId = ctx.deps.statusInstanceId;
77568
+ const isRemote = nodeDaemonId && selfDaemonId && !daemonIdsEquivalent(nodeDaemonId, selfDaemonId);
77569
+ if (isRemote && ctx.deps.dispatchMeshCommand && !args?._meshDirectDispatch) {
77570
+ const forwarded = await ctx.deps.dispatchMeshCommand(nodeDaemonId, "fast_forward_mesh_node", {
77571
+ ...typeof args === "object" && args !== null ? args : {},
77572
+ workspace,
77573
+ _meshDirectDispatch: true
77574
+ });
77575
+ return forwarded ?? { success: false, error: "no response from remote node" };
77325
77576
  }
77326
- allowAutoPublishSubmoduleMainCommits = mesh?.policy?.allowAutoPublishSubmoduleMainCommits === true;
77327
- nodeDaemonId = typeof node?.daemonId === "string" ? node.daemonId.trim() : void 0;
77328
- }
77329
- const selfDaemonId = ctx.deps.statusInstanceId;
77330
- const isRemote = nodeDaemonId && selfDaemonId && !daemonIdsEquivalent(nodeDaemonId, selfDaemonId);
77331
- if (isRemote && ctx.deps.dispatchMeshCommand && !args?._meshDirectDispatch) {
77332
- const forwarded = await ctx.deps.dispatchMeshCommand(nodeDaemonId, "fast_forward_mesh_node", {
77333
- ...typeof args === "object" && args !== null ? args : {},
77577
+ const result = await fastForwardMeshNode({
77578
+ meshId: meshId || void 0,
77579
+ nodeId: nodeId || void 0,
77334
77580
  workspace,
77335
- _meshDirectDispatch: true
77581
+ branch: typeof args?.branch === "string" ? args.branch : void 0,
77582
+ execute: args?.execute === true,
77583
+ dryRun: args?.dryRun === true,
77584
+ updateSubmodules: args?.updateSubmodules === true,
77585
+ submoduleIgnorePaths,
77586
+ mode: args?.mode === "push" ? "push" : "merge",
77587
+ pushSubmodules: args?.pushSubmodules === true,
77588
+ allowAutoPublishSubmoduleMainCommits
77336
77589
  });
77337
- return forwarded ?? { success: false, error: "no response from remote node" };
77590
+ return result;
77591
+ } catch (e) {
77592
+ const errorMessage = e?.message || String(e);
77593
+ return {
77594
+ success: false,
77595
+ code: "fast_forward_safety_gate_error",
77596
+ ...meshIdForError ? { meshId: meshIdForError } : {},
77597
+ ...nodeIdForError ? { nodeId: nodeIdForError } : {},
77598
+ workspace: workspaceForError,
77599
+ mode: args?.mode === "push" ? "push" : "merge",
77600
+ allowed: false,
77601
+ willRun: false,
77602
+ executed: false,
77603
+ // Surface the throw as a blocking reason instead of an opaque IPC crash
77604
+ // so the coordinator gets the same structured shape a clean node returns.
77605
+ blockingReasons: ["fast_forward_safety_gate_error"],
77606
+ operationError: errorMessage,
77607
+ error: errorMessage
77608
+ };
77338
77609
  }
77339
- const result = await fastForwardMeshNode({
77340
- meshId: meshId || void 0,
77341
- nodeId: nodeId || void 0,
77342
- workspace,
77343
- branch: typeof args?.branch === "string" ? args.branch : void 0,
77344
- execute: args?.execute === true,
77345
- dryRun: args?.dryRun === true,
77346
- updateSubmodules: args?.updateSubmodules === true,
77347
- submoduleIgnorePaths,
77348
- mode: args?.mode === "push" ? "push" : "merge",
77349
- pushSubmodules: args?.pushSubmodules === true,
77350
- allowAutoPublishSubmoduleMainCommits
77351
- });
77352
- return result;
77353
77610
  },
77354
77611
  refine_mesh_node: async (ctx, args) => {
77355
77612
  const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
@@ -77498,6 +77755,56 @@ ${formatManifestValidationIssues2(validation2.issues)}`);
77498
77755
  return "";
77499
77756
  }
77500
77757
  };
77758
+ const buildRecentActivityBestEffort = async (id) => {
77759
+ try {
77760
+ const { getLedgerSummary: getLedgerSummary2, readLedgerEntries: readLedgerEntries2 } = await Promise.resolve().then(() => (init_mesh_ledger(), mesh_ledger_exports));
77761
+ const { getMeshQueueStats: getMeshQueueStats2 } = await Promise.resolve().then(() => (init_mesh_work_queue(), mesh_work_queue_exports));
77762
+ const summary = getLedgerSummary2(id);
77763
+ const queue = getMeshQueueStats2(id);
77764
+ const failureEntries = readLedgerEntries2(id, { kind: ["task_failed"], tail: 5 });
77765
+ const recentFailures = failureEntries.map((e) => {
77766
+ const p = e.payload || {};
77767
+ const raw = typeof p.taskSummary === "string" ? p.taskSummary : typeof p.message === "string" ? p.message : typeof p.error === "string" ? p.error : "";
77768
+ const summaryText = raw.length > 160 ? `${raw.slice(0, 160)}\u2026` : raw;
77769
+ return {
77770
+ timestamp: e.timestamp,
77771
+ nodeId: e.nodeId,
77772
+ summary: summaryText
77773
+ };
77774
+ });
77775
+ return {
77776
+ recentFailures,
77777
+ recentFailureCount: summary.recentFailures,
77778
+ pendingTasks: queue.pending,
77779
+ assignedTasks: queue.assigned,
77780
+ stalledTasks: summary.taskStalled,
77781
+ lastActivityAt: summary.lastActivityAt
77782
+ };
77783
+ } catch {
77784
+ return void 0;
77785
+ }
77786
+ };
77787
+ const buildOperatingNotesBestEffort = async (id) => {
77788
+ try {
77789
+ const { readLedgerEntries: readLedgerEntries2 } = await Promise.resolve().then(() => (init_mesh_ledger(), mesh_ledger_exports));
77790
+ const noteEntries = readLedgerEntries2(id, { kind: ["coordinator_operating_note"], tail: 20 });
77791
+ const notes = noteEntries.map((e) => {
77792
+ const p = e.payload || {};
77793
+ const text = typeof p.text === "string" ? p.text.trim() : "";
77794
+ if (!text) return null;
77795
+ const category = p.category === "provider_quirk" || p.category === "pattern_to_avoid" || p.category === "recovery_lesson" ? p.category : void 0;
77796
+ return {
77797
+ text,
77798
+ category,
77799
+ createdAt: typeof p.createdAt === "string" ? p.createdAt : e.timestamp,
77800
+ sourceCoordinator: typeof p.sourceCoordinator === "string" ? p.sourceCoordinator : void 0
77801
+ };
77802
+ }).filter((n) => n !== null);
77803
+ return notes.length ? notes : void 0;
77804
+ } catch {
77805
+ return void 0;
77806
+ }
77807
+ };
77501
77808
  let mesh;
77502
77809
  if (args?.inlineMesh && typeof args.inlineMesh === "object") {
77503
77810
  mesh = args.inlineMesh;
@@ -77588,7 +77895,7 @@ ${formatManifestValidationIssues2(validation2.issues)}`);
77588
77895
  if (coordinatorSetup.kind === "cli_command") {
77589
77896
  let cliCmdSystemPrompt = "";
77590
77897
  try {
77591
- cliCmdSystemPrompt = buildCoordinatorSystemPrompt2({ mesh, coordinatorCliType: cliType, userInstruction: extraSystemPrompt || void 0, missionSection: buildMissionSectionBestEffort(mesh.id) });
77898
+ cliCmdSystemPrompt = buildCoordinatorSystemPrompt2({ mesh, coordinatorCliType: cliType, userInstruction: extraSystemPrompt || void 0, missionSection: buildMissionSectionBestEffort(mesh.id), recentActivity: await buildRecentActivityBestEffort(mesh.id), operatingNotes: await buildOperatingNotesBestEffort(mesh.id) });
77592
77899
  } catch (error48) {
77593
77900
  const message = error48?.message || String(error48);
77594
77901
  LOG2.error("MeshCoordinator", `Failed to build coordinator prompt: ${message}`);
@@ -77765,7 +78072,7 @@ ${ptyResult.output.slice(-2e3)}`);
77765
78072
  }
77766
78073
  let systemPrompt = "";
77767
78074
  try {
77768
- systemPrompt = buildCoordinatorSystemPrompt2({ mesh, coordinatorCliType: cliType, userInstruction: extraSystemPrompt || void 0, missionSection: buildMissionSectionBestEffort(mesh.id) });
78075
+ systemPrompt = buildCoordinatorSystemPrompt2({ mesh, coordinatorCliType: cliType, userInstruction: extraSystemPrompt || void 0, missionSection: buildMissionSectionBestEffort(mesh.id), recentActivity: await buildRecentActivityBestEffort(mesh.id), operatingNotes: await buildOperatingNotesBestEffort(mesh.id) });
77769
78076
  } catch (error48) {
77770
78077
  const message = error48?.message || String(error48);
77771
78078
  LOG2.error("MeshCoordinator", `Failed to build coordinator prompt: ${message}`);