@adhdev/daemon-core 0.9.82-rc.430 → 0.9.82-rc.432

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
@@ -409,10 +409,10 @@ function readInjected(value) {
409
409
  }
410
410
  function getDaemonBuildInfo() {
411
411
  if (cached) return cached;
412
- const commit = readInjected(true ? "c7dba412b544423c5eee2bac9e1004739ecab503" : void 0) ?? "unknown";
413
- const commitShort = readInjected(true ? "c7dba412" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
414
- const version = readInjected(true ? "0.9.82-rc.430" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
415
- const builtAt = readInjected(true ? "2026-06-30T05:29:05.430Z" : void 0);
412
+ const commit = readInjected(true ? "818d857089de19d818903a7a416b3f84ccb594e3" : void 0) ?? "unknown";
413
+ const commitShort = readInjected(true ? "818d8570" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
414
+ const version = readInjected(true ? "0.9.82-rc.432" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
415
+ const builtAt = readInjected(true ? "2026-06-30T07:51:07.054Z" : void 0);
416
416
  cached = builtAt ? { commit, commitShort, version, builtAt } : { commit, commitShort, version };
417
417
  return cached;
418
418
  }
@@ -16782,7 +16782,9 @@ function flushPendingForMeshIdleCoordinators(components, meshId) {
16782
16782
  if (readNonEmptyString2(settings.meshCoordinatorFor) !== meshId) continue;
16783
16783
  const status = readNonEmptyString2(state.status).toLowerCase();
16784
16784
  const modalParked = typeof inst.isModalParked === "function" ? inst.isModalParked() === true : status === "waiting_choice" || status === "waiting_approval";
16785
- if (status === "idle" && !modalParked) {
16785
+ const drainStatus = typeof inst.getDrainStatus === "function" ? inst.getDrainStatus() : null;
16786
+ const idle = drainStatus !== null ? drainStatus === "idle" : status === "idle";
16787
+ if (idle && !modalParked) {
16786
16788
  idleCoordinators.push({ instance: inst, sessionId: readNonEmptyString2(state.instanceId) });
16787
16789
  }
16788
16790
  }
@@ -16955,6 +16957,9 @@ function resolveAutoPruneMinAgeMs() {
16955
16957
  }
16956
16958
  return DEFAULT_AUTO_PRUNE_MIN_AGE_MS;
16957
16959
  }
16960
+ function resolvePendingHeldDrainEscalateMs() {
16961
+ return resolveTunedReconcileMs("MESH_PENDING_HELD_DRAIN_ESCALATE_MS", DEFAULT_PENDING_HELD_DRAIN_ESCALATE_MS, 4e3, 5 * 6e4);
16962
+ }
16958
16963
  function resolveReconcileIntervalMs() {
16959
16964
  const raw = readNonEmptyString2(process.env.MESH_RECONCILE_INTERVAL_MS);
16960
16965
  if (raw) {
@@ -17017,6 +17022,8 @@ function findLiveCoordinators(components) {
17017
17022
  if (!meshId) continue;
17018
17023
  const status = readNonEmptyString2(state.status).toLowerCase();
17019
17024
  const modalParked = typeof inst.isModalParked === "function" ? inst.isModalParked() === true : status === "waiting_choice" || status === "waiting_approval";
17025
+ const drainStatus = typeof inst.getDrainStatus === "function" ? inst.getDrainStatus() : null;
17026
+ const idle = drainStatus !== null ? drainStatus === "idle" : status === "idle";
17020
17027
  const sessionId = readNonEmptyString2(state.instanceId);
17021
17028
  if (getLogLevel() === "debug") {
17022
17029
  let adapterRaw = "?";
@@ -17031,7 +17038,7 @@ function findLiveCoordinators(components) {
17031
17038
  const lastStatus = readNonEmptyString2(inst.lastStatus) || "?";
17032
17039
  const autoApproveBusy = inst.autoApproveBusy;
17033
17040
  const maskSince = inst.autoApproveMaskSince;
17034
- LOG.debug("MeshReconcile", `coordDiag sess=${sessionId || "?"} mesh=${meshId} getState=${status || "?"} lastStatus=${lastStatus} adapterRaw=${adapterRaw} autoApproveBusy=${autoApproveBusy === true} maskSince=${maskSince || 0}`);
17041
+ LOG.debug("MeshReconcile", `coordDiag sess=${sessionId || "?"} mesh=${meshId} getState=${status || "?"} drainStatus=${drainStatus || "n/a"} lastStatus=${lastStatus} adapterRaw=${adapterRaw} autoApproveBusy=${autoApproveBusy === true} maskSince=${maskSince || 0}`);
17035
17042
  }
17036
17043
  const stateKey = `${meshId}::${sessionId || "?"}`;
17037
17044
  const prevParked = coordinatorModalParkState.get(stateKey);
@@ -17043,7 +17050,7 @@ function findLiveCoordinators(components) {
17043
17050
  LOG.info("MeshReconcile", `Coordinator ${sessionId || "?"} (mesh ${meshId}) left modal-park (status=${status}) \u2014 held events will drain on this/next tick`);
17044
17051
  }
17045
17052
  }
17046
- out.push({ meshId, instance: inst, sessionId, idle: status === "idle", modalParked });
17053
+ out.push({ meshId, instance: inst, sessionId, idle, modalParked });
17047
17054
  }
17048
17055
  return out;
17049
17056
  }
@@ -17138,6 +17145,63 @@ function recordHeldTerminalEventsToLedger(meshId, drainDaemonIds, reason, heldFo
17138
17145
  }
17139
17146
  }
17140
17147
  }
17148
+ function oldestHeldTerminalEventAgeMs(meshId, drainDaemonIds) {
17149
+ let pending;
17150
+ try {
17151
+ pending = getPendingMeshCoordinatorEvents(meshId, drainDaemonIds.length > 0 ? drainDaemonIds : void 0);
17152
+ } catch {
17153
+ return 0;
17154
+ }
17155
+ const now = Date.now();
17156
+ let maxAge = 0;
17157
+ for (const event of pending) {
17158
+ if (!shouldForceInjectMeshEvent(event.event)) continue;
17159
+ const queuedAt = typeof event.queuedAt === "number" ? event.queuedAt : now;
17160
+ const age = now - queuedAt;
17161
+ if (age > maxAge) maxAge = age;
17162
+ }
17163
+ return maxAge;
17164
+ }
17165
+ function reconfirmGenuinelyIdleCoordinators(generating) {
17166
+ const out = [];
17167
+ for (const c of generating) {
17168
+ const inst = c.instance;
17169
+ const drainStatus = typeof inst?.getDrainStatus === "function" ? inst.getDrainStatus() : null;
17170
+ const genuinelyIdle = drainStatus !== null ? drainStatus === "idle" : c.idle;
17171
+ if (genuinelyIdle) out.push({ ...c, idle: true });
17172
+ }
17173
+ return out;
17174
+ }
17175
+ function drainAndInjectIntoTargets(meshId, drainDaemonIds, localDaemonId, targetCoordinators, logLabel) {
17176
+ let pendingEvents = [];
17177
+ try {
17178
+ pendingEvents = drainPendingMeshCoordinatorEvents(
17179
+ meshId,
17180
+ drainDaemonIds.length > 0 ? drainDaemonIds : localDaemonId
17181
+ );
17182
+ } catch (e) {
17183
+ LOG.warn("MeshReconcile", `Drain failed for mesh ${meshId}: ${e?.message || e}`);
17184
+ return 0;
17185
+ }
17186
+ if (pendingEvents.length === 0) return 0;
17187
+ LOG.info("MeshReconcile", `Reconcile inject \u2192 ${logLabel}: ${pendingEvents.length} pending event(s) \u2192 ${targetCoordinators.length} coordinator(s) for mesh ${meshId}`);
17188
+ for (const pending of pendingEvents) {
17189
+ const wantSession = readNonEmptyString2(pending.targetCoordinatorSessionId);
17190
+ if (wantSession) {
17191
+ const matched = targetCoordinators.filter((c) => c.sessionId === wantSession);
17192
+ if (matched.length === 0) {
17193
+ holdOrExpireStrictUnmatchedEvent(pending, wantSession, meshId);
17194
+ continue;
17195
+ }
17196
+ for (const c of matched) injectPendingIntoCoordinator(c.instance, pending);
17197
+ continue;
17198
+ }
17199
+ for (const c of targetCoordinators) {
17200
+ injectPendingIntoCoordinator(c.instance, pending);
17201
+ }
17202
+ }
17203
+ return pendingEvents.length;
17204
+ }
17141
17205
  function recoverStrandedAssignedDispatches(meshId, store) {
17142
17206
  const assigned = getQueue(meshId, { status: ["assigned"] });
17143
17207
  if (!assigned.length) return;
@@ -17349,6 +17413,19 @@ async function runMeshReconcileTick(components) {
17349
17413
  }
17350
17414
  }
17351
17415
  if (hasPending) {
17416
+ const escalateMs = resolvePendingHeldDrainEscalateMs();
17417
+ const heldAgeMs = oldestHeldTerminalEventAgeMs(
17418
+ meshId,
17419
+ drainDaemonIds.length > 0 ? drainDaemonIds : localDaemonId ? [localDaemonId] : []
17420
+ );
17421
+ if (heldAgeMs >= escalateMs) {
17422
+ const escapeTargets = reconfirmGenuinelyIdleCoordinators(generatingCoordinators);
17423
+ if (escapeTargets.length > 0) {
17424
+ LOG.info("MeshReconcile", `Reconcile age-escape \u2192 generating-hold: held terminal event(s) for mesh ${meshId} aged ${Math.round(heldAgeMs / 1e3)}s (\u2265 ${Math.round(escalateMs / 1e3)}s) and ${escapeTargets.length} coordinator(s) re-confirmed genuinely idle on the raw adapter \u2014 draining once`);
17425
+ const drained = drainAndInjectIntoTargets(meshId, drainDaemonIds, localDaemonId, escapeTargets, "age-escape");
17426
+ if (drained > 0) continue;
17427
+ }
17428
+ }
17352
17429
  LOG.info("MeshReconcile", `Reconcile skip \u2192 generating: holding pending event(s) for mesh ${meshId} (${generatingCoordinators.length} coordinator(s) busy; events left queued for the next idle tick)`);
17353
17430
  if (getLogLevel() === "debug") {
17354
17431
  LOG.debug("MeshReconcile", `coordHoldGenerating mesh=${meshId} heldFor=[${generatingCoordinators.map((c) => c.sessionId || "?").join(",")}] (these were classified busy; cross-ref same-tick coordDiag by sessionId)`);
@@ -17369,33 +17446,7 @@ async function runMeshReconcileTick(components) {
17369
17446
  } catch {
17370
17447
  }
17371
17448
  }
17372
- let pendingEvents = [];
17373
- try {
17374
- pendingEvents = drainPendingMeshCoordinatorEvents(
17375
- meshId,
17376
- drainDaemonIds.length > 0 ? drainDaemonIds : localDaemonId
17377
- );
17378
- } catch (e) {
17379
- LOG.warn("MeshReconcile", `Drain failed for mesh ${meshId}: ${e?.message || e}`);
17380
- continue;
17381
- }
17382
- if (pendingEvents.length === 0) continue;
17383
- LOG.info("MeshReconcile", `Reconcile inject \u2192 idle: ${pendingEvents.length} pending event(s) \u2192 ${targetCoordinators.length} coordinator(s) for mesh ${meshId}`);
17384
- for (const pending of pendingEvents) {
17385
- const wantSession = readNonEmptyString2(pending.targetCoordinatorSessionId);
17386
- if (wantSession) {
17387
- const matched = targetCoordinators.filter((c) => c.sessionId === wantSession);
17388
- if (matched.length === 0) {
17389
- holdOrExpireStrictUnmatchedEvent(pending, wantSession, meshId);
17390
- continue;
17391
- }
17392
- for (const c of matched) injectPendingIntoCoordinator(c.instance, pending);
17393
- continue;
17394
- }
17395
- for (const c of targetCoordinators) {
17396
- injectPendingIntoCoordinator(c.instance, pending);
17397
- }
17398
- }
17449
+ drainAndInjectIntoTargets(meshId, drainDaemonIds, localDaemonId, targetCoordinators, "idle");
17399
17450
  }
17400
17451
  }
17401
17452
  function holdOrExpireStrictUnmatchedEvent(pending, wantSession, meshId) {
@@ -17845,7 +17896,7 @@ function setupMeshReconcileLoop(components) {
17845
17896
  }
17846
17897
  };
17847
17898
  }
17848
- var DEFAULT_RECONCILE_INTERVAL_MS, DEFAULT_AUTO_PRUNE_MIN_AGE_MS, ACKED_DEATH_CONSECUTIVE_READ_FAILURES, inFlightAckedHoldState, coordinatorModalParkState, heldEventLedgerRecorded, ASSIGNED_STRANDED_DEADLINE_MS, STRICT_SESSION_MATCH_TTL_MS, unresolvedForwardRejectionCounts, MAX_FORWARD_REJECTIONS;
17899
+ var DEFAULT_RECONCILE_INTERVAL_MS, DEFAULT_AUTO_PRUNE_MIN_AGE_MS, DEFAULT_PENDING_HELD_DRAIN_ESCALATE_MS, ACKED_DEATH_CONSECUTIVE_READ_FAILURES, inFlightAckedHoldState, coordinatorModalParkState, heldEventLedgerRecorded, ASSIGNED_STRANDED_DEADLINE_MS, STRICT_SESSION_MATCH_TTL_MS, unresolvedForwardRejectionCounts, MAX_FORWARD_REJECTIONS;
17849
17900
  var init_mesh_reconcile_loop = __esm({
17850
17901
  "src/mesh/mesh-reconcile-loop.ts"() {
17851
17902
  "use strict";
@@ -17867,6 +17918,7 @@ var init_mesh_reconcile_loop = __esm({
17867
17918
  init_chat_message_normalization();
17868
17919
  DEFAULT_RECONCILE_INTERVAL_MS = 4e3;
17869
17920
  DEFAULT_AUTO_PRUNE_MIN_AGE_MS = 24 * 60 * 6e4;
17921
+ DEFAULT_PENDING_HELD_DRAIN_ESCALATE_MS = 12e3;
17870
17922
  ACKED_DEATH_CONSECUTIVE_READ_FAILURES = 3;
17871
17923
  inFlightAckedHoldState = /* @__PURE__ */ new Map();
17872
17924
  coordinatorModalParkState = /* @__PURE__ */ new Map();
@@ -41239,6 +41291,49 @@ var CliProviderInstance = class _CliProviderInstance {
41239
41291
  isModalParked() {
41240
41292
  return this.resolveModalParkStatus() !== null;
41241
41293
  }
41294
+ /**
41295
+ * PTY-OVERTRUST-DRAIN (Defect B). The deliverability/drain status the mesh
41296
+ * reconcile loop must consult — the RAW adapter turn-state, with the
41297
+ * auto-approve "hold-idle" visual mask STRIPPED.
41298
+ *
41299
+ * getState().status overlays `autoApproveHoldIdle`/`autoApproveActive` to paint a
41300
+ * genuinely-idle adapter as `generating` (a UI-flicker suppression while an
41301
+ * auto-approve key-press settles — see getState() ~:800). That mask is correct
41302
+ * for the dashboard, but the reconcile loop trusts it as "the coordinator is
41303
+ * busy" and therefore HOLDS a worker's completion under
41304
+ * `generating_no_idle_coordinator` even though the coordinator's PTY is at a real
41305
+ * turn end and would accept the inject as a turn — the completion is stranded.
41306
+ *
41307
+ * This accessor reports the drain truth instead:
41308
+ * - 'modal_parked' — a GENUINE human-await modal (AskUserQuestion / a non-
41309
+ * transient tool-consent). Still excluded from drain (a force-inject here
41310
+ * writes raw keystrokes the modal eats → data corruption). Mirrors
41311
+ * isModalParked(), evaluated first so a parked session never reads idle.
41312
+ * - 'idle' — the RAW adapter is at a turn end (adapter.getStatus(allowParse:false)
41313
+ * === 'idle') and the session is not modal-parked. Drain-eligible REGARDLESS
41314
+ * of the auto-approve mask. This is the case the mask used to hide.
41315
+ * - 'generating' — the raw adapter is genuinely mid-turn. Held (a raw PTY write
41316
+ * into a generating claude-cli is not consumed as a turn → data loss). The
41317
+ * intentional removal of force-inject-into-generating is preserved.
41318
+ * - 'other' — any other raw status (error / starting / waiting_choice handled by
41319
+ * modal-park above). Not a drain target.
41320
+ *
41321
+ * Uses allowParse:false (engine.activeModal only, side-effect-free) so it never
41322
+ * mutates the very auto-approve mask state the diagnostics read.
41323
+ */
41324
+ getDrainStatus() {
41325
+ if (this.isModalParked()) return "modal_parked";
41326
+ let rawStatus;
41327
+ try {
41328
+ const raw = this.adapter.getStatus({ allowParse: false })?.status;
41329
+ rawStatus = typeof raw === "string" ? raw.trim() : "";
41330
+ } catch {
41331
+ return "other";
41332
+ }
41333
+ if (rawStatus === "idle") return "idle";
41334
+ if (isCliGeneratingLikeStatus(rawStatus)) return "generating";
41335
+ return "other";
41336
+ }
41242
41337
  onEvent(event, data) {
41243
41338
  if (event === "send_message") {
41244
41339
  const input = normalizeInputEnvelope(data);