@adhdev/daemon-core 0.9.82-rc.396 → 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 ? "109c5230408ea2b33e9083395b42b1c3e894aed2" : void 0) ?? "unknown";
382
- const commitShort = readInjected(true ? "109c5230" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
383
- const version = readInjected(true ? "0.9.82-rc.396" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
384
- const builtAt = readInjected(true ? "2026-06-27T07:15:39.648Z" : 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));
@@ -10779,7 +10784,7 @@ function deliverTaskToSession(dispatchThunk, ctx, warmup) {
10779
10784
  }
10780
10785
  function tryAssignQueueTask(components, meshId, nodeId, sessionId, providerType) {
10781
10786
  const mesh = getMeshWithCache(components, meshId);
10782
- const node = mesh?.nodes.find((n) => readMeshNodeId(n) === nodeId);
10787
+ const node = mesh?.nodes.find((n) => meshNodeIdMatches(n, nodeId));
10783
10788
  const gateNode = mesh?.nodes?.find((n) => meshNodeIdMatches(n, nodeId));
10784
10789
  if (gateNode?.worktreeBootstrap?.status === "running") {
10785
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)`);
@@ -11388,7 +11393,7 @@ async function triggerMeshQueue(components, meshId) {
11388
11393
  const providerType = state.type || readNonEmptyString2(settings.providerType);
11389
11394
  if (providerType) {
11390
11395
  localIdleSessionsChecked += 1;
11391
- 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)) });
11392
11397
  } else {
11393
11398
  skippedSessions.push({
11394
11399
  nodeId,
@@ -19589,6 +19594,16 @@ var init_provider_cli_adapter = __esm({
19589
19594
  providerSessionId = null;
19590
19595
  responseTimeout = null;
19591
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;
19592
19607
  startupBuffer = "";
19593
19608
  startupParseGate = false;
19594
19609
  startupSettleTimer = null;
@@ -19875,6 +19890,7 @@ ${lastSnapshot}`;
19875
19890
  this.resetTerminalScreen(DEFAULT_SESSION_HOST_ROWS4, DEFAULT_SESSION_HOST_COLS4);
19876
19891
  this.pendingTerminalQueryTail = "";
19877
19892
  this.ready = false;
19893
+ this.firstTurnSent = false;
19878
19894
  await this.ptyProcess.ready;
19879
19895
  this.engine.onSpawnReady();
19880
19896
  this.scheduleStartupSettleCheck();
@@ -20339,6 +20355,7 @@ ${lastSnapshot}`;
20339
20355
  commitSendUserTurn(state) {
20340
20356
  if (state.didCommitUserTurn) return;
20341
20357
  state.didCommitUserTurn = true;
20358
+ this.firstTurnSent = true;
20342
20359
  }
20343
20360
  armResponseTimeout() {
20344
20361
  if (this.responseTimeout) clearTimeout(this.responseTimeout);
@@ -20361,12 +20378,30 @@ ${lastSnapshot}`;
20361
20378
  LOG.warn("CLI", `[${this.cliType}] ${mode} write failed: ${error?.message || error}`);
20362
20379
  });
20363
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
+ }
20364
20399
  retrySubmitIfStuck(state, attempt) {
20365
20400
  this.submitRetryTimer = null;
20366
20401
  if (!this.isSubmitStuck(state.normalizedPromptSnippet)) return;
20367
20402
  this.engine.responseSettleIgnoreUntil = Date.now() + this.timeouts.outputSettle + 400;
20368
20403
  LOG.info("CLI", `[${this.cliType}] Retrying submit key for stuck prompt (attempt ${attempt})`);
20369
- this.writeSubmitKeyForRetry("submit_retry");
20404
+ this.writeStuckRetry(state, "submit_retry");
20370
20405
  if (attempt >= 3) {
20371
20406
  this.engine.submitRetryUsed = true;
20372
20407
  return;
@@ -20378,7 +20413,7 @@ ${lastSnapshot}`;
20378
20413
  if (!this.isSubmitStuck(state.normalizedPromptSnippet)) return;
20379
20414
  this.engine.responseSettleIgnoreUntil = Date.now() + this.timeouts.outputSettle + 400;
20380
20415
  LOG.info("CLI", `[${this.cliType}] Retrying submit key for stuck prompt (attempt 1)`);
20381
- this.writeSubmitKeyForRetry("immediate_retry");
20416
+ this.writeStuckRetry(state, "immediate_retry");
20382
20417
  this.engine.submitRetryUsed = true;
20383
20418
  }
20384
20419
  submitSendKey(state, completion) {
@@ -20631,7 +20666,9 @@ ${lastSnapshot}`;
20631
20666
  submitDelayMs,
20632
20667
  maxEchoWaitMs,
20633
20668
  retryDelayMs,
20634
- didCommitUserTurn: false
20669
+ didCommitUserTurn: false,
20670
+ // Capture BEFORE the send commits — commitSendUserTurn flips firstTurnSent.
20671
+ isFirstTurn: !this.firstTurnSent
20635
20672
  };
20636
20673
  this.engine.responseSettleIgnoreUntil = Date.now() + submitDelayMs + this.timeouts.outputSettle + 250;
20637
20674
  await new Promise((resolve24, reject) => {
@@ -20649,7 +20686,8 @@ ${lastSnapshot}`;
20649
20686
  reject(error);
20650
20687
  }
20651
20688
  };
20652
- if (this.submitStrategy === "immediate") {
20689
+ const useAtomicFirstTurn = this.submitStrategy === "immediate" || process.platform === "win32" && sendState.isFirstTurn;
20690
+ if (useAtomicFirstTurn) {
20653
20691
  this.submitImmediatePrompt(sendState, completion);
20654
20692
  return;
20655
20693
  }
@@ -54030,7 +54068,14 @@ ${hintLines.join("\n")}` : "",
54030
54068
  nodeId,
54031
54069
  sessionCleanupMode: refineSessionCleanupMode,
54032
54070
  ...refineSessionIds && refineSessionIds.length > 0 ? { sessionIds: refineSessionIds } : {},
54033
- 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
54034
54079
  });
54035
54080
  recordMeshRefineStage(refineStages, "cleanup", removeResult?.success === false ? "failed" : "passed", cleanupStarted, {
54036
54081
  removed: removeResult?.removed,