@adhdev/daemon-standalone 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.js CHANGED
@@ -30217,10 +30217,10 @@ var require_dist3 = __commonJS({
30217
30217
  }
30218
30218
  function getDaemonBuildInfo() {
30219
30219
  if (cached2) return cached2;
30220
- const commit = readInjected(true ? "be22dd93c4d346e18a1c16b2d451c0b3d085e5e3" : void 0) ?? "unknown";
30221
- const commitShort = readInjected(true ? "be22dd93" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
30222
- const version2 = readInjected(true ? "0.9.82-rc.556" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
30223
- const builtAt = readInjected(true ? "2026-07-17T09:34:59.099Z" : void 0);
30220
+ const commit = readInjected(true ? "97717181f86a63a5331c149f92111ee72088620c" : void 0) ?? "unknown";
30221
+ const commitShort = readInjected(true ? "97717181" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
30222
+ const version2 = readInjected(true ? "0.9.82-rc.558" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
30223
+ const builtAt = readInjected(true ? "2026-07-17T12:23:47.341Z" : void 0);
30224
30224
  cached2 = builtAt ? { commit, commitShort, version: version2, builtAt } : { commit, commitShort, version: version2 };
30225
30225
  return cached2;
30226
30226
  }
@@ -77451,9 +77451,30 @@ ${body}
77451
77451
  // event. Unlike the StatusMonitor no-progress watchdog (which only runs while a
77452
77452
  // turn is generating), this observes pure screen stasis regardless of the
77453
77453
  // reported status — a worker parked idle, wedged mid-turn, or spawned with no
77454
- // output at all. 180s matches DEFAULT_MONITOR_CONFIG.noProgressThresholdSec so
77455
- // the two watchdogs agree on the same "long interval" bound.
77456
- static MESH_WORKER_STALL_THRESHOLD_MS = 18e4;
77454
+ // output at all.
77455
+ //
77456
+ // FALSE-STALL-WATCHDOG-OVERFIRE (fix C): the threshold is now turn-scoped. When
77457
+ // an explicit turn is in flight (hasAdapterPendingResponse() — the adapter's
77458
+ // currentTurnScope / isWaitingForResponse / isProcessing / partial buffer), a
77459
+ // long silent thinking gap (claude-cli opus/high can go minutes between visible
77460
+ // tokens) is normal, so the bar is raised to MESH_WORKER_STALL_TURN_THRESHOLD_MS.
77461
+ // Outside a turn (idle) the tighter MESH_WORKER_STALL_IDLE_THRESHOLD_MS applies.
77462
+ // This is a THRESHOLD RAISE, not a suppression: a genuine mid-turn wedge still
77463
+ // fires (late, at the turn bound) rather than being hidden behind a sticky
77464
+ // generating status. 180s matches DEFAULT_MONITOR_CONFIG.noProgressThresholdSec
77465
+ // so the idle bound agrees with the StatusMonitor watchdog's "long interval".
77466
+ static MESH_WORKER_STALL_IDLE_THRESHOLD_MS = 18e4;
77467
+ static MESH_WORKER_STALL_TURN_THRESHOLD_MS = 36e4;
77468
+ // FALSE-STALL-WATCHDOG-OVERFIRE (fix E): minimum spacing between two stall
77469
+ // notifications for the SAME session, even across anchor re-arms. The
77470
+ // per-anchor meshStallEmittedForAnchor guard already stops a single continuous
77471
+ // stall from re-firing; this cooldown additionally throttles the churn where a
77472
+ // worker dribbles one byte every few minutes (each re-arming the anchor and then
77473
+ // re-crossing the bar), which would otherwise page the coordinator repeatedly.
77474
+ // The stall is still fired for observability — just not more than once per
77475
+ // window per session. Set larger than the stall thresholds so consecutive
77476
+ // re-armed stalls a few minutes apart collapse into a single notification.
77477
+ static MESH_WORKER_STALL_REFIRE_COOLDOWN_MS = 6e5;
77457
77478
  adapter;
77458
77479
  context = null;
77459
77480
  events = [];
@@ -77477,6 +77498,18 @@ ${body}
77477
77498
  // -1 = not yet initialised for this session.
77478
77499
  meshStallAnchorAt = -1;
77479
77500
  meshStallEmittedForAnchor = false;
77501
+ // FALSE-STALL-WATCHDOG-OVERFIRE (fix B): the turn-active state observed on the
77502
+ // PREVIOUS stall tick. When a turn ends (active → inactive: the completion/idle
77503
+ // transition), the anchor is force re-armed to `now` so the completed→idle valley
77504
+ // does not fire against the pre-completion output clock. The turn-end edge is the
77505
+ // signal; updateStatus's own idle transition does not touch the stall anchor, so
77506
+ // this watchdog-local edge detector owns the re-arm. undefined = no prior tick.
77507
+ meshStallTurnActiveLast = void 0;
77508
+ // FALSE-STALL-WATCHDOG-OVERFIRE (fix E): wall-clock of the most recent stall
77509
+ // emission for this session, or -1 if none. Enforces
77510
+ // MESH_WORKER_STALL_REFIRE_COOLDOWN_MS between successive emissions across
77511
+ // anchor re-arms (the per-anchor guard only covers a single continuous stall).
77512
+ meshStallLastFiredAt = -1;
77480
77513
  // FALSE-IDLE continuity epoch: monotonically bumped on EVERY entry into a busy
77481
77514
  // phase (→generating or →waiting_approval). The completedDebouncePending snapshots
77482
77515
  // this value at arm time (busyEpochAtArm); the flush guard requires it UNCHANGED
@@ -78728,43 +78761,62 @@ ${body}
78728
78761
  * ProviderInstanceManager's existing 5s onTick loop (NO new timer) — see
78729
78762
  * ProviderInstanceManager.startTicking. Reuses the adapter's raw-PTY-output
78730
78763
  * clock (lastOutputAt, bumped on every output chunk) as the sole signal: if a
78731
- * live worker's screen has been byte-for-byte unchanged for
78732
- * MESH_WORKER_STALL_THRESHOLD_MS (180s), fire ONE informational
78733
- * monitor:no_progress event down the existing task_stalled ledger +
78734
- * pendingCoordinatorEvent path.
78764
+ * live worker's screen has been byte-for-byte unchanged past the turn-scoped
78765
+ * threshold (below), fire ONE informational monitor:no_progress event down the
78766
+ * existing task_stalled ledger + pendingCoordinatorEvent path.
78735
78767
  *
78736
- * Deliberately status-agnostic: it does NOT read getStatus()'s reported status
78737
- * (which would couple it to the generating-only StatusMonitor and the
78738
- * idle-timeout FSM). A normally-idle worker CAN trip this after 3 quiet
78739
- * minutes; that is accepted and surfaced as an informational stall (NOT a
78740
- * failure/auto-restart) so the coordinator judges. getStatus/getState are NOT
78741
- * called here, so status heartbeats never move the stall anchor.
78768
+ * The reported status is read for TWO bounded purposes only — it does NOT
78769
+ * suppress the fire (sticky-status blindness would hide a real wedge):
78770
+ * Fix B (anchor re-arm on turn end): the FSM's completion/idle transition
78771
+ * never touches the stall anchor, so a completed worker that goes idle would
78772
+ * otherwise keep counting from its LAST pre-completion output and false-fire
78773
+ * in the quiet valley right after finishing. We detect the turn-active edge
78774
+ * (hasAdapterPendingResponse()) and, on active → inactive, re-arm the anchor
78775
+ * to `now` so the post-completion idle valley starts a fresh clock.
78776
+ * • Fix C (turn-scoped threshold): while a turn is genuinely in flight the bar
78777
+ * is raised (MESH_WORKER_STALL_TURN_THRESHOLD_MS) to absorb long normal
78778
+ * thinking gaps; outside a turn the tighter idle bound applies. This is a
78779
+ * RAISE, not a skip — a real mid-turn wedge still fires late at the turn bound.
78742
78780
  *
78743
78781
  * Anchoring: the episode arms against the current lastOutputAt; a worker that
78744
78782
  * has emitted nothing yet (lastOutputAt === 0) anchors on this.startedAt (spawn
78745
78783
  * time) so a silent spawn is still caught. Any new output re-arms the anchor
78746
78784
  * and clears the emitted flag, so one continuous stall emits at most once and a
78747
- * later stall re-arms cleanly.
78785
+ * later stall re-arms cleanly. Fix E adds a per-session refire cooldown so a
78786
+ * dribble of one-byte-per-few-minutes output cannot page the coordinator on
78787
+ * every re-arm.
78748
78788
  */
78749
78789
  checkMeshWorkerStall(now = Date.now()) {
78750
78790
  if (!this.isMeshWorkerSession()) {
78751
- this.meshStallAnchorAt = -1;
78752
- this.meshStallEmittedForAnchor = false;
78791
+ this.resetMeshStallEpisode();
78753
78792
  return;
78754
78793
  }
78755
78794
  if (typeof this.adapter.isAlive === "function" && !this.adapter.isAlive()) {
78756
- this.meshStallAnchorAt = -1;
78757
- this.meshStallEmittedForAnchor = false;
78795
+ this.resetMeshStallEpisode();
78758
78796
  return;
78759
78797
  }
78760
78798
  let lastOutputAt;
78799
+ let observedStatus = "unknown";
78761
78800
  try {
78762
78801
  const status = this.adapter.getStatus({ allowParse: false });
78763
78802
  lastOutputAt = typeof status?.lastOutputAt === "number" && Number.isFinite(status.lastOutputAt) ? status.lastOutputAt : 0;
78803
+ if (typeof status?.status === "string" && status.status) observedStatus = status.status;
78764
78804
  } catch {
78765
78805
  return;
78766
78806
  }
78807
+ let turnActive = false;
78808
+ try {
78809
+ turnActive = this.hasAdapterPendingResponse();
78810
+ } catch {
78811
+ }
78812
+ const turnEnded = this.meshStallTurnActiveLast === true && !turnActive;
78813
+ this.meshStallTurnActiveLast = turnActive;
78767
78814
  const anchor = lastOutputAt > 0 ? lastOutputAt : this.startedAt;
78815
+ if (turnEnded && this.meshStallAnchorAt !== -1) {
78816
+ this.meshStallAnchorAt = Math.max(anchor, now);
78817
+ this.meshStallEmittedForAnchor = false;
78818
+ return;
78819
+ }
78768
78820
  if (this.meshStallAnchorAt === -1) {
78769
78821
  this.meshStallAnchorAt = anchor;
78770
78822
  this.meshStallEmittedForAnchor = false;
@@ -78776,15 +78828,14 @@ ${body}
78776
78828
  return;
78777
78829
  }
78778
78830
  if (this.meshStallEmittedForAnchor) return;
78831
+ const threshold = turnActive ? _CliProviderInstance.MESH_WORKER_STALL_TURN_THRESHOLD_MS : _CliProviderInstance.MESH_WORKER_STALL_IDLE_THRESHOLD_MS;
78779
78832
  const stalledMs = now - this.meshStallAnchorAt;
78780
- if (stalledMs < _CliProviderInstance.MESH_WORKER_STALL_THRESHOLD_MS) return;
78833
+ if (stalledMs < threshold) return;
78781
78834
  this.meshStallEmittedForAnchor = true;
78782
- let observedStatus = "unknown";
78783
- try {
78784
- const s2 = this.adapter.getStatus({ allowParse: false })?.status;
78785
- if (typeof s2 === "string" && s2) observedStatus = s2;
78786
- } catch {
78835
+ if (this.meshStallLastFiredAt >= 0 && now - this.meshStallLastFiredAt < _CliProviderInstance.MESH_WORKER_STALL_REFIRE_COOLDOWN_MS) {
78836
+ return;
78787
78837
  }
78838
+ this.meshStallLastFiredAt = now;
78788
78839
  if (this.isMeshWorkerSession()) {
78789
78840
  traceMeshEventStage("fired", this.meshTraceCtx("monitor:no_progress"), "mesh_worker_stall_watchdog");
78790
78841
  }
@@ -78804,6 +78855,19 @@ ${body}
78804
78855
  taskId: this.completingTurnTaskId()
78805
78856
  });
78806
78857
  }
78858
+ /**
78859
+ * FALSE-STALL-WATCHDOG-OVERFIRE: drop the entire stall episode for this session.
78860
+ * Called when the session is no longer a mesh worker or the PTY is dead — the
78861
+ * next live tick re-arms a fresh episode. Clears the fix-B turn-edge state and
78862
+ * the fix-E refire cooldown alongside the base anchor so a re-armed session
78863
+ * starts with a clean slate (a restart is not throttled by a prior stall).
78864
+ */
78865
+ resetMeshStallEpisode() {
78866
+ this.meshStallAnchorAt = -1;
78867
+ this.meshStallEmittedForAnchor = false;
78868
+ this.meshStallTurnActiveLast = void 0;
78869
+ this.meshStallLastFiredAt = -1;
78870
+ }
78807
78871
  /**
78808
78872
  * AUTOAPPROVE-FLAP-RECUR (Fix A+B): how long a busy blip / modal scroll-out may
78809
78873
  * persist before the in-progress settle gate is torn down. For a delegated