@adhdev/daemon-standalone 1.0.28-rc.32 → 1.0.28-rc.34
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 +254 -21
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -33311,10 +33311,10 @@ var require_dist3 = __commonJS({
|
|
|
33311
33311
|
}
|
|
33312
33312
|
function getDaemonBuildInfo() {
|
|
33313
33313
|
if (cached2) return cached2;
|
|
33314
|
-
const commit = readInjected(true ? "
|
|
33315
|
-
const commitShort = readInjected(true ? "
|
|
33316
|
-
const version2 = readInjected(true ? "1.0.28-rc.
|
|
33317
|
-
const builtAt = readInjected(true ? "2026-07-
|
|
33314
|
+
const commit = readInjected(true ? "fcccd1309a13173048d54bcfb1edbf698ee22ee3" : void 0) ?? "unknown";
|
|
33315
|
+
const commitShort = readInjected(true ? "fcccd130" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
|
|
33316
|
+
const version2 = readInjected(true ? "1.0.28-rc.34" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
|
|
33317
|
+
const builtAt = readInjected(true ? "2026-07-31T01:14:11.973Z" : void 0);
|
|
33318
33318
|
cached2 = builtAt ? { commit, commitShort, version: version2, builtAt } : { commit, commitShort, version: version2 };
|
|
33319
33319
|
return cached2;
|
|
33320
33320
|
}
|
|
@@ -38307,6 +38307,37 @@ Next step: ${nextStep}`;
|
|
|
38307
38307
|
nowMs: args.nowMs
|
|
38308
38308
|
});
|
|
38309
38309
|
}
|
|
38310
|
+
function rebindAttemptToLiveHolder(args) {
|
|
38311
|
+
const holder = typeof args.holderSessionId === "string" ? args.holderSessionId.trim() : "";
|
|
38312
|
+
if (!holder) return { rebound: false, reason: "no_holder" };
|
|
38313
|
+
const store = MeshRuntimeStore.getInstance();
|
|
38314
|
+
const attempt = store.getCurrentTurnAttempt(args.meshId, args.taskId);
|
|
38315
|
+
if (!attempt) return { rebound: false, reason: "no_attempt" };
|
|
38316
|
+
if (attempt.terminalOutcome) return { rebound: false, reason: "attempt_terminal", attemptId: attempt.attemptId };
|
|
38317
|
+
if (attempt.sessionId && sessionIdsEquivalent(attempt.sessionId, holder)) {
|
|
38318
|
+
return { rebound: false, reason: "same_session", attemptId: attempt.attemptId };
|
|
38319
|
+
}
|
|
38320
|
+
const nowMs = args.nowMs ?? Date.now();
|
|
38321
|
+
const nowIso = new Date(nowMs).toISOString();
|
|
38322
|
+
const ok = store.rebindTurnAttemptSession(attempt.attemptId, holder, nowIso);
|
|
38323
|
+
if (!ok) return { rebound: false, reason: "store_rejected", attemptId: attempt.attemptId };
|
|
38324
|
+
try {
|
|
38325
|
+
store.insertTurnEvent({
|
|
38326
|
+
eventId: (0, import_crypto5.randomUUID)(),
|
|
38327
|
+
meshId: args.meshId,
|
|
38328
|
+
attemptId: attempt.attemptId,
|
|
38329
|
+
taskId: args.taskId,
|
|
38330
|
+
kind: "session_rebound",
|
|
38331
|
+
dedupeKey: holder,
|
|
38332
|
+
payload: safeEvidenceJson({ fromSessionId: attempt.sessionId ?? null, toSessionId: holder, reason: "duplicate_dispatch_refused" }),
|
|
38333
|
+
occurredAtMs: nowMs,
|
|
38334
|
+
recordedAt: nowIso
|
|
38335
|
+
});
|
|
38336
|
+
} catch {
|
|
38337
|
+
}
|
|
38338
|
+
LOG2.info("TurnLedger", `Rebound attempt ${attempt.attemptId} (task ${args.taskId}) from session ${attempt.sessionId ?? "none"} to live holder ${holder} after a duplicate-dispatch refusal`);
|
|
38339
|
+
return { rebound: true, attemptId: attempt.attemptId, fromSessionId: attempt.sessionId ?? void 0, toSessionId: holder };
|
|
38340
|
+
}
|
|
38310
38341
|
function evaluateRedrive(meshId, taskId, nowMs = Date.now()) {
|
|
38311
38342
|
const store = MeshRuntimeStore.getInstance();
|
|
38312
38343
|
const attempt = store.getCurrentTurnAttempt(meshId, taskId);
|
|
@@ -39597,6 +39628,32 @@ Next step: ${nextStep}`;
|
|
|
39597
39628
|
return false;
|
|
39598
39629
|
}
|
|
39599
39630
|
}
|
|
39631
|
+
function requeueDrainedPendingMeshCoordinatorEvent(event) {
|
|
39632
|
+
const fingerprint = buildPendingEventFingerprint(event);
|
|
39633
|
+
if (!fingerprint.trim()) return false;
|
|
39634
|
+
let requeued = false;
|
|
39635
|
+
try {
|
|
39636
|
+
requeued = MeshRuntimeStore.getInstance().requeueDrainedPendingEventByFingerprint(event.meshId, fingerprint);
|
|
39637
|
+
} catch (e) {
|
|
39638
|
+
LOG2.warn("MeshEvents", `SQLite re-queue of held ${event.event} failed for mesh ${event.meshId}: ${e?.message || e}`);
|
|
39639
|
+
}
|
|
39640
|
+
try {
|
|
39641
|
+
const path50 = getPendingEventsPath(event.meshId, event.targetCoordinatorDaemonId);
|
|
39642
|
+
const alreadyOnDisk = readPendingMeshCoordinatorEventsFromDisk(event.meshId, event.targetCoordinatorDaemonId).some((pending) => buildPendingEventFingerprint(pending) === fingerprint);
|
|
39643
|
+
if (!alreadyOnDisk) {
|
|
39644
|
+
trimPendingEventsIfNeeded(path50);
|
|
39645
|
+
(0, import_fs5.appendFileSync)(path50, JSON.stringify(event) + "\n", "utf-8");
|
|
39646
|
+
requeued = true;
|
|
39647
|
+
}
|
|
39648
|
+
} catch (e) {
|
|
39649
|
+
if (!requeued) {
|
|
39650
|
+
LOG2.warn("MeshEvents", `Failed to durably re-queue held ${event.event} for mesh ${event.meshId}: ${e?.message || e}`);
|
|
39651
|
+
return false;
|
|
39652
|
+
}
|
|
39653
|
+
LOG2.warn("MeshEvents", `JSONL re-queue append failed for mesh ${event.meshId}; SQLite holds the event: ${e?.message || e}`);
|
|
39654
|
+
}
|
|
39655
|
+
return requeued;
|
|
39656
|
+
}
|
|
39600
39657
|
function atomicDrainFile(path50) {
|
|
39601
39658
|
const tmpPath = `${path50}.draining`;
|
|
39602
39659
|
try {
|
|
@@ -43395,6 +43452,49 @@ Next step: ${nextStep}`;
|
|
|
43395
43452
|
`UPDATE mesh_pending_events SET drained = 1, drained_at = ? WHERE drained = 0 AND id IN (${idList.map(() => "?").join(",")})`
|
|
43396
43453
|
).run(now, ...idList).changes;
|
|
43397
43454
|
}
|
|
43455
|
+
/**
|
|
43456
|
+
* STRICT-ROUTE-HOLD-DURABILITY: return an ALREADY-DRAINED row to the queue
|
|
43457
|
+
* (drained=1 → drained=0), in place, by fingerprint.
|
|
43458
|
+
*
|
|
43459
|
+
* Why this exists (the rc.33 defect): a strict-routed completion whose originating
|
|
43460
|
+
* coordinator session is not currently live is "held" by re-queuing it. That
|
|
43461
|
+
* re-queue used to call the normal insert path, which CANNOT work for a held
|
|
43462
|
+
* event — three independent suppressors reject it:
|
|
43463
|
+
*
|
|
43464
|
+
* 1. `idx_mesh_pending_events_fingerprint` is UNIQUE on (mesh_id, fingerprint)
|
|
43465
|
+
* with NO `drained` qualifier, and insertPendingEvent uses INSERT OR IGNORE.
|
|
43466
|
+
* The just-drained row still occupies that fingerprint, so the "fresh
|
|
43467
|
+
* undrained copy" is silently ignored — changes = 0, no row added.
|
|
43468
|
+
* 2. hasPendingCoordinatorEventDuplicate → hasPendingEventFingerprint queries
|
|
43469
|
+
* `drained = 0`, so it does NOT see the drained original and reports no
|
|
43470
|
+
* duplicate — the caller believes the re-queue succeeded.
|
|
43471
|
+
* 3. Even if a copy did land, the v2 eventId is already in
|
|
43472
|
+
* drainedEventIdsForMesh(), so routeV2EventsForDrainer would skip it as
|
|
43473
|
+
* already-delivered on the next drain.
|
|
43474
|
+
*
|
|
43475
|
+
* The pre-restart hold only ever worked because the in-memory reconcile loop
|
|
43476
|
+
* re-read the event; nothing durable was written. A restart inside the 60s TTL
|
|
43477
|
+
* therefore lost the completion permanently (observed: task ec6c901a — exactly
|
|
43478
|
+
* one row, drained=1, and zero lines in the JSONL mirror).
|
|
43479
|
+
*
|
|
43480
|
+
* Flipping the EXISTING row back to drained=0 is the only correct move: it keeps
|
|
43481
|
+
* the unique fingerprint (no duplicate row can ever be created), removes the
|
|
43482
|
+
* eventId from the drained-baseline so the v2 idempotency filter stops swallowing
|
|
43483
|
+
* it, and makes the hold survive a process restart. queued_at is deliberately
|
|
43484
|
+
* PRESERVED so the strict TTL keeps measuring the event's true age across holds
|
|
43485
|
+
* and cannot be refreshed into an immortal row.
|
|
43486
|
+
*
|
|
43487
|
+
* Returns true when a drained row was found and returned to the queue.
|
|
43488
|
+
*/
|
|
43489
|
+
requeueDrainedPendingEventByFingerprint(meshId, fingerprint) {
|
|
43490
|
+
if (!fingerprint) return false;
|
|
43491
|
+
const changes = this.db.prepare(
|
|
43492
|
+
`UPDATE mesh_pending_events SET drained = 0, drained_at = NULL
|
|
43493
|
+
WHERE mesh_id = ? AND fingerprint = ? AND drained = 1`
|
|
43494
|
+
).run(meshId, fingerprint).changes;
|
|
43495
|
+
if (changes > 0) this.maybeCheckpointWal();
|
|
43496
|
+
return changes > 0;
|
|
43497
|
+
}
|
|
43398
43498
|
/**
|
|
43399
43499
|
* Hard-delete pending-event rows by id (including the dedup fingerprint history).
|
|
43400
43500
|
* Used to expire an unresolved-delegate outbox entry that has exhausted its retry
|
|
@@ -43586,6 +43686,23 @@ Next step: ${nextStep}`;
|
|
|
43586
43686
|
`).run(leaseDeadlineMs, updatedAt, attemptId);
|
|
43587
43687
|
this.maybeCheckpointWal();
|
|
43588
43688
|
}
|
|
43689
|
+
/**
|
|
43690
|
+
* DUP-CLAIM-REBIND: point a still-open attempt at the session that is ACTUALLY
|
|
43691
|
+
* working it. Used when a node refuses a duplicate dispatch and names the live
|
|
43692
|
+
* holder — the attempt was opened against the session we tried to dispatch to,
|
|
43693
|
+
* but the work is running on the holder, so the binding (not the attempt) is what
|
|
43694
|
+
* is wrong. Conditional on `terminal_outcome IS NULL` so a settled attempt is
|
|
43695
|
+
* never rewritten; returns whether the rebind landed.
|
|
43696
|
+
*/
|
|
43697
|
+
rebindTurnAttemptSession(attemptId, sessionId, updatedAt) {
|
|
43698
|
+
const res = this.db.prepare(`
|
|
43699
|
+
UPDATE mesh_turn_attempts
|
|
43700
|
+
SET session_id = ?, updated_at = ?
|
|
43701
|
+
WHERE attempt_id = ? AND terminal_outcome IS NULL
|
|
43702
|
+
`).run(sessionId, updatedAt, attemptId);
|
|
43703
|
+
this.maybeCheckpointWal();
|
|
43704
|
+
return res.changes > 0;
|
|
43705
|
+
}
|
|
43589
43706
|
// ── TURN-LEDGER (Stage 5): idempotency-keyed causal events ───────────────
|
|
43590
43707
|
/**
|
|
43591
43708
|
* Append a causal event. INSERT OR IGNORE on UNIQUE(attempt_id, kind, dedupe_key)
|
|
@@ -44810,7 +44927,8 @@ Valid status values: \`completed\` | \`failed\` | \`blocked\` | \`partial\`.`;
|
|
|
44810
44927
|
"task_reclaimed",
|
|
44811
44928
|
"task_approval_needed",
|
|
44812
44929
|
"task_question_pending",
|
|
44813
|
-
"p2p_dispatch_failed"
|
|
44930
|
+
"p2p_dispatch_failed",
|
|
44931
|
+
"dispatch_duplicate_rebound"
|
|
44814
44932
|
]);
|
|
44815
44933
|
LEDGER_DIR_NAME = "mesh-ledger";
|
|
44816
44934
|
MAX_FILE_SIZE_BYTES = 10 * 1024 * 1024;
|
|
@@ -53910,6 +54028,42 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
|
|
|
53910
54028
|
]);
|
|
53911
54029
|
}
|
|
53912
54030
|
});
|
|
54031
|
+
function encodeDuplicateMeshDispatchCode(holderSessionId) {
|
|
54032
|
+
const holder = typeof holderSessionId === "string" ? holderSessionId.trim() : "";
|
|
54033
|
+
return holder ? `${DUPLICATE_MESH_DISPATCH_CODE}:${holder}` : DUPLICATE_MESH_DISPATCH_CODE;
|
|
54034
|
+
}
|
|
54035
|
+
function classifyDuplicateMeshDispatch(err) {
|
|
54036
|
+
if (!err || typeof err !== "object") return null;
|
|
54037
|
+
const e = err;
|
|
54038
|
+
if (e.code === DUPLICATE_MESH_DISPATCH_CODE) {
|
|
54039
|
+
const holder = typeof e.holderSessionId === "string" ? e.holderSessionId.trim() : "";
|
|
54040
|
+
return holder ? { holderSessionId: holder } : {};
|
|
54041
|
+
}
|
|
54042
|
+
for (const raw of [e.meshCode, e.code]) {
|
|
54043
|
+
if (typeof raw !== "string") continue;
|
|
54044
|
+
if (raw !== DUPLICATE_MESH_DISPATCH_CODE && !raw.startsWith(`${DUPLICATE_MESH_DISPATCH_CODE}:`)) continue;
|
|
54045
|
+
const holder = raw.slice(DUPLICATE_MESH_DISPATCH_CODE.length + 1).trim();
|
|
54046
|
+
return holder ? { holderSessionId: holder } : {};
|
|
54047
|
+
}
|
|
54048
|
+
return null;
|
|
54049
|
+
}
|
|
54050
|
+
var DUPLICATE_MESH_DISPATCH_CODE;
|
|
54051
|
+
var DuplicateMeshDispatchError;
|
|
54052
|
+
var init_mesh_duplicate_dispatch = __esm2({
|
|
54053
|
+
"src/mesh/mesh-duplicate-dispatch.ts"() {
|
|
54054
|
+
"use strict";
|
|
54055
|
+
DUPLICATE_MESH_DISPATCH_CODE = "DUPLICATE_MESH_DISPATCH";
|
|
54056
|
+
DuplicateMeshDispatchError = class extends Error {
|
|
54057
|
+
code = DUPLICATE_MESH_DISPATCH_CODE;
|
|
54058
|
+
holderSessionId;
|
|
54059
|
+
constructor(message, info = {}) {
|
|
54060
|
+
super(message);
|
|
54061
|
+
this.name = "DuplicateMeshDispatchError";
|
|
54062
|
+
this.holderSessionId = info.holderSessionId;
|
|
54063
|
+
}
|
|
54064
|
+
};
|
|
54065
|
+
}
|
|
54066
|
+
});
|
|
53913
54067
|
function localCoordinatorDaemonId() {
|
|
53914
54068
|
return canonicalDaemonId(readNonEmptyString(loadConfig2().machineId));
|
|
53915
54069
|
}
|
|
@@ -54110,6 +54264,37 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
|
|
|
54110
54264
|
}
|
|
54111
54265
|
}).catch((e) => {
|
|
54112
54266
|
if (timer) clearTimeout(timer);
|
|
54267
|
+
const duplicate = classifyDuplicateMeshDispatch(e);
|
|
54268
|
+
if (duplicate?.holderSessionId) {
|
|
54269
|
+
const rebind = rebindAttemptToLiveHolder({
|
|
54270
|
+
meshId: ctx.meshId,
|
|
54271
|
+
taskId: ctx.task.id,
|
|
54272
|
+
holderSessionId: duplicate.holderSessionId
|
|
54273
|
+
});
|
|
54274
|
+
if (rebind.rebound || rebind.reason === "same_session") {
|
|
54275
|
+
LOG2.info("MeshQueue", `Duplicate dispatch of task ${ctx.task.id} refused by node ${ctx.nodeId}: it is already being worked by live session ${duplicate.holderSessionId}. Task stays assigned; turn attempt ${rebind.attemptId ?? "n/a"} ${rebind.rebound ? "rebound to that session" : "was already bound to it"}.`);
|
|
54276
|
+
updateSessionDeliveryStatus(delivery.id, "delivered");
|
|
54277
|
+
try {
|
|
54278
|
+
appendLedgerEntry(ctx.meshId, {
|
|
54279
|
+
kind: "dispatch_duplicate_rebound",
|
|
54280
|
+
nodeId: ctx.nodeId,
|
|
54281
|
+
sessionId: duplicate.holderSessionId,
|
|
54282
|
+
payload: {
|
|
54283
|
+
taskId: ctx.task.id,
|
|
54284
|
+
deliveryId: delivery.id,
|
|
54285
|
+
transport: ctx.transport,
|
|
54286
|
+
attemptedSessionId: ctx.sessionId,
|
|
54287
|
+
holderSessionId: duplicate.holderSessionId,
|
|
54288
|
+
...rebind.attemptId ? { attemptId: rebind.attemptId } : {},
|
|
54289
|
+
rebound: rebind.rebound
|
|
54290
|
+
}
|
|
54291
|
+
});
|
|
54292
|
+
} catch {
|
|
54293
|
+
}
|
|
54294
|
+
return;
|
|
54295
|
+
}
|
|
54296
|
+
LOG2.warn("MeshQueue", `Duplicate dispatch of task ${ctx.task.id} refused by node ${ctx.nodeId} (holder ${duplicate.holderSessionId}), but the turn attempt could not be rebound (${rebind.reason}) \u2014 falling back to the requeue path.`);
|
|
54297
|
+
}
|
|
54113
54298
|
LOG2.error("MeshQueue", `Failed to dispatch task via ${ctx.transport} to node ${ctx.nodeId}: ${e?.message}`);
|
|
54114
54299
|
updateSessionDeliveryStatus(delivery.id, "failed", { lastError: e?.message, incrementAttempt: true });
|
|
54115
54300
|
endTaskDispatchInFlight(ctx.meshId, ctx.task.id);
|
|
@@ -55682,6 +55867,7 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
|
|
|
55682
55867
|
init_mesh_task_inflight();
|
|
55683
55868
|
init_model_provider_compat();
|
|
55684
55869
|
init_mesh_turn_ledger();
|
|
55870
|
+
init_mesh_duplicate_dispatch();
|
|
55685
55871
|
IDLE_AUTO_FAST_FORWARD_THROTTLE_MS = 30 * 60 * 1e3;
|
|
55686
55872
|
idleAutoFastForwardLastAttempt = /* @__PURE__ */ new Map();
|
|
55687
55873
|
CONTINUOUS_AUTO_FAST_FORWARD_SCAN_COOLDOWN_MS = 45 * 1e3;
|
|
@@ -60859,23 +61045,51 @@ ${cleanBody}`;
|
|
|
60859
61045
|
async function pollAssignedTaskTerminalEvidence(components, mesh, row, opts) {
|
|
60860
61046
|
const sessionId = readNonEmptyString(row.assignedSessionId);
|
|
60861
61047
|
const nodeId = readNonEmptyString(row.assignedNodeId);
|
|
60862
|
-
|
|
61048
|
+
const traceCtx = {
|
|
61049
|
+
taskId: row.id,
|
|
61050
|
+
...sessionId ? { sessionId } : {},
|
|
61051
|
+
...nodeId ? { nodeId } : {},
|
|
61052
|
+
meshId: mesh.id,
|
|
61053
|
+
event: "agent:generating_completed"
|
|
61054
|
+
};
|
|
61055
|
+
const declined = (reason, detail) => {
|
|
61056
|
+
traceMeshEventDrop(`poll_terminal_evidence_${reason}`, traceCtx, detail);
|
|
61057
|
+
return null;
|
|
61058
|
+
};
|
|
61059
|
+
if (!sessionId || !nodeId) {
|
|
61060
|
+
return declined("no_assigned_worker", `sessionId=${sessionId ?? "none"} nodeId=${nodeId ?? "none"}`);
|
|
61061
|
+
}
|
|
60863
61062
|
const providerType = readNonEmptyString(row.assignedProviderType);
|
|
60864
61063
|
const payload = await runSessionEvidenceCollection(sessionId, () => fetchAssignedTaskChatTail(components, mesh, row));
|
|
60865
|
-
if (!payload) return
|
|
60866
|
-
|
|
61064
|
+
if (!payload) return declined("chat_tail_unreadable", "worker transcript read returned no payload (offline/unreachable?)");
|
|
61065
|
+
const payloadStatus = readChatPayloadStatus(payload);
|
|
61066
|
+
if (payloadStatus !== "idle") return declined("session_not_idle", `status=${payloadStatus ?? "unknown"} \u2014 mid-turn, not a turn-end`);
|
|
60867
61067
|
const messages = Array.isArray(payload.messages) ? payload.messages : [];
|
|
60868
61068
|
const evidence = extractFinalAssistantSummaryEvidence(messages);
|
|
60869
|
-
if (!evidence.finalSummary) return
|
|
60870
|
-
if (hasTrailingToolActivityAfterFinalAssistant(messages))
|
|
61069
|
+
if (!evidence.finalSummary) return declined("no_final_assistant_summary", `idle with ${messages.length} message(s) but no assistant result`);
|
|
61070
|
+
if (hasTrailingToolActivityAfterFinalAssistant(messages)) {
|
|
61071
|
+
return declined("trailing_tool_activity", "tool/terminal bubble trails the final assistant \u2014 worker is mid-turn");
|
|
61072
|
+
}
|
|
60871
61073
|
const dispatchedAtMs = Date.parse(readNonEmptyString(row.dispatchTimestamp));
|
|
60872
61074
|
const transcriptAtMs = Date.parse(evidence.transcriptMessageAt ?? "");
|
|
60873
61075
|
if (!(Number.isFinite(dispatchedAtMs) && Number.isFinite(transcriptAtMs) && transcriptAtMs >= dispatchedAtMs)) {
|
|
60874
|
-
|
|
61076
|
+
const unusable = !Number.isFinite(dispatchedAtMs) || !Number.isFinite(transcriptAtMs);
|
|
61077
|
+
return declined(
|
|
61078
|
+
unusable ? "timestamp_unusable" : "summary_predates_dispatch",
|
|
61079
|
+
`dispatchTimestamp=${row.dispatchTimestamp ?? "none"} transcriptMessageAt=${evidence.transcriptMessageAt ?? "none"}`
|
|
61080
|
+
);
|
|
60875
61081
|
}
|
|
60876
61082
|
if (typeof opts?.minFinalAssistantAgeMs === "number" && opts.minFinalAssistantAgeMs > 0 && Date.now() - transcriptAtMs < opts.minFinalAssistantAgeMs) {
|
|
60877
|
-
return
|
|
61083
|
+
return declined(
|
|
61084
|
+
"final_assistant_not_settled",
|
|
61085
|
+
`age=${Date.now() - transcriptAtMs}ms < minFinalAssistantAgeMs=${opts.minFinalAssistantAgeMs} \u2014 treated as in-flight narration`
|
|
61086
|
+
);
|
|
60878
61087
|
}
|
|
61088
|
+
traceMeshEventStage(
|
|
61089
|
+
"poll_terminal_evidence_completed",
|
|
61090
|
+
traceCtx,
|
|
61091
|
+
`idle with final assistant after dispatch \u2014 task is completed, re-drive prevented`
|
|
61092
|
+
);
|
|
60879
61093
|
return {
|
|
60880
61094
|
outcome: "completed",
|
|
60881
61095
|
finalSummary: evidence.finalSummary,
|
|
@@ -61002,7 +61216,7 @@ ${cleanBody}`;
|
|
|
61002
61216
|
...force ? { force: true } : {}
|
|
61003
61217
|
});
|
|
61004
61218
|
}
|
|
61005
|
-
function recordHeldTerminalEventsToLedger(meshId, drainDaemonIds, reason, heldForCoordinatorCount) {
|
|
61219
|
+
function recordHeldTerminalEventsToLedger(meshId, drainDaemonIds, reason, heldForCoordinatorCount, strictRoutedFingerprints) {
|
|
61006
61220
|
let pending;
|
|
61007
61221
|
try {
|
|
61008
61222
|
pending = getPendingMeshCoordinatorEvents(meshId, drainDaemonIds.length > 0 ? drainDaemonIds : void 0);
|
|
@@ -61010,6 +61224,7 @@ ${cleanBody}`;
|
|
|
61010
61224
|
return;
|
|
61011
61225
|
}
|
|
61012
61226
|
for (const event of pending) {
|
|
61227
|
+
if (strictRoutedFingerprints?.has(buildPendingEventFingerprint(event))) continue;
|
|
61013
61228
|
if (!shouldForceInjectMeshEvent(event.event)) continue;
|
|
61014
61229
|
const fingerprint = buildPendingEventFingerprint(event);
|
|
61015
61230
|
const key2 = `${meshId}::${fingerprint || `${event.event}::${event.nodeId || ""}::${event.queuedAt}`}`;
|
|
@@ -62089,6 +62304,7 @@ ${cleanBody}`;
|
|
|
62089
62304
|
meshCoordinators.map((c) => readNonEmptyString(c.sessionId)).filter(Boolean)
|
|
62090
62305
|
);
|
|
62091
62306
|
let orphanEscaped = 0;
|
|
62307
|
+
const strictRoutedFingerprints = /* @__PURE__ */ new Set();
|
|
62092
62308
|
const hasPendingForOrphanPeek = !store || (() => {
|
|
62093
62309
|
try {
|
|
62094
62310
|
return store.pendingEventCount(meshId) > 0;
|
|
@@ -62123,10 +62339,11 @@ ${cleanBody}`;
|
|
|
62123
62339
|
for (const pending of drained) {
|
|
62124
62340
|
if (isOrphan(pending)) {
|
|
62125
62341
|
holdOrExpireStrictUnmatchedEvent(pending, readNonEmptyString(pending.targetCoordinatorSessionId), meshId);
|
|
62342
|
+
strictRoutedFingerprints.add(buildPendingEventFingerprint(pending));
|
|
62126
62343
|
orphanEscaped++;
|
|
62127
62344
|
} else {
|
|
62128
62345
|
try {
|
|
62129
|
-
|
|
62346
|
+
requeueDrainedPendingMeshCoordinatorEvent(pending);
|
|
62130
62347
|
} catch {
|
|
62131
62348
|
}
|
|
62132
62349
|
}
|
|
@@ -62149,7 +62366,8 @@ ${cleanBody}`;
|
|
|
62149
62366
|
meshId,
|
|
62150
62367
|
drainDaemonIds.length > 0 ? drainDaemonIds : localDaemonId ? [localDaemonId] : [],
|
|
62151
62368
|
"modal_parked",
|
|
62152
|
-
modalParkedCoordinators.length
|
|
62369
|
+
modalParkedCoordinators.length,
|
|
62370
|
+
strictRoutedFingerprints
|
|
62153
62371
|
);
|
|
62154
62372
|
}
|
|
62155
62373
|
} else if (generatingCoordinators.length > 0) {
|
|
@@ -62208,15 +62426,15 @@ ${cleanBody}`;
|
|
|
62208
62426
|
const queuedAt = typeof pending.queuedAt === "number" ? pending.queuedAt : Date.now();
|
|
62209
62427
|
if (Date.now() - queuedAt <= STRICT_SESSION_MATCH_TTL_MS) {
|
|
62210
62428
|
try {
|
|
62211
|
-
|
|
62212
|
-
LOG2.info("MeshReconcile", `Strict route hold: coordinator session ${wantSession} not live on mesh ${meshId} \u2014 re-queued (${pending.event})`);
|
|
62429
|
+
const requeued = requeueDrainedPendingMeshCoordinatorEvent(pending);
|
|
62430
|
+
LOG2.info("MeshReconcile", `Strict route hold: coordinator session ${wantSession} not live on mesh ${meshId} \u2014 re-queued (${pending.event})${requeued ? "" : " [WARN: not durably re-queued]"}`);
|
|
62213
62431
|
traceMeshEventDrop("strict_route_hold", {
|
|
62214
62432
|
taskId: pending.metadataEvent?.taskId,
|
|
62215
62433
|
sessionId: pending.metadataEvent?.targetSessionId ?? wantSession,
|
|
62216
62434
|
nodeId: pending.nodeId,
|
|
62217
62435
|
meshId,
|
|
62218
62436
|
event: pending.event
|
|
62219
|
-
}, `coordinatorSession=${wantSession} not live`);
|
|
62437
|
+
}, `coordinatorSession=${wantSession} not live durable=${requeued}`);
|
|
62220
62438
|
} catch (e) {
|
|
62221
62439
|
LOG2.warn("MeshReconcile", `Strict route re-queue failed for ${pending.event} on mesh ${meshId}: ${e?.message || e}`);
|
|
62222
62440
|
}
|
|
@@ -70820,6 +71038,7 @@ ${lastSnapshot}`;
|
|
|
70820
71038
|
DEFAULT_STATUS_P2P_REPORT_INTERVAL_MS: () => DEFAULT_STATUS_P2P_REPORT_INTERVAL_MS,
|
|
70821
71039
|
DEFAULT_STATUS_SERVER_REPORT_INTERVAL_MS: () => DEFAULT_STATUS_SERVER_REPORT_INTERVAL_MS,
|
|
70822
71040
|
DEV_SERVER_PORT: () => DEV_SERVER_PORT,
|
|
71041
|
+
DUPLICATE_MESH_DISPATCH_CODE: () => DUPLICATE_MESH_DISPATCH_CODE,
|
|
70823
71042
|
DaemonAgentStreamManager: () => DaemonAgentStreamManager,
|
|
70824
71043
|
DaemonCdpInitializer: () => DaemonCdpInitializer,
|
|
70825
71044
|
DaemonCdpManager: () => DaemonCdpManager,
|
|
@@ -70829,6 +71048,7 @@ ${lastSnapshot}`;
|
|
|
70829
71048
|
DaemonCommandRouter: () => DaemonCommandRouter,
|
|
70830
71049
|
DaemonStatusReporter: () => DaemonStatusReporter,
|
|
70831
71050
|
DevServer: () => DevServer,
|
|
71051
|
+
DuplicateMeshDispatchError: () => DuplicateMeshDispatchError,
|
|
70832
71052
|
FsmDriver: () => FsmDriver,
|
|
70833
71053
|
GOAL_PREVIEW_MAX: () => GOAL_PREVIEW_MAX,
|
|
70834
71054
|
GitCommandError: () => GitCommandError,
|
|
@@ -70938,6 +71158,7 @@ ${lastSnapshot}`;
|
|
|
70938
71158
|
canonicalDaemonId: () => canonicalDaemonId,
|
|
70939
71159
|
claimNextTask: () => claimNextTask,
|
|
70940
71160
|
classifyChatMessageVisibility: () => classifyChatMessageVisibility,
|
|
71161
|
+
classifyDuplicateMeshDispatch: () => classifyDuplicateMeshDispatch,
|
|
70941
71162
|
classifyHotChatSessionsForSubscriptionFlush: () => classifyHotChatSessionsForSubscriptionFlush2,
|
|
70942
71163
|
classifyP2pRelayFailure: () => classifyP2pRelayFailure,
|
|
70943
71164
|
classifyShadowDivergence: () => classifyShadowDivergence,
|
|
@@ -70980,6 +71201,7 @@ ${lastSnapshot}`;
|
|
|
70980
71201
|
detectIDEs: () => detectIDEs,
|
|
70981
71202
|
detectNewlySettledCompletedSessions: () => detectNewlySettledCompletedSessions2,
|
|
70982
71203
|
drainPendingMeshCoordinatorEvents: () => drainPendingMeshCoordinatorEvents,
|
|
71204
|
+
encodeDuplicateMeshDispatchCode: () => encodeDuplicateMeshDispatchCode,
|
|
70983
71205
|
enqueueTask: () => enqueueTask,
|
|
70984
71206
|
ensureSessionHostReady: () => ensureSessionHostReady2,
|
|
70985
71207
|
evaluateFsm: () => evaluateFsm,
|
|
@@ -73540,6 +73762,7 @@ ${lastSnapshot}`;
|
|
|
73540
73762
|
this.authEpoch = context.authEpoch;
|
|
73541
73763
|
}
|
|
73542
73764
|
};
|
|
73765
|
+
init_mesh_duplicate_dispatch();
|
|
73543
73766
|
init_state_store();
|
|
73544
73767
|
var import_child_process5 = require("child_process");
|
|
73545
73768
|
var import_util22 = require("util");
|
|
@@ -85232,6 +85455,7 @@ ${body}
|
|
|
85232
85455
|
init_recent_activity();
|
|
85233
85456
|
init_hash();
|
|
85234
85457
|
init_coordinator_registry();
|
|
85458
|
+
init_mesh_duplicate_dispatch();
|
|
85235
85459
|
init_summary_metadata();
|
|
85236
85460
|
var os19 = __toESM2(require("os"));
|
|
85237
85461
|
var crypto5 = __toESM2(require("crypto"));
|
|
@@ -94745,7 +94969,10 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
94745
94969
|
} catch {
|
|
94746
94970
|
}
|
|
94747
94971
|
if (stampResult && stampResult.stamped === false && stampResult.reason === "task_already_stamped_on_live_instance") {
|
|
94748
|
-
throw new
|
|
94972
|
+
throw new DuplicateMeshDispatchError(
|
|
94973
|
+
`Refusing duplicate mesh dispatch: task ${meshContext.taskId} is already being worked by a live session on this daemon`,
|
|
94974
|
+
{ holderSessionId: stampResult.holderSessionId }
|
|
94975
|
+
);
|
|
94749
94976
|
}
|
|
94750
94977
|
if (meshContext.silentIdlePush === true) {
|
|
94751
94978
|
try {
|
|
@@ -110513,7 +110740,13 @@ ${e?.stderr || ""}`;
|
|
|
110513
110740
|
* marker in state.settings). Returns `{ stamped: true }` when the stamp was
|
|
110514
110741
|
* applied, or `{ stamped: false, reason }` when it was refused — the instance
|
|
110515
110742
|
* was missing / has no attach method, or the DOUBLE-DISPATCH idempotence guard
|
|
110516
|
-
* fired (the same task is already running on another live session here).
|
|
110743
|
+
* fired (the same task is already running on another live session here).
|
|
110744
|
+
*
|
|
110745
|
+
* DUP-CLAIM-REBIND: when the guard fires, the id of the live session that already
|
|
110746
|
+
* holds the task is returned as `holderSessionId`. The coordinator needs it to
|
|
110747
|
+
* REBIND its turn-ledger attempt onto the real worker instead of cancelling the
|
|
110748
|
+
* attempt — the guard already resolved that instance, so surfacing it here keeps
|
|
110749
|
+
* the caller from having to parse it back out of an error string. */
|
|
110517
110750
|
attachMeshAssignmentToInstance(instanceId, assignment) {
|
|
110518
110751
|
const inst = this.instances.get(instanceId);
|
|
110519
110752
|
if (!inst || typeof inst.attachMeshAssignment !== "function") {
|
|
@@ -110524,7 +110757,7 @@ ${e?.stderr || ""}`;
|
|
|
110524
110757
|
const conflict = this.findLiveWorkingTaskHolder(assignment.meshId, assignment.taskId, instanceId);
|
|
110525
110758
|
if (conflict) {
|
|
110526
110759
|
LOG2.warn("MeshDispatch", `attachMeshAssignment refused: task ${assignment.taskId} (mesh ${assignment.meshId}) is already being worked by live session ${conflict} \u2014 skipping duplicate stamp on ${instanceId}`);
|
|
110527
|
-
return { stamped: false, reason: "task_already_stamped_on_live_instance" };
|
|
110760
|
+
return { stamped: false, reason: "task_already_stamped_on_live_instance", holderSessionId: conflict };
|
|
110528
110761
|
}
|
|
110529
110762
|
}
|
|
110530
110763
|
inst.attachMeshAssignment(assignment);
|