@adhdev/daemon-core 1.0.28-rc.15 → 1.0.28-rc.17

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.d.ts CHANGED
@@ -143,7 +143,7 @@ export type { ProviderModule, AutoApproveMode, AutoApproveModesConfig, AutoAppro
143
143
  export type { ProviderSourceConfigSnapshot, ProviderSourceConfigUpdate } from './config/provider-source-config.js';
144
144
  export { parseProviderSourceConfigUpdate } from './config/provider-source-config.js';
145
145
  export { normalizeInputEnvelope, normalizeMessageParts, flattenMessageParts } from './providers/io-contracts.js';
146
- export { BUILTIN_CHAT_MESSAGE_KINDS, isBuiltinChatMessageKind, normalizeChatMessageKind, resolveChatMessageKind, buildChatMessage, buildSystemChatMessage, buildRuntimeSystemChatMessage, buildAssistantChatMessage, buildThoughtChatMessage, buildToolChatMessage, buildTerminalChatMessage, buildUserChatMessage, normalizeChatMessage, normalizeChatMessages, CHAT_MESSAGE_VISIBILITIES, CHAT_MESSAGE_TRANSCRIPT_VISIBILITIES, CHAT_MESSAGE_AUDIENCES, CHAT_MESSAGE_SOURCES, CHAT_MESSAGE_ACTIVITY_SOURCES, CHAT_MESSAGE_INTERNAL_SOURCES, classifyChatMessageVisibility, isUserFacingChatMessage, isActivityChatMessage, isInternalChatMessage, filterUserFacingChatMessages, filterActivityChatMessages, filterInternalChatMessages, filterChatMessagesByVisibility, } from './providers/chat-message-normalization.js';
146
+ export { BUILTIN_CHAT_MESSAGE_KINDS, isBuiltinChatMessageKind, normalizeChatMessageKind, resolveChatMessageKind, buildChatMessage, buildSystemChatMessage, buildRuntimeSystemChatMessage, buildAssistantChatMessage, buildThoughtChatMessage, buildToolChatMessage, buildTerminalChatMessage, buildUserChatMessage, normalizeChatMessage, normalizeChatMessages, CHAT_MESSAGE_VISIBILITIES, CHAT_MESSAGE_TRANSCRIPT_VISIBILITIES, CHAT_MESSAGE_AUDIENCES, CHAT_MESSAGE_SOURCES, CHAT_MESSAGE_ACTIVITY_SOURCES, CHAT_MESSAGE_INTERNAL_SOURCES, classifyChatMessageVisibility, hasTrailingToolActivityAfterFinalAssistant, isUserFacingChatMessage, isActivityChatMessage, isInternalChatMessage, filterUserFacingChatMessages, filterActivityChatMessages, filterInternalChatMessages, filterChatMessagesByVisibility, } from './providers/chat-message-normalization.js';
147
147
  export type { BuiltinChatMessageKind, ChatMessageKind, ChatMessageVisibility, ChatMessageTranscriptVisibility, ChatMessageAudience, ChatMessageSource, ChatMessageTranscriptSurface, ChatMessageVisibilityClassification } from './providers/chat-message-normalization.js';
148
148
  export { VersionArchive, detectAllVersions } from './providers/version-archive.js';
149
149
  export type { ProviderVersionInfo, VersionHistory } from './providers/version-archive.js';
package/dist/index.js CHANGED
@@ -791,10 +791,10 @@ function readInjected(value) {
791
791
  }
792
792
  function getDaemonBuildInfo() {
793
793
  if (cached) return cached;
794
- const commit = readInjected(true ? "3c6684c9e2549bf7ab1508195857595a89ae9ec1" : void 0) ?? "unknown";
795
- const commitShort = readInjected(true ? "3c6684c" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
796
- const version = readInjected(true ? "1.0.28-rc.15" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
797
- const builtAt = readInjected(true ? "2026-07-26T13:11:34.159Z" : void 0);
794
+ const commit = readInjected(true ? "9452bd039720355425e62fc7469808a0dda3ab80" : void 0) ?? "unknown";
795
+ const commitShort = readInjected(true ? "9452bd03" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
796
+ const version = readInjected(true ? "1.0.28-rc.17" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
797
+ const builtAt = readInjected(true ? "2026-07-27T01:42:15.160Z" : void 0);
798
798
  cached = builtAt ? { commit, commitShort, version, builtAt } : { commit, commitShort, version };
799
799
  return cached;
800
800
  }
@@ -16437,6 +16437,31 @@ var init_debug_trace = __esm({
16437
16437
  function recordSynthCompletionGateTrace(stage, payload) {
16438
16438
  recordDebugTrace({ category: "completion-gate", stage, level: "debug", payload });
16439
16439
  }
16440
+ function evaluateTranscriptSynthAdmission(admission) {
16441
+ if (!admission) return { admitted: true };
16442
+ if (admission.trailingToolActivityAfterFinalAssistant === true) {
16443
+ return { admitted: false, reason: "trailing_tool_activity_after_final_assistant" };
16444
+ }
16445
+ if (!admission.boundedBackstop && typeof admission.liveTurnPendingEvidence === "function") {
16446
+ let pending = false;
16447
+ try {
16448
+ pending = admission.liveTurnPendingEvidence() === true;
16449
+ } catch {
16450
+ }
16451
+ if (pending) return { admitted: false, reason: "live_turn_pending_evidence" };
16452
+ }
16453
+ return { admitted: true };
16454
+ }
16455
+ function resolveLiveTurnPendingEvidence(components, sessionId) {
16456
+ try {
16457
+ const instance = components?.instanceManager?.getInstance?.(sessionId);
16458
+ if (typeof instance?.hasLiveTurnPendingEvidence !== "function") return void 0;
16459
+ const probe = instance.hasLiveTurnPendingEvidence.bind(instance);
16460
+ return () => probe();
16461
+ } catch {
16462
+ return void 0;
16463
+ }
16464
+ }
16440
16465
  function findRecentTerminalLedgerEvidence(args) {
16441
16466
  if (!args.sessionId && !args.nodeId) return null;
16442
16467
  const entries = readLedgerEntries(args.meshId, { tail: 200 });
@@ -16557,6 +16582,17 @@ function reconcileDirectDispatchCompletionFromTranscript(args) {
16557
16582
  })) {
16558
16583
  return { reconciled: false, alreadyTerminal: true, reason: "terminal_ledger_entry_exists" };
16559
16584
  }
16585
+ const admission = evaluateTranscriptSynthAdmission(args.causalAdmission);
16586
+ if (!admission.admitted) {
16587
+ LOG.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`);
16588
+ recordSynthCompletionGateTrace("synth-veto", {
16589
+ producer: "transcript_reconcile",
16590
+ source: args.source || "direct_task_transcript_reconciliation",
16591
+ taskId: args.taskId,
16592
+ reason: admission.reason
16593
+ });
16594
+ return { reconciled: false, reason: admission.reason };
16595
+ }
16560
16596
  const nodeId = readNonEmptyString(args.nodeId) || dispatch?.nodeId;
16561
16597
  const providerType = readNonEmptyString(args.providerType) || dispatch?.providerType || readNonEmptyString(dispatch?.payload.providerType);
16562
16598
  const completedAt = args.completedAt || (/* @__PURE__ */ new Date()).toISOString();
@@ -16718,6 +16754,7 @@ var init_mesh_events_stale = __esm({
16718
16754
  init_mesh_events_pending();
16719
16755
  init_mesh_events_utils();
16720
16756
  init_debug_trace();
16757
+ init_logger();
16721
16758
  init_dist();
16722
16759
  DIRECT_DISPATCH_RECONCILE_GRACE_MS = 6e4;
16723
16760
  DIRECT_DISPATCH_IDLE_SESSION_RECONCILE_GRACE_MS = 12e4;
@@ -19748,6 +19785,9 @@ function nodeHasActiveMeshWork(components, meshId, nodeId, currentSessionId) {
19748
19785
  }
19749
19786
  function isLaunchableNode(node) {
19750
19787
  if (!node || node.status === "disabled" || node.status === "removed") return false;
19788
+ if (shouldDeferDispatchForBootstrap(node)) {
19789
+ return false;
19790
+ }
19751
19791
  return isMeshNodeHealthLaunchable(node);
19752
19792
  }
19753
19793
  function isLocalAutoLaunchNode(node) {
@@ -22985,8 +23025,27 @@ function resolveActiveDirectDispatchTaskId(meshId, sessionId) {
22985
23025
  return void 0;
22986
23026
  }
22987
23027
  }
23028
+ function findInWindowUnclaimedAutoLaunchTask(meshId, sessionId, nowMs) {
23029
+ return getQueue(meshId, { status: ["pending"] }).find((task) => {
23030
+ const al = task.autoLaunch;
23031
+ if (!al || al.status !== "completed" || !al.sessionId) return false;
23032
+ if (!sessionIdsEquivalent(al.sessionId, sessionId)) return false;
23033
+ const launchedAtMs = Date.parse(al.updatedAt);
23034
+ return Number.isFinite(launchedAtMs) && nowMs - launchedAtMs < AUTO_LAUNCH_AWAIT_CLAIM_MS;
23035
+ });
23036
+ }
23037
+ function hasMatchingTaskDispatchedLedgerEntry(meshId, taskId, sessionId) {
23038
+ const entries = readLedgerEntries(meshId, { tail: 200 });
23039
+ for (let i = entries.length - 1; i >= 0; i--) {
23040
+ const entry = entries[i];
23041
+ if (entry.kind !== "task_dispatched") continue;
23042
+ if (!sessionIdsEquivalent(entry.sessionId, sessionId)) continue;
23043
+ if (readNonEmptyString(entry.payload?.taskId) === taskId) return true;
23044
+ }
23045
+ return false;
23046
+ }
22988
23047
  function evaluateMeshEventSuppression(args, ctx) {
22989
- const { traceCtx, eventSessionId, eventNodeId, eventTimestamp, workerCoordinatorDaemonId } = ctx;
23048
+ const { traceCtx, eventSessionId, eventNodeId, eventTimestamp, workerCoordinatorDaemonId, components } = ctx;
22990
23049
  const intentionalCleanupStop = shouldSuppressIntentionalCleanupStop({
22991
23050
  event: args.event,
22992
23051
  meshId: args.meshId,
@@ -23053,6 +23112,42 @@ function evaluateMeshEventSuppression(args, ctx) {
23053
23112
  }
23054
23113
  }
23055
23114
  if (args.event === "agent:generating_completed" && eventSessionId) {
23115
+ const liveInstance = components.instanceManager?.getInstance?.(eventSessionId);
23116
+ if (typeof liveInstance?.hasLiveTurnPendingEvidence === "function") {
23117
+ let midTurnPending = false;
23118
+ try {
23119
+ midTurnPending = liveInstance.hasLiveTurnPendingEvidence() === true;
23120
+ } catch {
23121
+ }
23122
+ if (midTurnPending) {
23123
+ LOG.info("MeshEvents", `Suppressed agent:generating_completed for session ${eventSessionId} (mesh ${args.meshId}): live adapter re-check shows the turn is still pending (mid-tool / streaming / modal) \u2014 treating as a premature/redraw-race emit; the adapter's own finalization retry or the reconcile loop's transcript evidence will surface the real completion`);
23124
+ traceMeshEventDrop("mid_turn_live_state_pending", traceCtx);
23125
+ return {
23126
+ kind: "suppress",
23127
+ result: { success: true, forwarded: 0, suppressed: true, midTurnLiveStatePending: true }
23128
+ };
23129
+ }
23130
+ }
23131
+ if (!readNonEmptyString(args.metadataEvent.taskId) && !sessionHasActiveAssignment(args.meshId, eventSessionId) && !findRecentTerminalLedgerEvidence({ meshId: args.meshId, sessionId: eventSessionId, nodeId: eventNodeId || void 0 }) && isWeakCompletionEvidence(args.metadataEvent)) {
23132
+ LOG.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`);
23133
+ traceMeshEventDrop("no_dispatch_native_completion", traceCtx);
23134
+ return {
23135
+ kind: "suppress",
23136
+ result: { success: true, forwarded: 0, suppressed: true, noDispatchNativeCompletion: true }
23137
+ };
23138
+ }
23139
+ const inWindowTask = findInWindowUnclaimedAutoLaunchTask(args.meshId, eventSessionId, Date.now());
23140
+ if (inWindowTask) {
23141
+ const causalEvidence = MeshRuntimeStore.getInstance().taskDeliveryConsumed(args.meshId, inWindowTask.id) || hasMatchingTaskDispatchedLedgerEntry(args.meshId, inWindowTask.id, eventSessionId);
23142
+ if (!causalEvidence) {
23143
+ LOG.warn("MeshEvents", `Suppressed premature agent:generating_completed for auto-launch session ${eventSessionId} (mesh ${args.meshId}): task ${inWindowTask.id} delivery not yet consumed and no turn-start evidence \u2014 likely a boot artifact before the task was ever dispatched`);
23144
+ traceMeshEventDrop("autolaunch_completion_before_causal_evidence", traceCtx, `taskId=${inWindowTask.id}`);
23145
+ return {
23146
+ kind: "suppress",
23147
+ result: { success: true, forwarded: 0, suppressed: true, autoLaunchCausalGateFailed: true, taskId: inWindowTask.id }
23148
+ };
23149
+ }
23150
+ }
23056
23151
  const terminal = findRecentTerminalLedgerEvidence({
23057
23152
  meshId: args.meshId,
23058
23153
  sessionId: eventSessionId,
@@ -23285,7 +23380,8 @@ function injectMeshSystemMessage(components, args) {
23285
23380
  eventSessionId,
23286
23381
  eventNodeId,
23287
23382
  eventTimestamp,
23288
- workerCoordinatorDaemonId
23383
+ workerCoordinatorDaemonId,
23384
+ components
23289
23385
  });
23290
23386
  if (suppression) {
23291
23387
  if (suppression.kind === "reconcile") {
@@ -24790,6 +24886,18 @@ async function reconcileUnterminatedDirectDispatches(components, mesh, selfIds,
24790
24886
  }
24791
24887
  const messages = Array.isArray(payload.messages) ? payload.messages : [];
24792
24888
  const evidence = extractFinalAssistantSummaryEvidence(messages);
24889
+ if (hasTrailingToolActivityAfterFinalAssistant(messages)) {
24890
+ setHoldState(synthKey, mesh.id, { liveConfirmedSinceAck: true, consecutiveReadFailures: 0 });
24891
+ LOG.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`);
24892
+ traceMeshEventDrop("reconcile_synth_veto_trailing_tool_activity", {
24893
+ taskId,
24894
+ sessionId,
24895
+ nodeId,
24896
+ meshId: mesh.id,
24897
+ event: "agent:generating_completed"
24898
+ });
24899
+ continue;
24900
+ }
24793
24901
  if (isAcked) {
24794
24902
  const ackedAtMs = Date.parse(readNonEmptyString(dispatch.updatedAt));
24795
24903
  const sinceAckMs = Number.isFinite(ackedAtMs) ? nowMs - ackedAtMs : Number.POSITIVE_INFINITY;
@@ -24864,6 +24972,17 @@ async function reconcileUnterminatedDirectDispatches(components, mesh, selfIds,
24864
24972
  // The ledger-recovered dispatching-coordinator daemon (inside the reconcile fn)
24865
24973
  // takes PRIORITY over this arg; this remains the best-available fallback.
24866
24974
  ...coordinatorDaemonId ? { targetCoordinatorDaemonId: coordinatorDaemonId } : {},
24975
+ // MID-TURN-CAUSAL-ADMISSION (rc.16): pass the LOCAL live adapter's synchronous
24976
+ // turn-state probe into the unified choke point — a pending verdict vetoes this
24977
+ // eager synth (never-acked first-idle / acked fast-track). The death-deadline
24978
+ // backstop is the bounded max-wait net and overrides the veto (genuine-final
24979
+ // fail-open preserved); a remote/missing live source resolves to undefined and
24980
+ // fails open onto the bounded transcript evidence above. The trailing-tool veto
24981
+ // already ran at the top of this tick.
24982
+ causalAdmission: {
24983
+ liveTurnPendingEvidence: resolveLiveTurnPendingEvidence(components, sessionId),
24984
+ boundedBackstop: backstopKind === "ackedHoldDeathDeadlineFired"
24985
+ },
24867
24986
  source: "daemon_reconcile_transcript_completion"
24868
24987
  });
24869
24988
  if (result.reconciled) {
@@ -25309,10 +25428,10 @@ async function evaluateEarlyIdleTranscriptArm(components, mesh, store, row, loca
25309
25428
  if (profile) return profile.emitsPtyTurnEvents === false;
25310
25429
  return verdict === "UNKNOWN";
25311
25430
  }
25312
- function propagateWatchdogTranscriptCompletion(meshId, row, evidence, source) {
25431
+ function propagateWatchdogTranscriptCompletion(components, meshId, row, evidence, source, opts) {
25313
25432
  const sessionId = readNonEmptyString(row.assignedSessionId) || evidence.sessionId;
25314
25433
  if (!sessionId || !readNonEmptyString(evidence.finalSummary)) {
25315
- return false;
25434
+ return "unavailable";
25316
25435
  }
25317
25436
  try {
25318
25437
  const result = reconcileDirectDispatchCompletionFromTranscript({
@@ -25328,11 +25447,26 @@ function propagateWatchdogTranscriptCompletion(meshId, row, evidence, source) {
25328
25447
  // The watchdog poll already enforced idle + post-dispatch + no-trailing-tool + streak;
25329
25448
  // skip the reconcile's own grace/transcript_not_proven gates (dedup backstops remain).
25330
25449
  preValidatedTranscriptEvidence: true,
25450
+ // MID-TURN-CAUSAL-ADMISSION (rc.16): the transcript poll's structural evidence can
25451
+ // still straddle a genuinely mid-turn LOCAL worker (the incident shape: transcript
25452
+ // reads idle-with-final-assistant while the raw PTY is mid-tool). Route the live
25453
+ // adapter's synchronous probe through the unified choke point. The EARLY-IDLE
25454
+ // caller is an eager path (no opts) → a pending verdict defers; the redrive-deadline
25455
+ // caller passes boundedBackstop (the max-wait net) → the veto yields, preserving the
25456
+ // genuine-final fail-open semantics.
25457
+ causalAdmission: {
25458
+ liveTurnPendingEvidence: resolveLiveTurnPendingEvidence(components, sessionId),
25459
+ boundedBackstop: opts?.boundedBackstop === true
25460
+ },
25331
25461
  source
25332
25462
  });
25333
- return result.reconciled || result.alreadyTerminal === true;
25463
+ if (result.reconciled || result.alreadyTerminal === true) return "propagated";
25464
+ if (result.reason === "live_turn_pending_evidence" || result.reason === "trailing_tool_activity_after_final_assistant") {
25465
+ return "deferred";
25466
+ }
25467
+ return "unavailable";
25334
25468
  } catch {
25335
- return false;
25469
+ return "unavailable";
25336
25470
  }
25337
25471
  }
25338
25472
  async function recoverStrandedAssignedDispatches(components, mesh, store, localDaemonId, selfIds = []) {
@@ -25366,14 +25500,28 @@ async function recoverStrandedAssignedDispatches(components, mesh, store, localD
25366
25500
  minFinalAssistantAgeMs: ASSIGNED_IDLE_TRANSCRIPT_COMPLETE_MS
25367
25501
  });
25368
25502
  if (terminalEvidence) {
25369
- assignedIdleFinalAssistantSince.delete(idleTranscriptStreakKey);
25370
- updateTaskStatus(meshId, row.id, terminalEvidence.outcome);
25371
- const propagated = propagateWatchdogTranscriptCompletion(
25503
+ const propagation = propagateWatchdogTranscriptCompletion(
25504
+ components,
25372
25505
  meshId,
25373
25506
  row,
25374
25507
  terminalEvidence,
25375
25508
  "early_idle_transcript_evidence"
25376
25509
  );
25510
+ if (propagation === "deferred") {
25511
+ assignedIdleFinalAssistantSince.delete(idleTranscriptStreakKey);
25512
+ LOG.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`);
25513
+ traceMeshEventDrop("early_idle_completion_deferred_live_pending", {
25514
+ taskId: row.id,
25515
+ sessionId: row.assignedSessionId,
25516
+ nodeId: row.assignedNodeId,
25517
+ meshId,
25518
+ event: "agent:generating_completed"
25519
+ });
25520
+ continue;
25521
+ }
25522
+ assignedIdleFinalAssistantSince.delete(idleTranscriptStreakKey);
25523
+ updateTaskStatus(meshId, row.id, terminalEvidence.outcome);
25524
+ const propagated = propagation === "propagated";
25377
25525
  if (!propagated && !findTerminalLedgerEvidenceForTask({ meshId, taskId: row.id })) {
25378
25526
  try {
25379
25527
  appendLedgerEntry(meshId, {
@@ -25548,12 +25696,15 @@ async function recoverStrandedAssignedDispatches(components, mesh, store, localD
25548
25696
  if (terminalEvidence) {
25549
25697
  deliveredNoTurnUnknownStreak.delete(streakKey);
25550
25698
  updateTaskStatus(meshId, row.id, terminalEvidence.outcome);
25551
- const propagated = propagateWatchdogTranscriptCompletion(
25699
+ const propagation = propagateWatchdogTranscriptCompletion(
25700
+ components,
25552
25701
  meshId,
25553
25702
  row,
25554
25703
  terminalEvidence,
25555
- "redrive_deadline_transcript_evidence"
25704
+ "redrive_deadline_transcript_evidence",
25705
+ { boundedBackstop: true }
25556
25706
  );
25707
+ const propagated = propagation === "propagated";
25557
25708
  if (!propagated && !findTerminalLedgerEvidenceForTask({ meshId, taskId: row.id })) {
25558
25709
  try {
25559
25710
  appendLedgerEntry(meshId, {
@@ -31094,7 +31245,9 @@ ${lastSnapshot}`;
31094
31245
  const requiredStreak = this.isAutonomousMeshSession() ? _ProviderCliAdapter.STATIC_IDLE_POLL_CONFIRM_COUNT : 1;
31095
31246
  this.staticIdlePollStreak += 1;
31096
31247
  if (this.staticIdlePollStreak >= requiredStreak) {
31097
- this.engine.confirmPollStaticIdle("poll_static_idle");
31248
+ if (this.engine.confirmPollStaticIdle("poll_static_idle")) {
31249
+ this.onStatusChange?.();
31250
+ }
31098
31251
  this.staticIdlePollStreak = 0;
31099
31252
  }
31100
31253
  } else {
@@ -32948,6 +33101,7 @@ __export(index_exports, {
32948
33101
  handleGitCommand: () => handleGitCommand,
32949
33102
  hasCdpManager: () => hasCdpManager,
32950
33103
  hasPendingDependents: () => hasPendingDependents,
33104
+ hasTrailingToolActivityAfterFinalAssistant: () => hasTrailingToolActivityAfterFinalAssistant,
32951
33105
  hashSignatureParts: () => hashSignatureParts,
32952
33106
  initDaemonComponents: () => initDaemonComponents,
32953
33107
  insertDirectDispatch: () => insertDirectDispatch,
@@ -51563,6 +51717,50 @@ var CliProviderInstance = class _CliProviderInstance {
51563
51717
  isModalParked() {
51564
51718
  return this.resolveModalParkStatus() !== null;
51565
51719
  }
51720
+ /**
51721
+ * MID-TURN-LIVE-STATE-GATE (broader false-idle RCA, mid-turn follow-up): a live,
51722
+ * synchronous re-check of whether this session's CURRENT turn genuinely still has
51723
+ * unresolved work. Public wrapper so the coordinator (mesh-event-forwarding) can
51724
+ * independently re-verify an incoming agent:generating_completed for a LOCAL session
51725
+ * before trusting it — defense-in-depth against a race where the completion emit and the
51726
+ * coordinator's receipt straddle a state change (screen-redraw parse artifact, decoupled-
51727
+ * immediate emit). Reuses the EXACT same discriminators this instance's own finalization
51728
+ * gate (getCompletedFinalizationBlock) uses — hasAdapterPendingResponse() (adapter
51729
+ * isWaitingForResponse / currentTurnScope / isProcessing() / a non-empty partial response)
51730
+ * OR isModalParked() (a live approval/choice modal) — so a session this method reports
51731
+ * pending is, by construction, one the local finalization gate would also refuse to
51732
+ * finalize right now.
51733
+ *
51734
+ * NATIVE-TRAILING-TOOL-GATE (rc.16 follow-up): the three adapter-state discriminators
51735
+ * above are blind to a background shell tool that keeps a turn alive without the adapter
51736
+ * reporting a pending response — e.g. a backgrounded `sleep 40 &` between narration
51737
+ * bubbles on a write-lag native-source provider (claude-cli), which is deliberately
51738
+ * un-floored (noExternalTranscriptSource omitted, mission f2f6da1b owner decision) so its
51739
+ * transcript write-lag emits promptly. That un-flooring is correct for the ordinary
51740
+ * fraction-of-a-second trail, but it also means the growth-hold / busy-lease protections
51741
+ * in getCompletedFinalizationBlock never engage for claude-cli, so an interim final-
51742
+ * LOOKING bubble followed by continuing tool calls can still finalize as a completion
51743
+ * while the transcript demonstrably shows the turn still executing. Close that gap here,
51744
+ * narrowly: for a native-source provider only, reuse the SAME bounded transcript read the
51745
+ * class's own completion judgment already performs (probeNativeTranscriptSignals) and
51746
+ * apply the SAME trailing-tool-activity veto the transcript-synth admission choke point
51747
+ * uses (hasTrailingToolActivityAfterFinalAssistant) — the latest final-looking assistant
51748
+ * bubble followed by tool/terminal activity is interim narration, not a turn end. Fail-open
51749
+ * by construction: a non-native-source class (probe returns null), an unresolved
51750
+ * transcript, or a read error never reaches the veto, so a missing/unavailable transcript
51751
+ * can never wedge a session as "pending" forever.
51752
+ */
51753
+ hasLiveTurnPendingEvidence() {
51754
+ if (this.hasAdapterPendingResponse() || this.isModalParked()) return true;
51755
+ try {
51756
+ const probe = this.probeNativeTranscriptSignals();
51757
+ if (probe?.snapshot?.available === true && Array.isArray(probe.messages)) {
51758
+ if (hasTrailingToolActivityAfterFinalAssistant(probe.messages)) return true;
51759
+ }
51760
+ } catch {
51761
+ }
51762
+ return false;
51763
+ }
51566
51764
  /**
51567
51765
  * PTY-OVERTRUST-DRAIN (Defect B). The deliverability/drain status the mesh
51568
51766
  * reconcile loop must consult — the RAW adapter turn-state, with the
@@ -52053,7 +52251,8 @@ var CliProviderInstance = class _CliProviderInstance {
52053
52251
  }
52054
52252
  completionFinalAssistantEvidence(parsedMessages, turnStartedAt) {
52055
52253
  const turnClosed = !this.hasAdapterPendingResponse();
52056
- if (this.completionHasFinalAssistantMessage(parsedMessages, turnStartedAt)) {
52254
+ const preferNativeOverParsed = this.adapter?.chatMessagesOwnedExternally === true && this.busyLeaseGateEnabled();
52255
+ if (!preferNativeOverParsed && this.completionHasFinalAssistantMessage(parsedMessages, turnStartedAt)) {
52057
52256
  return {
52058
52257
  present: turnClosed,
52059
52258
  messages: Array.isArray(parsedMessages) ? parsedMessages : [],
@@ -52063,7 +52262,8 @@ var CliProviderInstance = class _CliProviderInstance {
52063
52262
  const externalMessages = this.readExternalCompletionMessages();
52064
52263
  if (externalMessages) {
52065
52264
  const injectedTaskGenerating = this.injectedTaskHasStartedGenerating();
52066
- const present = injectedTaskGenerating && turnClosed && this.completionHasFinalAssistantMessage(externalMessages, turnStartedAt);
52265
+ const trailingToolActivity = hasTrailingToolActivityAfterFinalAssistant(externalMessages);
52266
+ const present = injectedTaskGenerating && turnClosed && !trailingToolActivity && this.completionHasFinalAssistantMessage(externalMessages, turnStartedAt);
52067
52267
  const lastVisibleAssistant = this.lastVisibleAssistantSummaryDetail(externalMessages);
52068
52268
  if (lastVisibleAssistant.content) {
52069
52269
  this.lastCompletionSummary = { content: lastVisibleAssistant.content, receivedAt: Date.now(), sourceTimestampMs: lastVisibleAssistant.timestampMs };
@@ -52074,6 +52274,13 @@ var CliProviderInstance = class _CliProviderInstance {
52074
52274
  source: "external-native"
52075
52275
  };
52076
52276
  }
52277
+ if (preferNativeOverParsed && this.completionHasFinalAssistantMessage(parsedMessages, turnStartedAt)) {
52278
+ return {
52279
+ present: turnClosed,
52280
+ messages: Array.isArray(parsedMessages) ? parsedMessages : [],
52281
+ source: "parsed"
52282
+ };
52283
+ }
52077
52284
  return {
52078
52285
  present: false,
52079
52286
  messages: Array.isArray(parsedMessages) ? parsedMessages : [],
@@ -52301,6 +52508,18 @@ var CliProviderInstance = class _CliProviderInstance {
52301
52508
  } catch {
52302
52509
  }
52303
52510
  }
52511
+ if (adapterOwnsMessagesElsewhere && finalAssistantEvidence.source === "external-native" && this.busyLeaseGateEnabled()) {
52512
+ try {
52513
+ const snapshot = this.lastTranscriptSignalSnapshot;
52514
+ const transcriptAgeMs = snapshot?.available === true && typeof snapshot.detail?.ageMs === "number" && Number.isFinite(snapshot.detail.ageMs) ? snapshot.detail.ageMs : void 0;
52515
+ if (typeof transcriptAgeMs === "number") {
52516
+ if (transcriptAgeMs < PTY_PARSED_FINAL_ASSISTANT_QUIET_DWELL_MS) {
52517
+ return { reason: "native_source_final_assistant_quiet_dwell", terminal: false };
52518
+ }
52519
+ }
52520
+ } catch {
52521
+ }
52522
+ }
52304
52523
  return null;
52305
52524
  }
52306
52525
  // (FALSEIDLE-a) Positive, structural proof that the latest approval entry was resolved
@@ -52928,7 +53147,7 @@ var CliProviderInstance = class _CliProviderInstance {
52928
53147
  return;
52929
53148
  }
52930
53149
  const latestOutputAt = typeof latestStatus?.lastOutputAt === "number" ? latestStatus.lastOutputAt : void 0;
52931
- if (typeof pending.lastOutputAtArm === "number" && typeof latestOutputAt === "number" && latestOutputAt > pending.lastOutputAtArm) {
53150
+ if (!pending.loggedBlockReason && typeof pending.lastOutputAtArm === "number" && typeof latestOutputAt === "number" && latestOutputAt > pending.lastOutputAtArm) {
52932
53151
  LOG.info("CLI", `[${this.type}] cancelled pending completed (new PTY output during settle: ${pending.lastOutputAtArm}\u2192${latestOutputAt})`);
52933
53152
  if (this.completionTraceOn()) this.recordCompletionGateTrace("cancel", {
52934
53153
  blockReason: "new_pty_output",
@@ -56917,6 +57136,7 @@ init_state_store();
56917
57136
  init_recent_activity();
56918
57137
  init_chat_history();
56919
57138
  init_mesh_events_utils();
57139
+ init_mesh_queue_assignment();
56920
57140
  init_logger();
56921
57141
  async function forwardConversationPrefsToCoordinator(ctx, sessionId, patch) {
56922
57142
  const dispatch = ctx.deps.dispatchMeshCommand;
@@ -57031,8 +57251,8 @@ var cliAgentHandlers = {
57031
57251
  };
57032
57252
  },
57033
57253
  agent_command: async (ctx, args) => {
57254
+ const dispatchSessionId = readStringValue(args?.targetSessionId, args?.sessionId, args?.instanceId);
57034
57255
  {
57035
- const dispatchSessionId = readStringValue(args?.targetSessionId, args?.sessionId, args?.instanceId);
57036
57256
  const dispatchMeshContext = args?.meshContext;
57037
57257
  if (dispatchSessionId && dispatchMeshContext) {
57038
57258
  try {
@@ -57066,18 +57286,23 @@ var cliAgentHandlers = {
57066
57286
  const nodeObj = Array.isArray(meshObj?.nodes) ? meshObj.nodes.find((n) => meshNodeIdMatches(n, dispatchNodeId)) : void 0;
57067
57287
  const { shouldDeferDispatchForBootstrap: shouldDeferDispatchForBootstrap2 } = await Promise.resolve().then(() => (init_worktree_bootstrap_config(), worktree_bootstrap_config_exports));
57068
57288
  if (shouldDeferDispatchForBootstrap2(nodeObj)) {
57069
- return {
57070
- success: false,
57071
- recoverable: true,
57072
- dispatched: false,
57073
- code: "mesh_node_bootstrap_pending",
57074
- reason: "bootstrap_still_running",
57075
- nodeId: dispatchNodeId,
57076
- meshId: dispatchMeshId,
57077
- ...readStringValue(meshCtx?.taskId) ? { taskId: readStringValue(meshCtx?.taskId) } : {},
57078
- 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.`,
57079
- 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."
57080
- };
57289
+ const dispatchSessionState = dispatchSessionId ? ctx.deps.instanceManager?.getInstance?.(dispatchSessionId)?.getState?.() : void 0;
57290
+ const sessionConfirmedReady = !!dispatchSessionState && isIdleSessionState(dispatchSessionState);
57291
+ if (!sessionConfirmedReady) {
57292
+ return {
57293
+ success: false,
57294
+ recoverable: true,
57295
+ dispatched: false,
57296
+ code: "mesh_node_bootstrap_pending",
57297
+ reason: "bootstrap_still_running",
57298
+ nodeId: dispatchNodeId,
57299
+ meshId: dispatchMeshId,
57300
+ ...readStringValue(meshCtx?.taskId) ? { taskId: readStringValue(meshCtx?.taskId) } : {},
57301
+ 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.`,
57302
+ 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."
57303
+ };
57304
+ }
57305
+ LOG.info("MeshQueue", `Overriding stale worktreeBootstrap 'running' flag for node ${dispatchNodeId}: explicit target session ${dispatchSessionId} is independently confirmed idle/ready \u2014 dispatching mesh_send_task directly.`);
57081
57306
  }
57082
57307
  } catch {
57083
57308
  }
@@ -78744,6 +78969,7 @@ var V1_CONTRACT_VERSION = "1.0.0";
78744
78969
  handleGitCommand,
78745
78970
  hasCdpManager,
78746
78971
  hasPendingDependents,
78972
+ hasTrailingToolActivityAfterFinalAssistant,
78747
78973
  hashSignatureParts,
78748
78974
  initDaemonComponents,
78749
78975
  insertDirectDispatch,