@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.
@@ -20,8 +20,8 @@ export declare function buildRefineJobHandle(self: DaemonCommandRouter, args: {
20
20
  * The full `CommandRouterResult` (with `validationSummary.commandsRun[]` carrying
21
21
  * per-command stdout/stderr, `rejectedCommands`, `suggestions`, `suggestedConfig`,
22
22
  * the full `patchEquivalence`, and `submoduleReachability.entries[]`/`.unreachable[]`)
23
- * routinely exceeds 70KB and overflows the coordinator token limit when it rides on a
24
- * `mesh_wait_events` payload. The full detail is still persisted verbatim to the ledger
23
+ * routinely exceeds 70KB and overflows the coordinator token limit when surfaced as a
24
+ * coordinator event payload. The full detail is still persisted verbatim to the ledger
25
25
  * (`appendRefineJobLedger`) and `terminalRefineJobs`, so slimming only the EVENT loses
26
26
  * nothing — the coordinator can pull the full record on demand via
27
27
  * `evidence.ledgerCommand` / `taskHistoryKind`.
package/dist/index.d.ts CHANGED
@@ -62,6 +62,7 @@ export type { MeshWorkQueueEntry, MeshTaskStatus, MeshTaskMode, MeshTaskPriority
62
62
  export { buildCompactStaleDirectWorkSummary, buildMeshActiveWork, buildMeshActiveWorkSummary, collectPendingApprovals, classifyStaleDirectForPrune, pruneStaleDirectDispatches, PRUNABLE_ORPHAN_STALE_REASONS } from './mesh/mesh-active-work.js';
63
63
  export type { StaleDirectPruneClassification, StaleDirectPruneResult, PruneStaleDirectDispatchesOptions } from './mesh/mesh-active-work.js';
64
64
  export type { MeshActiveWorkRecord, MeshActiveWorkStatus, MeshActiveWorkSummary, MeshActiveWorkSource, MeshStaleDirectWorkSummary, MeshPendingApproval } from './mesh/mesh-active-work.js';
65
+ export { maybeInjectIdleActiveMissionReminder, shouldFireIdleReminder, buildIdleReminderMessage, missionSetHash, IDLE_REMINDER_DEBOUNCE_MS } from './mesh/mesh-idle-reminder.js';
65
66
  export { buildMeshAsyncRefineJobs, summarizeMeshAsyncRefineJobs, STALE_TERMINAL_REFINE_WINDOW_MS, RECENT_TERMINAL_REFINE_CAP } from './mesh/mesh-refine-status.js';
66
67
  export type { MeshAsyncRefineJobStatus, MeshAsyncRefineJobSummary, MeshAsyncRefineJobsSummary } from './mesh/mesh-refine-status.js';
67
68
  export { buildMeshMagiActivity, summarizeMeshMagiActivity, getMeshMagiActivityByGroup, STALE_MAGI_WINDOW_MS, RECENT_MAGI_CAP, MAGI_NEEDS_VERIFICATION_PREVIEW_CAP } from './mesh/mesh-magi-status.js';
package/dist/index.js CHANGED
@@ -175,7 +175,10 @@ var init_repo_mesh_types = __esm({
175
175
  // auto-launched sessions are cleaned — see RepoMeshMagiSessionCleanupMode.
176
176
  magiSessionCleanup: "stop_and_delete",
177
177
  autoFastForward: { enabled: true },
178
- maxTaskRetries: 1
178
+ maxTaskRetries: 1,
179
+ // Nudge the coordinator when the mesh is fully idle but active missions linger,
180
+ // so a mission is never left drifting in `active` after its work is really done.
181
+ idleActiveMissionReminder: true
179
182
  };
180
183
  SESSION_CLEANUP_MODES = /* @__PURE__ */ new Set([
181
184
  "preserve",
@@ -414,10 +417,10 @@ function readInjected(value) {
414
417
  }
415
418
  function getDaemonBuildInfo() {
416
419
  if (cached) return cached;
417
- const commit = readInjected(true ? "c05e29374bd592e460427419beb06a7fde594f4b" : void 0) ?? "unknown";
418
- const commitShort = readInjected(true ? "c05e2937" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
419
- const version = readInjected(true ? "0.9.82-rc.494" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
420
- const builtAt = readInjected(true ? "2026-07-10T09:19:42.151Z" : void 0);
420
+ const commit = readInjected(true ? "bafa66a406e7efc123493af30c0779646ea02c5c" : void 0) ?? "unknown";
421
+ const commitShort = readInjected(true ? "bafa66a4" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
422
+ const version = readInjected(true ? "0.9.82-rc.496" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
423
+ const builtAt = readInjected(true ? "2026-07-11T16:11:16.059Z" : void 0);
421
424
  cached = builtAt ? { commit, commitShort, version, builtAt } : { commit, commitShort, version };
422
425
  return cached;
423
426
  }
@@ -2930,7 +2933,6 @@ var init_dist = __esm({
2930
2933
  "mesh_forget_note",
2931
2934
  "mesh_reconcile_ledger",
2932
2935
  "mesh_requeue_held_events",
2933
- "mesh_wait_events",
2934
2936
  "mesh_mission_upsert",
2935
2937
  "mesh_mission_list",
2936
2938
  "mesh_review_inbox",
@@ -3944,7 +3946,6 @@ var init_coordinator_prompt = __esm({
3944
3946
  | \`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 |
3945
3947
  | \`mesh_reconcile_ledger\` | Reconcile daemon-local ledgers over P2P \u2014 import missing entries from remote nodes into the coordinator local ledger |
3946
3948
  | \`mesh_requeue_held_events\` | Restore recoverable held coordinator events (T6 quarantine / pending-trim) back to the pending queue; lossless, no double-requeue |
3947
- | \`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 |
3948
3949
  | \`mesh_review_inbox\` | List local worktree nodes needing human review \u2014 merge candidates and Refinery-blocked results with evidence/diff summaries |
3949
3950
  | \`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 |
3950
3951
  | \`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) |
@@ -6499,6 +6500,13 @@ var init_mesh_runtime_store = __esm({
6499
6500
  db;
6500
6501
  dbPath;
6501
6502
  migratedMeshIds = /* @__PURE__ */ new Set();
6503
+ // Idle-active-mission-reminder debounce (mesh-idle-reminder.ts). In-memory only:
6504
+ // this is a spam guard for a best-effort coordinator nudge, so a daemon restart
6505
+ // resetting it (at most one extra reminder) is harmless — no SQLite persistence
6506
+ // is warranted. Keyed by meshId; the value records when the last reminder fired
6507
+ // and the hash of the active-mission id set it named, so a changed mission set
6508
+ // re-fires before the time window elapses.
6509
+ idleReminderState = /* @__PURE__ */ new Map();
6502
6510
  fingerprintSweepCounter = 0;
6503
6511
  walWriteCounter = 0;
6504
6512
  // Independent cadence for the tool-call-log sweep. Must NOT share walWriteCounter:
@@ -8094,6 +8102,22 @@ var init_mesh_runtime_store = __esm({
8094
8102
  "UPDATE mesh_missions SET close_candidate_emitted_at = ? WHERE mesh_id = ? AND id = ?"
8095
8103
  ).run(emittedAt, meshId, missionId).changes;
8096
8104
  }
8105
+ /**
8106
+ * Read the last idle-active-mission-reminder debounce marker for a mesh, or null if
8107
+ * none has fired this process. In-memory only (see idleReminderState) — best-effort
8108
+ * spam guard for a coordinator nudge, intentionally not SQLite-backed.
8109
+ */
8110
+ getIdleReminderState(meshId) {
8111
+ return this.idleReminderState.get(meshId) ?? null;
8112
+ }
8113
+ /** Record that an idle-active-mission reminder just fired for a mesh (debounce marker). */
8114
+ setIdleReminderState(meshId, state) {
8115
+ this.idleReminderState.set(meshId, state);
8116
+ }
8117
+ /** Clear the idle-reminder debounce marker for a mesh — mesh deletion / test cleanup. */
8118
+ clearIdleReminderState(meshId) {
8119
+ this.idleReminderState.delete(meshId);
8120
+ }
8097
8121
  /** Remove all missions for a mesh — mesh deletion / test cleanup. */
8098
8122
  clearMissionsForMesh(meshId) {
8099
8123
  return this.db.prepare("DELETE FROM mesh_missions WHERE mesh_id = ?").run(meshId).changes;
@@ -12601,6 +12625,72 @@ var init_mesh_active_work = __esm({
12601
12625
  }
12602
12626
  });
12603
12627
 
12628
+ // src/mesh/mesh-idle-reminder.ts
12629
+ function missionSetHash(missions) {
12630
+ return missions.map((m) => m.id).sort().join(",");
12631
+ }
12632
+ function shouldFireIdleReminder(last, hash, now, debounceMs = IDLE_REMINDER_DEBOUNCE_MS) {
12633
+ if (!last) return true;
12634
+ if (now - last.emittedAt > debounceMs) return true;
12635
+ return hash !== last.missionSetHash;
12636
+ }
12637
+ function buildIdleReminderMessage(missions) {
12638
+ const shown = missions.slice(0, MISSION_LIST_CAP);
12639
+ const lines = shown.map((m) => `- ${m.title} (${m.id})`);
12640
+ const overflow = missions.length - shown.length;
12641
+ if (overflow > 0) lines.push(`- \u2026and ${overflow} more`);
12642
+ return `[System] Coordinator idle with ${missions.length} active mission(s):
12643
+ ${lines.join("\n")}
12644
+ 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.`;
12645
+ }
12646
+ function maybeInjectIdleActiveMissionReminder(meshId, coordinator, policy, now = Date.now()) {
12647
+ try {
12648
+ if (!coordinator) return false;
12649
+ if (policy?.idleActiveMissionReminder === false) return false;
12650
+ const activeMissions = getMeshMissions(meshId, ["active"]);
12651
+ if (activeMissions.length === 0) return false;
12652
+ const summary = buildMeshActiveWork({
12653
+ meshId,
12654
+ queue: getQueue(meshId),
12655
+ directDispatches: getActiveDirectDispatches(meshId),
12656
+ ledgerEntries: readLedgerEntries(meshId, { tail: 200 }),
12657
+ now
12658
+ }).summary;
12659
+ if (summary.totalActiveCount !== 0 || summary.generatingCount !== 0) return false;
12660
+ const store = MeshRuntimeStore.getInstance();
12661
+ const hash = missionSetHash(activeMissions);
12662
+ const last = store.getIdleReminderState(meshId);
12663
+ if (!shouldFireIdleReminder(last, hash, now)) return false;
12664
+ const message = buildIdleReminderMessage(activeMissions);
12665
+ coordinator.onEvent("send_message", {
12666
+ input: { text: message, textFallback: message }
12667
+ });
12668
+ store.setIdleReminderState(meshId, { emittedAt: now, missionSetHash: hash });
12669
+ LOG.info(
12670
+ "MeshIdleReminder",
12671
+ `Injected idle reminder for mesh ${meshId} (${activeMissions.length} active mission(s), fully idle)`
12672
+ );
12673
+ return true;
12674
+ } catch (e) {
12675
+ LOG.warn("MeshIdleReminder", `maybeInjectIdleActiveMissionReminder failed for mesh ${meshId}: ${e?.message || e}`);
12676
+ return false;
12677
+ }
12678
+ }
12679
+ var IDLE_REMINDER_DEBOUNCE_MS, MISSION_LIST_CAP;
12680
+ var init_mesh_idle_reminder = __esm({
12681
+ "src/mesh/mesh-idle-reminder.ts"() {
12682
+ "use strict";
12683
+ init_logger();
12684
+ init_mesh_runtime_store();
12685
+ init_mesh_missions();
12686
+ init_mesh_work_queue();
12687
+ init_mesh_ledger();
12688
+ init_mesh_active_work();
12689
+ IDLE_REMINDER_DEBOUNCE_MS = 3e5;
12690
+ MISSION_LIST_CAP = 10;
12691
+ }
12692
+ });
12693
+
12604
12694
  // src/mesh/mesh-magi-status.ts
12605
12695
  var mesh_magi_status_exports = {};
12606
12696
  __export(mesh_magi_status_exports, {
@@ -20478,6 +20568,12 @@ function setupMeshEventForwarding(components) {
20478
20568
  ...forcePending ? { force: true } : {}
20479
20569
  });
20480
20570
  }
20571
+ } else {
20572
+ maybeInjectIdleActiveMissionReminder(
20573
+ coordinatorMeshId,
20574
+ flushSource,
20575
+ getMesh(coordinatorMeshId)?.policy
20576
+ );
20481
20577
  }
20482
20578
  } catch (e) {
20483
20579
  LOG.warn("MeshEvents", `Failed to auto-flush pending coordinator events: ${e?.message || e}`);
@@ -20537,6 +20633,7 @@ var init_mesh_event_forwarding = __esm({
20537
20633
  init_mesh_work_queue();
20538
20634
  init_mesh_delivery_policy();
20539
20635
  init_mesh_runtime_store();
20636
+ init_mesh_idle_reminder();
20540
20637
  init_mesh_events_pending();
20541
20638
  init_mesh_routing();
20542
20639
  init_mesh_host_ownership();
@@ -20871,7 +20968,7 @@ async function collectLiveNodesWithSessions(components, mesh, selfIds, localDaem
20871
20968
  let statusResult;
20872
20969
  try {
20873
20970
  if (isLocalNode) {
20874
- statusResult = await components.commandHandler.handle("get_status_metadata", {});
20971
+ statusResult = await components.router.execute("get_status_metadata", {}, "mesh");
20875
20972
  } else if (dispatchMeshCommand) {
20876
20973
  statusResult = await dispatchMeshCommand(nodeDaemonId, "get_status_metadata", {});
20877
20974
  } else {
@@ -21838,7 +21935,14 @@ async function runMeshReconcileTick(components) {
21838
21935
  }
21839
21936
  if (store) {
21840
21937
  try {
21841
- if (store.pendingEventCount(meshId) === 0) continue;
21938
+ if (store.pendingEventCount(meshId) === 0) {
21939
+ maybeInjectIdleActiveMissionReminder(
21940
+ meshId,
21941
+ targetCoordinators[0].instance,
21942
+ getMesh(meshId)?.policy
21943
+ );
21944
+ continue;
21945
+ }
21842
21946
  } catch {
21843
21947
  }
21844
21948
  }
@@ -22012,6 +22116,7 @@ var init_mesh_reconcile_loop = __esm({
22012
22116
  "use strict";
22013
22117
  init_config();
22014
22118
  init_mesh_config();
22119
+ init_mesh_idle_reminder();
22015
22120
  init_logger();
22016
22121
  init_mesh_events_pending();
22017
22122
  init_mesh_ledger();
@@ -27945,6 +28050,7 @@ __export(index_exports, {
27945
28050
  GOAL_PREVIEW_MAX: () => GOAL_PREVIEW_MAX,
27946
28051
  GitCommandError: () => GitCommandError,
27947
28052
  GitWorkspaceMonitor: () => GitWorkspaceMonitor,
28053
+ IDLE_REMINDER_DEBOUNCE_MS: () => IDLE_REMINDER_DEBOUNCE_MS,
27948
28054
  IdeProviderInstance: () => IdeProviderInstance,
27949
28055
  InMemoryGitSnapshotStore: () => InMemoryGitSnapshotStore,
27950
28056
  LOG: () => LOG,
@@ -28005,6 +28111,7 @@ __export(index_exports, {
28005
28111
  buildClaudeInteractiveToolResult: () => buildClaudeInteractiveToolResult,
28006
28112
  buildCompactStaleDirectWorkSummary: () => buildCompactStaleDirectWorkSummary,
28007
28113
  buildCoordinatorSystemPrompt: () => buildCoordinatorSystemPrompt,
28114
+ buildIdleReminderMessage: () => buildIdleReminderMessage,
28008
28115
  buildIpcStatusHttpResponse: () => buildIpcStatusHttpResponse,
28009
28116
  buildMachineInfo: () => buildMachineInfo,
28010
28117
  buildMeshActiveWork: () => buildMeshActiveWork,
@@ -28179,11 +28286,13 @@ __export(index_exports, {
28179
28286
  markSessionDeliveriesTerminal: () => markSessionDeliveriesTerminal,
28180
28287
  markSetupComplete: () => markSetupComplete,
28181
28288
  markStaleDirectDispatches: () => markStaleDirectDispatches,
28289
+ maybeInjectIdleActiveMissionReminder: () => maybeInjectIdleActiveMissionReminder,
28182
28290
  maybeRunDaemonUpgradeHelperFromEnv: () => maybeRunDaemonUpgradeHelperFromEnv,
28183
28291
  mergeAndNormalizePolicy: () => mergeAndNormalizePolicy,
28184
28292
  meshNodeIdMatches: () => meshNodeIdMatches,
28185
28293
  meshTaskNotBeforeReady: () => meshTaskNotBeforeReady,
28186
28294
  meshTaskPriorityRank: () => meshTaskPriorityRank,
28295
+ missionSetHash: () => missionSetHash,
28187
28296
  namedKeyToAnsi: () => namedKeyToAnsi,
28188
28297
  namedKeysToAnsi: () => namedKeysToAnsi,
28189
28298
  nodeSatisfiesRequiredTags: () => nodeSatisfiesRequiredTags,
@@ -28280,6 +28389,7 @@ __export(index_exports, {
28280
28389
  setupIdeInstance: () => setupIdeInstance,
28281
28390
  shouldAutoRestoreHostedSessionsOnStartup: () => shouldAutoRestoreHostedSessionsOnStartup,
28282
28391
  shouldCollectTraceCategory: () => shouldCollectTraceCategory,
28392
+ shouldFireIdleReminder: () => shouldFireIdleReminder,
28283
28393
  shutdownDaemonComponents: () => shutdownDaemonComponents,
28284
28394
  spawnDetachedDaemonUpgradeHelper: () => spawnDetachedDaemonUpgradeHelper,
28285
28395
  startDaemonDevSupport: () => startDaemonDevSupport,
@@ -29679,6 +29789,7 @@ function buildMeshLedgerReconciliationEvidence(meshId, replicas) {
29679
29789
  // src/index.ts
29680
29790
  init_mesh_work_queue();
29681
29791
  init_mesh_active_work();
29792
+ init_mesh_idle_reminder();
29682
29793
  init_mesh_refine_status();
29683
29794
  init_mesh_magi_status();
29684
29795
  init_mesh_scheduling_runtime();
@@ -29689,8 +29800,8 @@ init_mesh_events_utils();
29689
29800
  init_mesh_delivery_policy();
29690
29801
 
29691
29802
  // src/mesh/p2p-relay-failure.ts
29692
- var NO_FALLBACK_REASON = "Repo Mesh command/data-plane is P2P-only; WS/REST command fallback is intentionally disabled to preserve the transport boundary.";
29693
- 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.";
29803
+ 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.";
29804
+ 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.";
29694
29805
  var NON_P2P_NEXT_ACTION = "Inspect the provider/command error and fix the underlying logic or configuration before retrying.";
29695
29806
  function messageFromError(error) {
29696
29807
  if (error instanceof Error) return error.message;
@@ -70765,6 +70876,7 @@ var V1_CONTRACT_VERSION = "1.0.0";
70765
70876
  GOAL_PREVIEW_MAX,
70766
70877
  GitCommandError,
70767
70878
  GitWorkspaceMonitor,
70879
+ IDLE_REMINDER_DEBOUNCE_MS,
70768
70880
  IdeProviderInstance,
70769
70881
  InMemoryGitSnapshotStore,
70770
70882
  LOG,
@@ -70825,6 +70937,7 @@ var V1_CONTRACT_VERSION = "1.0.0";
70825
70937
  buildClaudeInteractiveToolResult,
70826
70938
  buildCompactStaleDirectWorkSummary,
70827
70939
  buildCoordinatorSystemPrompt,
70940
+ buildIdleReminderMessage,
70828
70941
  buildIpcStatusHttpResponse,
70829
70942
  buildMachineInfo,
70830
70943
  buildMeshActiveWork,
@@ -70999,11 +71112,13 @@ var V1_CONTRACT_VERSION = "1.0.0";
70999
71112
  markSessionDeliveriesTerminal,
71000
71113
  markSetupComplete,
71001
71114
  markStaleDirectDispatches,
71115
+ maybeInjectIdleActiveMissionReminder,
71002
71116
  maybeRunDaemonUpgradeHelperFromEnv,
71003
71117
  mergeAndNormalizePolicy,
71004
71118
  meshNodeIdMatches,
71005
71119
  meshTaskNotBeforeReady,
71006
71120
  meshTaskPriorityRank,
71121
+ missionSetHash,
71007
71122
  namedKeyToAnsi,
71008
71123
  namedKeysToAnsi,
71009
71124
  nodeSatisfiesRequiredTags,
@@ -71100,6 +71215,7 @@ var V1_CONTRACT_VERSION = "1.0.0";
71100
71215
  setupIdeInstance,
71101
71216
  shouldAutoRestoreHostedSessionsOnStartup,
71102
71217
  shouldCollectTraceCategory,
71218
+ shouldFireIdleReminder,
71103
71219
  shutdownDaemonComponents,
71104
71220
  spawnDetachedDaemonUpgradeHelper,
71105
71221
  startDaemonDevSupport,