@adhdev/daemon-core 0.9.82-rc.400 → 0.9.82-rc.401

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
@@ -394,10 +394,10 @@ function readInjected(value) {
394
394
  }
395
395
  function getDaemonBuildInfo() {
396
396
  if (cached) return cached;
397
- const commit = readInjected(true ? "2350563490670c1c560cc5cf6f863a9e61ef3f89" : void 0) ?? "unknown";
398
- const commitShort = readInjected(true ? "23505634" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
399
- const version = readInjected(true ? "0.9.82-rc.400" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
400
- const builtAt = readInjected(true ? "2026-06-27T13:15:45.410Z" : void 0);
397
+ const commit = readInjected(true ? "c31eb449e8febc28e378bd25394830a96a67594e" : void 0) ?? "unknown";
398
+ const commitShort = readInjected(true ? "c31eb449" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
399
+ const version = readInjected(true ? "0.9.82-rc.401" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
400
+ const builtAt = readInjected(true ? "2026-06-27T16:14:32.200Z" : void 0);
401
401
  cached = builtAt ? { commit, commitShort, version, builtAt } : { commit, commitShort, version };
402
402
  return cached;
403
403
  }
@@ -1441,16 +1441,103 @@ function resolveWorktreePath(repoRoot, meshName, branch) {
1441
1441
  const parentDir = path4.dirname(repoRoot);
1442
1442
  return path4.join(parentDir, WORKTREE_DIR_NAME, safeMeshName, safeBranch);
1443
1443
  }
1444
+ async function tryGit(cwd, args) {
1445
+ try {
1446
+ const { stdout, stderr } = await execFileAsync2("git", args, {
1447
+ cwd,
1448
+ encoding: "utf8",
1449
+ timeout: GIT_TIMEOUT_MS,
1450
+ maxBuffer: GIT_MAX_BUFFER,
1451
+ windowsHide: true
1452
+ });
1453
+ return { ok: true, stdout: (stdout || "").trim(), stderr: (stderr || "").trim() };
1454
+ } catch (error) {
1455
+ return {
1456
+ ok: false,
1457
+ stdout: typeof error?.stdout === "string" ? error.stdout.trim() : "",
1458
+ stderr: typeof error?.stderr === "string" ? error.stderr.trim() : error?.message || ""
1459
+ };
1460
+ }
1461
+ }
1462
+ async function resolveWorktreeBaseStartPoint(repoRoot, baseBranch, remote) {
1463
+ const fetchResult = await tryGit(repoRoot, ["fetch", remote, baseBranch]);
1464
+ const fetched = fetchResult.ok;
1465
+ const localRev = await tryGit(repoRoot, ["rev-parse", "--verify", "--quiet", `refs/heads/${baseBranch}`]);
1466
+ const remoteRev = await tryGit(repoRoot, ["rev-parse", "--verify", "--quiet", `refs/remotes/${remote}/${baseBranch}`]);
1467
+ const localSha = localRev.ok && localRev.stdout ? localRev.stdout : void 0;
1468
+ const remoteSha = remoteRev.ok && remoteRev.stdout ? remoteRev.stdout : void 0;
1469
+ const remoteRef = `${remote}/${baseBranch}`;
1470
+ const base = {
1471
+ branch: baseBranch,
1472
+ remote,
1473
+ startRef: baseBranch,
1474
+ fetched,
1475
+ localSha,
1476
+ remoteSha,
1477
+ behindBy: 0,
1478
+ aheadBy: 0,
1479
+ action: "up_to_date"
1480
+ };
1481
+ const fetchWarn = fetched ? "" : ` (warning: git fetch ${remote} ${baseBranch} failed: ${fetchResult.stderr || "unknown error"})`;
1482
+ if (!remoteSha) {
1483
+ return {
1484
+ ...base,
1485
+ action: "no_remote_ref_used_local",
1486
+ ...fetched ? {} : { warning: `Could not fetch ${remoteRef}${fetchWarn}; worktree branched from local ${baseBranch}.` }
1487
+ };
1488
+ }
1489
+ if (!localSha) {
1490
+ return {
1491
+ ...base,
1492
+ startRef: remoteRef,
1493
+ action: "no_local_ref_used_remote"
1494
+ };
1495
+ }
1496
+ if (localSha === remoteSha) {
1497
+ return base;
1498
+ }
1499
+ const localIsAncestor = (await tryGit(repoRoot, ["merge-base", "--is-ancestor", localSha, remoteSha])).ok;
1500
+ const remoteIsAncestor = (await tryGit(repoRoot, ["merge-base", "--is-ancestor", remoteSha, localSha])).ok;
1501
+ const behindBy = Number((await tryGit(repoRoot, ["rev-list", "--count", `${localSha}..${remoteSha}`])).stdout) || 0;
1502
+ const aheadBy = Number((await tryGit(repoRoot, ["rev-list", "--count", `${remoteSha}..${localSha}`])).stdout) || 0;
1503
+ if (localIsAncestor && !remoteIsAncestor) {
1504
+ return {
1505
+ ...base,
1506
+ startRef: remoteRef,
1507
+ behindBy,
1508
+ aheadBy,
1509
+ action: "local_behind_used_remote",
1510
+ warning: `Base node local ${baseBranch} was behind ${remoteRef} by ${behindBy} commit(s); worktree branched from ${remoteRef} (${remoteSha.slice(0, 8)}) instead of stale local ${localSha.slice(0, 8)}.${fetchWarn}`
1511
+ };
1512
+ }
1513
+ if (remoteIsAncestor) {
1514
+ return { ...base, behindBy, aheadBy, action: "local_ahead_used_local" };
1515
+ }
1516
+ return {
1517
+ ...base,
1518
+ behindBy,
1519
+ aheadBy,
1520
+ action: "diverged_used_local",
1521
+ warning: `Base node local ${baseBranch} (${localSha.slice(0, 8)}) has DIVERGED from ${remoteRef} (${remoteSha.slice(0, 8)}): behind ${behindBy}, ahead ${aheadBy}. Worktree branched from local; a rebase onto ${remoteRef} will be required before its push can fast-forward.${fetchWarn}`
1522
+ };
1523
+ }
1444
1524
  async function createWorktree(opts) {
1445
1525
  const { repoRoot, branch, baseBranch, meshName } = opts;
1526
+ const remote = (opts.remote || "origin").trim() || "origin";
1446
1527
  const targetDir = opts.targetDir || resolveWorktreePath(repoRoot, meshName, branch);
1447
1528
  if (existsSync2(targetDir)) {
1448
1529
  throw new Error(`Worktree target directory already exists: ${targetDir}`);
1449
1530
  }
1450
1531
  await mkdir(path4.dirname(targetDir), { recursive: true });
1532
+ let baseSync;
1533
+ let startRef = baseBranch;
1534
+ if (baseBranch && opts.syncBaseFromRemote !== false) {
1535
+ baseSync = await resolveWorktreeBaseStartPoint(repoRoot, baseBranch, remote);
1536
+ startRef = baseSync.startRef;
1537
+ }
1451
1538
  const args = ["worktree", "add", targetDir, "-b", branch];
1452
- if (baseBranch) {
1453
- args.push(baseBranch);
1539
+ if (startRef) {
1540
+ args.push(startRef);
1454
1541
  }
1455
1542
  try {
1456
1543
  await execFileAsync2("git", args, {
@@ -1473,7 +1560,8 @@ async function createWorktree(opts) {
1473
1560
  return {
1474
1561
  success: true,
1475
1562
  worktreePath: targetDir,
1476
- branch
1563
+ branch,
1564
+ ...baseSync ? { baseSync } : {}
1477
1565
  };
1478
1566
  }
1479
1567
  async function removeWorktree(repoRoot, worktreePath, opts = {}) {
@@ -5647,11 +5735,14 @@ var init_mesh_runtime_store = __esm({
5647
5735
  }
5648
5736
  /** A node may only execute one write task at a time (worktree isolation). */
5649
5737
  hasActiveNodeAssignment(meshId, nodeId) {
5738
+ const nodeIdForms = expandDaemonIdForms(nodeId);
5739
+ if (nodeIdForms.length === 0) return false;
5740
+ const placeholders = nodeIdForms.map(() => "?").join(", ");
5650
5741
  const row = this.db.prepare(`
5651
5742
  SELECT 1 FROM mesh_queue
5652
- WHERE mesh_id = ? AND status = 'assigned' AND assigned_node_id = ?
5743
+ WHERE mesh_id = ? AND status = 'assigned' AND assigned_node_id IN (${placeholders})
5653
5744
  LIMIT 1
5654
- `).get(meshId, nodeId);
5745
+ `).get(meshId, ...nodeIdForms);
5655
5746
  return row !== void 0;
5656
5747
  }
5657
5748
  /**
@@ -11870,7 +11961,14 @@ function tryAssignQueueTask(components, meshId, nodeId, sessionId, providerType)
11870
11961
  targetSessionId: sessionId,
11871
11962
  cliType: providerType,
11872
11963
  action: "send_chat",
11873
- message: task.message
11964
+ message: task.message,
11965
+ meshContext: {
11966
+ meshId,
11967
+ nodeId,
11968
+ taskId: task.id,
11969
+ ...readNonEmptyString2(loadConfig().machineId) ? { coordinatorDaemonId: readNonEmptyString2(loadConfig().machineId) } : {},
11970
+ ...readNonEmptyString2(task.sourceCoordinatorSessionId) ? { coordinatorSessionId: readNonEmptyString2(task.sourceCoordinatorSessionId) } : {}
11971
+ }
11874
11972
  }),
11875
11973
  {
11876
11974
  meshId,
@@ -19538,6 +19636,15 @@ var init_cli_state_engine = __esm({
19538
19636
  currentStatus = "starting";
19539
19637
  isWaitingForResponse = false;
19540
19638
  currentTurnScope = null;
19639
+ // ARCH-REFACTOR R1 (per-turn task identity): the mesh taskId bound to the most
19640
+ // recently STARTED turn. Unlike currentTurnScope (nulled the moment the turn
19641
+ // settles, before the completion event is even built), this persists past
19642
+ // completion and is only overwritten when the NEXT turn starts. That window is
19643
+ // exactly what the completion path needs: when a turn settles to idle, this still
19644
+ // holds THAT turn's taskId (the next task's turn cannot have started yet — it is
19645
+ // queued in pendingOutbound and only flushed asynchronously after idle), so the
19646
+ // completion event carries the correct id instead of the racy session scalar.
19647
+ currentTurnTaskId = null;
19541
19648
  activeModal = null;
19542
19649
  // ── Approval ─────────────────────────────────────
19543
19650
  lastApprovalResolvedAt = 0;
@@ -19647,6 +19754,7 @@ var init_cli_state_engine = __esm({
19647
19754
  this.finishRetryCount = 0;
19648
19755
  this.clearIdleFinishCandidate("send_message");
19649
19756
  this.currentTurnScope = turnScope;
19757
+ this.currentTurnTaskId = typeof turnScope.taskId === "string" && turnScope.taskId.trim() ? turnScope.taskId : null;
19650
19758
  this.responseEpoch += 1;
19651
19759
  }
19652
19760
  /** Called when PTY exits */
@@ -21598,15 +21706,18 @@ ${lastSnapshot}`;
21598
21706
  }
21599
21707
  async sendMessage(text, options = {}) {
21600
21708
  if (options.force === true) {
21601
- await this.forceSendMessage(text);
21709
+ await this.forceSendMessage(text, options.meshTaskId);
21602
21710
  return;
21603
21711
  }
21604
- await this.sendMessageNow(text, true);
21712
+ await this.sendMessageNow(text, true, options.meshTaskId);
21605
21713
  }
21606
- async forceSendMessage(text) {
21714
+ async forceSendMessage(text, meshTaskId) {
21607
21715
  if (!this.ptyProcess) throw new Error(`${this.cliName} is not running`);
21608
21716
  const content = String(text || "");
21609
21717
  if (!content.trim()) return;
21718
+ if (typeof meshTaskId === "string" && meshTaskId.trim()) {
21719
+ this.engine.currentTurnTaskId = meshTaskId;
21720
+ }
21610
21721
  if (this.engine.currentStatus === "waiting_approval" || this.engine.hasActionableApproval()) {
21611
21722
  LOG.info("CLI", `[${this.cliType}] force-send held \u2014 session parked on approval modal (status=${this.engine.currentStatus})`);
21612
21723
  return;
@@ -21619,7 +21730,7 @@ ${lastSnapshot}`;
21619
21730
  async waitForForceSubmitSettle() {
21620
21731
  await new Promise((resolve24) => setTimeout(resolve24, FORCE_SUBMIT_SETTLE_MS));
21621
21732
  }
21622
- enqueuePendingOutboundMessage(text, reason) {
21733
+ enqueuePendingOutboundMessage(text, reason, meshTaskId) {
21623
21734
  const content = String(text || "");
21624
21735
  const duplicate = this.pendingOutboundQueue.some((message2) => message2.content === content);
21625
21736
  if (duplicate) {
@@ -21631,7 +21742,8 @@ ${lastSnapshot}`;
21631
21742
  role: "user",
21632
21743
  content,
21633
21744
  queuedAt,
21634
- source: "sendMessage"
21745
+ source: "sendMessage",
21746
+ ...typeof meshTaskId === "string" && meshTaskId.trim() ? { meshTaskId } : {}
21635
21747
  };
21636
21748
  this.pendingOutboundQueue.push(message);
21637
21749
  LOG.info("CLI", `[${this.cliType}] queued outbound message while busy (${reason}); queue=${this.pendingOutboundQueue.length}`);
@@ -21674,7 +21786,7 @@ ${lastSnapshot}`;
21674
21786
  if (this.engine.currentStatus !== "idle" || this.engine.isWaitingForResponse || this.engine.hasActionableApproval()) break;
21675
21787
  const next = this.pendingOutboundQueue[0];
21676
21788
  try {
21677
- await this.sendMessageNow(next.content, false);
21789
+ await this.sendMessageNow(next.content, false, next.meshTaskId);
21678
21790
  this.pendingOutboundQueue.shift();
21679
21791
  this.onStatusChange?.();
21680
21792
  } catch (error) {
@@ -21687,7 +21799,7 @@ ${lastSnapshot}`;
21687
21799
  this.pendingOutboundFlushInFlight = false;
21688
21800
  }
21689
21801
  }
21690
- async sendMessageNow(text, allowQueue) {
21802
+ async sendMessageNow(text, allowQueue, meshTaskId) {
21691
21803
  if (!this.ptyProcess) throw new Error(`${this.cliName} is not running`);
21692
21804
  const allowInputDuringGeneration = this.provider.allowInputDuringGeneration === true;
21693
21805
  const allowInterventionPrompt = allowInputDuringGeneration && this.engine.isWaitingForResponse && !this.engine.hasActionableApproval();
@@ -21707,7 +21819,7 @@ ${lastSnapshot}`;
21707
21819
  })() : null;
21708
21820
  const queueReason = this.shouldQueuePendingOutboundMessage(parsedStatusBeforeSend);
21709
21821
  if (allowQueue && queueReason) {
21710
- this.enqueuePendingOutboundMessage(text, queueReason);
21822
+ this.enqueuePendingOutboundMessage(text, queueReason, meshTaskId);
21711
21823
  return;
21712
21824
  }
21713
21825
  if (!allowInterventionPrompt) {
@@ -21724,7 +21836,7 @@ ${lastSnapshot}`;
21724
21836
  }
21725
21837
  if (!this.ready) {
21726
21838
  if (allowQueue) {
21727
- this.enqueuePendingOutboundMessage(text, "not_ready_pending_prompt");
21839
+ this.enqueuePendingOutboundMessage(text, "not_ready_pending_prompt", meshTaskId);
21728
21840
  return;
21729
21841
  }
21730
21842
  throw new Error(`${this.cliName} not ready (status: ${this.engine.currentStatus})`);
@@ -21738,7 +21850,7 @@ ${lastSnapshot}`;
21738
21850
  const terminalLooksIdle = this.engine.currentStatus === "idle" && this.runDetectStatus(this.recentOutputBuffer) === "idle" && !this.engine.isWaitingForResponse && !this.engine.currentTurnScope && !this.engine.hasActionableApproval() && !parsedHasActionableModal;
21739
21851
  if (!terminalLooksIdle) {
21740
21852
  if (allowQueue) {
21741
- this.enqueuePendingOutboundMessage(text, `parsed_status_${parsedSessionStatus}`);
21853
+ this.enqueuePendingOutboundMessage(text, `parsed_status_${parsedSessionStatus}`, meshTaskId);
21742
21854
  return;
21743
21855
  }
21744
21856
  throw new Error(`${this.cliName} is still processing the previous prompt`);
@@ -21748,7 +21860,7 @@ ${lastSnapshot}`;
21748
21860
  const snap = this.getSnapshot();
21749
21861
  if (!this.engine.clearStaleIdleResponseGuard("send_message_guard", snap) && !this.engine.clearParsedIdleResponseGuard("send_message_parsed_idle_guard", parsedStatusBeforeSend, snap)) {
21750
21862
  if (allowQueue) {
21751
- this.enqueuePendingOutboundMessage(text, "waiting_for_response");
21863
+ this.enqueuePendingOutboundMessage(text, "waiting_for_response", meshTaskId);
21752
21864
  return;
21753
21865
  }
21754
21866
  throw new Error(`${this.cliName} is still processing the previous prompt`);
@@ -21759,7 +21871,11 @@ ${lastSnapshot}`;
21759
21871
  prompt: text,
21760
21872
  startedAt: Date.now(),
21761
21873
  bufferStart: this.accumulatedBuffer.length,
21762
- rawBufferStart: this.accumulatedRawBuffer.length
21874
+ rawBufferStart: this.accumulatedRawBuffer.length,
21875
+ // ARCH-REFACTOR R1: bind this turn to its mesh task. engine.onTurnStarted
21876
+ // copies this into currentTurnTaskId so the turn's completion event carries
21877
+ // the right id even if a later task overwrites the session scalar meanwhile.
21878
+ ...typeof meshTaskId === "string" && meshTaskId.trim() ? { taskId: meshTaskId } : {}
21763
21879
  };
21764
21880
  LOG.info("CLI", `[${this.cliType}] sendMessage turn scope buffer=${turnScope.bufferStart} raw=${turnScope.rawBufferStart} prompt=${JSON.stringify(text).slice(0, 120)}`);
21765
21881
  if (this.submitRetryTimer) {
@@ -22109,6 +22225,13 @@ ${lastSnapshot}`;
22109
22225
  set currentTurnScope(v) {
22110
22226
  this.engine.currentTurnScope = v;
22111
22227
  }
22228
+ // ARCH-REFACTOR R1: the mesh taskId bound to the most recently started turn,
22229
+ // surviving past turn settle until the next turn starts. The provider instance
22230
+ // reads this when stamping completion events so they carry the completing turn's
22231
+ // task rather than the racy last-write-wins session scalar.
22232
+ get currentTurnTaskId() {
22233
+ return this.engine.currentTurnTaskId;
22234
+ }
22112
22235
  get responseEpoch() {
22113
22236
  return this.engine.responseEpoch;
22114
22237
  }
@@ -40324,11 +40447,28 @@ var CliProviderInstance = class _CliProviderInstance {
40324
40447
  isMeshWorkerSession() {
40325
40448
  return !!(this.settings.meshNodeFor || this.settings.meshActiveTaskId || this.settings.meshNodeId || this.settings.launchedByCoordinator);
40326
40449
  }
40450
+ /**
40451
+ * ARCH-REFACTOR R1: the taskId to attribute the CURRENTLY-completing turn to.
40452
+ * Prefers the per-turn binding (engine.currentTurnTaskId, set when the turn was
40453
+ * submitted and surviving until the next turn starts) over the last-write-wins
40454
+ * session scalar (settings.meshActiveTaskId). The scalar is retained only as a
40455
+ * backward-compat alias for the "current/last assignment" and is the source of the
40456
+ * NOTIF-MISDELIVER / TASK-MSG-MISROUTE race: a second task attaching before this
40457
+ * turn completes overwrites it. Returns undefined for a non-task ad-hoc turn.
40458
+ */
40459
+ completingTurnTaskId() {
40460
+ const turnTaskId = this.adapter?.currentTurnTaskId;
40461
+ if (typeof turnTaskId === "string" && turnTaskId.trim()) return turnTaskId;
40462
+ const scalar = this.settings.meshActiveTaskId;
40463
+ return typeof scalar === "string" && scalar.trim() ? scalar : void 0;
40464
+ }
40327
40465
  // EVTTRACE correlation context for this session's completion lifecycle. taskId is
40328
40466
  // the primary grep anchor; instanceId is the session fallback.
40329
40467
  meshTraceCtx(event = "agent:generating_completed") {
40330
40468
  return {
40331
- taskId: this.settings.meshActiveTaskId,
40469
+ // ARCH-REFACTOR R1: trace the per-turn taskId (falling back to the scalar) so
40470
+ // EvtTrace anchors on the same id the completion event actually carries.
40471
+ taskId: this.completingTurnTaskId(),
40332
40472
  sessionId: this.instanceId,
40333
40473
  nodeId: this.settings.meshNodeId,
40334
40474
  meshId: this.settings.meshNodeFor,
@@ -40387,6 +40527,8 @@ var CliProviderInstance = class _CliProviderInstance {
40387
40527
  chatTitle: pending.chatTitle,
40388
40528
  duration: pending.duration,
40389
40529
  timestamp: pending.timestamp,
40530
+ // ARCH-REFACTOR R1: attribute to the turn captured at idle-transition.
40531
+ ...pending.taskId ? { taskId: pending.taskId } : {},
40390
40532
  // When finalization is forced past the timeout on a `parsed_status:` block
40391
40533
  // (the parser never confirmed a final assistant turn) we previously rode an
40392
40534
  // empty `finalSummary` unconditionally. That empty value propagates to the
@@ -40412,6 +40554,8 @@ var CliProviderInstance = class _CliProviderInstance {
40412
40554
  chatTitle: pending.chatTitle,
40413
40555
  duration: pending.duration,
40414
40556
  timestamp: pending.timestamp,
40557
+ // ARCH-REFACTOR R1: attribute to the turn captured at idle-transition.
40558
+ ...pending.taskId ? { taskId: pending.taskId } : {},
40415
40559
  finalSummary: this.completionFinalSummary(this.adapter?.getScriptParsedStatus()?.messages)
40416
40560
  });
40417
40561
  this.completedDebouncePending = null;
@@ -40688,7 +40832,11 @@ var CliProviderInstance = class _CliProviderInstance {
40688
40832
  duration,
40689
40833
  timestamp: now,
40690
40834
  firstObservedAt: now,
40691
- previousStatus: this.lastStatus
40835
+ previousStatus: this.lastStatus,
40836
+ // ARCH-REFACTOR R1: snapshot the completing turn's taskId NOW (sync),
40837
+ // before any follow-up task's flush can start a new turn and move
40838
+ // engine.currentTurnTaskId.
40839
+ ...this.completingTurnTaskId() ? { taskId: this.completingTurnTaskId() } : {}
40692
40840
  };
40693
40841
  const ownsExternalHistory = !!this.adapter?.chatMessagesOwnedExternally;
40694
40842
  const meshWorkerSession = this.isMeshWorkerSession();
@@ -40791,10 +40939,11 @@ var CliProviderInstance = class _CliProviderInstance {
40791
40939
  workspace: typeof event.workspace === "string" && event.workspace.trim() ? event.workspace : this.workingDir,
40792
40940
  providerSessionId: typeof event.providerSessionId === "string" && event.providerSessionId.trim() ? event.providerSessionId : this.providerSessionId
40793
40941
  };
40794
- if (this.isMeshWorkerSession() && this.settings.meshActiveTaskId) {
40942
+ if (this.isMeshWorkerSession()) {
40795
40943
  const existingTaskId = typeof enrichedEvent.taskId === "string" && enrichedEvent.taskId.trim() ? enrichedEvent.taskId : void 0;
40796
40944
  if (!existingTaskId) {
40797
- enrichedEvent.taskId = this.settings.meshActiveTaskId;
40945
+ const resolved = this.completingTurnTaskId();
40946
+ if (resolved) enrichedEvent.taskId = resolved;
40798
40947
  }
40799
40948
  }
40800
40949
  if (this.context?.emitProviderEvent) {
@@ -43679,11 +43828,15 @@ Run 'adhdev doctor' for detailed diagnostics.`
43679
43828
  }
43680
43829
  const message = input.textFallback;
43681
43830
  if (!message) throw new Error("message required for send_chat");
43831
+ const meshTaskId = meshContext && typeof meshContext === "object" && typeof meshContext.taskId === "string" && meshContext.taskId.trim() ? meshContext.taskId : void 0;
43682
43832
  const forceSend = args?.force === true || args?.forceSend === true;
43683
43833
  if (forceSend && typeof adapter.forceSendMessage === "function") {
43684
- await adapter.forceSendMessage(message);
43834
+ if (meshTaskId) await adapter.forceSendMessage(message, meshTaskId);
43835
+ else await adapter.forceSendMessage(message);
43685
43836
  } else if (forceSend) {
43686
- await adapter.sendMessage(message, { force: true });
43837
+ await adapter.sendMessage(message, meshTaskId ? { force: true, meshTaskId } : { force: true });
43838
+ } else if (meshTaskId) {
43839
+ await adapter.sendMessage(message, { meshTaskId });
43687
43840
  } else {
43688
43841
  await adapter.sendMessage(message);
43689
43842
  }
@@ -48211,6 +48364,11 @@ var meshCrudHandlers = {
48211
48364
  baseBranch,
48212
48365
  meshName: mesh.name
48213
48366
  });
48367
+ if (result.baseSync?.warning) {
48368
+ console.warn(`[mesh] clone_mesh_node base sync (${result.baseSync.action}): ${result.baseSync.warning}`);
48369
+ } else if (result.baseSync && result.baseSync.action !== "up_to_date") {
48370
+ console.log(`[mesh] clone_mesh_node base sync: ${result.baseSync.action} (startRef=${result.baseSync.startRef})`);
48371
+ }
48214
48372
  let node;
48215
48373
  if (meshRecord.inline) {
48216
48374
  const { randomUUID: randomUUID15 } = await import("crypto");
@@ -48401,6 +48559,8 @@ var meshCrudHandlers = {
48401
48559
  node,
48402
48560
  worktreePath: result.worktreePath,
48403
48561
  branch: result.branch,
48562
+ ...result.baseSync ? { baseSync: result.baseSync } : {},
48563
+ ...result.baseSync?.warning ? { baseStaleWarning: result.baseSync.warning } : {},
48404
48564
  worktreeBootstrap: runningBootstrapState,
48405
48565
  worktreeSetup: {
48406
48566
  status: "running",
@@ -48416,6 +48576,8 @@ var meshCrudHandlers = {
48416
48576
  node,
48417
48577
  worktreePath: result.worktreePath,
48418
48578
  branch: result.branch,
48579
+ ...result.baseSync ? { baseSync: result.baseSync } : {},
48580
+ ...result.baseSync?.warning ? { baseStaleWarning: result.baseSync.warning } : {},
48419
48581
  submodulesInitialized,
48420
48582
  worktreeBootstrap: bootstrapState
48421
48583
  };