@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 +1 -1
- package/dist/index.js +258 -32
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +257 -32
- package/dist/index.mjs.map +1 -1
- package/dist/mesh/mesh-events-stale.d.ts +59 -0
- package/dist/mesh/mesh-queue-assignment.d.ts +1 -0
- package/dist/providers/cli-provider-instance.d.ts +34 -0
- package/package.json +3 -3
- package/src/cli-adapters/provider-cli-adapter.ts +7 -1
- package/src/commands/med-family/cli-agent.ts +32 -13
- package/src/index.ts +1 -0
- package/src/mesh/mesh-completion-synthesis.ts +35 -1
- package/src/mesh/mesh-event-forwarding.ts +129 -1
- package/src/mesh/mesh-events-stale.ts +109 -0
- package/src/mesh/mesh-queue-assignment.ts +19 -1
- package/src/mesh/mesh-reconcile-loop.ts +59 -12
- package/src/providers/cli-provider-instance.ts +135 -7
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 ? "
|
|
795
|
-
const commitShort = readInjected(true ? "
|
|
796
|
-
const version = readInjected(true ? "1.0.28-rc.
|
|
797
|
-
const builtAt = readInjected(true ? "2026-07-
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
25370
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
57070
|
-
|
|
57071
|
-
|
|
57072
|
-
|
|
57073
|
-
|
|
57074
|
-
|
|
57075
|
-
|
|
57076
|
-
|
|
57077
|
-
|
|
57078
|
-
|
|
57079
|
-
|
|
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,
|