@adhdev/daemon-core 0.9.82-rc.420 → 0.9.82-rc.422

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.d.ts CHANGED
@@ -68,7 +68,7 @@ export type { MeshSchedulingRuntime, MeshNodeSchedulingRuntime, MeshNodeProvider
68
68
  export { buildMeshHostRequiredFailure, createDefaultMeshHostMetadata, isMeshHostOwner, normalizeMeshDaemonRole, requireMeshHostQueueOwner, resolveMeshHostStatus } from './mesh/mesh-host-ownership.js';
69
69
  export { triggerMeshQueue, drainPendingMeshCoordinatorEvents, getPendingMeshCoordinatorEvents, clearPendingMeshCoordinatorEvents, queuePendingMeshCoordinatorEvent, reconcileDirectDispatchCompletionFromTranscript } from './mesh/mesh-events.js';
70
70
  export type { PendingMeshCoordinatorEvent } from './mesh/mesh-events.js';
71
- export { resolveMeshSurfacedSessionPreview, readMeshCompletionSummary } from './mesh/mesh-events-utils.js';
71
+ export { resolveMeshSurfacedSessionPreview, readMeshCompletionSummary, isWeakCompletionEvidence } from './mesh/mesh-events-utils.js';
72
72
  export { resolveDeliveryDecision, createSessionDelivery, updateSessionDeliveryStatus, getActiveSessionDeliveries, markSessionDeliveriesTerminal, recordCompletionConflict, getRecentCompletionConflicts } from './mesh/mesh-delivery-policy.js';
73
73
  export type { MeshSessionDeliveryStatus, MeshSessionDeliveryKind, MeshDeliveryDecision, MeshDeliveryPolicyResult, SessionDeliveryRecord } from './mesh/mesh-delivery-policy.js';
74
74
  export { P2pRelayFailureError, buildP2pRelayFailurePayload, classifyP2pRelayFailure, isP2pRelayTransportFailure, } from './mesh/p2p-relay-failure.js';
package/dist/index.js CHANGED
@@ -389,10 +389,10 @@ function readInjected(value) {
389
389
  }
390
390
  function getDaemonBuildInfo() {
391
391
  if (cached) return cached;
392
- const commit = readInjected(true ? "bd19cb0fbe1e16db1d8d2fcd8c2c871aae3ce33b" : void 0) ?? "unknown";
393
- const commitShort = readInjected(true ? "bd19cb0f" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
394
- const version = readInjected(true ? "0.9.82-rc.420" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
395
- const builtAt = readInjected(true ? "2026-06-28T19:41:31.696Z" : void 0);
392
+ const commit = readInjected(true ? "308e099c65d2de2491f3db46913f9ced6aa3992c" : void 0) ?? "unknown";
393
+ const commitShort = readInjected(true ? "308e099c" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
394
+ const version = readInjected(true ? "0.9.82-rc.422" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
395
+ const builtAt = readInjected(true ? "2026-06-29T05:26:31.350Z" : void 0);
396
396
  cached = builtAt ? { commit, commitShort, version, builtAt } : { commit, commitShort, version };
397
397
  return cached;
398
398
  }
@@ -3686,21 +3686,6 @@ var init_async_batch_writer = __esm({
3686
3686
  });
3687
3687
 
3688
3688
  // src/logging/logger.ts
3689
- var logger_exports = {};
3690
- __export(logger_exports, {
3691
- LOG: () => LOG,
3692
- LOG_DIR_PATH: () => LOG_DIR_PATH,
3693
- LOG_PATH: () => LOG_PATH,
3694
- daemonLog: () => daemonLog,
3695
- getCurrentDaemonLogPath: () => getCurrentDaemonLogPath,
3696
- getDaemonLogDir: () => getDaemonLogDir,
3697
- getLogBufferSize: () => getLogBufferSize,
3698
- getLogLevel: () => getLogLevel,
3699
- getLogPath: () => getLogPath,
3700
- getRecentLogs: () => getRecentLogs,
3701
- installGlobalInterceptor: () => installGlobalInterceptor,
3702
- setLogLevel: () => setLogLevel
3703
- });
3704
3689
  function setLogLevel(level) {
3705
3690
  currentLevel = level;
3706
3691
  daemonLog("Logger", `Log level set to: ${level}`, "info");
@@ -3772,9 +3757,6 @@ function getRecentLogs(count = 50, minLevel = "info") {
3772
3757
  const filtered = ringBuffer.filter((e) => LEVEL_NUM[e.level] >= minNum);
3773
3758
  return filtered.slice(-count);
3774
3759
  }
3775
- function getLogBufferSize() {
3776
- return ringBuffer.length;
3777
- }
3778
3760
  function ts() {
3779
3761
  return (/* @__PURE__ */ new Date()).toISOString().slice(11, 23);
3780
3762
  }
@@ -3854,10 +3836,7 @@ function installGlobalInterceptor() {
3854
3836
  writeToFile(`Log file: ${currentLogFile}`);
3855
3837
  writeToFile(`Log level: ${currentLevel}`);
3856
3838
  }
3857
- function getLogPath() {
3858
- return currentLogFile;
3859
- }
3860
- var fs4, path9, os3, LEVEL_NUM, LEVEL_LABEL, currentLevel, ADHDEV_HOME, LOG_DIR, MAX_LOG_SIZE, MAX_LOG_DAYS, currentDate, currentLogFile, writeCount, RING_BUFFER_SIZE, ringBuffer, origConsoleLog, origConsoleError, origConsoleWarn, LOG, interceptorInstalled, LOG_PATH, LOG_DIR_PATH;
3839
+ var fs4, path9, os3, LEVEL_NUM, LEVEL_LABEL, currentLevel, ADHDEV_HOME, LOG_DIR, MAX_LOG_SIZE, MAX_LOG_DAYS, currentDate, currentLogFile, writeCount, RING_BUFFER_SIZE, ringBuffer, origConsoleLog, origConsoleError, origConsoleWarn, LOG, interceptorInstalled, LOG_PATH;
3861
3840
  var init_logger = __esm({
3862
3841
  "src/logging/logger.ts"() {
3863
3842
  "use strict";
@@ -3919,7 +3898,6 @@ var init_logger = __esm({
3919
3898
  };
3920
3899
  interceptorInstalled = false;
3921
3900
  LOG_PATH = path9.join(LOG_DIR, `daemon-${getDateStr()}.log`);
3922
- LOG_DIR_PATH = LOG_DIR;
3923
3901
  }
3924
3902
  });
3925
3903
 
@@ -12528,6 +12506,23 @@ function liveSessionCountForNode(components, meshId, nodeId) {
12528
12506
  return !isTerminalSessionStatus(status);
12529
12507
  }).length;
12530
12508
  }
12509
+ function nodeHasLiveSessionPendingClaim(components, meshId, nodeId) {
12510
+ const busySessionIds = new Set(
12511
+ getQueue(meshId, { status: ["assigned"] }).filter((task) => daemonIdsEquivalent(task.assignedNodeId, nodeId)).map((task) => readNonEmptyString2(task.assignedSessionId)).filter(Boolean)
12512
+ );
12513
+ return components.instanceManager.getByCategory("cli").some((inst) => {
12514
+ const state = inst.getState();
12515
+ const settings = state.settings || {};
12516
+ if (readNonEmptyString2(settings.meshNodeFor) !== meshId) return false;
12517
+ const instNodeId = readNonEmptyString2(settings.meshNodeId) || readNonEmptyString2(settings.nodeId);
12518
+ if (!daemonIdsEquivalent(instNodeId, nodeId)) return false;
12519
+ const status = readNonEmptyString2(state.status).toLowerCase();
12520
+ if (isTerminalSessionStatus(status)) return false;
12521
+ const sessionId = readNonEmptyString2(state.instanceId);
12522
+ if (sessionId && busySessionIds.has(sessionId)) return false;
12523
+ return true;
12524
+ });
12525
+ }
12531
12526
  function recordAutoLaunchEvent(meshId, args) {
12532
12527
  const dedupKey = `${meshId}:${args.taskId}`;
12533
12528
  const currentSig = `${args.phase}|${args.reason || ""}`;
@@ -12713,6 +12708,10 @@ async function maybeAutoLaunchOneQueueSession(components, meshId, mesh) {
12713
12708
  sweepExpiredCooldowns();
12714
12709
  continue;
12715
12710
  }
12711
+ if (nodeHasLiveSessionPendingClaim(components, meshId, nodeId)) {
12712
+ markAutoLaunch(meshId, task.id, { status: "skipped", reason: "node_has_live_session_pending_claim", nodeId });
12713
+ continue;
12714
+ }
12716
12715
  if (!isTaskReadonly(task) && nodeHasActiveAssignment(meshId, nodeId)) {
12717
12716
  markAutoLaunch(meshId, task.id, { status: "skipped", reason: "node_has_active_assignment", nodeId });
12718
12717
  continue;
@@ -16558,6 +16557,62 @@ function ackUnresolvedDelegateForwardByFingerprint(coordinatorDaemonId, eventNam
16558
16557
  );
16559
16558
  if (match) ackUnresolvedDelegateForward(match.id);
16560
16559
  }
16560
+ function flushPendingForMeshIdleCoordinators(components, meshId) {
16561
+ try {
16562
+ const store = MeshRuntimeStore.getInstance();
16563
+ if (store.pendingEventCount(meshId) === 0) return;
16564
+ } catch {
16565
+ }
16566
+ const idleCoordinators = [];
16567
+ try {
16568
+ for (const inst of components.instanceManager.getByCategory("cli")) {
16569
+ const state = inst.getState();
16570
+ const settings = state.settings && typeof state.settings === "object" ? state.settings : {};
16571
+ if (readNonEmptyString2(settings.meshCoordinatorFor) !== meshId) continue;
16572
+ const status = readNonEmptyString2(state.status).toLowerCase();
16573
+ const modalParked = typeof inst.isModalParked === "function" ? inst.isModalParked() === true : status === "waiting_choice" || status === "waiting_approval";
16574
+ if (status === "idle" && !modalParked) {
16575
+ idleCoordinators.push({ instance: inst, sessionId: readNonEmptyString2(state.instanceId) });
16576
+ }
16577
+ }
16578
+ } catch {
16579
+ return;
16580
+ }
16581
+ if (idleCoordinators.length === 0) return;
16582
+ const drainDaemonIds = resolveCoordinatorDrainDaemonIds(components);
16583
+ let pendingEvents;
16584
+ try {
16585
+ pendingEvents = drainPendingMeshCoordinatorEvents(meshId, drainDaemonIds.length > 0 ? drainDaemonIds : void 0);
16586
+ } catch (e) {
16587
+ LOG.warn("MeshEvents", `Event-driven coordinator drain failed for mesh ${meshId}: ${e?.message || e}`);
16588
+ return;
16589
+ }
16590
+ if (pendingEvents.length === 0) return;
16591
+ let delivered = 0;
16592
+ for (const pending of pendingEvents) {
16593
+ const wantSession = readNonEmptyString2(pending.targetCoordinatorSessionId);
16594
+ const targets = wantSession ? idleCoordinators.filter((c) => c.sessionId === wantSession) : idleCoordinators;
16595
+ if (targets.length === 0 || !pending.coordinatorMessage) {
16596
+ try {
16597
+ queuePendingMeshCoordinatorEvent(pending);
16598
+ } catch {
16599
+ }
16600
+ continue;
16601
+ }
16602
+ const message = pending.coordinatorMessage;
16603
+ const force = shouldForceInjectMeshEvent(pending.event);
16604
+ for (const c of targets) {
16605
+ c.instance.onEvent("send_message", {
16606
+ input: { text: message, textFallback: message },
16607
+ ...force ? { force: true } : {}
16608
+ });
16609
+ delivered++;
16610
+ }
16611
+ }
16612
+ if (delivered > 0) {
16613
+ LOG.info("MeshEvents", `Event-driven drain delivered ${delivered} pending event(s) to ${idleCoordinators.length} idle coordinator(s) for mesh ${meshId}`);
16614
+ }
16615
+ }
16561
16616
  function setupMeshEventForwarding(components) {
16562
16617
  components.instanceManager.onEvent((event) => {
16563
16618
  if (event.event === "agent:ready" || event.event === "agent:generating_completed") {
@@ -16629,6 +16684,7 @@ function setupMeshEventForwarding(components) {
16629
16684
  event: event.event,
16630
16685
  metadataEvent: event
16631
16686
  });
16687
+ flushPendingForMeshIdleCoordinators(components, routing.meshId);
16632
16688
  });
16633
16689
  }
16634
16690
  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;
@@ -16749,7 +16805,7 @@ function findLiveCoordinators(components) {
16749
16805
  const meshId = readNonEmptyString2(settings.meshCoordinatorFor);
16750
16806
  if (!meshId) continue;
16751
16807
  const status = readNonEmptyString2(state.status).toLowerCase();
16752
- const modalParked = status === "waiting_choice" || status === "waiting_approval";
16808
+ const modalParked = typeof inst.isModalParked === "function" ? inst.isModalParked() === true : status === "waiting_choice" || status === "waiting_approval";
16753
16809
  const sessionId = readNonEmptyString2(state.instanceId);
16754
16810
  const stateKey = `${meshId}::${sessionId || "?"}`;
16755
16811
  const prevParked = coordinatorModalParkState.get(stateKey);
@@ -23482,6 +23538,7 @@ __export(index_exports, {
23482
23538
  isSetupComplete: () => isSetupComplete,
23483
23539
  isTaskReadonly: () => isTaskReadonly,
23484
23540
  isUserFacingChatMessage: () => isUserFacingChatMessage,
23541
+ isWeakCompletionEvidence: () => isWeakCompletionEvidence,
23485
23542
  killIdeProcess: () => killIdeProcess,
23486
23543
  launchIDE: () => launchIDE,
23487
23544
  launchWithCdp: () => launchWithCdp,
@@ -41032,10 +41089,27 @@ var CliProviderInstance = class _CliProviderInstance {
41032
41089
  return null;
41033
41090
  }
41034
41091
  if (adapterStatus.status === "waiting_approval" && (!this.autoApproveEffectivelyActive(adapterStatus.status) || this.autoApproveMaskStalled())) {
41092
+ if (this.isTransientToolConsent()) {
41093
+ return null;
41094
+ }
41035
41095
  return "waiting_approval";
41036
41096
  }
41037
41097
  return null;
41038
41098
  }
41099
+ /**
41100
+ * NOTIF-HELD-DRAIN: true when this `waiting_approval` is a routine, transient tool-consent
41101
+ * of an autonomously-progressing mesh session rather than a genuine human-await modal —
41102
+ * i.e. it is a mesh coordinator/worker session, a turn is actively in flight
41103
+ * (hasAdapterPendingResponse), and no human is attending it by hand. Such a consent is
41104
+ * driven to resolution by the harness/operator as part of the in-flight turn, so holding
41105
+ * the mesh's completion events behind it (modal_parked) is the false-positive that stalls
41106
+ * delivery. Narrow by design: manual attendance or a non-progressing session falls through
41107
+ * to the genuine-modal classification.
41108
+ */
41109
+ isTransientToolConsent(now = Date.now()) {
41110
+ const isAutonomousMeshSession = this.isMeshWorkerSession() || !!this.settings.meshCoordinatorFor;
41111
+ return isAutonomousMeshSession && this.hasAdapterPendingResponse() && !this.manualAttendance.isAttended(now);
41112
+ }
41039
41113
  /** True when this session is parked on a modal awaiting a human answer. */
41040
41114
  isModalParked() {
41041
41115
  return this.resolveModalParkStatus() !== null;
@@ -44911,8 +44985,9 @@ Run 'adhdev doctor' for detailed diagnostics.`
44911
44985
  const meshContext = args?.meshContext;
44912
44986
  if (meshContext && typeof meshContext === "object" && typeof meshContext.meshId === "string" && meshContext.meshId) {
44913
44987
  const targetInstanceId = key2;
44988
+ let stampResult;
44914
44989
  try {
44915
- this.deps.getInstanceManager()?.attachMeshAssignmentToInstance(targetInstanceId, {
44990
+ stampResult = this.deps.getInstanceManager()?.attachMeshAssignmentToInstance(targetInstanceId, {
44916
44991
  meshId: meshContext.meshId,
44917
44992
  ...typeof meshContext.nodeId === "string" && meshContext.nodeId ? { nodeId: meshContext.nodeId } : {},
44918
44993
  ...typeof meshContext.taskId === "string" && meshContext.taskId ? { taskId: meshContext.taskId } : {},
@@ -44920,6 +44995,9 @@ Run 'adhdev doctor' for detailed diagnostics.`
44920
44995
  });
44921
44996
  } catch {
44922
44997
  }
44998
+ if (stampResult && stampResult.stamped === false && stampResult.reason === "task_already_stamped_on_live_instance") {
44999
+ throw new Error(`Refusing duplicate mesh dispatch: task ${meshContext.taskId} is already being worked by a live session on this daemon`);
45000
+ }
44923
45001
  }
44924
45002
  const input = normalizeInputEnvelope(args?.input ? { input: args.input } : args);
44925
45003
  const provider = this.providerLoader.resolve(agentType) || this.providerLoader.getMeta(agentType);
@@ -58527,25 +58605,54 @@ var ProviderInstanceManager = class {
58527
58605
  }
58528
58606
  /** Stamp a mesh assignment on a single instance (used by mesh_send_task
58529
58607
  * --direct so the worker's completion event has a coordinator routing
58530
- * marker in state.settings). Returns true if the instance existed and
58531
- * the stamp was applied. */
58608
+ * marker in state.settings). Returns `{ stamped: true }` when the stamp was
58609
+ * applied, or `{ stamped: false, reason }` when it was refused — the instance
58610
+ * was missing / has no attach method, or the DOUBLE-DISPATCH idempotence guard
58611
+ * fired (the same task is already running on another live session here). */
58532
58612
  attachMeshAssignmentToInstance(instanceId, assignment) {
58533
58613
  const inst = this.instances.get(instanceId);
58534
58614
  if (!inst || typeof inst.attachMeshAssignment !== "function") {
58535
- try {
58536
- const { LOG: LOG2 } = (init_logger(), __toCommonJS(logger_exports));
58537
- LOG2.warn?.("MeshDispatch", `attachMeshAssignment skipped: instance ${instanceId} ${inst ? "has no attach method" : "not found"}`);
58538
- } catch {
58615
+ LOG.warn("MeshDispatch", `attachMeshAssignment skipped: instance ${instanceId} ${inst ? "has no attach method" : "not found"}`);
58616
+ return { stamped: false, reason: inst ? "instance_has_no_attach_method" : "instance_not_found" };
58617
+ }
58618
+ if (assignment.taskId) {
58619
+ const conflict = this.findLiveWorkingTaskHolder(assignment.meshId, assignment.taskId, instanceId);
58620
+ if (conflict) {
58621
+ LOG.warn("MeshDispatch", `attachMeshAssignment refused: task ${assignment.taskId} (mesh ${assignment.meshId}) is already being worked by live session ${conflict} \u2014 skipping duplicate stamp on ${instanceId}`);
58622
+ return { stamped: false, reason: "task_already_stamped_on_live_instance" };
58539
58623
  }
58540
- return false;
58541
58624
  }
58542
58625
  inst.attachMeshAssignment(assignment);
58543
- try {
58544
- const { LOG: LOG2 } = (init_logger(), __toCommonJS(logger_exports));
58545
- LOG2.info?.("MeshDispatch", `stamped mesh assignment on ${instanceId}: mesh=${assignment.meshId} node=${assignment.nodeId || ""} task=${assignment.taskId || ""} coordinator=${assignment.coordinatorDaemonId || ""}`);
58546
- } catch {
58626
+ LOG.info("MeshDispatch", `stamped mesh assignment on ${instanceId}: mesh=${assignment.meshId} node=${assignment.nodeId || ""} task=${assignment.taskId || ""} coordinator=${assignment.coordinatorDaemonId || ""}`);
58627
+ return { stamped: true };
58628
+ }
58629
+ /**
58630
+ * DOUBLE-DISPATCH support: the id of another LIVE, actively-working instance that already
58631
+ * holds (meshId, taskId), or null. "Live working" = stamped with this exact mesh+task AND
58632
+ * currently mid-turn / booting toward it (generating / waiting on approval-or-choice /
58633
+ * starting) — NOT idle, stopped, or errored. A stale/dead/idle holder is deliberately
58634
+ * ignored so a legitimate re-dispatch (e.g. after a dispatch failure) is never blocked.
58635
+ * The instance being stamped (excludeInstanceId) is skipped so re-stamping the same
58636
+ * session stays idempotent. O(n) over instances — the count is small.
58637
+ */
58638
+ findLiveWorkingTaskHolder(meshId, taskId, excludeInstanceId) {
58639
+ const working = /* @__PURE__ */ new Set(["generating", "waiting_approval", "waiting_choice", "starting", "streaming", "working", "no_progress", "long_generating"]);
58640
+ for (const [id, inst] of this.instances) {
58641
+ if (id === excludeInstanceId) continue;
58642
+ let state;
58643
+ try {
58644
+ state = inst.getState();
58645
+ } catch {
58646
+ continue;
58647
+ }
58648
+ const settings = state.settings || {};
58649
+ if (settings.meshNodeFor !== meshId) continue;
58650
+ if (settings.meshActiveTaskId !== taskId) continue;
58651
+ const status = (typeof state.status === "string" ? state.status : "").toLowerCase();
58652
+ const chatStatus = (typeof state.activeChat?.status === "string" ? state.activeChat.status : "").toLowerCase();
58653
+ if (working.has(status) || working.has(chatStatus)) return id;
58547
58654
  }
58548
- return true;
58655
+ return null;
58549
58656
  }
58550
58657
  /** Clear a mesh assignment after the dispatched task reaches a terminal
58551
58658
  * state (generating_completed / stopped / failed). */
@@ -65244,6 +65351,7 @@ var V1_CONTRACT_VERSION = "1.0.0";
65244
65351
  isSetupComplete,
65245
65352
  isTaskReadonly,
65246
65353
  isUserFacingChatMessage,
65354
+ isWeakCompletionEvidence,
65247
65355
  killIdeProcess,
65248
65356
  launchIDE,
65249
65357
  launchWithCdp,