@adhdev/daemon-core 0.9.82-rc.274 → 0.9.82-rc.275

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
@@ -270,10 +270,10 @@ function readInjected(value) {
270
270
  }
271
271
  function getDaemonBuildInfo() {
272
272
  if (cached) return cached;
273
- const commit = readInjected(true ? "89d1ac61612c1dfe7fac53be61ec5dbfa67d00b2" : void 0) ?? "unknown";
274
- const commitShort = readInjected(true ? "89d1ac61" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
275
- const version = readInjected(true ? "0.9.82-rc.274" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
276
- const builtAt = readInjected(true ? "2026-06-15T07:04:52.710Z" : void 0);
273
+ const commit = readInjected(true ? "080b607ef221e44126942d9d52eaf547b4e92550" : void 0) ?? "unknown";
274
+ const commitShort = readInjected(true ? "080b607e" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
275
+ const version = readInjected(true ? "0.9.82-rc.275" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
276
+ const builtAt = readInjected(true ? "2026-06-15T08:24:26.468Z" : void 0);
277
277
  cached = builtAt ? { commit, commitShort, version, builtAt } : { commit, commitShort, version };
278
278
  return cached;
279
279
  }
@@ -4258,12 +4258,33 @@ var init_mesh_runtime_store = __esm({
4258
4258
  this.maybeCheckpointWal();
4259
4259
  return result.changes > 0;
4260
4260
  }
4261
- drainPendingEvents(meshId, coordinatorDaemonId) {
4261
+ /**
4262
+ * Drain undrained pending events for a mesh, atomically marking them drained.
4263
+ * When `opts.onlyEvents` is supplied, ONLY rows whose `event` is in that set are
4264
+ * drained — the rest stay queued (drained=0) for a later drain. This is how the
4265
+ * reconcile loop force-drains terminal/force-inject events into a *generating*
4266
+ * coordinator while leaving non-force progress events for the coordinator's next
4267
+ * idle transition. Filtering happens inside the same transaction as the
4268
+ * drained=1 marking, so force-drain + a concurrent full drain can never both
4269
+ * consume the same row.
4270
+ */
4271
+ drainPendingEvents(meshId, coordinatorDaemonId, opts) {
4262
4272
  return this.transaction(() => {
4263
- const whereClause = coordinatorDaemonId ? `WHERE mesh_id = ? AND drained = 0 AND (coordinator_daemon_id IS NULL OR coordinator_daemon_id = ?)` : `WHERE mesh_id = ? AND drained = 0`;
4264
- const params = coordinatorDaemonId ? [meshId, coordinatorDaemonId] : [meshId];
4273
+ const onlyEvents = opts?.onlyEvents;
4274
+ if (onlyEvents && onlyEvents.size === 0) return [];
4275
+ const eventList = onlyEvents ? [...onlyEvents] : [];
4276
+ const clauses = ["mesh_id = ?", "drained = 0"];
4277
+ const params = [meshId];
4278
+ if (coordinatorDaemonId) {
4279
+ clauses.push("(coordinator_daemon_id IS NULL OR coordinator_daemon_id = ?)");
4280
+ params.push(coordinatorDaemonId);
4281
+ }
4282
+ if (eventList.length > 0) {
4283
+ clauses.push(`event IN (${eventList.map(() => "?").join(",")})`);
4284
+ params.push(...eventList);
4285
+ }
4265
4286
  const rows = this.db.prepare(
4266
- `SELECT id, event, payload FROM mesh_pending_events ${whereClause} ORDER BY queued_at ASC LIMIT 100`
4287
+ `SELECT id, event, payload FROM mesh_pending_events WHERE ${clauses.join(" AND ")} ORDER BY queued_at ASC LIMIT 100`
4267
4288
  ).all(...params);
4268
4289
  if (rows.length === 0) return [];
4269
4290
  const ids = rows.map((r) => r.id);
@@ -6526,8 +6547,57 @@ function atomicDrainFile(path39) {
6526
6547
  return null;
6527
6548
  }
6528
6549
  }
6529
- function drainPendingMeshCoordinatorEvents(meshId, coordinatorDaemonId) {
6550
+ function selectiveDrainFile(path39, predicate) {
6551
+ const tmpPath = `${path39}.draining`;
6552
+ try {
6553
+ renameSync4(path39, tmpPath);
6554
+ } catch {
6555
+ return [];
6556
+ }
6557
+ let content;
6558
+ try {
6559
+ content = readFileSync10(tmpPath, "utf-8");
6560
+ } catch {
6561
+ try {
6562
+ unlinkSync2(tmpPath);
6563
+ } catch {
6564
+ }
6565
+ return [];
6566
+ }
6567
+ const consumed = [];
6568
+ const keptLines = [];
6569
+ for (const line of content.split("\n")) {
6570
+ if (!line) continue;
6571
+ let parsed;
6572
+ try {
6573
+ parsed = JSON.parse(line);
6574
+ } catch {
6575
+ parsed = void 0;
6576
+ }
6577
+ if (parsed && predicate(parsed)) {
6578
+ consumed.push(parsed);
6579
+ } else {
6580
+ keptLines.push(line);
6581
+ }
6582
+ }
6583
+ try {
6584
+ if (keptLines.length > 0) {
6585
+ writeFileSync6(path39, keptLines.join("\n") + "\n", "utf-8");
6586
+ }
6587
+ unlinkSync2(tmpPath);
6588
+ } catch {
6589
+ try {
6590
+ if (existsSync12(tmpPath) && !existsSync12(path39)) renameSync4(tmpPath, path39);
6591
+ } catch {
6592
+ }
6593
+ return [];
6594
+ }
6595
+ return consumed;
6596
+ }
6597
+ function drainPendingMeshCoordinatorEvents(meshId, coordinatorDaemonId, opts) {
6530
6598
  if (!meshId) return [];
6599
+ const onlyEvents = opts?.onlyEvents;
6600
+ const matchesFilter = (eventName) => !onlyEvents || onlyEvents.has(eventName);
6531
6601
  const merged = [];
6532
6602
  const seenFingerprints = /* @__PURE__ */ new Set();
6533
6603
  const pushUnique = (event) => {
@@ -6541,7 +6611,7 @@ function drainPendingMeshCoordinatorEvents(meshId, coordinatorDaemonId) {
6541
6611
  try {
6542
6612
  const store = MeshRuntimeStore.getInstance();
6543
6613
  if (store.pendingEventCount(meshId) > 0) {
6544
- for (const row of store.drainPendingEvents(meshId, coordinatorDaemonId)) {
6614
+ for (const row of store.drainPendingEvents(meshId, coordinatorDaemonId, onlyEvents ? { onlyEvents } : void 0)) {
6545
6615
  const event = row.payload;
6546
6616
  if (event) pushUnique(event);
6547
6617
  }
@@ -6550,6 +6620,14 @@ function drainPendingMeshCoordinatorEvents(meshId, coordinatorDaemonId) {
6550
6620
  }
6551
6621
  const paths = coordinatorDaemonId ? [getPendingEventsPath(meshId, coordinatorDaemonId), getPendingEventsPath(meshId)] : [getPendingEventsPath(meshId)];
6552
6622
  for (const path39 of paths) {
6623
+ const isSharedFile = coordinatorDaemonId && path39 === getPendingEventsPath(meshId);
6624
+ const targets = (e) => !isSharedFile || !e.targetCoordinatorDaemonId || e.targetCoordinatorDaemonId === coordinatorDaemonId;
6625
+ if (onlyEvents) {
6626
+ for (const event of selectiveDrainFile(path39, (e) => targets(e) && matchesFilter(e.event))) {
6627
+ pushUnique(event);
6628
+ }
6629
+ continue;
6630
+ }
6553
6631
  const content = atomicDrainFile(path39);
6554
6632
  if (!content) continue;
6555
6633
  const parsed = content.split("\n").filter(Boolean).flatMap((line) => {
@@ -6559,7 +6637,7 @@ function drainPendingMeshCoordinatorEvents(meshId, coordinatorDaemonId) {
6559
6637
  return [];
6560
6638
  }
6561
6639
  });
6562
- const filtered = coordinatorDaemonId && path39 === getPendingEventsPath(meshId) ? parsed.filter((e) => !e.targetCoordinatorDaemonId || e.targetCoordinatorDaemonId === coordinatorDaemonId) : parsed;
6640
+ const filtered = isSharedFile ? parsed.filter(targets) : parsed;
6563
6641
  for (const event of filtered) pushUnique(event);
6564
6642
  }
6565
6643
  if (merged.length === 0) return [];
@@ -8575,7 +8653,9 @@ async function runMeshReconcileTick(components) {
8575
8653
  }
8576
8654
  }
8577
8655
  const idleCoordinators = meshCoordinators.filter((c) => c.idle);
8578
- if (idleCoordinators.length === 0) continue;
8656
+ const generatingCoordinators = meshCoordinators.filter((c) => !c.idle);
8657
+ const targetCoordinators = idleCoordinators.length > 0 ? idleCoordinators : generatingCoordinators;
8658
+ const forceOnly = idleCoordinators.length === 0;
8579
8659
  if (store) {
8580
8660
  try {
8581
8661
  if (store.pendingEventCount(meshId) === 0) continue;
@@ -8584,15 +8664,20 @@ async function runMeshReconcileTick(components) {
8584
8664
  }
8585
8665
  let pendingEvents = [];
8586
8666
  try {
8587
- pendingEvents = drainPendingMeshCoordinatorEvents(meshId, localDaemonId);
8667
+ pendingEvents = drainPendingMeshCoordinatorEvents(
8668
+ meshId,
8669
+ localDaemonId,
8670
+ forceOnly ? { onlyEvents: MESH_FORCE_INJECT_EVENTS } : void 0
8671
+ );
8588
8672
  } catch (e) {
8589
8673
  LOG.warn("MeshReconcile", `Drain failed for mesh ${meshId}: ${e?.message || e}`);
8590
8674
  continue;
8591
8675
  }
8592
8676
  if (pendingEvents.length === 0) continue;
8593
- LOG.info("MeshReconcile", `Reconcile inject: ${pendingEvents.length} pending event(s) \u2192 ${idleCoordinators.length} idle coordinator(s) for mesh ${meshId}`);
8677
+ const mode = forceOnly ? "force-drain \u2192 generating" : "inject \u2192 idle";
8678
+ LOG.info("MeshReconcile", `Reconcile ${mode}: ${pendingEvents.length} pending event(s) \u2192 ${targetCoordinators.length} coordinator(s) for mesh ${meshId}`);
8594
8679
  for (const pending of pendingEvents) {
8595
- for (const c of idleCoordinators) {
8680
+ for (const c of targetCoordinators) {
8596
8681
  injectPendingIntoCoordinator(c.instance, pending);
8597
8682
  }
8598
8683
  }