@adhdev/daemon-standalone 1.0.28-rc.16 → 1.0.28-rc.18

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
@@ -33262,10 +33262,10 @@ var require_dist3 = __commonJS({
33262
33262
  }
33263
33263
  function getDaemonBuildInfo() {
33264
33264
  if (cached2) return cached2;
33265
- const commit = readInjected(true ? "3a48f660f00c3bf2e42ba36df7789edbc654b99c" : void 0) ?? "unknown";
33266
- const commitShort = readInjected(true ? "3a48f660" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
33267
- const version2 = readInjected(true ? "1.0.28-rc.16" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
33268
- const builtAt = readInjected(true ? "2026-07-26T16:41:21.955Z" : void 0);
33265
+ const commit = readInjected(true ? "2ab22815548d9465b9f6a28a058049ba230dfb61" : void 0) ?? "unknown";
33266
+ const commitShort = readInjected(true ? "2ab22815" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
33267
+ const version2 = readInjected(true ? "1.0.28-rc.18" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
33268
+ const builtAt = readInjected(true ? "2026-07-27T05:52:27.345Z" : void 0);
33269
33269
  cached2 = builtAt ? { commit, commitShort, version: version2, builtAt } : { commit, commitShort, version: version2 };
33270
33270
  return cached2;
33271
33271
  }
@@ -49047,6 +49047,31 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
49047
49047
  function recordSynthCompletionGateTrace(stage, payload) {
49048
49048
  recordDebugTrace({ category: "completion-gate", stage, level: "debug", payload });
49049
49049
  }
49050
+ function evaluateTranscriptSynthAdmission(admission) {
49051
+ if (!admission) return { admitted: true };
49052
+ if (admission.trailingToolActivityAfterFinalAssistant === true) {
49053
+ return { admitted: false, reason: "trailing_tool_activity_after_final_assistant" };
49054
+ }
49055
+ if (!admission.boundedBackstop && typeof admission.liveTurnPendingEvidence === "function") {
49056
+ let pending = false;
49057
+ try {
49058
+ pending = admission.liveTurnPendingEvidence() === true;
49059
+ } catch {
49060
+ }
49061
+ if (pending) return { admitted: false, reason: "live_turn_pending_evidence" };
49062
+ }
49063
+ return { admitted: true };
49064
+ }
49065
+ function resolveLiveTurnPendingEvidence(components, sessionId) {
49066
+ try {
49067
+ const instance = components?.instanceManager?.getInstance?.(sessionId);
49068
+ if (typeof instance?.hasLiveTurnPendingEvidence !== "function") return void 0;
49069
+ const probe = instance.hasLiveTurnPendingEvidence.bind(instance);
49070
+ return () => probe();
49071
+ } catch {
49072
+ return void 0;
49073
+ }
49074
+ }
49050
49075
  function findRecentTerminalLedgerEvidence(args) {
49051
49076
  if (!args.sessionId && !args.nodeId) return null;
49052
49077
  const entries = readLedgerEntries(args.meshId, { tail: 200 });
@@ -49167,6 +49192,17 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
49167
49192
  })) {
49168
49193
  return { reconciled: false, alreadyTerminal: true, reason: "terminal_ledger_entry_exists" };
49169
49194
  }
49195
+ const admission = evaluateTranscriptSynthAdmission(args.causalAdmission);
49196
+ if (!admission.admitted) {
49197
+ LOG2.info("MeshEvents", `Transcript synth vetoed for task ${args.taskId} session ${args.sessionId} (source ${args.source || "direct_task_transcript_reconciliation"}): ${admission.reason} \u2014 holding the completion; it re-evaluates on the next reconcile pass`);
49198
+ recordSynthCompletionGateTrace("synth-veto", {
49199
+ producer: "transcript_reconcile",
49200
+ source: args.source || "direct_task_transcript_reconciliation",
49201
+ taskId: args.taskId,
49202
+ reason: admission.reason
49203
+ });
49204
+ return { reconciled: false, reason: admission.reason };
49205
+ }
49170
49206
  const nodeId = readNonEmptyString(args.nodeId) || dispatch?.nodeId;
49171
49207
  const providerType = readNonEmptyString(args.providerType) || dispatch?.providerType || readNonEmptyString(dispatch?.payload.providerType);
49172
49208
  const completedAt = args.completedAt || (/* @__PURE__ */ new Date()).toISOString();
@@ -49329,6 +49365,7 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
49329
49365
  init_mesh_events_pending();
49330
49366
  init_mesh_events_utils();
49331
49367
  init_debug_trace();
49368
+ init_logger();
49332
49369
  init_dist();
49333
49370
  DIRECT_DISPATCH_RECONCILE_GRACE_MS = 6e4;
49334
49371
  DIRECT_DISPATCH_IDLE_SESSION_RECONCILE_GRACE_MS = 12e4;
@@ -55750,6 +55787,14 @@ ${cleanBody}`;
55750
55787
  };
55751
55788
  }
55752
55789
  }
55790
+ if (!readNonEmptyString(args.metadataEvent.taskId) && !sessionHasActiveAssignment(args.meshId, eventSessionId) && !findRecentTerminalLedgerEvidence({ meshId: args.meshId, sessionId: eventSessionId, nodeId: eventNodeId || void 0 }) && isWeakCompletionEvidence(args.metadataEvent)) {
55791
+ LOG2.info("MeshEvents", `Suppressed agent:generating_completed for session ${eventSessionId} (mesh ${args.meshId}): no taskId, no active assignment, and no prior terminal ledger evidence \u2014 a pre-dispatch startup/greeting artifact, not a real task completion`);
55792
+ traceMeshEventDrop("no_dispatch_native_completion", traceCtx);
55793
+ return {
55794
+ kind: "suppress",
55795
+ result: { success: true, forwarded: 0, suppressed: true, noDispatchNativeCompletion: true }
55796
+ };
55797
+ }
55753
55798
  const inWindowTask = findInWindowUnclaimedAutoLaunchTask(args.meshId, eventSessionId, Date.now());
55754
55799
  if (inWindowTask) {
55755
55800
  const causalEvidence = MeshRuntimeStore.getInstance().taskDeliveryConsumed(args.meshId, inWindowTask.id) || hasMatchingTaskDispatchedLedgerEntry(args.meshId, inWindowTask.id, eventSessionId);
@@ -57501,6 +57546,18 @@ ${cleanBody}`;
57501
57546
  }
57502
57547
  const messages = Array.isArray(payload.messages) ? payload.messages : [];
57503
57548
  const evidence = extractFinalAssistantSummaryEvidence(messages);
57549
+ if (hasTrailingToolActivityAfterFinalAssistant(messages)) {
57550
+ setHoldState(synthKey, mesh.id, { liveConfirmedSinceAck: true, consecutiveReadFailures: 0 });
57551
+ LOG2.info("MeshReconcile", `Mid-turn causal admission: task ${taskId} on node ${nodeId} (mesh ${mesh.id}) \u2014 the latest final-looking assistant bubble is followed by trailing tool/terminal activity (interim narration; the turn is still executing); holding the transcript synth`);
57552
+ traceMeshEventDrop("reconcile_synth_veto_trailing_tool_activity", {
57553
+ taskId,
57554
+ sessionId,
57555
+ nodeId,
57556
+ meshId: mesh.id,
57557
+ event: "agent:generating_completed"
57558
+ });
57559
+ continue;
57560
+ }
57504
57561
  if (isAcked) {
57505
57562
  const ackedAtMs = Date.parse(readNonEmptyString(dispatch.updatedAt));
57506
57563
  const sinceAckMs = Number.isFinite(ackedAtMs) ? nowMs - ackedAtMs : Number.POSITIVE_INFINITY;
@@ -57575,6 +57632,17 @@ ${cleanBody}`;
57575
57632
  // The ledger-recovered dispatching-coordinator daemon (inside the reconcile fn)
57576
57633
  // takes PRIORITY over this arg; this remains the best-available fallback.
57577
57634
  ...coordinatorDaemonId ? { targetCoordinatorDaemonId: coordinatorDaemonId } : {},
57635
+ // MID-TURN-CAUSAL-ADMISSION (rc.16): pass the LOCAL live adapter's synchronous
57636
+ // turn-state probe into the unified choke point — a pending verdict vetoes this
57637
+ // eager synth (never-acked first-idle / acked fast-track). The death-deadline
57638
+ // backstop is the bounded max-wait net and overrides the veto (genuine-final
57639
+ // fail-open preserved); a remote/missing live source resolves to undefined and
57640
+ // fails open onto the bounded transcript evidence above. The trailing-tool veto
57641
+ // already ran at the top of this tick.
57642
+ causalAdmission: {
57643
+ liveTurnPendingEvidence: resolveLiveTurnPendingEvidence(components, sessionId),
57644
+ boundedBackstop: backstopKind === "ackedHoldDeathDeadlineFired"
57645
+ },
57578
57646
  source: "daemon_reconcile_transcript_completion"
57579
57647
  });
57580
57648
  if (result.reconciled) {
@@ -58018,10 +58086,10 @@ ${cleanBody}`;
58018
58086
  if (profile) return profile.emitsPtyTurnEvents === false;
58019
58087
  return verdict === "UNKNOWN";
58020
58088
  }
58021
- function propagateWatchdogTranscriptCompletion(meshId, row, evidence, source) {
58089
+ function propagateWatchdogTranscriptCompletion(components, meshId, row, evidence, source, opts) {
58022
58090
  const sessionId = readNonEmptyString(row.assignedSessionId) || evidence.sessionId;
58023
58091
  if (!sessionId || !readNonEmptyString(evidence.finalSummary)) {
58024
- return false;
58092
+ return "unavailable";
58025
58093
  }
58026
58094
  try {
58027
58095
  const result = reconcileDirectDispatchCompletionFromTranscript({
@@ -58037,11 +58105,26 @@ ${cleanBody}`;
58037
58105
  // The watchdog poll already enforced idle + post-dispatch + no-trailing-tool + streak;
58038
58106
  // skip the reconcile's own grace/transcript_not_proven gates (dedup backstops remain).
58039
58107
  preValidatedTranscriptEvidence: true,
58108
+ // MID-TURN-CAUSAL-ADMISSION (rc.16): the transcript poll's structural evidence can
58109
+ // still straddle a genuinely mid-turn LOCAL worker (the incident shape: transcript
58110
+ // reads idle-with-final-assistant while the raw PTY is mid-tool). Route the live
58111
+ // adapter's synchronous probe through the unified choke point. The EARLY-IDLE
58112
+ // caller is an eager path (no opts) → a pending verdict defers; the redrive-deadline
58113
+ // caller passes boundedBackstop (the max-wait net) → the veto yields, preserving the
58114
+ // genuine-final fail-open semantics.
58115
+ causalAdmission: {
58116
+ liveTurnPendingEvidence: resolveLiveTurnPendingEvidence(components, sessionId),
58117
+ boundedBackstop: opts?.boundedBackstop === true
58118
+ },
58040
58119
  source
58041
58120
  });
58042
- return result.reconciled || result.alreadyTerminal === true;
58121
+ if (result.reconciled || result.alreadyTerminal === true) return "propagated";
58122
+ if (result.reason === "live_turn_pending_evidence" || result.reason === "trailing_tool_activity_after_final_assistant") {
58123
+ return "deferred";
58124
+ }
58125
+ return "unavailable";
58043
58126
  } catch {
58044
- return false;
58127
+ return "unavailable";
58045
58128
  }
58046
58129
  }
58047
58130
  async function recoverStrandedAssignedDispatches(components, mesh, store, localDaemonId, selfIds = []) {
@@ -58075,14 +58158,28 @@ ${cleanBody}`;
58075
58158
  minFinalAssistantAgeMs: ASSIGNED_IDLE_TRANSCRIPT_COMPLETE_MS
58076
58159
  });
58077
58160
  if (terminalEvidence) {
58078
- assignedIdleFinalAssistantSince.delete(idleTranscriptStreakKey);
58079
- updateTaskStatus(meshId, row.id, terminalEvidence.outcome);
58080
- const propagated = propagateWatchdogTranscriptCompletion(
58161
+ const propagation = propagateWatchdogTranscriptCompletion(
58162
+ components,
58081
58163
  meshId,
58082
58164
  row,
58083
58165
  terminalEvidence,
58084
58166
  "early_idle_transcript_evidence"
58085
58167
  );
58168
+ if (propagation === "deferred") {
58169
+ assignedIdleFinalAssistantSince.delete(idleTranscriptStreakKey);
58170
+ LOG2.info("MeshReconcile", `Deferred early transcript completion for task ${row.id} on mesh ${meshId} (node=${row.assignedNodeId ?? "?"} session=${row.assignedSessionId ?? "?"}): the live adapter still reports the turn pending (mid-tool / streaming / modal) \u2014 holding; the completion re-evaluates next tick`);
58171
+ traceMeshEventDrop("early_idle_completion_deferred_live_pending", {
58172
+ taskId: row.id,
58173
+ sessionId: row.assignedSessionId,
58174
+ nodeId: row.assignedNodeId,
58175
+ meshId,
58176
+ event: "agent:generating_completed"
58177
+ });
58178
+ continue;
58179
+ }
58180
+ assignedIdleFinalAssistantSince.delete(idleTranscriptStreakKey);
58181
+ updateTaskStatus(meshId, row.id, terminalEvidence.outcome);
58182
+ const propagated = propagation === "propagated";
58086
58183
  if (!propagated && !findTerminalLedgerEvidenceForTask({ meshId, taskId: row.id })) {
58087
58184
  try {
58088
58185
  appendLedgerEntry(meshId, {
@@ -58257,12 +58354,15 @@ ${cleanBody}`;
58257
58354
  if (terminalEvidence) {
58258
58355
  deliveredNoTurnUnknownStreak.delete(streakKey);
58259
58356
  updateTaskStatus(meshId, row.id, terminalEvidence.outcome);
58260
- const propagated = propagateWatchdogTranscriptCompletion(
58357
+ const propagation = propagateWatchdogTranscriptCompletion(
58358
+ components,
58261
58359
  meshId,
58262
58360
  row,
58263
58361
  terminalEvidence,
58264
- "redrive_deadline_transcript_evidence"
58362
+ "redrive_deadline_transcript_evidence",
58363
+ { boundedBackstop: true }
58265
58364
  );
58365
+ const propagated = propagation === "propagated";
58266
58366
  if (!propagated && !findTerminalLedgerEvidenceForTask({ meshId, taskId: row.id })) {
58267
58367
  try {
58268
58368
  appendLedgerEntry(meshId, {
@@ -62112,7 +62212,10 @@ ${cont}` : cont;
62112
62212
  const session = this.runParseSession(snap);
62113
62213
  if (!session) return;
62114
62214
  const { status, messages } = session;
62115
- const modal = session.activeModal ?? session.modal ?? null;
62215
+ const rawModal = session.activeModal ?? session.modal ?? null;
62216
+ const modal = rawModal && Array.isArray(rawModal.buttons) && rawModal.buttons.some(
62217
+ (button) => typeof button === "string" && button.trim().length > 0
62218
+ ) ? rawModal : null;
62116
62219
  const parsedStatus = session.parsedStatus ?? null;
62117
62220
  const parsedMessages = normalizeCliParsedMessages(messages, {
62118
62221
  scope: null,
@@ -65678,6 +65781,7 @@ ${lastSnapshot}`;
65678
65781
  handleGitCommand: () => handleGitCommand,
65679
65782
  hasCdpManager: () => hasCdpManager,
65680
65783
  hasPendingDependents: () => hasPendingDependents,
65784
+ hasTrailingToolActivityAfterFinalAssistant: () => hasTrailingToolActivityAfterFinalAssistant,
65681
65785
  hashSignatureParts: () => hashSignatureParts,
65682
65786
  initDaemonComponents: () => initDaemonComponents2,
65683
65787
  insertDirectDispatch: () => insertDirectDispatch,
@@ -72678,7 +72782,7 @@ ${effect.notification.body || ""}`.trim();
72678
72782
  });
72679
72783
  }
72680
72784
  }
72681
- if (isGeneratingLikeStatus(selectedStatus) && selectedTranscriptAuthority === "provider" && !hasNonEmptyModalButtons(activeModal) && hasFinalVisibleAssistantMessage(selectedMessages)) {
72785
+ if (isGeneratingLikeStatus(selectedStatus) && selectedTranscriptAuthority === "provider" && !hasNonEmptyModalButtons(activeModal) && hasFinalVisibleAssistantMessage(selectedMessages) && !hasTrailingToolActivityAfterFinalAssistant(selectedMessages) && !hasTrailingToolActivityAfterFinalAssistant(returnedMessages)) {
72682
72786
  selectedStatus = "idle";
72683
72787
  selectedMessages = finalizeStreamingMessagesWhenIdle(selectedMessages, selectedStatus);
72684
72788
  messageSource = {
@@ -84082,9 +84186,36 @@ ${body}
84082
84186
  * OR isModalParked() (a live approval/choice modal) — so a session this method reports
84083
84187
  * pending is, by construction, one the local finalization gate would also refuse to
84084
84188
  * finalize right now.
84189
+ *
84190
+ * NATIVE-TRAILING-TOOL-GATE (rc.16 follow-up): the three adapter-state discriminators
84191
+ * above are blind to a background shell tool that keeps a turn alive without the adapter
84192
+ * reporting a pending response — e.g. a backgrounded `sleep 40 &` between narration
84193
+ * bubbles on a write-lag native-source provider (claude-cli), which is deliberately
84194
+ * un-floored (noExternalTranscriptSource omitted, mission f2f6da1b owner decision) so its
84195
+ * transcript write-lag emits promptly. That un-flooring is correct for the ordinary
84196
+ * fraction-of-a-second trail, but it also means the growth-hold / busy-lease protections
84197
+ * in getCompletedFinalizationBlock never engage for claude-cli, so an interim final-
84198
+ * LOOKING bubble followed by continuing tool calls can still finalize as a completion
84199
+ * while the transcript demonstrably shows the turn still executing. Close that gap here,
84200
+ * narrowly: for a native-source provider only, reuse the SAME bounded transcript read the
84201
+ * class's own completion judgment already performs (probeNativeTranscriptSignals) and
84202
+ * apply the SAME trailing-tool-activity veto the transcript-synth admission choke point
84203
+ * uses (hasTrailingToolActivityAfterFinalAssistant) — the latest final-looking assistant
84204
+ * bubble followed by tool/terminal activity is interim narration, not a turn end. Fail-open
84205
+ * by construction: a non-native-source class (probe returns null), an unresolved
84206
+ * transcript, or a read error never reaches the veto, so a missing/unavailable transcript
84207
+ * can never wedge a session as "pending" forever.
84085
84208
  */
84086
84209
  hasLiveTurnPendingEvidence() {
84087
- return this.hasAdapterPendingResponse() || this.isModalParked();
84210
+ if (this.hasAdapterPendingResponse() || this.isModalParked()) return true;
84211
+ try {
84212
+ const probe = this.probeNativeTranscriptSignals();
84213
+ if (probe?.snapshot?.available === true && Array.isArray(probe.messages)) {
84214
+ if (hasTrailingToolActivityAfterFinalAssistant(probe.messages)) return true;
84215
+ }
84216
+ } catch {
84217
+ }
84218
+ return false;
84088
84219
  }
84089
84220
  /**
84090
84221
  * PTY-OVERTRUST-DRAIN (Defect B). The deliverability/drain status the mesh