@adhdev/daemon-core 0.9.82-rc.556 → 0.9.82-rc.558

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.mjs CHANGED
@@ -423,10 +423,10 @@ function readInjected(value) {
423
423
  }
424
424
  function getDaemonBuildInfo() {
425
425
  if (cached) return cached;
426
- const commit = readInjected(true ? "be22dd93c4d346e18a1c16b2d451c0b3d085e5e3" : void 0) ?? "unknown";
427
- const commitShort = readInjected(true ? "be22dd93" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
428
- const version = readInjected(true ? "0.9.82-rc.556" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
429
- const builtAt = readInjected(true ? "2026-07-17T09:34:20.876Z" : void 0);
426
+ const commit = readInjected(true ? "97717181f86a63a5331c149f92111ee72088620c" : void 0) ?? "unknown";
427
+ const commitShort = readInjected(true ? "97717181" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
428
+ const version = readInjected(true ? "0.9.82-rc.558" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
429
+ const builtAt = readInjected(true ? "2026-07-17T12:19:20.741Z" : void 0);
430
430
  cached = builtAt ? { commit, commitShort, version, builtAt } : { commit, commitShort, version };
431
431
  return cached;
432
432
  }
@@ -47271,9 +47271,30 @@ var CliProviderInstance = class _CliProviderInstance {
47271
47271
  // event. Unlike the StatusMonitor no-progress watchdog (which only runs while a
47272
47272
  // turn is generating), this observes pure screen stasis regardless of the
47273
47273
  // reported status — a worker parked idle, wedged mid-turn, or spawned with no
47274
- // output at all. 180s matches DEFAULT_MONITOR_CONFIG.noProgressThresholdSec so
47275
- // the two watchdogs agree on the same "long interval" bound.
47276
- static MESH_WORKER_STALL_THRESHOLD_MS = 18e4;
47274
+ // output at all.
47275
+ //
47276
+ // FALSE-STALL-WATCHDOG-OVERFIRE (fix C): the threshold is now turn-scoped. When
47277
+ // an explicit turn is in flight (hasAdapterPendingResponse() — the adapter's
47278
+ // currentTurnScope / isWaitingForResponse / isProcessing / partial buffer), a
47279
+ // long silent thinking gap (claude-cli opus/high can go minutes between visible
47280
+ // tokens) is normal, so the bar is raised to MESH_WORKER_STALL_TURN_THRESHOLD_MS.
47281
+ // Outside a turn (idle) the tighter MESH_WORKER_STALL_IDLE_THRESHOLD_MS applies.
47282
+ // This is a THRESHOLD RAISE, not a suppression: a genuine mid-turn wedge still
47283
+ // fires (late, at the turn bound) rather than being hidden behind a sticky
47284
+ // generating status. 180s matches DEFAULT_MONITOR_CONFIG.noProgressThresholdSec
47285
+ // so the idle bound agrees with the StatusMonitor watchdog's "long interval".
47286
+ static MESH_WORKER_STALL_IDLE_THRESHOLD_MS = 18e4;
47287
+ static MESH_WORKER_STALL_TURN_THRESHOLD_MS = 36e4;
47288
+ // FALSE-STALL-WATCHDOG-OVERFIRE (fix E): minimum spacing between two stall
47289
+ // notifications for the SAME session, even across anchor re-arms. The
47290
+ // per-anchor meshStallEmittedForAnchor guard already stops a single continuous
47291
+ // stall from re-firing; this cooldown additionally throttles the churn where a
47292
+ // worker dribbles one byte every few minutes (each re-arming the anchor and then
47293
+ // re-crossing the bar), which would otherwise page the coordinator repeatedly.
47294
+ // The stall is still fired for observability — just not more than once per
47295
+ // window per session. Set larger than the stall thresholds so consecutive
47296
+ // re-armed stalls a few minutes apart collapse into a single notification.
47297
+ static MESH_WORKER_STALL_REFIRE_COOLDOWN_MS = 6e5;
47277
47298
  adapter;
47278
47299
  context = null;
47279
47300
  events = [];
@@ -47297,6 +47318,18 @@ var CliProviderInstance = class _CliProviderInstance {
47297
47318
  // -1 = not yet initialised for this session.
47298
47319
  meshStallAnchorAt = -1;
47299
47320
  meshStallEmittedForAnchor = false;
47321
+ // FALSE-STALL-WATCHDOG-OVERFIRE (fix B): the turn-active state observed on the
47322
+ // PREVIOUS stall tick. When a turn ends (active → inactive: the completion/idle
47323
+ // transition), the anchor is force re-armed to `now` so the completed→idle valley
47324
+ // does not fire against the pre-completion output clock. The turn-end edge is the
47325
+ // signal; updateStatus's own idle transition does not touch the stall anchor, so
47326
+ // this watchdog-local edge detector owns the re-arm. undefined = no prior tick.
47327
+ meshStallTurnActiveLast = void 0;
47328
+ // FALSE-STALL-WATCHDOG-OVERFIRE (fix E): wall-clock of the most recent stall
47329
+ // emission for this session, or -1 if none. Enforces
47330
+ // MESH_WORKER_STALL_REFIRE_COOLDOWN_MS between successive emissions across
47331
+ // anchor re-arms (the per-anchor guard only covers a single continuous stall).
47332
+ meshStallLastFiredAt = -1;
47300
47333
  // FALSE-IDLE continuity epoch: monotonically bumped on EVERY entry into a busy
47301
47334
  // phase (→generating or →waiting_approval). The completedDebouncePending snapshots
47302
47335
  // this value at arm time (busyEpochAtArm); the flush guard requires it UNCHANGED
@@ -48548,43 +48581,62 @@ var CliProviderInstance = class _CliProviderInstance {
48548
48581
  * ProviderInstanceManager's existing 5s onTick loop (NO new timer) — see
48549
48582
  * ProviderInstanceManager.startTicking. Reuses the adapter's raw-PTY-output
48550
48583
  * clock (lastOutputAt, bumped on every output chunk) as the sole signal: if a
48551
- * live worker's screen has been byte-for-byte unchanged for
48552
- * MESH_WORKER_STALL_THRESHOLD_MS (180s), fire ONE informational
48553
- * monitor:no_progress event down the existing task_stalled ledger +
48554
- * pendingCoordinatorEvent path.
48584
+ * live worker's screen has been byte-for-byte unchanged past the turn-scoped
48585
+ * threshold (below), fire ONE informational monitor:no_progress event down the
48586
+ * existing task_stalled ledger + pendingCoordinatorEvent path.
48555
48587
  *
48556
- * Deliberately status-agnostic: it does NOT read getStatus()'s reported status
48557
- * (which would couple it to the generating-only StatusMonitor and the
48558
- * idle-timeout FSM). A normally-idle worker CAN trip this after 3 quiet
48559
- * minutes; that is accepted and surfaced as an informational stall (NOT a
48560
- * failure/auto-restart) so the coordinator judges. getStatus/getState are NOT
48561
- * called here, so status heartbeats never move the stall anchor.
48588
+ * The reported status is read for TWO bounded purposes only — it does NOT
48589
+ * suppress the fire (sticky-status blindness would hide a real wedge):
48590
+ * Fix B (anchor re-arm on turn end): the FSM's completion/idle transition
48591
+ * never touches the stall anchor, so a completed worker that goes idle would
48592
+ * otherwise keep counting from its LAST pre-completion output and false-fire
48593
+ * in the quiet valley right after finishing. We detect the turn-active edge
48594
+ * (hasAdapterPendingResponse()) and, on active → inactive, re-arm the anchor
48595
+ * to `now` so the post-completion idle valley starts a fresh clock.
48596
+ * • Fix C (turn-scoped threshold): while a turn is genuinely in flight the bar
48597
+ * is raised (MESH_WORKER_STALL_TURN_THRESHOLD_MS) to absorb long normal
48598
+ * thinking gaps; outside a turn the tighter idle bound applies. This is a
48599
+ * RAISE, not a skip — a real mid-turn wedge still fires late at the turn bound.
48562
48600
  *
48563
48601
  * Anchoring: the episode arms against the current lastOutputAt; a worker that
48564
48602
  * has emitted nothing yet (lastOutputAt === 0) anchors on this.startedAt (spawn
48565
48603
  * time) so a silent spawn is still caught. Any new output re-arms the anchor
48566
48604
  * and clears the emitted flag, so one continuous stall emits at most once and a
48567
- * later stall re-arms cleanly.
48605
+ * later stall re-arms cleanly. Fix E adds a per-session refire cooldown so a
48606
+ * dribble of one-byte-per-few-minutes output cannot page the coordinator on
48607
+ * every re-arm.
48568
48608
  */
48569
48609
  checkMeshWorkerStall(now = Date.now()) {
48570
48610
  if (!this.isMeshWorkerSession()) {
48571
- this.meshStallAnchorAt = -1;
48572
- this.meshStallEmittedForAnchor = false;
48611
+ this.resetMeshStallEpisode();
48573
48612
  return;
48574
48613
  }
48575
48614
  if (typeof this.adapter.isAlive === "function" && !this.adapter.isAlive()) {
48576
- this.meshStallAnchorAt = -1;
48577
- this.meshStallEmittedForAnchor = false;
48615
+ this.resetMeshStallEpisode();
48578
48616
  return;
48579
48617
  }
48580
48618
  let lastOutputAt;
48619
+ let observedStatus = "unknown";
48581
48620
  try {
48582
48621
  const status = this.adapter.getStatus({ allowParse: false });
48583
48622
  lastOutputAt = typeof status?.lastOutputAt === "number" && Number.isFinite(status.lastOutputAt) ? status.lastOutputAt : 0;
48623
+ if (typeof status?.status === "string" && status.status) observedStatus = status.status;
48584
48624
  } catch {
48585
48625
  return;
48586
48626
  }
48627
+ let turnActive = false;
48628
+ try {
48629
+ turnActive = this.hasAdapterPendingResponse();
48630
+ } catch {
48631
+ }
48632
+ const turnEnded = this.meshStallTurnActiveLast === true && !turnActive;
48633
+ this.meshStallTurnActiveLast = turnActive;
48587
48634
  const anchor = lastOutputAt > 0 ? lastOutputAt : this.startedAt;
48635
+ if (turnEnded && this.meshStallAnchorAt !== -1) {
48636
+ this.meshStallAnchorAt = Math.max(anchor, now);
48637
+ this.meshStallEmittedForAnchor = false;
48638
+ return;
48639
+ }
48588
48640
  if (this.meshStallAnchorAt === -1) {
48589
48641
  this.meshStallAnchorAt = anchor;
48590
48642
  this.meshStallEmittedForAnchor = false;
@@ -48596,15 +48648,14 @@ var CliProviderInstance = class _CliProviderInstance {
48596
48648
  return;
48597
48649
  }
48598
48650
  if (this.meshStallEmittedForAnchor) return;
48651
+ const threshold = turnActive ? _CliProviderInstance.MESH_WORKER_STALL_TURN_THRESHOLD_MS : _CliProviderInstance.MESH_WORKER_STALL_IDLE_THRESHOLD_MS;
48599
48652
  const stalledMs = now - this.meshStallAnchorAt;
48600
- if (stalledMs < _CliProviderInstance.MESH_WORKER_STALL_THRESHOLD_MS) return;
48653
+ if (stalledMs < threshold) return;
48601
48654
  this.meshStallEmittedForAnchor = true;
48602
- let observedStatus = "unknown";
48603
- try {
48604
- const s2 = this.adapter.getStatus({ allowParse: false })?.status;
48605
- if (typeof s2 === "string" && s2) observedStatus = s2;
48606
- } catch {
48655
+ if (this.meshStallLastFiredAt >= 0 && now - this.meshStallLastFiredAt < _CliProviderInstance.MESH_WORKER_STALL_REFIRE_COOLDOWN_MS) {
48656
+ return;
48607
48657
  }
48658
+ this.meshStallLastFiredAt = now;
48608
48659
  if (this.isMeshWorkerSession()) {
48609
48660
  traceMeshEventStage("fired", this.meshTraceCtx("monitor:no_progress"), "mesh_worker_stall_watchdog");
48610
48661
  }
@@ -48624,6 +48675,19 @@ var CliProviderInstance = class _CliProviderInstance {
48624
48675
  taskId: this.completingTurnTaskId()
48625
48676
  });
48626
48677
  }
48678
+ /**
48679
+ * FALSE-STALL-WATCHDOG-OVERFIRE: drop the entire stall episode for this session.
48680
+ * Called when the session is no longer a mesh worker or the PTY is dead — the
48681
+ * next live tick re-arms a fresh episode. Clears the fix-B turn-edge state and
48682
+ * the fix-E refire cooldown alongside the base anchor so a re-armed session
48683
+ * starts with a clean slate (a restart is not throttled by a prior stall).
48684
+ */
48685
+ resetMeshStallEpisode() {
48686
+ this.meshStallAnchorAt = -1;
48687
+ this.meshStallEmittedForAnchor = false;
48688
+ this.meshStallTurnActiveLast = void 0;
48689
+ this.meshStallLastFiredAt = -1;
48690
+ }
48627
48691
  /**
48628
48692
  * AUTOAPPROVE-FLAP-RECUR (Fix A+B): how long a busy blip / modal scroll-out may
48629
48693
  * persist before the in-progress settle gate is torn down. For a delegated