@adhdev/daemon-core 0.9.82-rc.465 → 0.9.82-rc.467

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 ? "1fb9559b573b07e5386c80329057766b4822dddb" : void 0) ?? "unknown";
413
- const commitShort = readInjected(true ? "1fb9559b" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
414
- const version = readInjected(true ? "0.9.82-rc.465" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
415
- const builtAt = readInjected(true ? "2026-07-05T07:20:34.545Z" : void 0);
412
+ const commit = readInjected(true ? "e0f04b7d54855e0f0d5ed4200078d95596ab9f6f" : void 0) ?? "unknown";
413
+ const commitShort = readInjected(true ? "e0f04b7d" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
414
+ const version = readInjected(true ? "0.9.82-rc.467" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
415
+ const builtAt = readInjected(true ? "2026-07-05T10:01:33.435Z" : void 0);
416
416
  cached = builtAt ? { commit, commitShort, version, builtAt } : { commit, commitShort, version };
417
417
  return cached;
418
418
  }
@@ -5151,7 +5151,8 @@ var init_mesh_ledger = __esm({
5151
5151
  "task_completed",
5152
5152
  "task_failed",
5153
5153
  "task_stalled",
5154
- "recovery_attempted"
5154
+ "recovery_attempted",
5155
+ "session_auto_launch"
5155
5156
  ]);
5156
5157
  DEFAULT_LEDGER_SLICE_LIMIT = 100;
5157
5158
  MAX_LEDGER_SLICE_LIMIT = 500;
@@ -7344,6 +7345,10 @@ var init_mesh_runtime_store = __esm({
7344
7345
  }
7345
7346
  // ── G2: Event Ledger ────────────────────────────────────────────────────
7346
7347
  appendLedgerEntry(entry) {
7348
+ if (!entry.kind || !String(entry.kind).trim()) {
7349
+ LOG.warn("MeshRuntimeStore", `Refusing to append ledger entry with empty kind for mesh ${entry.meshId} (id ${entry.id})`);
7350
+ return;
7351
+ }
7347
7352
  this.db.prepare(
7348
7353
  `INSERT OR IGNORE INTO mesh_event_ledger
7349
7354
  (id, mesh_id, timestamp, kind, node_id, session_id, provider_type, payload)
@@ -7478,6 +7483,7 @@ var init_mesh_runtime_store = __esm({
7478
7483
  );
7479
7484
  this.db.transaction(() => {
7480
7485
  for (const e of entries) {
7486
+ if (!e.kind || !String(e.kind).trim()) continue;
7481
7487
  const result = stmt.run(
7482
7488
  e.id,
7483
7489
  e.meshId,
@@ -7772,6 +7778,41 @@ var init_mesh_runtime_store = __esm({
7772
7778
  `DELETE FROM mesh_pending_events WHERE id IN (${idList.map(() => "?").join(",")})`
7773
7779
  ).run(...idList).changes;
7774
7780
  }
7781
+ /**
7782
+ * Retention prune for mesh_pending_events. This table has no lifecycle GC of its
7783
+ * own: a drained row is soft-marked (drained=1) and RETAINED — deliberately, so
7784
+ * drainedEventIdsForMesh() has a durable v2-eventId dedup baseline — and an
7785
+ * undrained row queued for a coordinator that never returned (a dead/evicted
7786
+ * coordinator identity) stays drained=0 forever. Both accumulate without bound
7787
+ * (observed: tens of thousands of rows, mostly stale). This is the missing
7788
+ * retention step. Two independent windows:
7789
+ *
7790
+ * - drained rows older than `drainedOlderThanMs`: the coordinator consumed them
7791
+ * long ago; the only thing they still back is the eventId re-delivery guard,
7792
+ * which is only meaningful for the recent past (a re-delivery of a week-old
7793
+ * event cannot occur — its producer session is long gone). Safe to delete.
7794
+ * - UNDRAINED rows older than `undrainedOlderThanMs` (a much wider window):
7795
+ * these are orphaned events for a coordinator identity that never drained
7796
+ * them. Kept wide so a genuinely-offline-but-returning coordinator still
7797
+ * receives its backlog; only genuinely unrecoverable orphans are swept.
7798
+ *
7799
+ * Both windows key off `queued_at` (always present) — `drained_at` can be NULL on
7800
+ * legacy rows. Returns the number of rows deleted. Best-effort / idempotent:
7801
+ * running it repeatedly with nothing to prune is a cheap no-op.
7802
+ */
7803
+ prunePendingEvents(opts) {
7804
+ const now = Date.now();
7805
+ const drainedCutoff = now - Math.max(0, opts.drainedOlderThanMs);
7806
+ const undrainedCutoff = now - Math.max(0, opts.undrainedOlderThanMs);
7807
+ let removed = 0;
7808
+ removed += this.db.prepare(
7809
+ "DELETE FROM mesh_pending_events WHERE drained = 1 AND queued_at < ?"
7810
+ ).run(drainedCutoff).changes;
7811
+ removed += this.db.prepare(
7812
+ "DELETE FROM mesh_pending_events WHERE drained = 0 AND queued_at < ?"
7813
+ ).run(undrainedCutoff).changes;
7814
+ return removed;
7815
+ }
7775
7816
  };
7776
7817
  }
7777
7818
  });
@@ -11768,6 +11809,21 @@ function reconcilePendingMeshCoordinatorEvents(meshId, events) {
11768
11809
  const reconciled = terminalJobIds.size === 0 ? events : events.filter((event) => !(event.event === "refine:accepted" && terminalJobIds.has(readRefineJobId2(event))));
11769
11810
  return backfilled.length === 0 ? reconciled : [...reconciled, ...backfilled];
11770
11811
  }
11812
+ function prunePendingMeshCoordinatorEventsRetention() {
11813
+ try {
11814
+ const removed = MeshRuntimeStore.getInstance().prunePendingEvents({
11815
+ drainedOlderThanMs: PENDING_EVENTS_DRAINED_RETENTION_MS,
11816
+ undrainedOlderThanMs: PENDING_EVENTS_UNDRAINED_RETENTION_MS
11817
+ });
11818
+ if (removed > 0) {
11819
+ LOG.info("MeshEvents", `Pruned ${removed} stale pending-event row(s) (drained >7d / undrained >30d)`);
11820
+ }
11821
+ return removed;
11822
+ } catch (e) {
11823
+ LOG.warn("MeshEvents", `Pending-event retention prune failed: ${e?.message || e}`);
11824
+ return 0;
11825
+ }
11826
+ }
11771
11827
  function trimPendingEventsIfNeeded(path45) {
11772
11828
  try {
11773
11829
  if (!(0, import_fs11.existsSync)(path45)) return;
@@ -12138,7 +12194,7 @@ function clearPendingMeshCoordinatorEvents(meshId, coordinatorDaemonId) {
12138
12194
  }
12139
12195
  }
12140
12196
  }
12141
- var import_fs11, import_path10, import_crypto8, REFINE_TERMINAL_EVENTS, meshV2DrainCounters, warnedV2Violations, TERMINAL_COMPLETION_EVENTS, MAX_PENDING_EVENTS_BYTES, MAX_PENDING_EVENTS_KEEP;
12197
+ var import_fs11, import_path10, import_crypto8, REFINE_TERMINAL_EVENTS, meshV2DrainCounters, warnedV2Violations, TERMINAL_COMPLETION_EVENTS, MAX_PENDING_EVENTS_BYTES, MAX_PENDING_EVENTS_KEEP, PENDING_EVENTS_DRAINED_RETENTION_MS, PENDING_EVENTS_UNDRAINED_RETENTION_MS;
12142
12198
  var init_mesh_events_pending = __esm({
12143
12199
  "src/mesh/mesh-events-pending.ts"() {
12144
12200
  "use strict";
@@ -12182,6 +12238,8 @@ var init_mesh_events_pending = __esm({
12182
12238
  TERMINAL_COMPLETION_EVENTS = /* @__PURE__ */ new Set(["agent:generating_completed", "agent:stopped"]);
12183
12239
  MAX_PENDING_EVENTS_BYTES = 100 * 1024;
12184
12240
  MAX_PENDING_EVENTS_KEEP = 50;
12241
+ PENDING_EVENTS_DRAINED_RETENTION_MS = 7 * 24 * 60 * 60 * 1e3;
12242
+ PENDING_EVENTS_UNDRAINED_RETENTION_MS = 30 * 24 * 60 * 60 * 1e3;
12185
12243
  }
12186
12244
  });
12187
12245
 
@@ -17239,6 +17297,11 @@ function sweepExpiredRemoteIdleSessions() {
17239
17297
  MeshRuntimeStore.getInstance().pruneExpiredRemoteIdleSessions();
17240
17298
  } catch {
17241
17299
  }
17300
+ const now = Date.now();
17301
+ if (now - lastPendingEventsPruneAt >= PENDING_EVENTS_PRUNE_INTERVAL_MS) {
17302
+ lastPendingEventsPruneAt = now;
17303
+ prunePendingMeshCoordinatorEventsRetention();
17304
+ }
17242
17305
  }
17243
17306
  function isIntentionalCleanupStopMetadata(event) {
17244
17307
  return event.intentional === true || event.intentionalStop === true || event.operatorCleanup === true || event.reason === "operator_cleanup" || event.stopReason === "operator_cleanup" || event.cleanupReason === "operator_cleanup" || event.source === "mesh_cleanup_sessions" || event.source === "mesh_remove_node";
@@ -18297,7 +18360,7 @@ function setupMeshEventForwarding(components) {
18297
18360
  flushPendingForMeshIdleCoordinators(components, routing.meshId);
18298
18361
  });
18299
18362
  }
18300
- var REMOTE_IDLE_SESSION_TTL_MS, meshByWorkspaceCache, MESH_WORKSPACE_CACHE_TTL_MS, INTENTIONAL_CLEANUP_STOP_SUPPRESSION_MS, RECENT_COMPLETION_FINGERPRINT_TTL_MS, RECONCILED_COMPLETION_SOURCES, coordinatorForwardLanes;
18363
+ var REMOTE_IDLE_SESSION_TTL_MS, meshByWorkspaceCache, MESH_WORKSPACE_CACHE_TTL_MS, lastPendingEventsPruneAt, PENDING_EVENTS_PRUNE_INTERVAL_MS, INTENTIONAL_CLEANUP_STOP_SUPPRESSION_MS, RECENT_COMPLETION_FINGERPRINT_TTL_MS, RECONCILED_COMPLETION_SOURCES, coordinatorForwardLanes;
18301
18364
  var init_mesh_event_forwarding = __esm({
18302
18365
  "src/mesh/mesh-event-forwarding.ts"() {
18303
18366
  "use strict";
@@ -18324,6 +18387,8 @@ var init_mesh_event_forwarding = __esm({
18324
18387
  REMOTE_IDLE_SESSION_TTL_MS = 5 * 60 * 1e3;
18325
18388
  meshByWorkspaceCache = /* @__PURE__ */ new Map();
18326
18389
  MESH_WORKSPACE_CACHE_TTL_MS = 5e3;
18390
+ lastPendingEventsPruneAt = 0;
18391
+ PENDING_EVENTS_PRUNE_INTERVAL_MS = 60 * 60 * 1e3;
18327
18392
  INTENTIONAL_CLEANUP_STOP_SUPPRESSION_MS = 30 * 60 * 1e3;
18328
18393
  RECENT_COMPLETION_FINGERPRINT_TTL_MS = 10 * 60 * 1e3;
18329
18394
  RECONCILED_COMPLETION_SOURCES = /* @__PURE__ */ new Set([
@@ -42709,6 +42774,33 @@ var CliProviderInstance = class _CliProviderInstance {
42709
42774
  * from scratch rather than firing on a stale timestamp.
42710
42775
  */
42711
42776
  static AUTO_APPROVE_GATE_HYSTERESIS_MS = 1500;
42777
+ /**
42778
+ * AUTOAPPROVE-FLAP-RECUR (Fix B): extended busy-side continuity window for a
42779
+ * DELEGATED-WORKER auto-approve episode that is genuinely still cycling.
42780
+ *
42781
+ * The default AUTO_APPROVE_GATE_HYSTERESIS_MS (1500) absorbs a *momentary*
42782
+ * `generating` blip. But a delegated worker running a Bash approval observed
42783
+ * the FSM cycle the FULL state waiting_approval → busy → waiting_approval on a
42784
+ * 2–5s period (the button set scrolls in/out AND the modal question repaints,
42785
+ * so the adapter genuinely reports status=generating for whole seconds between
42786
+ * approval frames). Each busy phase outran the 1500ms hysteresis, so the
42787
+ * settle clock was WIPED (the genuine-resolution branch), the 600ms settle
42788
+ * window never accumulated across the flap, resolveModal never fired
42789
+ * (resolveModal count 0), and the mask-stall clock instead tripped at 4500ms →
42790
+ * coordinator nudge → the flap the coordinator observed.
42791
+ *
42792
+ * A genuine resolution and a flap both start with a busy phase; they diverge
42793
+ * only in whether waiting_approval RETURNS. So we cannot simply lengthen the
42794
+ * blanket hysteresis (that would make every real resolution hold the gate
42795
+ * open for seconds). Instead this longer window applies ONLY while an active
42796
+ * mask episode is alive (autoApproveMaskSince > 0) AND the session is a
42797
+ * delegated worker — i.e. exactly the never-resolving-flap case. A foreground
42798
+ * / attended session keeps the tight 1500ms window unchanged. The mask-stall
42799
+ * bound below still caps the episode, so a worker whose approval truly never
42800
+ * returns is surfaced to the coordinator within AUTO_APPROVE_MASK_STALL_MS
42801
+ * rather than held forever.
42802
+ */
42803
+ static AUTO_APPROVE_FLAP_CONTINUITY_MS = 4e3;
42712
42804
  /**
42713
42805
  * STATUS-MISMATCH: upper bound on how long the auto-approve→`generating` SURFACE
42714
42806
  * mask may hide a worker's `waiting_approval` (status + activeModal) before we give
@@ -42783,9 +42875,22 @@ var CliProviderInstance = class _CliProviderInstance {
42783
42875
  pendingAutoApprovalSince = 0;
42784
42876
  autoApproveSettleTimer = null;
42785
42877
  // Wall-clock when auto-approve first observed status!=waiting_approval while
42786
- // a settle gate was in progress. Drives AUTO_APPROVE_GATE_HYSTERESIS_MS so a
42878
+ // a settle gate was in progress. Drives AUTO_APPROVE_GATE_HYSTERESIS_MS (or,
42879
+ // for a delegated-worker flap episode, AUTO_APPROVE_FLAP_CONTINUITY_MS) so a
42787
42880
  // brief generating flip does not immediately wipe the settle clock.
42788
42881
  autoApproveInactiveSince = 0;
42882
+ // AUTOAPPROVE-FLAP-RECUR (Fix A): wall-clock when the CURRENT waiting_approval
42883
+ // episode last presented a concrete, captured modal (buttons.length > 0). The
42884
+ // Claude TUI momentarily reports status=waiting_approval with activeModal=null
42885
+ // / an empty button block while the button block scrolls out of the captured
42886
+ // frame; the raw guard below (buttons.length===0) used to bail on that frame,
42887
+ // never advancing the settle gate and leaving no re-check armed — so a modal
42888
+ // that flapped modal=none ↔ N-buttons around the settle boundary never
42889
+ // accumulated its 600ms. This tracks the last GOOD-modal frame so a short
42890
+ // scroll-out blip is absorbed (settle keeps running against the last captured
42891
+ // signature) while a genuinely closed modal — buttons empty continuously past
42892
+ // the continuity window — is still recognised and resets the gate.
42893
+ autoApproveLastModalSeenAt = 0;
42789
42894
  // STATUS-MISMATCH: wall-clock when the CURRENT auto-approve episode (waiting_approval
42790
42895
  // + shouldAutoApprove) first began wanting to mask. Unlike pendingAutoApprovalSince it
42791
42896
  // is NOT reset when the modal signature changes (a still-streaming/flapping prompt) and
@@ -43748,6 +43853,20 @@ var CliProviderInstance = class _CliProviderInstance {
43748
43853
  isMeshWorkerSession() {
43749
43854
  return !!(this.settings.meshNodeFor || this.settings.meshActiveTaskId || this.settings.meshNodeId || this.settings.launchedByCoordinator);
43750
43855
  }
43856
+ /**
43857
+ * AUTOAPPROVE-FLAP-RECUR (Fix A+B): how long a busy blip / modal scroll-out may
43858
+ * persist before the in-progress settle gate is torn down. For a delegated
43859
+ * worker whose auto-approve episode is genuinely still cycling (mask clock
43860
+ * alive), the FSM's full waiting_approval → busy → waiting_approval flap runs
43861
+ * on a multi-second period, so the settle continuity window is extended to
43862
+ * AUTO_APPROVE_FLAP_CONTINUITY_MS to bridge it (still bounded, and still capped
43863
+ * by AUTO_APPROVE_MASK_STALL_MS). Every other case — foreground/attended
43864
+ * session, or no active mask episode — keeps the tight default hysteresis so a
43865
+ * genuine resolution frees the gate promptly.
43866
+ */
43867
+ autoApproveContinuityWindowMs() {
43868
+ return this.autoApproveMaskSince > 0 && this.isMeshWorkerSession() ? _CliProviderInstance.AUTO_APPROVE_FLAP_CONTINUITY_MS : _CliProviderInstance.AUTO_APPROVE_GATE_HYSTERESIS_MS;
43869
+ }
43751
43870
  // FALSE-IDLE (self-coordinator settle): an autonomously-progressing mesh session
43752
43871
  // is either a delegated worker (isMeshWorkerSession) OR the coordinator's OWN
43753
43872
  // claude-cli session (meshCoordinatorFor). Both run auto-approved tool turns whose
@@ -43983,6 +44102,7 @@ var CliProviderInstance = class _CliProviderInstance {
43983
44102
  this.autoApproveInactiveSince = 0;
43984
44103
  this.autoApproveMaskSince = 0;
43985
44104
  this.stalledApprovalNudgeEpisode = 0;
44105
+ this.autoApproveLastModalSeenAt = 0;
43986
44106
  if (this.autoApproveSettleTimer) clearTimeout(this.autoApproveSettleTimer);
43987
44107
  this.autoApproveSettleTimer = setTimeout(() => {
43988
44108
  this.autoApproveSettleTimer = null;
@@ -43996,12 +44116,13 @@ var CliProviderInstance = class _CliProviderInstance {
43996
44116
  if (this.pendingAutoApprovalSince) {
43997
44117
  if (!this.autoApproveInactiveSince) this.autoApproveInactiveSince = now;
43998
44118
  const goneForMs = now - this.autoApproveInactiveSince;
43999
- if (goneForMs < _CliProviderInstance.AUTO_APPROVE_GATE_HYSTERESIS_MS) {
44119
+ const continuityMs = this.autoApproveContinuityWindowMs();
44120
+ if (goneForMs < continuityMs) {
44000
44121
  if (this.autoApproveSettleTimer) clearTimeout(this.autoApproveSettleTimer);
44001
44122
  this.autoApproveSettleTimer = setTimeout(() => {
44002
44123
  this.autoApproveSettleTimer = null;
44003
44124
  this.recheckAutoApproveSettled();
44004
- }, _CliProviderInstance.AUTO_APPROVE_GATE_HYSTERESIS_MS - goneForMs + 20);
44125
+ }, continuityMs - goneForMs + 20);
44005
44126
  return autoApproveActive;
44006
44127
  }
44007
44128
  }
@@ -44010,6 +44131,7 @@ var CliProviderInstance = class _CliProviderInstance {
44010
44131
  this.autoApproveInactiveSince = 0;
44011
44132
  this.autoApproveMaskSince = 0;
44012
44133
  this.stalledApprovalNudgeEpisode = 0;
44134
+ this.autoApproveLastModalSeenAt = 0;
44013
44135
  if (this.autoApproveSettleTimer) {
44014
44136
  clearTimeout(this.autoApproveSettleTimer);
44015
44137
  this.autoApproveSettleTimer = null;
@@ -44022,8 +44144,22 @@ var CliProviderInstance = class _CliProviderInstance {
44022
44144
  const modal = adapterStatus.activeModal;
44023
44145
  const buttons = Array.isArray(modal?.buttons) ? modal.buttons.map((b) => String(b || "").trim()).filter(Boolean) : [];
44024
44146
  if (!modal || buttons.length === 0) {
44147
+ const blipForMs = this.autoApproveLastModalSeenAt ? now - this.autoApproveLastModalSeenAt : Infinity;
44148
+ if (this.pendingAutoApprovalSince && blipForMs < this.autoApproveContinuityWindowMs()) {
44149
+ if (this.autoApproveSettleTimer) clearTimeout(this.autoApproveSettleTimer);
44150
+ this.autoApproveSettleTimer = setTimeout(() => {
44151
+ this.autoApproveSettleTimer = null;
44152
+ this.recheckAutoApproveSettled();
44153
+ }, this.autoApproveContinuityWindowMs() - blipForMs + 20);
44154
+ return autoApproveActive;
44155
+ }
44156
+ if (blipForMs >= this.autoApproveContinuityWindowMs()) {
44157
+ this.pendingAutoApprovalSignature = "";
44158
+ this.pendingAutoApprovalSince = 0;
44159
+ }
44025
44160
  return autoApproveActive;
44026
44161
  }
44162
+ this.autoApproveLastModalSeenAt = now;
44027
44163
  const modalKind = typeof modal?.kind === "string" ? modal.kind : "approval";
44028
44164
  if (modalKind !== "approval") {
44029
44165
  return autoApproveActive;
@@ -44067,6 +44203,7 @@ var CliProviderInstance = class _CliProviderInstance {
44067
44203
  this.autoApproveInactiveSince = 0;
44068
44204
  this.autoApproveMaskSince = 0;
44069
44205
  this.stalledApprovalNudgeEpisode = 0;
44206
+ this.autoApproveLastModalSeenAt = 0;
44070
44207
  if (this.autoApproveBusyTimer) clearTimeout(this.autoApproveBusyTimer);
44071
44208
  this.autoApproveBusyTimer = setTimeout(() => {
44072
44209
  this.autoApproveBusy = false;
@@ -44712,6 +44849,8 @@ ${effect.notification.body || ""}`.trim();
44712
44849
  if (!this.isMeshWorkerSession()) return;
44713
44850
  if (adapterStatus?.status !== "waiting_approval") return;
44714
44851
  if (!this.autoApproveMaskStalled(now)) return;
44852
+ const modalButtons = Array.isArray(adapterStatus.activeModal?.buttons) ? adapterStatus.activeModal.buttons.map((b) => String(b || "").trim()).filter(Boolean) : [];
44853
+ if (this.pendingAutoApprovalSince && modalButtons.length > 0) return;
44715
44854
  if (this.stalledApprovalNudgeEpisode === this.autoApproveMaskSince) return;
44716
44855
  this.stalledApprovalNudgeEpisode = this.autoApproveMaskSince;
44717
44856
  const modal = adapterStatus.activeModal;