@adhdev/daemon-core 0.9.82-rc.395 → 0.9.82-rc.397

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
@@ -378,10 +378,10 @@ function readInjected(value) {
378
378
  }
379
379
  function getDaemonBuildInfo() {
380
380
  if (cached) return cached;
381
- const commit = readInjected(true ? "dea560a6fcafcb5579e0a62e3a2461d6af9aa289" : void 0) ?? "unknown";
382
- const commitShort = readInjected(true ? "dea560a6" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
383
- const version = readInjected(true ? "0.9.82-rc.395" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
384
- const builtAt = readInjected(true ? "2026-06-27T06:46:26.696Z" : void 0);
381
+ const commit = readInjected(true ? "5e6a6bcc5ba51a08f3941445f431cb0411217547" : void 0) ?? "unknown";
382
+ const commitShort = readInjected(true ? "5e6a6bcc" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
383
+ const version = readInjected(true ? "0.9.82-rc.397" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
384
+ const builtAt = readInjected(true ? "2026-06-27T08:32:58.380Z" : void 0);
385
385
  cached = builtAt ? { commit, commitShort, version, builtAt } : { commit, commitShort, version };
386
386
  return cached;
387
387
  }
@@ -5190,6 +5190,7 @@ var init_mesh_runtime_store = __esm({
5190
5190
  init_load_better_sqlite3();
5191
5191
  init_mesh_ledger();
5192
5192
  init_mesh_work_queue();
5193
+ init_dist();
5193
5194
  loggedMigrationFailure = false;
5194
5195
  MeshRuntimeStore = class _MeshRuntimeStore {
5195
5196
  static instance;
@@ -5722,6 +5723,8 @@ var init_mesh_runtime_store = __esm({
5722
5723
  if (providerType && typeof providerMaxParallel === "number" && Number.isFinite(providerMaxParallel) && providerMaxParallel >= 0 && this.activeProviderAssignmentCount(meshId, nodeId, providerType) >= providerMaxParallel) {
5723
5724
  return null;
5724
5725
  }
5726
+ const nodeIdForms = expandDaemonIdForms(nodeId);
5727
+ const nodePinnedPlaceholders = nodeIdForms.map(() => "?").join(", ");
5725
5728
  const rows = [
5726
5729
  ...this.db.prepare(`
5727
5730
  SELECT payload FROM mesh_queue
@@ -5730,9 +5733,9 @@ var init_mesh_runtime_store = __esm({
5730
5733
  `).all(meshId, sessionId),
5731
5734
  ...this.db.prepare(`
5732
5735
  SELECT payload FROM mesh_queue
5733
- WHERE mesh_id = ? AND status = 'pending' AND target_node_id = ? AND target_session_id IS NULL
5736
+ WHERE mesh_id = ? AND status = 'pending' AND target_node_id IN (${nodePinnedPlaceholders}) AND target_session_id IS NULL
5734
5737
  ORDER BY created_at ASC
5735
- `).all(meshId, nodeId),
5738
+ `).all(meshId, ...nodeIdForms),
5736
5739
  ...this.db.prepare(`
5737
5740
  SELECT payload FROM mesh_queue
5738
5741
  WHERE mesh_id = ? AND status = 'pending' AND target_node_id IS NULL AND target_session_id IS NULL
@@ -5762,7 +5765,9 @@ var init_mesh_runtime_store = __esm({
5762
5765
  const convergenceAllows = (candidate) => candidate.taskMode !== "convergence" || !nodeIsWorktree;
5763
5766
  const targetMatches = (candidate) => {
5764
5767
  if (candidate.targetSessionId && candidate.targetSessionId !== sessionId) return false;
5765
- if (candidate.targetNodeId && candidate.targetNodeId !== nodeId) return false;
5768
+ if (candidate.targetNodeId && !daemonIdsEquivalent(candidate.targetNodeId, nodeId) && !meshNodeIdMatches({ id: candidate.targetNodeId }, nodeId)) {
5769
+ return false;
5770
+ }
5766
5771
  return true;
5767
5772
  };
5768
5773
  const entry = candidates.find((candidate) => nodeSatisfiesRequiredTags(candidate.requiredTags, capabilityTags) && dependenciesSatisfied(candidate) && convergenceAllows(candidate) && targetMatches(candidate) && nodeConflictAllows(candidate));
@@ -9859,27 +9864,32 @@ function reconcileDirectDispatchCompletionFromTranscript(args) {
9859
9864
  updateDirectDispatchStatus(args.meshId, args.sessionId, kind === "task_completed" ? "completed" : "failed", args.taskId);
9860
9865
  markSessionDeliveriesTerminal(args.meshId, args.sessionId, kind === "task_completed" ? "completed" : "failed");
9861
9866
  setImmediate(() => cleanupTerminalDirectDispatches());
9867
+ const eventName = kind === "task_completed" ? "agent:generating_completed" : "agent:stopped";
9868
+ const nodeLabel = nodeId ? `Node '${nodeId}'` : "Remote agent";
9869
+ const metadataEvent = {
9870
+ targetSessionId: args.sessionId,
9871
+ providerType: providerType || void 0,
9872
+ providerSessionId: readNonEmptyString2(args.providerSessionId),
9873
+ finalSummary,
9874
+ taskId: args.taskId,
9875
+ workerResult,
9876
+ completionDiagnostic: {
9877
+ reason: "direct_task_transcript_reconciliation",
9878
+ terminalLedgerKind: kind,
9879
+ terminalLedgerId: entry.id
9880
+ }
9881
+ };
9882
+ const targetCoordinatorSessionId = readNonEmptyString2(args.targetCoordinatorSessionId) || readNonEmptyString2(dispatch?.payload?.coordinatorSessionId);
9862
9883
  queuePendingMeshCoordinatorEvent({
9863
- event: kind === "task_completed" ? "agent:generating_completed" : "agent:stopped",
9884
+ event: eventName,
9864
9885
  meshId: args.meshId,
9865
- nodeLabel: nodeId ? `Node '${nodeId}'` : "Remote agent",
9886
+ nodeLabel,
9866
9887
  nodeId: nodeId || void 0,
9867
- metadataEvent: {
9868
- targetSessionId: args.sessionId,
9869
- providerType: providerType || void 0,
9870
- providerSessionId: readNonEmptyString2(args.providerSessionId),
9871
- finalSummary,
9872
- taskId: args.taskId,
9873
- workerResult,
9874
- completionDiagnostic: {
9875
- reason: "direct_task_transcript_reconciliation",
9876
- terminalLedgerKind: kind,
9877
- terminalLedgerId: entry.id
9878
- }
9879
- },
9880
- coordinatorMessage: void 0,
9888
+ metadataEvent,
9889
+ coordinatorMessage: buildMeshSystemMessage({ event: eventName, nodeLabel, metadataEvent }),
9881
9890
  queuedAt: Date.now(),
9882
- ...readNonEmptyString2(args.targetCoordinatorDaemonId) ? { targetCoordinatorDaemonId: readNonEmptyString2(args.targetCoordinatorDaemonId) } : {}
9891
+ ...readNonEmptyString2(args.targetCoordinatorDaemonId) ? { targetCoordinatorDaemonId: readNonEmptyString2(args.targetCoordinatorDaemonId) } : {},
9892
+ ...targetCoordinatorSessionId ? { targetCoordinatorSessionId } : {}
9883
9893
  });
9884
9894
  return { reconciled: true, kind, workerResult, ledgerEntryId: entry.id };
9885
9895
  }
@@ -10774,7 +10784,7 @@ function deliverTaskToSession(dispatchThunk, ctx, warmup) {
10774
10784
  }
10775
10785
  function tryAssignQueueTask(components, meshId, nodeId, sessionId, providerType) {
10776
10786
  const mesh = getMeshWithCache(components, meshId);
10777
- const node = mesh?.nodes.find((n) => readMeshNodeId(n) === nodeId);
10787
+ const node = mesh?.nodes.find((n) => meshNodeIdMatches(n, nodeId));
10778
10788
  const gateNode = mesh?.nodes?.find((n) => meshNodeIdMatches(n, nodeId));
10779
10789
  if (gateNode?.worktreeBootstrap?.status === "running") {
10780
10790
  LOG.info("MeshQueue", `Gating queue claim for worktree node ${nodeId} (${sessionId}): worktree bootstrap still running \u2014 task left pending; claim re-fires once bootstrap reaches a terminal state (guards against dispatching into a half-built worktree \u2192 empty session)`);
@@ -11383,7 +11393,7 @@ async function triggerMeshQueue(components, meshId) {
11383
11393
  const providerType = state.type || readNonEmptyString2(settings.providerType);
11384
11394
  if (providerType) {
11385
11395
  localIdleSessionsChecked += 1;
11386
- localCandidates.push({ nodeId, sessionId, providerType, origin: "local", node: mesh.nodes.find((n) => readMeshNodeId(n) === nodeId) });
11396
+ localCandidates.push({ nodeId, sessionId, providerType, origin: "local", node: mesh.nodes.find((n) => meshNodeIdMatches(n, nodeId)) });
11387
11397
  } else {
11388
11398
  skippedSessions.push({
11389
11399
  nodeId,
@@ -15217,7 +15227,19 @@ function shouldHoldPendingDrainForBusyLocalCoordinator(components, meshId, reque
15217
15227
  return localIds.some((id) => daemonIdsEquivalent(id, requested));
15218
15228
  }
15219
15229
  function injectPendingIntoCoordinator(coordinator, pending) {
15220
- if (!coordinator || !pending.coordinatorMessage) return;
15230
+ if (!coordinator) return;
15231
+ let coordinatorMessage = pending.coordinatorMessage;
15232
+ if (!coordinatorMessage) {
15233
+ if (!shouldForceInjectMeshEvent(pending.event)) return;
15234
+ const metadataEvent = pending.metadataEvent && typeof pending.metadataEvent === "object" ? pending.metadataEvent : {};
15235
+ coordinatorMessage = buildMeshSystemMessage({
15236
+ event: pending.event,
15237
+ nodeLabel: pending.nodeLabel,
15238
+ metadataEvent
15239
+ });
15240
+ if (!coordinatorMessage) return;
15241
+ LOG.warn("MeshReconcile", `Lazily synthesized missing coordinatorMessage for ${pending.event} (mesh ${pending.meshId}) at inject time \u2014 a queued terminal event arrived message-less`);
15242
+ }
15221
15243
  const force = shouldForceInjectMeshEvent(pending.event);
15222
15244
  traceMeshEventStage("surfaced", {
15223
15245
  taskId: pending.metadataEvent?.taskId,
@@ -15227,7 +15249,7 @@ function injectPendingIntoCoordinator(coordinator, pending) {
15227
15249
  event: pending.event
15228
15250
  }, force ? "force-inject" : "inject");
15229
15251
  coordinator.onEvent("send_message", {
15230
- input: { text: pending.coordinatorMessage, textFallback: pending.coordinatorMessage },
15252
+ input: { text: coordinatorMessage, textFallback: coordinatorMessage },
15231
15253
  ...force ? { force: true } : {}
15232
15254
  });
15233
15255
  }
@@ -19572,6 +19594,16 @@ var init_provider_cli_adapter = __esm({
19572
19594
  providerSessionId = null;
19573
19595
  responseTimeout = null;
19574
19596
  ready = false;
19597
+ // WIN32-READY-HOLD: the ready barrier can release on screen/spec-FSM grace
19598
+ // before win32 ConPTY's input layer is live. The first split write (text, then a
19599
+ // separate trailing CR via waitForEchoAndSubmit) then has its submit CR swallowed,
19600
+ // and every CR-only retry re-sends a bare CR the input layer keeps dropping — the
19601
+ // first message is typed-but-never-submitted and lost. Routing only the FIRST turn
19602
+ // through the atomic content+sendKey single write (submitImmediatePrompt) keeps the
19603
+ // Enter in the same PTY write unit as the text, the invariant win32 ConPTY needs to
19604
+ // recognize a submit, so the swallow is bypassed. Subsequent turns (input layer now
19605
+ // proven live) keep the normal echo-gated path. Flips true on first committed turn.
19606
+ firstTurnSent = false;
19575
19607
  startupBuffer = "";
19576
19608
  startupParseGate = false;
19577
19609
  startupSettleTimer = null;
@@ -19858,6 +19890,7 @@ ${lastSnapshot}`;
19858
19890
  this.resetTerminalScreen(DEFAULT_SESSION_HOST_ROWS4, DEFAULT_SESSION_HOST_COLS4);
19859
19891
  this.pendingTerminalQueryTail = "";
19860
19892
  this.ready = false;
19893
+ this.firstTurnSent = false;
19861
19894
  await this.ptyProcess.ready;
19862
19895
  this.engine.onSpawnReady();
19863
19896
  this.scheduleStartupSettleCheck();
@@ -20322,6 +20355,7 @@ ${lastSnapshot}`;
20322
20355
  commitSendUserTurn(state) {
20323
20356
  if (state.didCommitUserTurn) return;
20324
20357
  state.didCommitUserTurn = true;
20358
+ this.firstTurnSent = true;
20325
20359
  }
20326
20360
  armResponseTimeout() {
20327
20361
  if (this.responseTimeout) clearTimeout(this.responseTimeout);
@@ -20344,12 +20378,30 @@ ${lastSnapshot}`;
20344
20378
  LOG.warn("CLI", `[${this.cliType}] ${mode} write failed: ${error?.message || error}`);
20345
20379
  });
20346
20380
  }
20381
+ // WIN32-READY-HOLD: choose the retry write for a stuck prompt. When the FIRST turn
20382
+ // is stuck on win32 — the premature-ready swallow window — the prompt text itself
20383
+ // may have been partially eaten by a not-yet-live ConPTY input layer, so re-sending
20384
+ // a bare CR keeps hitting nothing. Re-type the whole `text + sendKey` atomically
20385
+ // once so the input layer (now live) receives a self-contained, submit-coupled
20386
+ // write. All other cases keep the cheap bare-CR retry (the prompt is fully echoed
20387
+ // and only the Enter is missing).
20388
+ writeStuckRetry(state, mode) {
20389
+ const retypeFirstTurn = process.platform === "win32" && state.isFirstTurn;
20390
+ if (retypeFirstTurn) {
20391
+ LOG.info("CLI", `[${this.cliType}] ${mode}: re-typing full prompt atomically (win32 first-turn swallow recovery)`);
20392
+ void this.writeToPty(state.text + this.sendKey).catch((error) => {
20393
+ LOG.warn("CLI", `[${this.cliType}] ${mode} re-type write failed: ${error?.message || error}`);
20394
+ });
20395
+ return;
20396
+ }
20397
+ this.writeSubmitKeyForRetry(mode);
20398
+ }
20347
20399
  retrySubmitIfStuck(state, attempt) {
20348
20400
  this.submitRetryTimer = null;
20349
20401
  if (!this.isSubmitStuck(state.normalizedPromptSnippet)) return;
20350
20402
  this.engine.responseSettleIgnoreUntil = Date.now() + this.timeouts.outputSettle + 400;
20351
20403
  LOG.info("CLI", `[${this.cliType}] Retrying submit key for stuck prompt (attempt ${attempt})`);
20352
- this.writeSubmitKeyForRetry("submit_retry");
20404
+ this.writeStuckRetry(state, "submit_retry");
20353
20405
  if (attempt >= 3) {
20354
20406
  this.engine.submitRetryUsed = true;
20355
20407
  return;
@@ -20361,7 +20413,7 @@ ${lastSnapshot}`;
20361
20413
  if (!this.isSubmitStuck(state.normalizedPromptSnippet)) return;
20362
20414
  this.engine.responseSettleIgnoreUntil = Date.now() + this.timeouts.outputSettle + 400;
20363
20415
  LOG.info("CLI", `[${this.cliType}] Retrying submit key for stuck prompt (attempt 1)`);
20364
- this.writeSubmitKeyForRetry("immediate_retry");
20416
+ this.writeStuckRetry(state, "immediate_retry");
20365
20417
  this.engine.submitRetryUsed = true;
20366
20418
  }
20367
20419
  submitSendKey(state, completion) {
@@ -20614,7 +20666,9 @@ ${lastSnapshot}`;
20614
20666
  submitDelayMs,
20615
20667
  maxEchoWaitMs,
20616
20668
  retryDelayMs,
20617
- didCommitUserTurn: false
20669
+ didCommitUserTurn: false,
20670
+ // Capture BEFORE the send commits — commitSendUserTurn flips firstTurnSent.
20671
+ isFirstTurn: !this.firstTurnSent
20618
20672
  };
20619
20673
  this.engine.responseSettleIgnoreUntil = Date.now() + submitDelayMs + this.timeouts.outputSettle + 250;
20620
20674
  await new Promise((resolve24, reject) => {
@@ -20632,7 +20686,8 @@ ${lastSnapshot}`;
20632
20686
  reject(error);
20633
20687
  }
20634
20688
  };
20635
- if (this.submitStrategy === "immediate") {
20689
+ const useAtomicFirstTurn = this.submitStrategy === "immediate" || process.platform === "win32" && sendState.isFirstTurn;
20690
+ if (useAtomicFirstTurn) {
20636
20691
  this.submitImmediatePrompt(sendState, completion);
20637
20692
  return;
20638
20693
  }
@@ -54013,7 +54068,14 @@ ${hintLines.join("\n")}` : "",
54013
54068
  nodeId,
54014
54069
  sessionCleanupMode: refineSessionCleanupMode,
54015
54070
  ...refineSessionIds && refineSessionIds.length > 0 ? { sessionIds: refineSessionIds } : {},
54016
- inlineMesh: args?.inlineMesh
54071
+ inlineMesh: args?.inlineMesh,
54072
+ // REFINE-CLEANUP: refine reaches cleanup only AFTER a verified merge
54073
+ // convergence, so any residual worktree dirtiness here is incidental
54074
+ // (e.g. a bootstrap lockfile rewrite) — never unmerged work. `force`
54075
+ // sets requireClean=false so a plain-dirty worktree no longer aborts
54076
+ // removal with merged_cleanup_failed. Branch-ref deletion still keys off
54077
+ // mergeConvergence (NOT the force flag), so no merged work can be lost.
54078
+ force: true
54017
54079
  });
54018
54080
  recordMeshRefineStage(refineStages, "cleanup", removeResult?.success === false ? "failed" : "passed", cleanupStarted, {
54019
54081
  removed: removeResult?.removed,