@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.js CHANGED
@@ -428,10 +428,10 @@ function readInjected(value) {
428
428
  }
429
429
  function getDaemonBuildInfo() {
430
430
  if (cached) return cached;
431
- const commit = readInjected(true ? "be22dd93c4d346e18a1c16b2d451c0b3d085e5e3" : void 0) ?? "unknown";
432
- const commitShort = readInjected(true ? "be22dd93" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
433
- const version = readInjected(true ? "0.9.82-rc.556" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
434
- const builtAt = readInjected(true ? "2026-07-17T09:34:20.876Z" : void 0);
431
+ const commit = readInjected(true ? "97717181f86a63a5331c149f92111ee72088620c" : void 0) ?? "unknown";
432
+ const commitShort = readInjected(true ? "97717181" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
433
+ const version = readInjected(true ? "0.9.82-rc.558" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
434
+ const builtAt = readInjected(true ? "2026-07-17T12:19:20.741Z" : void 0);
435
435
  cached = builtAt ? { commit, commitShort, version, builtAt } : { commit, commitShort, version };
436
436
  return cached;
437
437
  }
@@ -47704,9 +47704,30 @@ var CliProviderInstance = class _CliProviderInstance {
47704
47704
  // event. Unlike the StatusMonitor no-progress watchdog (which only runs while a
47705
47705
  // turn is generating), this observes pure screen stasis regardless of the
47706
47706
  // reported status — a worker parked idle, wedged mid-turn, or spawned with no
47707
- // output at all. 180s matches DEFAULT_MONITOR_CONFIG.noProgressThresholdSec so
47708
- // the two watchdogs agree on the same "long interval" bound.
47709
- static MESH_WORKER_STALL_THRESHOLD_MS = 18e4;
47707
+ // output at all.
47708
+ //
47709
+ // FALSE-STALL-WATCHDOG-OVERFIRE (fix C): the threshold is now turn-scoped. When
47710
+ // an explicit turn is in flight (hasAdapterPendingResponse() — the adapter's
47711
+ // currentTurnScope / isWaitingForResponse / isProcessing / partial buffer), a
47712
+ // long silent thinking gap (claude-cli opus/high can go minutes between visible
47713
+ // tokens) is normal, so the bar is raised to MESH_WORKER_STALL_TURN_THRESHOLD_MS.
47714
+ // Outside a turn (idle) the tighter MESH_WORKER_STALL_IDLE_THRESHOLD_MS applies.
47715
+ // This is a THRESHOLD RAISE, not a suppression: a genuine mid-turn wedge still
47716
+ // fires (late, at the turn bound) rather than being hidden behind a sticky
47717
+ // generating status. 180s matches DEFAULT_MONITOR_CONFIG.noProgressThresholdSec
47718
+ // so the idle bound agrees with the StatusMonitor watchdog's "long interval".
47719
+ static MESH_WORKER_STALL_IDLE_THRESHOLD_MS = 18e4;
47720
+ static MESH_WORKER_STALL_TURN_THRESHOLD_MS = 36e4;
47721
+ // FALSE-STALL-WATCHDOG-OVERFIRE (fix E): minimum spacing between two stall
47722
+ // notifications for the SAME session, even across anchor re-arms. The
47723
+ // per-anchor meshStallEmittedForAnchor guard already stops a single continuous
47724
+ // stall from re-firing; this cooldown additionally throttles the churn where a
47725
+ // worker dribbles one byte every few minutes (each re-arming the anchor and then
47726
+ // re-crossing the bar), which would otherwise page the coordinator repeatedly.
47727
+ // The stall is still fired for observability — just not more than once per
47728
+ // window per session. Set larger than the stall thresholds so consecutive
47729
+ // re-armed stalls a few minutes apart collapse into a single notification.
47730
+ static MESH_WORKER_STALL_REFIRE_COOLDOWN_MS = 6e5;
47710
47731
  adapter;
47711
47732
  context = null;
47712
47733
  events = [];
@@ -47730,6 +47751,18 @@ var CliProviderInstance = class _CliProviderInstance {
47730
47751
  // -1 = not yet initialised for this session.
47731
47752
  meshStallAnchorAt = -1;
47732
47753
  meshStallEmittedForAnchor = false;
47754
+ // FALSE-STALL-WATCHDOG-OVERFIRE (fix B): the turn-active state observed on the
47755
+ // PREVIOUS stall tick. When a turn ends (active → inactive: the completion/idle
47756
+ // transition), the anchor is force re-armed to `now` so the completed→idle valley
47757
+ // does not fire against the pre-completion output clock. The turn-end edge is the
47758
+ // signal; updateStatus's own idle transition does not touch the stall anchor, so
47759
+ // this watchdog-local edge detector owns the re-arm. undefined = no prior tick.
47760
+ meshStallTurnActiveLast = void 0;
47761
+ // FALSE-STALL-WATCHDOG-OVERFIRE (fix E): wall-clock of the most recent stall
47762
+ // emission for this session, or -1 if none. Enforces
47763
+ // MESH_WORKER_STALL_REFIRE_COOLDOWN_MS between successive emissions across
47764
+ // anchor re-arms (the per-anchor guard only covers a single continuous stall).
47765
+ meshStallLastFiredAt = -1;
47733
47766
  // FALSE-IDLE continuity epoch: monotonically bumped on EVERY entry into a busy
47734
47767
  // phase (→generating or →waiting_approval). The completedDebouncePending snapshots
47735
47768
  // this value at arm time (busyEpochAtArm); the flush guard requires it UNCHANGED
@@ -48981,43 +49014,62 @@ var CliProviderInstance = class _CliProviderInstance {
48981
49014
  * ProviderInstanceManager's existing 5s onTick loop (NO new timer) — see
48982
49015
  * ProviderInstanceManager.startTicking. Reuses the adapter's raw-PTY-output
48983
49016
  * clock (lastOutputAt, bumped on every output chunk) as the sole signal: if a
48984
- * live worker's screen has been byte-for-byte unchanged for
48985
- * MESH_WORKER_STALL_THRESHOLD_MS (180s), fire ONE informational
48986
- * monitor:no_progress event down the existing task_stalled ledger +
48987
- * pendingCoordinatorEvent path.
49017
+ * live worker's screen has been byte-for-byte unchanged past the turn-scoped
49018
+ * threshold (below), fire ONE informational monitor:no_progress event down the
49019
+ * existing task_stalled ledger + pendingCoordinatorEvent path.
48988
49020
  *
48989
- * Deliberately status-agnostic: it does NOT read getStatus()'s reported status
48990
- * (which would couple it to the generating-only StatusMonitor and the
48991
- * idle-timeout FSM). A normally-idle worker CAN trip this after 3 quiet
48992
- * minutes; that is accepted and surfaced as an informational stall (NOT a
48993
- * failure/auto-restart) so the coordinator judges. getStatus/getState are NOT
48994
- * called here, so status heartbeats never move the stall anchor.
49021
+ * The reported status is read for TWO bounded purposes only — it does NOT
49022
+ * suppress the fire (sticky-status blindness would hide a real wedge):
49023
+ * Fix B (anchor re-arm on turn end): the FSM's completion/idle transition
49024
+ * never touches the stall anchor, so a completed worker that goes idle would
49025
+ * otherwise keep counting from its LAST pre-completion output and false-fire
49026
+ * in the quiet valley right after finishing. We detect the turn-active edge
49027
+ * (hasAdapterPendingResponse()) and, on active → inactive, re-arm the anchor
49028
+ * to `now` so the post-completion idle valley starts a fresh clock.
49029
+ * • Fix C (turn-scoped threshold): while a turn is genuinely in flight the bar
49030
+ * is raised (MESH_WORKER_STALL_TURN_THRESHOLD_MS) to absorb long normal
49031
+ * thinking gaps; outside a turn the tighter idle bound applies. This is a
49032
+ * RAISE, not a skip — a real mid-turn wedge still fires late at the turn bound.
48995
49033
  *
48996
49034
  * Anchoring: the episode arms against the current lastOutputAt; a worker that
48997
49035
  * has emitted nothing yet (lastOutputAt === 0) anchors on this.startedAt (spawn
48998
49036
  * time) so a silent spawn is still caught. Any new output re-arms the anchor
48999
49037
  * and clears the emitted flag, so one continuous stall emits at most once and a
49000
- * later stall re-arms cleanly.
49038
+ * later stall re-arms cleanly. Fix E adds a per-session refire cooldown so a
49039
+ * dribble of one-byte-per-few-minutes output cannot page the coordinator on
49040
+ * every re-arm.
49001
49041
  */
49002
49042
  checkMeshWorkerStall(now = Date.now()) {
49003
49043
  if (!this.isMeshWorkerSession()) {
49004
- this.meshStallAnchorAt = -1;
49005
- this.meshStallEmittedForAnchor = false;
49044
+ this.resetMeshStallEpisode();
49006
49045
  return;
49007
49046
  }
49008
49047
  if (typeof this.adapter.isAlive === "function" && !this.adapter.isAlive()) {
49009
- this.meshStallAnchorAt = -1;
49010
- this.meshStallEmittedForAnchor = false;
49048
+ this.resetMeshStallEpisode();
49011
49049
  return;
49012
49050
  }
49013
49051
  let lastOutputAt;
49052
+ let observedStatus = "unknown";
49014
49053
  try {
49015
49054
  const status = this.adapter.getStatus({ allowParse: false });
49016
49055
  lastOutputAt = typeof status?.lastOutputAt === "number" && Number.isFinite(status.lastOutputAt) ? status.lastOutputAt : 0;
49056
+ if (typeof status?.status === "string" && status.status) observedStatus = status.status;
49017
49057
  } catch {
49018
49058
  return;
49019
49059
  }
49060
+ let turnActive = false;
49061
+ try {
49062
+ turnActive = this.hasAdapterPendingResponse();
49063
+ } catch {
49064
+ }
49065
+ const turnEnded = this.meshStallTurnActiveLast === true && !turnActive;
49066
+ this.meshStallTurnActiveLast = turnActive;
49020
49067
  const anchor = lastOutputAt > 0 ? lastOutputAt : this.startedAt;
49068
+ if (turnEnded && this.meshStallAnchorAt !== -1) {
49069
+ this.meshStallAnchorAt = Math.max(anchor, now);
49070
+ this.meshStallEmittedForAnchor = false;
49071
+ return;
49072
+ }
49021
49073
  if (this.meshStallAnchorAt === -1) {
49022
49074
  this.meshStallAnchorAt = anchor;
49023
49075
  this.meshStallEmittedForAnchor = false;
@@ -49029,15 +49081,14 @@ var CliProviderInstance = class _CliProviderInstance {
49029
49081
  return;
49030
49082
  }
49031
49083
  if (this.meshStallEmittedForAnchor) return;
49084
+ const threshold = turnActive ? _CliProviderInstance.MESH_WORKER_STALL_TURN_THRESHOLD_MS : _CliProviderInstance.MESH_WORKER_STALL_IDLE_THRESHOLD_MS;
49032
49085
  const stalledMs = now - this.meshStallAnchorAt;
49033
- if (stalledMs < _CliProviderInstance.MESH_WORKER_STALL_THRESHOLD_MS) return;
49086
+ if (stalledMs < threshold) return;
49034
49087
  this.meshStallEmittedForAnchor = true;
49035
- let observedStatus = "unknown";
49036
- try {
49037
- const s2 = this.adapter.getStatus({ allowParse: false })?.status;
49038
- if (typeof s2 === "string" && s2) observedStatus = s2;
49039
- } catch {
49088
+ if (this.meshStallLastFiredAt >= 0 && now - this.meshStallLastFiredAt < _CliProviderInstance.MESH_WORKER_STALL_REFIRE_COOLDOWN_MS) {
49089
+ return;
49040
49090
  }
49091
+ this.meshStallLastFiredAt = now;
49041
49092
  if (this.isMeshWorkerSession()) {
49042
49093
  traceMeshEventStage("fired", this.meshTraceCtx("monitor:no_progress"), "mesh_worker_stall_watchdog");
49043
49094
  }
@@ -49057,6 +49108,19 @@ var CliProviderInstance = class _CliProviderInstance {
49057
49108
  taskId: this.completingTurnTaskId()
49058
49109
  });
49059
49110
  }
49111
+ /**
49112
+ * FALSE-STALL-WATCHDOG-OVERFIRE: drop the entire stall episode for this session.
49113
+ * Called when the session is no longer a mesh worker or the PTY is dead — the
49114
+ * next live tick re-arms a fresh episode. Clears the fix-B turn-edge state and
49115
+ * the fix-E refire cooldown alongside the base anchor so a re-armed session
49116
+ * starts with a clean slate (a restart is not throttled by a prior stall).
49117
+ */
49118
+ resetMeshStallEpisode() {
49119
+ this.meshStallAnchorAt = -1;
49120
+ this.meshStallEmittedForAnchor = false;
49121
+ this.meshStallTurnActiveLast = void 0;
49122
+ this.meshStallLastFiredAt = -1;
49123
+ }
49060
49124
  /**
49061
49125
  * AUTOAPPROVE-FLAP-RECUR (Fix A+B): how long a busy blip / modal scroll-out may
49062
49126
  * persist before the in-progress settle gate is torn down. For a delegated