@adhdev/daemon-standalone 1.0.28-rc.32 → 1.0.28-rc.33

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -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 ? "9d291b6668878c1d0e3c210fad52ff57cf9ec1f8" : void 0) ?? "unknown";
33315
- const commitShort = readInjected(true ? "9d291b66" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
33316
- const version2 = readInjected(true ? "1.0.28-rc.32" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
33317
- const builtAt = readInjected(true ? "2026-07-30T17:15:53.842Z" : void 0);
33314
+ const commit = readInjected(true ? "5e05ac37dcef7e88d50d419fe2cf93bfbf77fc88" : void 0) ?? "unknown";
33315
+ const commitShort = readInjected(true ? "5e05ac37" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
33316
+ const version2 = readInjected(true ? "1.0.28-rc.33" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
33317
+ const builtAt = readInjected(true ? "2026-07-31T00:24:14.883Z" : void 0);
33318
33318
  cached2 = builtAt ? { commit, commitShort, version: version2, builtAt } : { commit, commitShort, version: version2 };
33319
33319
  return cached2;
33320
33320
  }
@@ -39597,6 +39597,32 @@ Next step: ${nextStep}`;
39597
39597
  return false;
39598
39598
  }
39599
39599
  }
39600
+ function requeueDrainedPendingMeshCoordinatorEvent(event) {
39601
+ const fingerprint = buildPendingEventFingerprint(event);
39602
+ if (!fingerprint.trim()) return false;
39603
+ let requeued = false;
39604
+ try {
39605
+ requeued = MeshRuntimeStore.getInstance().requeueDrainedPendingEventByFingerprint(event.meshId, fingerprint);
39606
+ } catch (e) {
39607
+ LOG2.warn("MeshEvents", `SQLite re-queue of held ${event.event} failed for mesh ${event.meshId}: ${e?.message || e}`);
39608
+ }
39609
+ try {
39610
+ const path50 = getPendingEventsPath(event.meshId, event.targetCoordinatorDaemonId);
39611
+ const alreadyOnDisk = readPendingMeshCoordinatorEventsFromDisk(event.meshId, event.targetCoordinatorDaemonId).some((pending) => buildPendingEventFingerprint(pending) === fingerprint);
39612
+ if (!alreadyOnDisk) {
39613
+ trimPendingEventsIfNeeded(path50);
39614
+ (0, import_fs5.appendFileSync)(path50, JSON.stringify(event) + "\n", "utf-8");
39615
+ requeued = true;
39616
+ }
39617
+ } catch (e) {
39618
+ if (!requeued) {
39619
+ LOG2.warn("MeshEvents", `Failed to durably re-queue held ${event.event} for mesh ${event.meshId}: ${e?.message || e}`);
39620
+ return false;
39621
+ }
39622
+ LOG2.warn("MeshEvents", `JSONL re-queue append failed for mesh ${event.meshId}; SQLite holds the event: ${e?.message || e}`);
39623
+ }
39624
+ return requeued;
39625
+ }
39600
39626
  function atomicDrainFile(path50) {
39601
39627
  const tmpPath = `${path50}.draining`;
39602
39628
  try {
@@ -43395,6 +43421,49 @@ Next step: ${nextStep}`;
43395
43421
  `UPDATE mesh_pending_events SET drained = 1, drained_at = ? WHERE drained = 0 AND id IN (${idList.map(() => "?").join(",")})`
43396
43422
  ).run(now, ...idList).changes;
43397
43423
  }
43424
+ /**
43425
+ * STRICT-ROUTE-HOLD-DURABILITY: return an ALREADY-DRAINED row to the queue
43426
+ * (drained=1 → drained=0), in place, by fingerprint.
43427
+ *
43428
+ * Why this exists (the rc.33 defect): a strict-routed completion whose originating
43429
+ * coordinator session is not currently live is "held" by re-queuing it. That
43430
+ * re-queue used to call the normal insert path, which CANNOT work for a held
43431
+ * event — three independent suppressors reject it:
43432
+ *
43433
+ * 1. `idx_mesh_pending_events_fingerprint` is UNIQUE on (mesh_id, fingerprint)
43434
+ * with NO `drained` qualifier, and insertPendingEvent uses INSERT OR IGNORE.
43435
+ * The just-drained row still occupies that fingerprint, so the "fresh
43436
+ * undrained copy" is silently ignored — changes = 0, no row added.
43437
+ * 2. hasPendingCoordinatorEventDuplicate → hasPendingEventFingerprint queries
43438
+ * `drained = 0`, so it does NOT see the drained original and reports no
43439
+ * duplicate — the caller believes the re-queue succeeded.
43440
+ * 3. Even if a copy did land, the v2 eventId is already in
43441
+ * drainedEventIdsForMesh(), so routeV2EventsForDrainer would skip it as
43442
+ * already-delivered on the next drain.
43443
+ *
43444
+ * The pre-restart hold only ever worked because the in-memory reconcile loop
43445
+ * re-read the event; nothing durable was written. A restart inside the 60s TTL
43446
+ * therefore lost the completion permanently (observed: task ec6c901a — exactly
43447
+ * one row, drained=1, and zero lines in the JSONL mirror).
43448
+ *
43449
+ * Flipping the EXISTING row back to drained=0 is the only correct move: it keeps
43450
+ * the unique fingerprint (no duplicate row can ever be created), removes the
43451
+ * eventId from the drained-baseline so the v2 idempotency filter stops swallowing
43452
+ * it, and makes the hold survive a process restart. queued_at is deliberately
43453
+ * PRESERVED so the strict TTL keeps measuring the event's true age across holds
43454
+ * and cannot be refreshed into an immortal row.
43455
+ *
43456
+ * Returns true when a drained row was found and returned to the queue.
43457
+ */
43458
+ requeueDrainedPendingEventByFingerprint(meshId, fingerprint) {
43459
+ if (!fingerprint) return false;
43460
+ const changes = this.db.prepare(
43461
+ `UPDATE mesh_pending_events SET drained = 0, drained_at = NULL
43462
+ WHERE mesh_id = ? AND fingerprint = ? AND drained = 1`
43463
+ ).run(meshId, fingerprint).changes;
43464
+ if (changes > 0) this.maybeCheckpointWal();
43465
+ return changes > 0;
43466
+ }
43398
43467
  /**
43399
43468
  * Hard-delete pending-event rows by id (including the dedup fingerprint history).
43400
43469
  * Used to expire an unresolved-delegate outbox entry that has exhausted its retry
@@ -60859,23 +60928,51 @@ ${cleanBody}`;
60859
60928
  async function pollAssignedTaskTerminalEvidence(components, mesh, row, opts) {
60860
60929
  const sessionId = readNonEmptyString(row.assignedSessionId);
60861
60930
  const nodeId = readNonEmptyString(row.assignedNodeId);
60862
- if (!sessionId || !nodeId) return null;
60931
+ const traceCtx = {
60932
+ taskId: row.id,
60933
+ ...sessionId ? { sessionId } : {},
60934
+ ...nodeId ? { nodeId } : {},
60935
+ meshId: mesh.id,
60936
+ event: "agent:generating_completed"
60937
+ };
60938
+ const declined = (reason, detail) => {
60939
+ traceMeshEventDrop(`poll_terminal_evidence_${reason}`, traceCtx, detail);
60940
+ return null;
60941
+ };
60942
+ if (!sessionId || !nodeId) {
60943
+ return declined("no_assigned_worker", `sessionId=${sessionId ?? "none"} nodeId=${nodeId ?? "none"}`);
60944
+ }
60863
60945
  const providerType = readNonEmptyString(row.assignedProviderType);
60864
60946
  const payload = await runSessionEvidenceCollection(sessionId, () => fetchAssignedTaskChatTail(components, mesh, row));
60865
- if (!payload) return null;
60866
- if (readChatPayloadStatus(payload) !== "idle") return null;
60947
+ if (!payload) return declined("chat_tail_unreadable", "worker transcript read returned no payload (offline/unreachable?)");
60948
+ const payloadStatus = readChatPayloadStatus(payload);
60949
+ if (payloadStatus !== "idle") return declined("session_not_idle", `status=${payloadStatus ?? "unknown"} \u2014 mid-turn, not a turn-end`);
60867
60950
  const messages = Array.isArray(payload.messages) ? payload.messages : [];
60868
60951
  const evidence = extractFinalAssistantSummaryEvidence(messages);
60869
- if (!evidence.finalSummary) return null;
60870
- if (hasTrailingToolActivityAfterFinalAssistant(messages)) return null;
60952
+ if (!evidence.finalSummary) return declined("no_final_assistant_summary", `idle with ${messages.length} message(s) but no assistant result`);
60953
+ if (hasTrailingToolActivityAfterFinalAssistant(messages)) {
60954
+ return declined("trailing_tool_activity", "tool/terminal bubble trails the final assistant \u2014 worker is mid-turn");
60955
+ }
60871
60956
  const dispatchedAtMs = Date.parse(readNonEmptyString(row.dispatchTimestamp));
60872
60957
  const transcriptAtMs = Date.parse(evidence.transcriptMessageAt ?? "");
60873
60958
  if (!(Number.isFinite(dispatchedAtMs) && Number.isFinite(transcriptAtMs) && transcriptAtMs >= dispatchedAtMs)) {
60874
- return null;
60959
+ const unusable = !Number.isFinite(dispatchedAtMs) || !Number.isFinite(transcriptAtMs);
60960
+ return declined(
60961
+ unusable ? "timestamp_unusable" : "summary_predates_dispatch",
60962
+ `dispatchTimestamp=${row.dispatchTimestamp ?? "none"} transcriptMessageAt=${evidence.transcriptMessageAt ?? "none"}`
60963
+ );
60875
60964
  }
60876
60965
  if (typeof opts?.minFinalAssistantAgeMs === "number" && opts.minFinalAssistantAgeMs > 0 && Date.now() - transcriptAtMs < opts.minFinalAssistantAgeMs) {
60877
- return null;
60966
+ return declined(
60967
+ "final_assistant_not_settled",
60968
+ `age=${Date.now() - transcriptAtMs}ms < minFinalAssistantAgeMs=${opts.minFinalAssistantAgeMs} \u2014 treated as in-flight narration`
60969
+ );
60878
60970
  }
60971
+ traceMeshEventStage(
60972
+ "poll_terminal_evidence_completed",
60973
+ traceCtx,
60974
+ `idle with final assistant after dispatch \u2014 task is completed, re-drive prevented`
60975
+ );
60879
60976
  return {
60880
60977
  outcome: "completed",
60881
60978
  finalSummary: evidence.finalSummary,
@@ -61002,7 +61099,7 @@ ${cleanBody}`;
61002
61099
  ...force ? { force: true } : {}
61003
61100
  });
61004
61101
  }
61005
- function recordHeldTerminalEventsToLedger(meshId, drainDaemonIds, reason, heldForCoordinatorCount) {
61102
+ function recordHeldTerminalEventsToLedger(meshId, drainDaemonIds, reason, heldForCoordinatorCount, strictRoutedFingerprints) {
61006
61103
  let pending;
61007
61104
  try {
61008
61105
  pending = getPendingMeshCoordinatorEvents(meshId, drainDaemonIds.length > 0 ? drainDaemonIds : void 0);
@@ -61010,6 +61107,7 @@ ${cleanBody}`;
61010
61107
  return;
61011
61108
  }
61012
61109
  for (const event of pending) {
61110
+ if (strictRoutedFingerprints?.has(buildPendingEventFingerprint(event))) continue;
61013
61111
  if (!shouldForceInjectMeshEvent(event.event)) continue;
61014
61112
  const fingerprint = buildPendingEventFingerprint(event);
61015
61113
  const key2 = `${meshId}::${fingerprint || `${event.event}::${event.nodeId || ""}::${event.queuedAt}`}`;
@@ -62089,6 +62187,7 @@ ${cleanBody}`;
62089
62187
  meshCoordinators.map((c) => readNonEmptyString(c.sessionId)).filter(Boolean)
62090
62188
  );
62091
62189
  let orphanEscaped = 0;
62190
+ const strictRoutedFingerprints = /* @__PURE__ */ new Set();
62092
62191
  const hasPendingForOrphanPeek = !store || (() => {
62093
62192
  try {
62094
62193
  return store.pendingEventCount(meshId) > 0;
@@ -62123,10 +62222,11 @@ ${cleanBody}`;
62123
62222
  for (const pending of drained) {
62124
62223
  if (isOrphan(pending)) {
62125
62224
  holdOrExpireStrictUnmatchedEvent(pending, readNonEmptyString(pending.targetCoordinatorSessionId), meshId);
62225
+ strictRoutedFingerprints.add(buildPendingEventFingerprint(pending));
62126
62226
  orphanEscaped++;
62127
62227
  } else {
62128
62228
  try {
62129
- queuePendingMeshCoordinatorEvent(pending);
62229
+ requeueDrainedPendingMeshCoordinatorEvent(pending);
62130
62230
  } catch {
62131
62231
  }
62132
62232
  }
@@ -62149,7 +62249,8 @@ ${cleanBody}`;
62149
62249
  meshId,
62150
62250
  drainDaemonIds.length > 0 ? drainDaemonIds : localDaemonId ? [localDaemonId] : [],
62151
62251
  "modal_parked",
62152
- modalParkedCoordinators.length
62252
+ modalParkedCoordinators.length,
62253
+ strictRoutedFingerprints
62153
62254
  );
62154
62255
  }
62155
62256
  } else if (generatingCoordinators.length > 0) {
@@ -62208,15 +62309,15 @@ ${cleanBody}`;
62208
62309
  const queuedAt = typeof pending.queuedAt === "number" ? pending.queuedAt : Date.now();
62209
62310
  if (Date.now() - queuedAt <= STRICT_SESSION_MATCH_TTL_MS) {
62210
62311
  try {
62211
- queuePendingMeshCoordinatorEvent(pending);
62212
- LOG2.info("MeshReconcile", `Strict route hold: coordinator session ${wantSession} not live on mesh ${meshId} \u2014 re-queued (${pending.event})`);
62312
+ const requeued = requeueDrainedPendingMeshCoordinatorEvent(pending);
62313
+ 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
62314
  traceMeshEventDrop("strict_route_hold", {
62214
62315
  taskId: pending.metadataEvent?.taskId,
62215
62316
  sessionId: pending.metadataEvent?.targetSessionId ?? wantSession,
62216
62317
  nodeId: pending.nodeId,
62217
62318
  meshId,
62218
62319
  event: pending.event
62219
- }, `coordinatorSession=${wantSession} not live`);
62320
+ }, `coordinatorSession=${wantSession} not live durable=${requeued}`);
62220
62321
  } catch (e) {
62221
62322
  LOG2.warn("MeshReconcile", `Strict route re-queue failed for ${pending.event} on mesh ${meshId}: ${e?.message || e}`);
62222
62323
  }