@adhdev/daemon-core 0.9.82-rc.132 → 0.9.82-rc.134

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -1198,7 +1198,7 @@ function buildRulesSection(coordinatorCliType) {
1198
1198
 
1199
1199
  - **Minimize coordinator context.** The coordinator's job is routing, not implementing. Do not read source files, run commands, or analyze code directly \u2014 delegate all of that to node agents. Your context should stay lean.
1200
1200
  - **Delegate analysis too.** If you need to understand a bug or explore the codebase, send that investigation as a task to the queue or a node. Do not do it yourself.
1201
- - **Respect explicit provider requests.** If the user names an agent/provider, pass the matching provider type to \`mesh_launch_session\`: Hermes \u2192 \`hermes-cli\`, Claude Code/Claude \u2192 \`claude-cli\`, Codex \u2192 \`codex-cli\`, Gemini \u2192 \`gemini-cli\`. Never substitute \`claude-cli\` just because the coordinator itself is Claude Code.
1201
+ - **Respect explicit provider requests.** If the user names an agent/provider, pass the matching provider type to \`mesh_launch_session\`: Hermes \u2192 \`hermes-cli\`, Claude Code/Claude \u2192 \`claude-cli\`, Codex \u2192 \`codex-cli\`, Gemini \u2192 \`gemini-cli\`, Antigravity \u2192 \`antigravity-cli\`. Never substitute \`claude-cli\` just because the coordinator itself is Claude Code.
1202
1202
  - **Front-load new task messages.** When calling \`mesh_enqueue_task\` or \`mesh_send_task\` for a new task, include everything the agent needs: what files to touch, what the problem is, what the fix should look like. The agent won't ask follow-up questions.
1203
1203
  - **Avoid context-wasting restarts.** For follow-up, retry, commit/push, preview, or cleanup work on the same issue, prefer the existing idle session and send only the delta from its last verified state. Start a fresh chat/session only for genuinely independent work, explicit provider/user request, unsafe transcript contamination, or required branch/worktree isolation.
1204
1204
  - **Don't inspect code.** Treat delegated agent summaries as self-reports, not verification. Verify side effects via \`mesh_git_status\` (including related repo freshness when configured), not by reading source files.
@@ -2814,14 +2814,26 @@ function findRecentTerminalLedgerEvidence(args) {
2814
2814
  const entry = entries[i];
2815
2815
  if (entry.kind !== "task_completed" && entry.kind !== "task_failed" && entry.kind !== "task_stalled") continue;
2816
2816
  if (args.sessionId && entry.sessionId === args.sessionId) {
2817
- return { kind: entry.kind, payload: entry.payload || {}, timestamp: entry.timestamp };
2817
+ return { id: entry.id, kind: entry.kind, payload: entry.payload || {}, timestamp: entry.timestamp };
2818
2818
  }
2819
2819
  if (!args.sessionId && args.nodeId && entry.nodeId === args.nodeId) {
2820
- return { kind: entry.kind, payload: entry.payload || {}, timestamp: entry.timestamp };
2820
+ return { id: entry.id, kind: entry.kind, payload: entry.payload || {}, timestamp: entry.timestamp };
2821
2821
  }
2822
2822
  }
2823
2823
  return null;
2824
2824
  }
2825
+ function hasDispatchAfterTerminal(meshId, sessionId, terminalId) {
2826
+ const entries = readLedgerEntries(meshId);
2827
+ let pastTerminal = false;
2828
+ for (const entry of entries) {
2829
+ if (!pastTerminal) {
2830
+ if (entry.id === terminalId) pastTerminal = true;
2831
+ continue;
2832
+ }
2833
+ if (entry.kind === "task_dispatched" && entry.sessionId === sessionId) return true;
2834
+ }
2835
+ return false;
2836
+ }
2825
2837
  function buildLongGeneratingCompletionReconciliation(args) {
2826
2838
  const sessionId = resolveEventSessionId(args.metadataEvent, args.sourceInstanceId);
2827
2839
  const nodeId = readNonEmptyString2(args.nodeId) || readNonEmptyString2(args.metadataEvent.meshNodeId);
@@ -3326,13 +3338,16 @@ function injectMeshSystemMessage(components, args) {
3326
3338
  nodeId: eventNodeId || void 0
3327
3339
  });
3328
3340
  if (terminal?.kind === "task_completed" && !sessionHasActiveAssignment(args.meshId, eventSessionId)) {
3329
- const terminalProviderSessionId = readNonEmptyString2(terminal.payload.providerSessionId);
3330
- const terminalFinalSummary = readNonEmptyString2(terminal.payload.finalSummary);
3331
- const eventProviderSessionId = readNonEmptyString2(args.metadataEvent.providerSessionId);
3332
- const eventFinalSummary = readNonEmptyString2(args.metadataEvent.finalSummary);
3333
- if (terminalProviderSessionId && terminalProviderSessionId === eventProviderSessionId || terminalFinalSummary && terminalFinalSummary === eventFinalSummary || args.metadataEvent.source === "long_generating_reconciliation") {
3334
- LOG.info("MeshEvents", `Suppressed duplicate completion with existing terminal ledger evidence for mesh ${args.meshId} session ${eventSessionId}`);
3335
- return { success: true, forwarded: 0, suppressed: true, duplicateCompletion: true, terminalLedgerEvidence: true };
3341
+ const newDispatchAfterTerminal = hasDispatchAfterTerminal(args.meshId, eventSessionId, terminal.id);
3342
+ if (!newDispatchAfterTerminal) {
3343
+ const terminalProviderSessionId = readNonEmptyString2(terminal.payload.providerSessionId);
3344
+ const terminalFinalSummary = readNonEmptyString2(terminal.payload.finalSummary);
3345
+ const eventProviderSessionId = readNonEmptyString2(args.metadataEvent.providerSessionId);
3346
+ const eventFinalSummary = readNonEmptyString2(args.metadataEvent.finalSummary);
3347
+ if (terminalProviderSessionId && terminalProviderSessionId === eventProviderSessionId || terminalFinalSummary && terminalFinalSummary === eventFinalSummary || args.metadataEvent.source === "long_generating_reconciliation") {
3348
+ LOG.info("MeshEvents", `Suppressed duplicate completion with existing terminal ledger evidence for mesh ${args.meshId} session ${eventSessionId}`);
3349
+ return { success: true, forwarded: 0, suppressed: true, duplicateCompletion: true, terminalLedgerEvidence: true };
3350
+ }
3336
3351
  }
3337
3352
  }
3338
3353
  const duplicateCompletion = isDuplicateMeshCompletionEvent({
@@ -3559,7 +3574,13 @@ function injectMeshSystemMessage(components, args) {
3559
3574
  }
3560
3575
  return { success: true, forwarded: 0 };
3561
3576
  }
3562
- if (!isRefineTerminalEvent) {
3577
+ const allCoordinatorsGenerating = isRefineTerminalEvent && coordinatorInstances.every((inst) => {
3578
+ const s = inst.getState();
3579
+ const status = readNonEmptyString2(s.status).toLowerCase();
3580
+ const activeChatStatus = readNonEmptyString2(s.activeChat?.status).toLowerCase();
3581
+ return status === "generating" || status === "streaming" || status === "long_generating" || activeChatStatus === "generating" || activeChatStatus === "streaming";
3582
+ });
3583
+ if (!isRefineTerminalEvent || allCoordinatorsGenerating) {
3563
3584
  if (queuePendingMeshCoordinatorEvent({
3564
3585
  event: args.event,
3565
3586
  meshId: args.meshId,
@@ -3573,9 +3594,16 @@ function injectMeshSystemMessage(components, args) {
3573
3594
  coordinatorMessage: messageText,
3574
3595
  queuedAt: Date.now()
3575
3596
  })) {
3576
- LOG.info("MeshEvents", `Queued ${args.event} for MCP coordinator (mesh ${args.meshId})`);
3597
+ if (allCoordinatorsGenerating) {
3598
+ LOG.info("MeshEvents", `Queued ${args.event} for generating CLI coordinator (mesh ${args.meshId}) \u2014 will be delivered via get_pending_mesh_events when coordinator returns to idle`);
3599
+ } else {
3600
+ LOG.info("MeshEvents", `Queued ${args.event} for MCP coordinator (mesh ${args.meshId})`);
3601
+ }
3577
3602
  }
3578
3603
  }
3604
+ if (allCoordinatorsGenerating) {
3605
+ return { success: true, forwarded: 0, bufferedForGeneratingCoordinator: true };
3606
+ }
3579
3607
  for (const coord of coordinatorInstances) {
3580
3608
  const coordState = coord.getState();
3581
3609
  LOG.info("MeshEvents", `Forwarding mesh event to coordinator ${coordState.instanceId}`);
@@ -9942,6 +9970,7 @@ function buildMeshActiveWorkSummary(activeWork) {
9942
9970
  statusCounts[item.status] += 1;
9943
9971
  }
9944
9972
  const staleDirectCount = activeWork.filter((item) => item.source === "direct" && item.staleReason).length;
9973
+ const staleDirectUnacknowledgedCount = activeWork.filter((item) => item.source === "direct" && item.staleDispatchUnacknowledged).length;
9945
9974
  return {
9946
9975
  totalActiveCount: activeWork.length,
9947
9976
  queueActiveCount: sourceCounts.queue,
@@ -9953,6 +9982,7 @@ function buildMeshActiveWorkSummary(activeWork) {
9953
9982
  sourceCounts,
9954
9983
  statusCounts,
9955
9984
  staleDirectCount,
9985
+ ...staleDirectUnacknowledgedCount > 0 ? { staleDirectUnacknowledgedCount } : {},
9956
9986
  ...staleDirectCount > 0 ? { staleDirectNote: "Stale direct records are orphaned ledger entries whose node/session no longer exists. They are historical recovery evidence only \u2014 not active or unresolved work. The queue (source: queue) is authoritative for pending/assigned tasks." } : {}
9957
9987
  };
9958
9988
  }
@@ -9989,9 +10019,13 @@ function buildMeshActiveWork(opts) {
9989
10019
  const live = sessionStatusFromNodes(opts.nodes, dispatch.nodeId, dispatch.sessionId);
9990
10020
  const status = terminalStatus || live.status || "assigned";
9991
10021
  const terminalRow = Boolean(terminal && terminal.kind !== "task_approval_needed");
9992
- const ledgerOnlyStaleReason = !terminalRow && (status === "idle" || !terminalStatus && !live.status) ? "direct task dispatch has no provider acknowledgement, transcript append, or active runtime transition" : void 0;
10022
+ const dispatchedToIdleSession = dispatch.payload?.dispatchedToIdleSession === true;
10023
+ const isNoTransition = !terminalStatus && !live.status;
10024
+ const isIdleUnacknowledged = status === "idle";
10025
+ const ledgerOnlyStaleReason = !terminalRow && (isIdleUnacknowledged || isNoTransition || dispatchedToIdleSession && isIdleUnacknowledged) ? "direct task dispatch has no provider acknowledgement, transcript append, or active runtime transition" : void 0;
9993
10026
  const message = readString2(dispatch.payload?.message) || readString2(dispatch.payload?.summary) || "";
9994
10027
  const { title, summary: summary2 } = summarizeMessage(message);
10028
+ const isFreshUnacknowledged = Boolean(ledgerOnlyStaleReason && !live.staleReason);
9995
10029
  const record = {
9996
10030
  taskId,
9997
10031
  source: "direct",
@@ -10010,7 +10044,8 @@ function buildMeshActiveWork(opts) {
10010
10044
  terminal: terminalRow,
10011
10045
  terminalKind: terminal?.kind,
10012
10046
  terminalAt: terminal?.timestamp,
10013
- staleReason: live.staleReason || ledgerOnlyStaleReason
10047
+ staleReason: live.staleReason || ledgerOnlyStaleReason,
10048
+ ...isFreshUnacknowledged ? { staleDispatchUnacknowledged: true } : {}
10014
10049
  };
10015
10050
  if (terminalRow) {
10016
10051
  terminalDirectWork.push(record);
@@ -10027,7 +10062,11 @@ function buildMeshActiveWork(opts) {
10027
10062
  terminalDirectWork.sort((a, b) => new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime());
10028
10063
  const summary = buildMeshActiveWorkSummary(records);
10029
10064
  summary.staleDirectCount = staleDirectWork.length;
10030
- const staleDirectWorkNote = staleDirectWork.length > 0 ? "These are orphaned ledger entries whose original node or session no longer exists in the live mesh. They are historical/recovery evidence only \u2014 not active or unresolved work. Do not treat staleDirectCount as a status mismatch; use the queue (source: queue) as authoritative for pending/assigned tasks." : void 0;
10065
+ const unacknowledgedCount = staleDirectWork.filter((r) => r.staleDispatchUnacknowledged).length;
10066
+ if (unacknowledgedCount > 0) {
10067
+ summary.staleDirectUnacknowledgedCount = unacknowledgedCount;
10068
+ }
10069
+ const staleDirectWorkNote = staleDirectWork.length > 0 ? unacknowledgedCount > 0 && unacknowledgedCount === staleDirectWork.length ? `${unacknowledgedCount} direct dispatch(es) were not acknowledged by the target session \u2014 the session received the agent_command but never transitioned to generating. This is a fresh dispatch failure, not historical noise. Recovery: launch a fresh session on the same node and retry the task, or use mesh_enqueue_task for queue-based assignment.` : unacknowledgedCount > 0 ? `${unacknowledgedCount} of ${staleDirectWork.length} stale direct record(s) are fresh unacknowledged dispatch failures (session still live but never transitioned to generating); the rest are orphaned historical entries whose node/session no longer exists. Fresh unacknowledged dispatches need recovery: launch a fresh session and retry. Orphaned entries are historical evidence only \u2014 not active or unresolved work.` : "These are orphaned ledger entries whose original node or session no longer exists in the live mesh. They are historical/recovery evidence only \u2014 not active or unresolved work. Do not treat staleDirectCount as a status mismatch; use the queue (source: queue) as authoritative for pending/assigned tasks." : void 0;
10031
10070
  if (staleDirectWorkNote) {
10032
10071
  summary.staleDirectNote = staleDirectWorkNote;
10033
10072
  }
@@ -21062,7 +21101,10 @@ var CliProviderInstance = class {
21062
21101
  if (!isCliGeneratingLikeStatus(parsedRawStatus)) return false;
21063
21102
  if (adapterRawStatus !== "idle") return false;
21064
21103
  if (hasNonEmptyCliModalButtons(parsedStatus?.activeModal ?? parsedStatus?.modal)) return false;
21065
- return !this.hasAdapterPendingResponse();
21104
+ if (this.hasAdapterPendingResponse()) return false;
21105
+ const adapterAny = this.adapter;
21106
+ if (typeof adapterAny?.responseBuffer === "string" && adapterAny.responseBuffer.trim()) return false;
21107
+ return true;
21066
21108
  }
21067
21109
  getCompletedFinalizationBlock(latestVisibleStatus) {
21068
21110
  if (latestVisibleStatus !== "idle") return { reason: `status:${latestVisibleStatus}`, terminal: true };
@@ -21260,13 +21302,30 @@ var CliProviderInstance = class {
21260
21302
  } else if (newStatus === "idle" && (this.lastStatus === "generating" || this.lastStatus === "waiting_approval")) {
21261
21303
  const duration = this.generatingStartedAt ? Math.round((now - this.generatingStartedAt) / 1e3) : 0;
21262
21304
  if (this.generatingDebouncePending) {
21263
- LOG.info("CLI", `[${this.type}] suppressed short generating (${now - this.generatingStartedAt}ms)`);
21305
+ const shortDurationMs = this.generatingStartedAt ? now - this.generatingStartedAt : 0;
21306
+ LOG.info("CLI", `[${this.type}] suppressed short generating (${shortDurationMs}ms)`);
21264
21307
  if (this.generatingDebounceTimer) {
21265
21308
  clearTimeout(this.generatingDebounceTimer);
21266
21309
  this.generatingDebounceTimer = null;
21267
21310
  }
21268
21311
  this.generatingDebouncePending = null;
21269
21312
  this.generatingStartedAt = 0;
21313
+ let shortFinalSummary;
21314
+ try {
21315
+ shortFinalSummary = extractFinalSummaryFromMessages(this.adapter?.getScriptParsedStatus()?.messages);
21316
+ } catch {
21317
+ }
21318
+ this.pushEvent({
21319
+ event: "agent:generating_completed",
21320
+ chatTitle,
21321
+ duration: 0,
21322
+ timestamp: now,
21323
+ finalSummary: shortFinalSummary,
21324
+ completionDiagnostic: {
21325
+ reason: "short_generating_suppressed",
21326
+ shortDurationMs
21327
+ }
21328
+ });
21270
21329
  } else {
21271
21330
  this.completedDebouncePending = { chatTitle, duration, timestamp: now, firstObservedAt: now };
21272
21331
  this.scheduleCompletedDebounceFlush(3e3);