@adhdev/daemon-core 0.9.82-rc.494 → 0.9.82-rc.496

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
@@ -170,7 +170,10 @@ var init_repo_mesh_types = __esm({
170
170
  // auto-launched sessions are cleaned — see RepoMeshMagiSessionCleanupMode.
171
171
  magiSessionCleanup: "stop_and_delete",
172
172
  autoFastForward: { enabled: true },
173
- maxTaskRetries: 1
173
+ maxTaskRetries: 1,
174
+ // Nudge the coordinator when the mesh is fully idle but active missions linger,
175
+ // so a mission is never left drifting in `active` after its work is really done.
176
+ idleActiveMissionReminder: true
174
177
  };
175
178
  SESSION_CLEANUP_MODES = /* @__PURE__ */ new Set([
176
179
  "preserve",
@@ -409,10 +412,10 @@ function readInjected(value) {
409
412
  }
410
413
  function getDaemonBuildInfo() {
411
414
  if (cached) return cached;
412
- const commit = readInjected(true ? "c05e29374bd592e460427419beb06a7fde594f4b" : void 0) ?? "unknown";
413
- const commitShort = readInjected(true ? "c05e2937" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
414
- const version = readInjected(true ? "0.9.82-rc.494" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
415
- const builtAt = readInjected(true ? "2026-07-10T09:19:42.151Z" : void 0);
415
+ const commit = readInjected(true ? "bafa66a406e7efc123493af30c0779646ea02c5c" : void 0) ?? "unknown";
416
+ const commitShort = readInjected(true ? "bafa66a4" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
417
+ const version = readInjected(true ? "0.9.82-rc.496" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
418
+ const builtAt = readInjected(true ? "2026-07-11T16:11:16.059Z" : void 0);
416
419
  cached = builtAt ? { commit, commitShort, version, builtAt } : { commit, commitShort, version };
417
420
  return cached;
418
421
  }
@@ -2924,7 +2927,6 @@ var init_dist = __esm({
2924
2927
  "mesh_forget_note",
2925
2928
  "mesh_reconcile_ledger",
2926
2929
  "mesh_requeue_held_events",
2927
- "mesh_wait_events",
2928
2930
  "mesh_mission_upsert",
2929
2931
  "mesh_mission_list",
2930
2932
  "mesh_review_inbox",
@@ -3938,7 +3940,6 @@ var init_coordinator_prompt = __esm({
3938
3940
  | \`mesh_ledger_query\` | Read-only ledger query along the kind/time/node axes (complement to task-axis mesh_task_history): filter by kind, since, node, tail \u2014 answer "what happened on node X / what failed since T" without scanning transcripts |
3939
3941
  | \`mesh_reconcile_ledger\` | Reconcile daemon-local ledgers over P2P \u2014 import missing entries from remote nodes into the coordinator local ledger |
3940
3942
  | \`mesh_requeue_held_events\` | Restore recoverable held coordinator events (T6 quarantine / pending-trim) back to the pending queue; lossless, no double-requeue |
3941
- | \`mesh_wait_events\` | Long-poll blocking wait for coordinator events (worker completions/approvals/nudges) up to timeoutMs \u2014 drains immediately if any are pending, else blocks until they arrive. Use this instead of busy-polling mesh_status/mesh_view_queue after dispatching work |
3942
3943
  | \`mesh_review_inbox\` | List local worktree nodes needing human review \u2014 merge candidates and Refinery-blocked results with evidence/diff summaries |
3943
3944
  | \`mesh_record_note\` | Record a durable, provider-neutral operating note (provider quirk / pattern to avoid / recovery lesson). Future coordinators see it under "## Operating Notes" at launch |
3944
3945
  | \`mesh_forget_note\` | Retract a stale/wrong operating note by note_id or exact text so it stops riding into future coordinators' prompts (append-only tombstone; history preserved) |
@@ -6492,6 +6493,13 @@ var init_mesh_runtime_store = __esm({
6492
6493
  db;
6493
6494
  dbPath;
6494
6495
  migratedMeshIds = /* @__PURE__ */ new Set();
6496
+ // Idle-active-mission-reminder debounce (mesh-idle-reminder.ts). In-memory only:
6497
+ // this is a spam guard for a best-effort coordinator nudge, so a daemon restart
6498
+ // resetting it (at most one extra reminder) is harmless — no SQLite persistence
6499
+ // is warranted. Keyed by meshId; the value records when the last reminder fired
6500
+ // and the hash of the active-mission id set it named, so a changed mission set
6501
+ // re-fires before the time window elapses.
6502
+ idleReminderState = /* @__PURE__ */ new Map();
6495
6503
  fingerprintSweepCounter = 0;
6496
6504
  walWriteCounter = 0;
6497
6505
  // Independent cadence for the tool-call-log sweep. Must NOT share walWriteCounter:
@@ -8087,6 +8095,22 @@ var init_mesh_runtime_store = __esm({
8087
8095
  "UPDATE mesh_missions SET close_candidate_emitted_at = ? WHERE mesh_id = ? AND id = ?"
8088
8096
  ).run(emittedAt, meshId, missionId).changes;
8089
8097
  }
8098
+ /**
8099
+ * Read the last idle-active-mission-reminder debounce marker for a mesh, or null if
8100
+ * none has fired this process. In-memory only (see idleReminderState) — best-effort
8101
+ * spam guard for a coordinator nudge, intentionally not SQLite-backed.
8102
+ */
8103
+ getIdleReminderState(meshId) {
8104
+ return this.idleReminderState.get(meshId) ?? null;
8105
+ }
8106
+ /** Record that an idle-active-mission reminder just fired for a mesh (debounce marker). */
8107
+ setIdleReminderState(meshId, state) {
8108
+ this.idleReminderState.set(meshId, state);
8109
+ }
8110
+ /** Clear the idle-reminder debounce marker for a mesh — mesh deletion / test cleanup. */
8111
+ clearIdleReminderState(meshId) {
8112
+ this.idleReminderState.delete(meshId);
8113
+ }
8090
8114
  /** Remove all missions for a mesh — mesh deletion / test cleanup. */
8091
8115
  clearMissionsForMesh(meshId) {
8092
8116
  return this.db.prepare("DELETE FROM mesh_missions WHERE mesh_id = ?").run(meshId).changes;
@@ -12594,6 +12618,72 @@ var init_mesh_active_work = __esm({
12594
12618
  }
12595
12619
  });
12596
12620
 
12621
+ // src/mesh/mesh-idle-reminder.ts
12622
+ function missionSetHash(missions) {
12623
+ return missions.map((m) => m.id).sort().join(",");
12624
+ }
12625
+ function shouldFireIdleReminder(last, hash, now, debounceMs = IDLE_REMINDER_DEBOUNCE_MS) {
12626
+ if (!last) return true;
12627
+ if (now - last.emittedAt > debounceMs) return true;
12628
+ return hash !== last.missionSetHash;
12629
+ }
12630
+ function buildIdleReminderMessage(missions) {
12631
+ const shown = missions.slice(0, MISSION_LIST_CAP);
12632
+ const lines = shown.map((m) => `- ${m.title} (${m.id})`);
12633
+ const overflow = missions.length - shown.length;
12634
+ if (overflow > 0) lines.push(`- \u2026and ${overflow} more`);
12635
+ return `[System] Coordinator idle with ${missions.length} active mission(s):
12636
+ ${lines.join("\n")}
12637
+ The mesh has no work in flight. For each mission, decide its outcome: continue it (enqueue/dispatch the remaining work) or close it with mesh_mission_upsert(mission_id, status: "completed" | "abandoned"). Do not leave a finished mission in 'active'. This is a one-time reminder.`;
12638
+ }
12639
+ function maybeInjectIdleActiveMissionReminder(meshId, coordinator, policy, now = Date.now()) {
12640
+ try {
12641
+ if (!coordinator) return false;
12642
+ if (policy?.idleActiveMissionReminder === false) return false;
12643
+ const activeMissions = getMeshMissions(meshId, ["active"]);
12644
+ if (activeMissions.length === 0) return false;
12645
+ const summary = buildMeshActiveWork({
12646
+ meshId,
12647
+ queue: getQueue(meshId),
12648
+ directDispatches: getActiveDirectDispatches(meshId),
12649
+ ledgerEntries: readLedgerEntries(meshId, { tail: 200 }),
12650
+ now
12651
+ }).summary;
12652
+ if (summary.totalActiveCount !== 0 || summary.generatingCount !== 0) return false;
12653
+ const store = MeshRuntimeStore.getInstance();
12654
+ const hash = missionSetHash(activeMissions);
12655
+ const last = store.getIdleReminderState(meshId);
12656
+ if (!shouldFireIdleReminder(last, hash, now)) return false;
12657
+ const message = buildIdleReminderMessage(activeMissions);
12658
+ coordinator.onEvent("send_message", {
12659
+ input: { text: message, textFallback: message }
12660
+ });
12661
+ store.setIdleReminderState(meshId, { emittedAt: now, missionSetHash: hash });
12662
+ LOG.info(
12663
+ "MeshIdleReminder",
12664
+ `Injected idle reminder for mesh ${meshId} (${activeMissions.length} active mission(s), fully idle)`
12665
+ );
12666
+ return true;
12667
+ } catch (e) {
12668
+ LOG.warn("MeshIdleReminder", `maybeInjectIdleActiveMissionReminder failed for mesh ${meshId}: ${e?.message || e}`);
12669
+ return false;
12670
+ }
12671
+ }
12672
+ var IDLE_REMINDER_DEBOUNCE_MS, MISSION_LIST_CAP;
12673
+ var init_mesh_idle_reminder = __esm({
12674
+ "src/mesh/mesh-idle-reminder.ts"() {
12675
+ "use strict";
12676
+ init_logger();
12677
+ init_mesh_runtime_store();
12678
+ init_mesh_missions();
12679
+ init_mesh_work_queue();
12680
+ init_mesh_ledger();
12681
+ init_mesh_active_work();
12682
+ IDLE_REMINDER_DEBOUNCE_MS = 3e5;
12683
+ MISSION_LIST_CAP = 10;
12684
+ }
12685
+ });
12686
+
12597
12687
  // src/mesh/mesh-magi-status.ts
12598
12688
  var mesh_magi_status_exports = {};
12599
12689
  __export(mesh_magi_status_exports, {
@@ -20480,6 +20570,12 @@ function setupMeshEventForwarding(components) {
20480
20570
  ...forcePending ? { force: true } : {}
20481
20571
  });
20482
20572
  }
20573
+ } else {
20574
+ maybeInjectIdleActiveMissionReminder(
20575
+ coordinatorMeshId,
20576
+ flushSource,
20577
+ getMesh(coordinatorMeshId)?.policy
20578
+ );
20483
20579
  }
20484
20580
  } catch (e) {
20485
20581
  LOG.warn("MeshEvents", `Failed to auto-flush pending coordinator events: ${e?.message || e}`);
@@ -20539,6 +20635,7 @@ var init_mesh_event_forwarding = __esm({
20539
20635
  init_mesh_work_queue();
20540
20636
  init_mesh_delivery_policy();
20541
20637
  init_mesh_runtime_store();
20638
+ init_mesh_idle_reminder();
20542
20639
  init_mesh_events_pending();
20543
20640
  init_mesh_routing();
20544
20641
  init_mesh_host_ownership();
@@ -20873,7 +20970,7 @@ async function collectLiveNodesWithSessions(components, mesh, selfIds, localDaem
20873
20970
  let statusResult;
20874
20971
  try {
20875
20972
  if (isLocalNode) {
20876
- statusResult = await components.commandHandler.handle("get_status_metadata", {});
20973
+ statusResult = await components.router.execute("get_status_metadata", {}, "mesh");
20877
20974
  } else if (dispatchMeshCommand) {
20878
20975
  statusResult = await dispatchMeshCommand(nodeDaemonId, "get_status_metadata", {});
20879
20976
  } else {
@@ -21840,7 +21937,14 @@ async function runMeshReconcileTick(components) {
21840
21937
  }
21841
21938
  if (store) {
21842
21939
  try {
21843
- if (store.pendingEventCount(meshId) === 0) continue;
21940
+ if (store.pendingEventCount(meshId) === 0) {
21941
+ maybeInjectIdleActiveMissionReminder(
21942
+ meshId,
21943
+ targetCoordinators[0].instance,
21944
+ getMesh(meshId)?.policy
21945
+ );
21946
+ continue;
21947
+ }
21844
21948
  } catch {
21845
21949
  }
21846
21950
  }
@@ -22014,6 +22118,7 @@ var init_mesh_reconcile_loop = __esm({
22014
22118
  "use strict";
22015
22119
  init_config();
22016
22120
  init_mesh_config();
22121
+ init_mesh_idle_reminder();
22017
22122
  init_logger();
22018
22123
  init_mesh_events_pending();
22019
22124
  init_mesh_ledger();
@@ -29259,6 +29364,7 @@ function buildMeshLedgerReconciliationEvidence(meshId, replicas) {
29259
29364
  // src/index.ts
29260
29365
  init_mesh_work_queue();
29261
29366
  init_mesh_active_work();
29367
+ init_mesh_idle_reminder();
29262
29368
  init_mesh_refine_status();
29263
29369
  init_mesh_magi_status();
29264
29370
  init_mesh_scheduling_runtime();
@@ -29269,8 +29375,8 @@ init_mesh_events_utils();
29269
29375
  init_mesh_delivery_policy();
29270
29376
 
29271
29377
  // src/mesh/p2p-relay-failure.ts
29272
- var NO_FALLBACK_REASON = "Repo Mesh command/data-plane is P2P-only; WS/REST command fallback is intentionally disabled to preserve the transport boundary.";
29273
- var P2P_NEXT_ACTION = "Check daemon/P2P health, wait briefly for connection establishment, then do one bounded retry or requeue the mesh task after clearing stale target session metadata.";
29378
+ var NO_FALLBACK_REASON = "This mesh operation needs a live peer-to-peer connection to the node, which is not open right now. This is often transient \u2014 the peer may be connecting, slow via TURN relay, or briefly offline. Wait a moment and retry, or re-establish the node's connection. Mesh commands use P2P only by design \u2014 there is no cloud/WS relay fallback.";
29379
+ var P2P_NEXT_ACTION = "The peer connection is recoverable. Wait a moment for the connection to establish (especially over TURN relay), then retry. If the node remains unreachable, check that the target daemon is running and online, then re-establish its connection.";
29274
29380
  var NON_P2P_NEXT_ACTION = "Inspect the provider/command error and fix the underlying logic or configuration before retrying.";
29275
29381
  function messageFromError(error) {
29276
29382
  if (error instanceof Error) return error.message;
@@ -70359,6 +70465,7 @@ export {
70359
70465
  GOAL_PREVIEW_MAX,
70360
70466
  GitCommandError,
70361
70467
  GitWorkspaceMonitor,
70468
+ IDLE_REMINDER_DEBOUNCE_MS,
70362
70469
  IdeProviderInstance,
70363
70470
  InMemoryGitSnapshotStore,
70364
70471
  LOG,
@@ -70419,6 +70526,7 @@ export {
70419
70526
  buildClaudeInteractiveToolResult,
70420
70527
  buildCompactStaleDirectWorkSummary,
70421
70528
  buildCoordinatorSystemPrompt,
70529
+ buildIdleReminderMessage,
70422
70530
  buildIpcStatusHttpResponse,
70423
70531
  buildMachineInfo,
70424
70532
  buildMeshActiveWork,
@@ -70593,11 +70701,13 @@ export {
70593
70701
  markSessionDeliveriesTerminal,
70594
70702
  markSetupComplete,
70595
70703
  markStaleDirectDispatches,
70704
+ maybeInjectIdleActiveMissionReminder,
70596
70705
  maybeRunDaemonUpgradeHelperFromEnv,
70597
70706
  mergeAndNormalizePolicy,
70598
70707
  meshNodeIdMatches,
70599
70708
  meshTaskNotBeforeReady,
70600
70709
  meshTaskPriorityRank,
70710
+ missionSetHash,
70601
70711
  namedKeyToAnsi,
70602
70712
  namedKeysToAnsi,
70603
70713
  nodeSatisfiesRequiredTags,
@@ -70694,6 +70804,7 @@ export {
70694
70804
  setupIdeInstance,
70695
70805
  shouldAutoRestoreHostedSessionsOnStartup,
70696
70806
  shouldCollectTraceCategory,
70807
+ shouldFireIdleReminder,
70697
70808
  shutdownDaemonComponents,
70698
70809
  spawnDetachedDaemonUpgradeHelper,
70699
70810
  startDaemonDevSupport,