@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.
@@ -39,6 +39,7 @@ export declare class ProviderCliAdapter implements CliAdapter {
39
39
  private providerSessionId;
40
40
  private responseTimeout;
41
41
  private ready;
42
+ private firstTurnSent;
42
43
  private startupBuffer;
43
44
  private startupParseGate;
44
45
  private startupSettleTimer;
@@ -178,6 +179,7 @@ export declare class ProviderCliAdapter implements CliAdapter {
178
179
  private commitSendUserTurn;
179
180
  private armResponseTimeout;
180
181
  private writeSubmitKeyForRetry;
182
+ private writeStuckRetry;
181
183
  private retrySubmitIfStuck;
182
184
  private retryImmediateSubmitIfStuck;
183
185
  private submitSendKey;
package/dist/index.js CHANGED
@@ -383,10 +383,10 @@ function readInjected(value) {
383
383
  }
384
384
  function getDaemonBuildInfo() {
385
385
  if (cached) return cached;
386
- const commit = readInjected(true ? "109c5230408ea2b33e9083395b42b1c3e894aed2" : void 0) ?? "unknown";
387
- const commitShort = readInjected(true ? "109c5230" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
388
- const version = readInjected(true ? "0.9.82-rc.396" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
389
- const builtAt = readInjected(true ? "2026-06-27T07:15:39.648Z" : void 0);
386
+ const commit = readInjected(true ? "5e6a6bcc5ba51a08f3941445f431cb0411217547" : void 0) ?? "unknown";
387
+ const commitShort = readInjected(true ? "5e6a6bcc" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
388
+ const version = readInjected(true ? "0.9.82-rc.397" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
389
+ const builtAt = readInjected(true ? "2026-06-27T08:32:58.380Z" : void 0);
390
390
  cached = builtAt ? { commit, commitShort, version, builtAt } : { commit, commitShort, version };
391
391
  return cached;
392
392
  }
@@ -5197,6 +5197,7 @@ var init_mesh_runtime_store = __esm({
5197
5197
  init_load_better_sqlite3();
5198
5198
  init_mesh_ledger();
5199
5199
  init_mesh_work_queue();
5200
+ init_dist();
5200
5201
  loggedMigrationFailure = false;
5201
5202
  MeshRuntimeStore = class _MeshRuntimeStore {
5202
5203
  static instance;
@@ -5729,6 +5730,8 @@ var init_mesh_runtime_store = __esm({
5729
5730
  if (providerType && typeof providerMaxParallel === "number" && Number.isFinite(providerMaxParallel) && providerMaxParallel >= 0 && this.activeProviderAssignmentCount(meshId, nodeId, providerType) >= providerMaxParallel) {
5730
5731
  return null;
5731
5732
  }
5733
+ const nodeIdForms = expandDaemonIdForms(nodeId);
5734
+ const nodePinnedPlaceholders = nodeIdForms.map(() => "?").join(", ");
5732
5735
  const rows = [
5733
5736
  ...this.db.prepare(`
5734
5737
  SELECT payload FROM mesh_queue
@@ -5737,9 +5740,9 @@ var init_mesh_runtime_store = __esm({
5737
5740
  `).all(meshId, sessionId),
5738
5741
  ...this.db.prepare(`
5739
5742
  SELECT payload FROM mesh_queue
5740
- WHERE mesh_id = ? AND status = 'pending' AND target_node_id = ? AND target_session_id IS NULL
5743
+ WHERE mesh_id = ? AND status = 'pending' AND target_node_id IN (${nodePinnedPlaceholders}) AND target_session_id IS NULL
5741
5744
  ORDER BY created_at ASC
5742
- `).all(meshId, nodeId),
5745
+ `).all(meshId, ...nodeIdForms),
5743
5746
  ...this.db.prepare(`
5744
5747
  SELECT payload FROM mesh_queue
5745
5748
  WHERE mesh_id = ? AND status = 'pending' AND target_node_id IS NULL AND target_session_id IS NULL
@@ -5769,7 +5772,9 @@ var init_mesh_runtime_store = __esm({
5769
5772
  const convergenceAllows = (candidate) => candidate.taskMode !== "convergence" || !nodeIsWorktree;
5770
5773
  const targetMatches = (candidate) => {
5771
5774
  if (candidate.targetSessionId && candidate.targetSessionId !== sessionId) return false;
5772
- if (candidate.targetNodeId && candidate.targetNodeId !== nodeId) return false;
5775
+ if (candidate.targetNodeId && !daemonIdsEquivalent(candidate.targetNodeId, nodeId) && !meshNodeIdMatches({ id: candidate.targetNodeId }, nodeId)) {
5776
+ return false;
5777
+ }
5773
5778
  return true;
5774
5779
  };
5775
5780
  const entry = candidates.find((candidate) => nodeSatisfiesRequiredTags(candidate.requiredTags, capabilityTags) && dependenciesSatisfied(candidate) && convergenceAllows(candidate) && targetMatches(candidate) && nodeConflictAllows(candidate));
@@ -10783,7 +10788,7 @@ function deliverTaskToSession(dispatchThunk, ctx, warmup) {
10783
10788
  }
10784
10789
  function tryAssignQueueTask(components, meshId, nodeId, sessionId, providerType) {
10785
10790
  const mesh = getMeshWithCache(components, meshId);
10786
- const node = mesh?.nodes.find((n) => readMeshNodeId(n) === nodeId);
10791
+ const node = mesh?.nodes.find((n) => meshNodeIdMatches(n, nodeId));
10787
10792
  const gateNode = mesh?.nodes?.find((n) => meshNodeIdMatches(n, nodeId));
10788
10793
  if (gateNode?.worktreeBootstrap?.status === "running") {
10789
10794
  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)`);
@@ -11392,7 +11397,7 @@ async function triggerMeshQueue(components, meshId) {
11392
11397
  const providerType = state.type || readNonEmptyString2(settings.providerType);
11393
11398
  if (providerType) {
11394
11399
  localIdleSessionsChecked += 1;
11395
- localCandidates.push({ nodeId, sessionId, providerType, origin: "local", node: mesh.nodes.find((n) => readMeshNodeId(n) === nodeId) });
11400
+ localCandidates.push({ nodeId, sessionId, providerType, origin: "local", node: mesh.nodes.find((n) => meshNodeIdMatches(n, nodeId)) });
11396
11401
  } else {
11397
11402
  skippedSessions.push({
11398
11403
  nodeId,
@@ -19596,6 +19601,16 @@ var init_provider_cli_adapter = __esm({
19596
19601
  providerSessionId = null;
19597
19602
  responseTimeout = null;
19598
19603
  ready = false;
19604
+ // WIN32-READY-HOLD: the ready barrier can release on screen/spec-FSM grace
19605
+ // before win32 ConPTY's input layer is live. The first split write (text, then a
19606
+ // separate trailing CR via waitForEchoAndSubmit) then has its submit CR swallowed,
19607
+ // and every CR-only retry re-sends a bare CR the input layer keeps dropping — the
19608
+ // first message is typed-but-never-submitted and lost. Routing only the FIRST turn
19609
+ // through the atomic content+sendKey single write (submitImmediatePrompt) keeps the
19610
+ // Enter in the same PTY write unit as the text, the invariant win32 ConPTY needs to
19611
+ // recognize a submit, so the swallow is bypassed. Subsequent turns (input layer now
19612
+ // proven live) keep the normal echo-gated path. Flips true on first committed turn.
19613
+ firstTurnSent = false;
19599
19614
  startupBuffer = "";
19600
19615
  startupParseGate = false;
19601
19616
  startupSettleTimer = null;
@@ -19882,6 +19897,7 @@ ${lastSnapshot}`;
19882
19897
  this.resetTerminalScreen(import_session_host_core5.DEFAULT_SESSION_HOST_ROWS, import_session_host_core5.DEFAULT_SESSION_HOST_COLS);
19883
19898
  this.pendingTerminalQueryTail = "";
19884
19899
  this.ready = false;
19900
+ this.firstTurnSent = false;
19885
19901
  await this.ptyProcess.ready;
19886
19902
  this.engine.onSpawnReady();
19887
19903
  this.scheduleStartupSettleCheck();
@@ -20346,6 +20362,7 @@ ${lastSnapshot}`;
20346
20362
  commitSendUserTurn(state) {
20347
20363
  if (state.didCommitUserTurn) return;
20348
20364
  state.didCommitUserTurn = true;
20365
+ this.firstTurnSent = true;
20349
20366
  }
20350
20367
  armResponseTimeout() {
20351
20368
  if (this.responseTimeout) clearTimeout(this.responseTimeout);
@@ -20368,12 +20385,30 @@ ${lastSnapshot}`;
20368
20385
  LOG.warn("CLI", `[${this.cliType}] ${mode} write failed: ${error?.message || error}`);
20369
20386
  });
20370
20387
  }
20388
+ // WIN32-READY-HOLD: choose the retry write for a stuck prompt. When the FIRST turn
20389
+ // is stuck on win32 — the premature-ready swallow window — the prompt text itself
20390
+ // may have been partially eaten by a not-yet-live ConPTY input layer, so re-sending
20391
+ // a bare CR keeps hitting nothing. Re-type the whole `text + sendKey` atomically
20392
+ // once so the input layer (now live) receives a self-contained, submit-coupled
20393
+ // write. All other cases keep the cheap bare-CR retry (the prompt is fully echoed
20394
+ // and only the Enter is missing).
20395
+ writeStuckRetry(state, mode) {
20396
+ const retypeFirstTurn = process.platform === "win32" && state.isFirstTurn;
20397
+ if (retypeFirstTurn) {
20398
+ LOG.info("CLI", `[${this.cliType}] ${mode}: re-typing full prompt atomically (win32 first-turn swallow recovery)`);
20399
+ void this.writeToPty(state.text + this.sendKey).catch((error) => {
20400
+ LOG.warn("CLI", `[${this.cliType}] ${mode} re-type write failed: ${error?.message || error}`);
20401
+ });
20402
+ return;
20403
+ }
20404
+ this.writeSubmitKeyForRetry(mode);
20405
+ }
20371
20406
  retrySubmitIfStuck(state, attempt) {
20372
20407
  this.submitRetryTimer = null;
20373
20408
  if (!this.isSubmitStuck(state.normalizedPromptSnippet)) return;
20374
20409
  this.engine.responseSettleIgnoreUntil = Date.now() + this.timeouts.outputSettle + 400;
20375
20410
  LOG.info("CLI", `[${this.cliType}] Retrying submit key for stuck prompt (attempt ${attempt})`);
20376
- this.writeSubmitKeyForRetry("submit_retry");
20411
+ this.writeStuckRetry(state, "submit_retry");
20377
20412
  if (attempt >= 3) {
20378
20413
  this.engine.submitRetryUsed = true;
20379
20414
  return;
@@ -20385,7 +20420,7 @@ ${lastSnapshot}`;
20385
20420
  if (!this.isSubmitStuck(state.normalizedPromptSnippet)) return;
20386
20421
  this.engine.responseSettleIgnoreUntil = Date.now() + this.timeouts.outputSettle + 400;
20387
20422
  LOG.info("CLI", `[${this.cliType}] Retrying submit key for stuck prompt (attempt 1)`);
20388
- this.writeSubmitKeyForRetry("immediate_retry");
20423
+ this.writeStuckRetry(state, "immediate_retry");
20389
20424
  this.engine.submitRetryUsed = true;
20390
20425
  }
20391
20426
  submitSendKey(state, completion) {
@@ -20638,7 +20673,9 @@ ${lastSnapshot}`;
20638
20673
  submitDelayMs,
20639
20674
  maxEchoWaitMs,
20640
20675
  retryDelayMs,
20641
- didCommitUserTurn: false
20676
+ didCommitUserTurn: false,
20677
+ // Capture BEFORE the send commits — commitSendUserTurn flips firstTurnSent.
20678
+ isFirstTurn: !this.firstTurnSent
20642
20679
  };
20643
20680
  this.engine.responseSettleIgnoreUntil = Date.now() + submitDelayMs + this.timeouts.outputSettle + 250;
20644
20681
  await new Promise((resolve24, reject) => {
@@ -20656,7 +20693,8 @@ ${lastSnapshot}`;
20656
20693
  reject(error);
20657
20694
  }
20658
20695
  };
20659
- if (this.submitStrategy === "immediate") {
20696
+ const useAtomicFirstTurn = this.submitStrategy === "immediate" || process.platform === "win32" && sendState.isFirstTurn;
20697
+ if (useAtomicFirstTurn) {
20660
20698
  this.submitImmediatePrompt(sendState, completion);
20661
20699
  return;
20662
20700
  }
@@ -54406,7 +54444,14 @@ ${hintLines.join("\n")}` : "",
54406
54444
  nodeId,
54407
54445
  sessionCleanupMode: refineSessionCleanupMode,
54408
54446
  ...refineSessionIds && refineSessionIds.length > 0 ? { sessionIds: refineSessionIds } : {},
54409
- inlineMesh: args?.inlineMesh
54447
+ inlineMesh: args?.inlineMesh,
54448
+ // REFINE-CLEANUP: refine reaches cleanup only AFTER a verified merge
54449
+ // convergence, so any residual worktree dirtiness here is incidental
54450
+ // (e.g. a bootstrap lockfile rewrite) — never unmerged work. `force`
54451
+ // sets requireClean=false so a plain-dirty worktree no longer aborts
54452
+ // removal with merged_cleanup_failed. Branch-ref deletion still keys off
54453
+ // mergeConvergence (NOT the force flag), so no merged work can be lost.
54454
+ force: true
54410
54455
  });
54411
54456
  recordMeshRefineStage(refineStages, "cleanup", removeResult?.success === false ? "failed" : "passed", cleanupStarted, {
54412
54457
  removed: removeResult?.removed,