@adhdev/daemon-core 1.0.28-rc.16 → 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 +143 -14
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +142 -14
- package/dist/index.mjs.map +1 -1
- package/dist/mesh/mesh-events-stale.d.ts +59 -0
- package/dist/providers/cli-provider-instance.d.ts +19 -0
- package/package.json +3 -3
- package/src/index.ts +1 -0
- package/src/mesh/mesh-completion-synthesis.ts +35 -1
- package/src/mesh/mesh-event-forwarding.ts +25 -0
- package/src/mesh/mesh-events-stale.ts +109 -0
- package/src/mesh/mesh-reconcile-loop.ts +59 -12
- package/src/providers/cli-provider-instance.ts +27 -1
package/dist/index.mjs
CHANGED
|
@@ -786,10 +786,10 @@ function readInjected(value) {
|
|
|
786
786
|
}
|
|
787
787
|
function getDaemonBuildInfo() {
|
|
788
788
|
if (cached) return cached;
|
|
789
|
-
const commit = readInjected(true ? "
|
|
790
|
-
const commitShort = readInjected(true ? "
|
|
791
|
-
const version = readInjected(true ? "1.0.28-rc.
|
|
792
|
-
const builtAt = readInjected(true ? "2026-07-
|
|
789
|
+
const commit = readInjected(true ? "9452bd039720355425e62fc7469808a0dda3ab80" : void 0) ?? "unknown";
|
|
790
|
+
const commitShort = readInjected(true ? "9452bd03" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
|
|
791
|
+
const version = readInjected(true ? "1.0.28-rc.17" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
|
|
792
|
+
const builtAt = readInjected(true ? "2026-07-27T01:42:15.160Z" : void 0);
|
|
793
793
|
cached = builtAt ? { commit, commitShort, version, builtAt } : { commit, commitShort, version };
|
|
794
794
|
return cached;
|
|
795
795
|
}
|
|
@@ -16439,6 +16439,31 @@ var init_debug_trace = __esm({
|
|
|
16439
16439
|
function recordSynthCompletionGateTrace(stage, payload) {
|
|
16440
16440
|
recordDebugTrace({ category: "completion-gate", stage, level: "debug", payload });
|
|
16441
16441
|
}
|
|
16442
|
+
function evaluateTranscriptSynthAdmission(admission) {
|
|
16443
|
+
if (!admission) return { admitted: true };
|
|
16444
|
+
if (admission.trailingToolActivityAfterFinalAssistant === true) {
|
|
16445
|
+
return { admitted: false, reason: "trailing_tool_activity_after_final_assistant" };
|
|
16446
|
+
}
|
|
16447
|
+
if (!admission.boundedBackstop && typeof admission.liveTurnPendingEvidence === "function") {
|
|
16448
|
+
let pending = false;
|
|
16449
|
+
try {
|
|
16450
|
+
pending = admission.liveTurnPendingEvidence() === true;
|
|
16451
|
+
} catch {
|
|
16452
|
+
}
|
|
16453
|
+
if (pending) return { admitted: false, reason: "live_turn_pending_evidence" };
|
|
16454
|
+
}
|
|
16455
|
+
return { admitted: true };
|
|
16456
|
+
}
|
|
16457
|
+
function resolveLiveTurnPendingEvidence(components, sessionId) {
|
|
16458
|
+
try {
|
|
16459
|
+
const instance = components?.instanceManager?.getInstance?.(sessionId);
|
|
16460
|
+
if (typeof instance?.hasLiveTurnPendingEvidence !== "function") return void 0;
|
|
16461
|
+
const probe = instance.hasLiveTurnPendingEvidence.bind(instance);
|
|
16462
|
+
return () => probe();
|
|
16463
|
+
} catch {
|
|
16464
|
+
return void 0;
|
|
16465
|
+
}
|
|
16466
|
+
}
|
|
16442
16467
|
function findRecentTerminalLedgerEvidence(args) {
|
|
16443
16468
|
if (!args.sessionId && !args.nodeId) return null;
|
|
16444
16469
|
const entries = readLedgerEntries(args.meshId, { tail: 200 });
|
|
@@ -16559,6 +16584,17 @@ function reconcileDirectDispatchCompletionFromTranscript(args) {
|
|
|
16559
16584
|
})) {
|
|
16560
16585
|
return { reconciled: false, alreadyTerminal: true, reason: "terminal_ledger_entry_exists" };
|
|
16561
16586
|
}
|
|
16587
|
+
const admission = evaluateTranscriptSynthAdmission(args.causalAdmission);
|
|
16588
|
+
if (!admission.admitted) {
|
|
16589
|
+
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`);
|
|
16590
|
+
recordSynthCompletionGateTrace("synth-veto", {
|
|
16591
|
+
producer: "transcript_reconcile",
|
|
16592
|
+
source: args.source || "direct_task_transcript_reconciliation",
|
|
16593
|
+
taskId: args.taskId,
|
|
16594
|
+
reason: admission.reason
|
|
16595
|
+
});
|
|
16596
|
+
return { reconciled: false, reason: admission.reason };
|
|
16597
|
+
}
|
|
16562
16598
|
const nodeId = readNonEmptyString(args.nodeId) || dispatch?.nodeId;
|
|
16563
16599
|
const providerType = readNonEmptyString(args.providerType) || dispatch?.providerType || readNonEmptyString(dispatch?.payload.providerType);
|
|
16564
16600
|
const completedAt = args.completedAt || (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -16720,6 +16756,7 @@ var init_mesh_events_stale = __esm({
|
|
|
16720
16756
|
init_mesh_events_pending();
|
|
16721
16757
|
init_mesh_events_utils();
|
|
16722
16758
|
init_debug_trace();
|
|
16759
|
+
init_logger();
|
|
16723
16760
|
init_dist();
|
|
16724
16761
|
DIRECT_DISPATCH_RECONCILE_GRACE_MS = 6e4;
|
|
16725
16762
|
DIRECT_DISPATCH_IDLE_SESSION_RECONCILE_GRACE_MS = 12e4;
|
|
@@ -23093,6 +23130,14 @@ function evaluateMeshEventSuppression(args, ctx) {
|
|
|
23093
23130
|
};
|
|
23094
23131
|
}
|
|
23095
23132
|
}
|
|
23133
|
+
if (!readNonEmptyString(args.metadataEvent.taskId) && !sessionHasActiveAssignment(args.meshId, eventSessionId) && !findRecentTerminalLedgerEvidence({ meshId: args.meshId, sessionId: eventSessionId, nodeId: eventNodeId || void 0 }) && isWeakCompletionEvidence(args.metadataEvent)) {
|
|
23134
|
+
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`);
|
|
23135
|
+
traceMeshEventDrop("no_dispatch_native_completion", traceCtx);
|
|
23136
|
+
return {
|
|
23137
|
+
kind: "suppress",
|
|
23138
|
+
result: { success: true, forwarded: 0, suppressed: true, noDispatchNativeCompletion: true }
|
|
23139
|
+
};
|
|
23140
|
+
}
|
|
23096
23141
|
const inWindowTask = findInWindowUnclaimedAutoLaunchTask(args.meshId, eventSessionId, Date.now());
|
|
23097
23142
|
if (inWindowTask) {
|
|
23098
23143
|
const causalEvidence = MeshRuntimeStore.getInstance().taskDeliveryConsumed(args.meshId, inWindowTask.id) || hasMatchingTaskDispatchedLedgerEntry(args.meshId, inWindowTask.id, eventSessionId);
|
|
@@ -24849,6 +24894,18 @@ async function reconcileUnterminatedDirectDispatches(components, mesh, selfIds,
|
|
|
24849
24894
|
}
|
|
24850
24895
|
const messages = Array.isArray(payload.messages) ? payload.messages : [];
|
|
24851
24896
|
const evidence = extractFinalAssistantSummaryEvidence(messages);
|
|
24897
|
+
if (hasTrailingToolActivityAfterFinalAssistant(messages)) {
|
|
24898
|
+
setHoldState(synthKey, mesh.id, { liveConfirmedSinceAck: true, consecutiveReadFailures: 0 });
|
|
24899
|
+
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`);
|
|
24900
|
+
traceMeshEventDrop("reconcile_synth_veto_trailing_tool_activity", {
|
|
24901
|
+
taskId,
|
|
24902
|
+
sessionId,
|
|
24903
|
+
nodeId,
|
|
24904
|
+
meshId: mesh.id,
|
|
24905
|
+
event: "agent:generating_completed"
|
|
24906
|
+
});
|
|
24907
|
+
continue;
|
|
24908
|
+
}
|
|
24852
24909
|
if (isAcked) {
|
|
24853
24910
|
const ackedAtMs = Date.parse(readNonEmptyString(dispatch.updatedAt));
|
|
24854
24911
|
const sinceAckMs = Number.isFinite(ackedAtMs) ? nowMs - ackedAtMs : Number.POSITIVE_INFINITY;
|
|
@@ -24923,6 +24980,17 @@ async function reconcileUnterminatedDirectDispatches(components, mesh, selfIds,
|
|
|
24923
24980
|
// The ledger-recovered dispatching-coordinator daemon (inside the reconcile fn)
|
|
24924
24981
|
// takes PRIORITY over this arg; this remains the best-available fallback.
|
|
24925
24982
|
...coordinatorDaemonId ? { targetCoordinatorDaemonId: coordinatorDaemonId } : {},
|
|
24983
|
+
// MID-TURN-CAUSAL-ADMISSION (rc.16): pass the LOCAL live adapter's synchronous
|
|
24984
|
+
// turn-state probe into the unified choke point — a pending verdict vetoes this
|
|
24985
|
+
// eager synth (never-acked first-idle / acked fast-track). The death-deadline
|
|
24986
|
+
// backstop is the bounded max-wait net and overrides the veto (genuine-final
|
|
24987
|
+
// fail-open preserved); a remote/missing live source resolves to undefined and
|
|
24988
|
+
// fails open onto the bounded transcript evidence above. The trailing-tool veto
|
|
24989
|
+
// already ran at the top of this tick.
|
|
24990
|
+
causalAdmission: {
|
|
24991
|
+
liveTurnPendingEvidence: resolveLiveTurnPendingEvidence(components, sessionId),
|
|
24992
|
+
boundedBackstop: backstopKind === "ackedHoldDeathDeadlineFired"
|
|
24993
|
+
},
|
|
24926
24994
|
source: "daemon_reconcile_transcript_completion"
|
|
24927
24995
|
});
|
|
24928
24996
|
if (result.reconciled) {
|
|
@@ -25368,10 +25436,10 @@ async function evaluateEarlyIdleTranscriptArm(components, mesh, store, row, loca
|
|
|
25368
25436
|
if (profile) return profile.emitsPtyTurnEvents === false;
|
|
25369
25437
|
return verdict === "UNKNOWN";
|
|
25370
25438
|
}
|
|
25371
|
-
function propagateWatchdogTranscriptCompletion(meshId, row, evidence, source) {
|
|
25439
|
+
function propagateWatchdogTranscriptCompletion(components, meshId, row, evidence, source, opts) {
|
|
25372
25440
|
const sessionId = readNonEmptyString(row.assignedSessionId) || evidence.sessionId;
|
|
25373
25441
|
if (!sessionId || !readNonEmptyString(evidence.finalSummary)) {
|
|
25374
|
-
return
|
|
25442
|
+
return "unavailable";
|
|
25375
25443
|
}
|
|
25376
25444
|
try {
|
|
25377
25445
|
const result = reconcileDirectDispatchCompletionFromTranscript({
|
|
@@ -25387,11 +25455,26 @@ function propagateWatchdogTranscriptCompletion(meshId, row, evidence, source) {
|
|
|
25387
25455
|
// The watchdog poll already enforced idle + post-dispatch + no-trailing-tool + streak;
|
|
25388
25456
|
// skip the reconcile's own grace/transcript_not_proven gates (dedup backstops remain).
|
|
25389
25457
|
preValidatedTranscriptEvidence: true,
|
|
25458
|
+
// MID-TURN-CAUSAL-ADMISSION (rc.16): the transcript poll's structural evidence can
|
|
25459
|
+
// still straddle a genuinely mid-turn LOCAL worker (the incident shape: transcript
|
|
25460
|
+
// reads idle-with-final-assistant while the raw PTY is mid-tool). Route the live
|
|
25461
|
+
// adapter's synchronous probe through the unified choke point. The EARLY-IDLE
|
|
25462
|
+
// caller is an eager path (no opts) → a pending verdict defers; the redrive-deadline
|
|
25463
|
+
// caller passes boundedBackstop (the max-wait net) → the veto yields, preserving the
|
|
25464
|
+
// genuine-final fail-open semantics.
|
|
25465
|
+
causalAdmission: {
|
|
25466
|
+
liveTurnPendingEvidence: resolveLiveTurnPendingEvidence(components, sessionId),
|
|
25467
|
+
boundedBackstop: opts?.boundedBackstop === true
|
|
25468
|
+
},
|
|
25390
25469
|
source
|
|
25391
25470
|
});
|
|
25392
|
-
|
|
25471
|
+
if (result.reconciled || result.alreadyTerminal === true) return "propagated";
|
|
25472
|
+
if (result.reason === "live_turn_pending_evidence" || result.reason === "trailing_tool_activity_after_final_assistant") {
|
|
25473
|
+
return "deferred";
|
|
25474
|
+
}
|
|
25475
|
+
return "unavailable";
|
|
25393
25476
|
} catch {
|
|
25394
|
-
return
|
|
25477
|
+
return "unavailable";
|
|
25395
25478
|
}
|
|
25396
25479
|
}
|
|
25397
25480
|
async function recoverStrandedAssignedDispatches(components, mesh, store, localDaemonId, selfIds = []) {
|
|
@@ -25425,14 +25508,28 @@ async function recoverStrandedAssignedDispatches(components, mesh, store, localD
|
|
|
25425
25508
|
minFinalAssistantAgeMs: ASSIGNED_IDLE_TRANSCRIPT_COMPLETE_MS
|
|
25426
25509
|
});
|
|
25427
25510
|
if (terminalEvidence) {
|
|
25428
|
-
|
|
25429
|
-
|
|
25430
|
-
const propagated = propagateWatchdogTranscriptCompletion(
|
|
25511
|
+
const propagation = propagateWatchdogTranscriptCompletion(
|
|
25512
|
+
components,
|
|
25431
25513
|
meshId,
|
|
25432
25514
|
row,
|
|
25433
25515
|
terminalEvidence,
|
|
25434
25516
|
"early_idle_transcript_evidence"
|
|
25435
25517
|
);
|
|
25518
|
+
if (propagation === "deferred") {
|
|
25519
|
+
assignedIdleFinalAssistantSince.delete(idleTranscriptStreakKey);
|
|
25520
|
+
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`);
|
|
25521
|
+
traceMeshEventDrop("early_idle_completion_deferred_live_pending", {
|
|
25522
|
+
taskId: row.id,
|
|
25523
|
+
sessionId: row.assignedSessionId,
|
|
25524
|
+
nodeId: row.assignedNodeId,
|
|
25525
|
+
meshId,
|
|
25526
|
+
event: "agent:generating_completed"
|
|
25527
|
+
});
|
|
25528
|
+
continue;
|
|
25529
|
+
}
|
|
25530
|
+
assignedIdleFinalAssistantSince.delete(idleTranscriptStreakKey);
|
|
25531
|
+
updateTaskStatus(meshId, row.id, terminalEvidence.outcome);
|
|
25532
|
+
const propagated = propagation === "propagated";
|
|
25436
25533
|
if (!propagated && !findTerminalLedgerEvidenceForTask({ meshId, taskId: row.id })) {
|
|
25437
25534
|
try {
|
|
25438
25535
|
appendLedgerEntry(meshId, {
|
|
@@ -25607,12 +25704,15 @@ async function recoverStrandedAssignedDispatches(components, mesh, store, localD
|
|
|
25607
25704
|
if (terminalEvidence) {
|
|
25608
25705
|
deliveredNoTurnUnknownStreak.delete(streakKey);
|
|
25609
25706
|
updateTaskStatus(meshId, row.id, terminalEvidence.outcome);
|
|
25610
|
-
const
|
|
25707
|
+
const propagation = propagateWatchdogTranscriptCompletion(
|
|
25708
|
+
components,
|
|
25611
25709
|
meshId,
|
|
25612
25710
|
row,
|
|
25613
25711
|
terminalEvidence,
|
|
25614
|
-
"redrive_deadline_transcript_evidence"
|
|
25712
|
+
"redrive_deadline_transcript_evidence",
|
|
25713
|
+
{ boundedBackstop: true }
|
|
25615
25714
|
);
|
|
25715
|
+
const propagated = propagation === "propagated";
|
|
25616
25716
|
if (!propagated && !findTerminalLedgerEvidenceForTask({ meshId, taskId: row.id })) {
|
|
25617
25717
|
try {
|
|
25618
25718
|
appendLedgerEntry(meshId, {
|
|
@@ -51187,9 +51287,36 @@ var CliProviderInstance = class _CliProviderInstance {
|
|
|
51187
51287
|
* OR isModalParked() (a live approval/choice modal) — so a session this method reports
|
|
51188
51288
|
* pending is, by construction, one the local finalization gate would also refuse to
|
|
51189
51289
|
* finalize right now.
|
|
51290
|
+
*
|
|
51291
|
+
* NATIVE-TRAILING-TOOL-GATE (rc.16 follow-up): the three adapter-state discriminators
|
|
51292
|
+
* above are blind to a background shell tool that keeps a turn alive without the adapter
|
|
51293
|
+
* reporting a pending response — e.g. a backgrounded `sleep 40 &` between narration
|
|
51294
|
+
* bubbles on a write-lag native-source provider (claude-cli), which is deliberately
|
|
51295
|
+
* un-floored (noExternalTranscriptSource omitted, mission f2f6da1b owner decision) so its
|
|
51296
|
+
* transcript write-lag emits promptly. That un-flooring is correct for the ordinary
|
|
51297
|
+
* fraction-of-a-second trail, but it also means the growth-hold / busy-lease protections
|
|
51298
|
+
* in getCompletedFinalizationBlock never engage for claude-cli, so an interim final-
|
|
51299
|
+
* LOOKING bubble followed by continuing tool calls can still finalize as a completion
|
|
51300
|
+
* while the transcript demonstrably shows the turn still executing. Close that gap here,
|
|
51301
|
+
* narrowly: for a native-source provider only, reuse the SAME bounded transcript read the
|
|
51302
|
+
* class's own completion judgment already performs (probeNativeTranscriptSignals) and
|
|
51303
|
+
* apply the SAME trailing-tool-activity veto the transcript-synth admission choke point
|
|
51304
|
+
* uses (hasTrailingToolActivityAfterFinalAssistant) — the latest final-looking assistant
|
|
51305
|
+
* bubble followed by tool/terminal activity is interim narration, not a turn end. Fail-open
|
|
51306
|
+
* by construction: a non-native-source class (probe returns null), an unresolved
|
|
51307
|
+
* transcript, or a read error never reaches the veto, so a missing/unavailable transcript
|
|
51308
|
+
* can never wedge a session as "pending" forever.
|
|
51190
51309
|
*/
|
|
51191
51310
|
hasLiveTurnPendingEvidence() {
|
|
51192
|
-
|
|
51311
|
+
if (this.hasAdapterPendingResponse() || this.isModalParked()) return true;
|
|
51312
|
+
try {
|
|
51313
|
+
const probe = this.probeNativeTranscriptSignals();
|
|
51314
|
+
if (probe?.snapshot?.available === true && Array.isArray(probe.messages)) {
|
|
51315
|
+
if (hasTrailingToolActivityAfterFinalAssistant(probe.messages)) return true;
|
|
51316
|
+
}
|
|
51317
|
+
} catch {
|
|
51318
|
+
}
|
|
51319
|
+
return false;
|
|
51193
51320
|
}
|
|
51194
51321
|
/**
|
|
51195
51322
|
* PTY-OVERTRUST-DRAIN (Defect B). The deliverability/drain status the mesh
|
|
@@ -78413,6 +78540,7 @@ export {
|
|
|
78413
78540
|
handleGitCommand,
|
|
78414
78541
|
hasCdpManager,
|
|
78415
78542
|
hasPendingDependents,
|
|
78543
|
+
hasTrailingToolActivityAfterFinalAssistant,
|
|
78416
78544
|
hashSignatureParts,
|
|
78417
78545
|
initDaemonComponents,
|
|
78418
78546
|
insertDirectDispatch,
|