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

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.js CHANGED
@@ -399,10 +399,10 @@ function readInjected(value) {
399
399
  }
400
400
  function getDaemonBuildInfo() {
401
401
  if (cached) return cached;
402
- const commit = readInjected(true ? "2350563490670c1c560cc5cf6f863a9e61ef3f89" : void 0) ?? "unknown";
403
- const commitShort = readInjected(true ? "23505634" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
404
- const version = readInjected(true ? "0.9.82-rc.400" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
405
- const builtAt = readInjected(true ? "2026-06-27T13:15:45.410Z" : void 0);
402
+ const commit = readInjected(true ? "93b00efeec1fccd6550c1faf5fa838106caef4bb" : void 0) ?? "unknown";
403
+ const commitShort = readInjected(true ? "93b00efe" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
404
+ const version = readInjected(true ? "0.9.82-rc.402" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
405
+ const builtAt = readInjected(true ? "2026-06-27T16:41:05.513Z" : void 0);
406
406
  cached = builtAt ? { commit, commitShort, version, builtAt } : { commit, commitShort, version };
407
407
  return cached;
408
408
  }
@@ -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 ((0, import_node_fs2.existsSync)(targetDir)) {
1448
1529
  throw new Error(`Worktree target directory already exists: ${targetDir}`);
1449
1530
  }
1450
1531
  await (0, import_promises3.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 = {}) {
@@ -4403,6 +4491,176 @@ var init_mesh_ledger = __esm({
4403
4491
  }
4404
4492
  });
4405
4493
 
4494
+ // src/mesh/mesh-delivery-policy.ts
4495
+ function resolveDeliveryDecision(sessionStatus, opts) {
4496
+ const status = (sessionStatus || "").trim().toLowerCase();
4497
+ if (!status) {
4498
+ return {
4499
+ decision: "rejected",
4500
+ reason: "unknown_session_status",
4501
+ message: "Session status is unknown. Delivery rejected (fail-closed). Use mesh_launch_session to start a fresh session."
4502
+ };
4503
+ }
4504
+ if (IMMEDIATE_DELIVERY_STATUSES.has(status)) {
4505
+ return {
4506
+ decision: "immediate",
4507
+ reason: `session_${status}`,
4508
+ message: `Session is ${status} \u2014 delivery allowed immediately.`
4509
+ };
4510
+ }
4511
+ if (BUSY_DELIVERY_STATUSES.has(status)) {
4512
+ if (opts?.allowBusyInjection) {
4513
+ return {
4514
+ decision: "immediate",
4515
+ reason: `session_${status}_busy_injection_allowed`,
4516
+ message: `Session is ${status} but provider supports busy injection. Delivered immediately.`
4517
+ };
4518
+ }
4519
+ if (status === "waiting_approval" && opts?.kind === "approval") {
4520
+ return {
4521
+ decision: "immediate",
4522
+ reason: "session_waiting_approval_approval_message",
4523
+ message: "Session is waiting for approval \u2014 approval message delivered immediately."
4524
+ };
4525
+ }
4526
+ return {
4527
+ decision: "queued",
4528
+ reason: `session_${status}_busy`,
4529
+ message: `Session is ${status}. Task queued for delivery when session becomes idle. Do not inject directly into a busy session.`
4530
+ };
4531
+ }
4532
+ if (TERMINAL_DELIVERY_STATUSES.has(status)) {
4533
+ return {
4534
+ decision: "rejected",
4535
+ reason: `session_${status}_terminal`,
4536
+ message: `Session is ${status} (terminal). Delivery rejected. Launch a new session before dispatching tasks.`
4537
+ };
4538
+ }
4539
+ return {
4540
+ decision: "rejected",
4541
+ reason: "unrecognized_session_status",
4542
+ message: `Session status '${sessionStatus}' is not recognized. Delivery rejected (fail-closed). Inspect session state before retrying.`
4543
+ };
4544
+ }
4545
+ function createSessionDelivery(opts) {
4546
+ const now = (/* @__PURE__ */ new Date()).toISOString();
4547
+ const id = (0, import_crypto5.randomUUID)();
4548
+ const record = {
4549
+ id,
4550
+ meshId: opts.meshId,
4551
+ nodeId: opts.nodeId,
4552
+ sessionId: opts.sessionId,
4553
+ providerType: opts.providerType,
4554
+ taskId: opts.taskId,
4555
+ kind: opts.kind,
4556
+ priority: opts.priority ?? 0,
4557
+ message: opts.message,
4558
+ status: opts.status,
4559
+ deliverAfter: opts.deliverAfter,
4560
+ expiresAt: opts.expiresAt,
4561
+ attemptCount: 0,
4562
+ sourceCoordinatorSessionId: opts.sourceCoordinatorSessionId,
4563
+ sourceCoordinatorDaemonId: opts.sourceCoordinatorDaemonId,
4564
+ createdAt: now,
4565
+ updatedAt: now
4566
+ };
4567
+ MeshRuntimeStore.getInstance().insertSessionDelivery({
4568
+ id,
4569
+ meshId: opts.meshId,
4570
+ nodeId: opts.nodeId,
4571
+ sessionId: opts.sessionId,
4572
+ providerType: opts.providerType,
4573
+ taskId: opts.taskId,
4574
+ kind: opts.kind,
4575
+ priority: opts.priority ?? 0,
4576
+ message: opts.message,
4577
+ status: opts.status,
4578
+ deliverAfter: opts.deliverAfter,
4579
+ expiresAt: opts.expiresAt,
4580
+ sourceCoordinatorSessionId: opts.sourceCoordinatorSessionId,
4581
+ sourceCoordinatorDaemonId: opts.sourceCoordinatorDaemonId,
4582
+ createdAt: now,
4583
+ updatedAt: now
4584
+ });
4585
+ return record;
4586
+ }
4587
+ function updateSessionDeliveryStatus(id, status, opts) {
4588
+ try {
4589
+ MeshRuntimeStore.getInstance().updateSessionDeliveryStatus(id, status, opts);
4590
+ } catch {
4591
+ }
4592
+ }
4593
+ function getActiveSessionDeliveries(meshId, sessionId) {
4594
+ try {
4595
+ return MeshRuntimeStore.getInstance().getActiveSessionDeliveries(meshId, sessionId);
4596
+ } catch {
4597
+ return [];
4598
+ }
4599
+ }
4600
+ function recordCompletionConflict(opts) {
4601
+ try {
4602
+ MeshRuntimeStore.getInstance().recordCompletionConflict({
4603
+ id: (0, import_crypto5.randomUUID)(),
4604
+ meshId: opts.meshId,
4605
+ fingerprint: opts.fingerprint,
4606
+ conflictingTaskId: opts.conflictingTaskId,
4607
+ conflictingSessionId: opts.conflictingSessionId,
4608
+ originalTaskId: opts.originalTaskId,
4609
+ originalSessionId: opts.originalSessionId,
4610
+ event: opts.event,
4611
+ createdAt: (/* @__PURE__ */ new Date()).toISOString()
4612
+ });
4613
+ } catch {
4614
+ }
4615
+ }
4616
+ function getRecentCompletionConflicts(meshId, limitMs) {
4617
+ try {
4618
+ return MeshRuntimeStore.getInstance().getRecentCompletionConflicts(meshId, limitMs);
4619
+ } catch {
4620
+ return [];
4621
+ }
4622
+ }
4623
+ function markSessionDeliveriesTerminal(meshId, sessionId, terminalStatus) {
4624
+ try {
4625
+ const active = MeshRuntimeStore.getInstance().getActiveSessionDeliveries(meshId, sessionId);
4626
+ for (const delivery of active) {
4627
+ MeshRuntimeStore.getInstance().updateSessionDeliveryStatus(delivery.id, terminalStatus);
4628
+ }
4629
+ } catch {
4630
+ }
4631
+ }
4632
+ var import_crypto5, IMMEDIATE_DELIVERY_STATUSES, BUSY_DELIVERY_STATUSES, TERMINAL_DELIVERY_STATUSES;
4633
+ var init_mesh_delivery_policy = __esm({
4634
+ "src/mesh/mesh-delivery-policy.ts"() {
4635
+ "use strict";
4636
+ import_crypto5 = require("crypto");
4637
+ init_mesh_runtime_store();
4638
+ IMMEDIATE_DELIVERY_STATUSES = /* @__PURE__ */ new Set([
4639
+ "idle",
4640
+ "waiting_input",
4641
+ "ready"
4642
+ ]);
4643
+ BUSY_DELIVERY_STATUSES = /* @__PURE__ */ new Set([
4644
+ "generating",
4645
+ "running",
4646
+ "streaming",
4647
+ "busy",
4648
+ "starting",
4649
+ "initializing",
4650
+ "waiting_approval"
4651
+ ]);
4652
+ TERMINAL_DELIVERY_STATUSES = /* @__PURE__ */ new Set([
4653
+ "stopped",
4654
+ "failed",
4655
+ "terminated",
4656
+ "exited",
4657
+ "closed",
4658
+ "deleted",
4659
+ "error"
4660
+ ]);
4661
+ }
4662
+ });
4663
+
4406
4664
  // src/mesh/mesh-work-queue.ts
4407
4665
  var mesh_work_queue_exports = {};
4408
4666
  __export(mesh_work_queue_exports, {
@@ -4764,7 +5022,7 @@ function enqueueTask(meshId, message, opts) {
4764
5022
  if (!modeValidation.valid) {
4765
5023
  throw new Error(`live_debug_readonly_guardrail_violation: forbidden operations (${modeValidation.violations.join(", ")})`);
4766
5024
  }
4767
- const id = typeof opts?.id === "string" && opts.id.trim() ? opts.id.trim() : (0, import_crypto5.randomUUID)();
5025
+ const id = typeof opts?.id === "string" && opts.id.trim() ? opts.id.trim() : (0, import_crypto6.randomUUID)();
4768
5026
  const dependsOn = normalizeDependsOn(opts?.dependsOn);
4769
5027
  return withQueueLock(meshId, () => {
4770
5028
  if (MeshRuntimeStore.getInstance().findQueueEntryById(meshId, id)) {
@@ -4825,6 +5083,18 @@ function recordDirectDispatchTask(meshId, message, opts) {
4825
5083
  updatedAt: now
4826
5084
  };
4827
5085
  MeshRuntimeStore.getInstance().insertQueueEntry(entry);
5086
+ try {
5087
+ createSessionDelivery({
5088
+ meshId,
5089
+ ...opts.assignedNodeId ? { nodeId: opts.assignedNodeId } : {},
5090
+ ...opts.assignedSessionId ? { sessionId: opts.assignedSessionId } : {},
5091
+ taskId,
5092
+ kind: "task",
5093
+ message,
5094
+ status: "delivered"
5095
+ });
5096
+ } catch {
5097
+ }
4828
5098
  return entry;
4829
5099
  });
4830
5100
  }
@@ -5098,17 +5368,18 @@ function recordMeshToolCall(opts) {
5098
5368
  return { rateLimitExceeded: false, callsInWindow: 0, advisory: null };
5099
5369
  }
5100
5370
  }
5101
- var import_crypto5, ACTIVE_MESH_QUEUE_STATUSES, HISTORICAL_MESH_QUEUE_STATUSES, MESH_TASK_MODES, LIVE_DEBUG_READONLY_FORBIDDEN, NEGATION_CUES, NEGATION_WINDOW_TOKENS, GIT_MUTATION_SUBCOMMANDS, GIT_STASH_READONLY_SUBCOMMANDS, DEPENDENCY_FAILURE_TERMINALS, MAX_STRANDED_RECLAIMS;
5371
+ var import_crypto6, ACTIVE_MESH_QUEUE_STATUSES, HISTORICAL_MESH_QUEUE_STATUSES, MESH_TASK_MODES, LIVE_DEBUG_READONLY_FORBIDDEN, NEGATION_CUES, NEGATION_WINDOW_TOKENS, GIT_MUTATION_SUBCOMMANDS, GIT_STASH_READONLY_SUBCOMMANDS, DEPENDENCY_FAILURE_TERMINALS, MAX_STRANDED_RECLAIMS;
5102
5372
  var init_mesh_work_queue = __esm({
5103
5373
  "src/mesh/mesh-work-queue.ts"() {
5104
5374
  "use strict";
5105
- import_crypto5 = require("crypto");
5375
+ import_crypto6 = require("crypto");
5106
5376
  init_mesh_host_ownership();
5107
5377
  init_repo_mesh_types();
5108
5378
  init_mesh_runtime_store();
5109
5379
  init_mesh_config();
5110
5380
  init_logger();
5111
5381
  init_mesh_ledger();
5382
+ init_mesh_delivery_policy();
5112
5383
  ACTIVE_MESH_QUEUE_STATUSES = ["pending", "assigned"];
5113
5384
  HISTORICAL_MESH_QUEUE_STATUSES = ["completed", "failed", "cancelled"];
5114
5385
  MESH_TASK_MODES = ["code_change", "validation", "live_debug_readonly", "launch_app", "convergence"];
@@ -5654,11 +5925,14 @@ var init_mesh_runtime_store = __esm({
5654
5925
  }
5655
5926
  /** A node may only execute one write task at a time (worktree isolation). */
5656
5927
  hasActiveNodeAssignment(meshId, nodeId) {
5928
+ const nodeIdForms = expandDaemonIdForms(nodeId);
5929
+ if (nodeIdForms.length === 0) return false;
5930
+ const placeholders = nodeIdForms.map(() => "?").join(", ");
5657
5931
  const row = this.db.prepare(`
5658
5932
  SELECT 1 FROM mesh_queue
5659
- WHERE mesh_id = ? AND status = 'assigned' AND assigned_node_id = ?
5933
+ WHERE mesh_id = ? AND status = 'assigned' AND assigned_node_id IN (${placeholders})
5660
5934
  LIMIT 1
5661
- `).get(meshId, nodeId);
5935
+ `).get(meshId, ...nodeIdForms);
5662
5936
  return row !== void 0;
5663
5937
  }
5664
5938
  /**
@@ -6759,7 +7033,7 @@ function upsertMeshMission(meshId, input) {
6759
7033
  if (input.status !== void 0 && !MESH_MISSION_STATUSES.includes(input.status)) {
6760
7034
  throw new Error(`invalid_mission_status: '${input.status}' (valid: ${MESH_MISSION_STATUSES.join(", ")})`);
6761
7035
  }
6762
- const id = typeof input.id === "string" && input.id.trim() ? input.id.trim() : (0, import_crypto6.randomUUID)();
7036
+ const id = typeof input.id === "string" && input.id.trim() ? input.id.trim() : (0, import_crypto7.randomUUID)();
6763
7037
  const store = MeshRuntimeStore.getInstance();
6764
7038
  const existing = store.getMission(meshId, id);
6765
7039
  const record = {
@@ -6875,11 +7149,11 @@ function buildMissionPromptSection(meshId) {
6875
7149
  );
6876
7150
  return lines.join("\n");
6877
7151
  }
6878
- var import_crypto6, MESH_MISSION_STATUSES, GOAL_PREVIEW_MAX, COMPACT_STATUS_GOAL_PREVIEW_MAX;
7152
+ var import_crypto7, MESH_MISSION_STATUSES, GOAL_PREVIEW_MAX, COMPACT_STATUS_GOAL_PREVIEW_MAX;
6879
7153
  var init_mesh_missions = __esm({
6880
7154
  "src/mesh/mesh-missions.ts"() {
6881
7155
  "use strict";
6882
- import_crypto6 = require("crypto");
7156
+ import_crypto7 = require("crypto");
6883
7157
  init_mesh_runtime_store();
6884
7158
  init_mesh_work_queue();
6885
7159
  init_mesh_task_stats();
@@ -9946,7 +10220,7 @@ function queuePendingMeshCoordinatorEvent(event) {
9946
10220
  let sqliteOk = false;
9947
10221
  try {
9948
10222
  MeshRuntimeStore.getInstance().insertPendingEvent({
9949
- id: (0, import_crypto7.randomUUID)(),
10223
+ id: (0, import_crypto8.randomUUID)(),
9950
10224
  meshId: event.meshId,
9951
10225
  coordinatorDaemonId: event.targetCoordinatorDaemonId ?? null,
9952
10226
  event: event.event,
@@ -10134,13 +10408,13 @@ function clearPendingMeshCoordinatorEvents(meshId, coordinatorDaemonId) {
10134
10408
  }
10135
10409
  }
10136
10410
  }
10137
- var import_fs10, import_path9, import_crypto7, REFINE_TERMINAL_EVENTS, TERMINAL_COMPLETION_EVENTS, MAX_PENDING_EVENTS_BYTES, MAX_PENDING_EVENTS_KEEP;
10411
+ var import_fs10, import_path9, import_crypto8, REFINE_TERMINAL_EVENTS, TERMINAL_COMPLETION_EVENTS, MAX_PENDING_EVENTS_BYTES, MAX_PENDING_EVENTS_KEEP;
10138
10412
  var init_mesh_events_pending = __esm({
10139
10413
  "src/mesh/mesh-events-pending.ts"() {
10140
10414
  "use strict";
10141
10415
  import_fs10 = require("fs");
10142
10416
  import_path9 = require("path");
10143
- import_crypto7 = require("crypto");
10417
+ import_crypto8 = require("crypto");
10144
10418
  init_logger();
10145
10419
  init_mesh_ledger();
10146
10420
  init_mesh_runtime_store();
@@ -10153,176 +10427,6 @@ var init_mesh_events_pending = __esm({
10153
10427
  }
10154
10428
  });
10155
10429
 
10156
- // src/mesh/mesh-delivery-policy.ts
10157
- function resolveDeliveryDecision(sessionStatus, opts) {
10158
- const status = (sessionStatus || "").trim().toLowerCase();
10159
- if (!status) {
10160
- return {
10161
- decision: "rejected",
10162
- reason: "unknown_session_status",
10163
- message: "Session status is unknown. Delivery rejected (fail-closed). Use mesh_launch_session to start a fresh session."
10164
- };
10165
- }
10166
- if (IMMEDIATE_DELIVERY_STATUSES.has(status)) {
10167
- return {
10168
- decision: "immediate",
10169
- reason: `session_${status}`,
10170
- message: `Session is ${status} \u2014 delivery allowed immediately.`
10171
- };
10172
- }
10173
- if (BUSY_DELIVERY_STATUSES.has(status)) {
10174
- if (opts?.allowBusyInjection) {
10175
- return {
10176
- decision: "immediate",
10177
- reason: `session_${status}_busy_injection_allowed`,
10178
- message: `Session is ${status} but provider supports busy injection. Delivered immediately.`
10179
- };
10180
- }
10181
- if (status === "waiting_approval" && opts?.kind === "approval") {
10182
- return {
10183
- decision: "immediate",
10184
- reason: "session_waiting_approval_approval_message",
10185
- message: "Session is waiting for approval \u2014 approval message delivered immediately."
10186
- };
10187
- }
10188
- return {
10189
- decision: "queued",
10190
- reason: `session_${status}_busy`,
10191
- message: `Session is ${status}. Task queued for delivery when session becomes idle. Do not inject directly into a busy session.`
10192
- };
10193
- }
10194
- if (TERMINAL_DELIVERY_STATUSES.has(status)) {
10195
- return {
10196
- decision: "rejected",
10197
- reason: `session_${status}_terminal`,
10198
- message: `Session is ${status} (terminal). Delivery rejected. Launch a new session before dispatching tasks.`
10199
- };
10200
- }
10201
- return {
10202
- decision: "rejected",
10203
- reason: "unrecognized_session_status",
10204
- message: `Session status '${sessionStatus}' is not recognized. Delivery rejected (fail-closed). Inspect session state before retrying.`
10205
- };
10206
- }
10207
- function createSessionDelivery(opts) {
10208
- const now = (/* @__PURE__ */ new Date()).toISOString();
10209
- const id = (0, import_crypto8.randomUUID)();
10210
- const record = {
10211
- id,
10212
- meshId: opts.meshId,
10213
- nodeId: opts.nodeId,
10214
- sessionId: opts.sessionId,
10215
- providerType: opts.providerType,
10216
- taskId: opts.taskId,
10217
- kind: opts.kind,
10218
- priority: opts.priority ?? 0,
10219
- message: opts.message,
10220
- status: opts.status,
10221
- deliverAfter: opts.deliverAfter,
10222
- expiresAt: opts.expiresAt,
10223
- attemptCount: 0,
10224
- sourceCoordinatorSessionId: opts.sourceCoordinatorSessionId,
10225
- sourceCoordinatorDaemonId: opts.sourceCoordinatorDaemonId,
10226
- createdAt: now,
10227
- updatedAt: now
10228
- };
10229
- MeshRuntimeStore.getInstance().insertSessionDelivery({
10230
- id,
10231
- meshId: opts.meshId,
10232
- nodeId: opts.nodeId,
10233
- sessionId: opts.sessionId,
10234
- providerType: opts.providerType,
10235
- taskId: opts.taskId,
10236
- kind: opts.kind,
10237
- priority: opts.priority ?? 0,
10238
- message: opts.message,
10239
- status: opts.status,
10240
- deliverAfter: opts.deliverAfter,
10241
- expiresAt: opts.expiresAt,
10242
- sourceCoordinatorSessionId: opts.sourceCoordinatorSessionId,
10243
- sourceCoordinatorDaemonId: opts.sourceCoordinatorDaemonId,
10244
- createdAt: now,
10245
- updatedAt: now
10246
- });
10247
- return record;
10248
- }
10249
- function updateSessionDeliveryStatus(id, status, opts) {
10250
- try {
10251
- MeshRuntimeStore.getInstance().updateSessionDeliveryStatus(id, status, opts);
10252
- } catch {
10253
- }
10254
- }
10255
- function getActiveSessionDeliveries(meshId, sessionId) {
10256
- try {
10257
- return MeshRuntimeStore.getInstance().getActiveSessionDeliveries(meshId, sessionId);
10258
- } catch {
10259
- return [];
10260
- }
10261
- }
10262
- function recordCompletionConflict(opts) {
10263
- try {
10264
- MeshRuntimeStore.getInstance().recordCompletionConflict({
10265
- id: (0, import_crypto8.randomUUID)(),
10266
- meshId: opts.meshId,
10267
- fingerprint: opts.fingerprint,
10268
- conflictingTaskId: opts.conflictingTaskId,
10269
- conflictingSessionId: opts.conflictingSessionId,
10270
- originalTaskId: opts.originalTaskId,
10271
- originalSessionId: opts.originalSessionId,
10272
- event: opts.event,
10273
- createdAt: (/* @__PURE__ */ new Date()).toISOString()
10274
- });
10275
- } catch {
10276
- }
10277
- }
10278
- function getRecentCompletionConflicts(meshId, limitMs) {
10279
- try {
10280
- return MeshRuntimeStore.getInstance().getRecentCompletionConflicts(meshId, limitMs);
10281
- } catch {
10282
- return [];
10283
- }
10284
- }
10285
- function markSessionDeliveriesTerminal(meshId, sessionId, terminalStatus) {
10286
- try {
10287
- const active = MeshRuntimeStore.getInstance().getActiveSessionDeliveries(meshId, sessionId);
10288
- for (const delivery of active) {
10289
- MeshRuntimeStore.getInstance().updateSessionDeliveryStatus(delivery.id, terminalStatus);
10290
- }
10291
- } catch {
10292
- }
10293
- }
10294
- var import_crypto8, IMMEDIATE_DELIVERY_STATUSES, BUSY_DELIVERY_STATUSES, TERMINAL_DELIVERY_STATUSES;
10295
- var init_mesh_delivery_policy = __esm({
10296
- "src/mesh/mesh-delivery-policy.ts"() {
10297
- "use strict";
10298
- import_crypto8 = require("crypto");
10299
- init_mesh_runtime_store();
10300
- IMMEDIATE_DELIVERY_STATUSES = /* @__PURE__ */ new Set([
10301
- "idle",
10302
- "waiting_input",
10303
- "ready"
10304
- ]);
10305
- BUSY_DELIVERY_STATUSES = /* @__PURE__ */ new Set([
10306
- "generating",
10307
- "running",
10308
- "streaming",
10309
- "busy",
10310
- "starting",
10311
- "initializing",
10312
- "waiting_approval"
10313
- ]);
10314
- TERMINAL_DELIVERY_STATUSES = /* @__PURE__ */ new Set([
10315
- "stopped",
10316
- "failed",
10317
- "terminated",
10318
- "exited",
10319
- "closed",
10320
- "deleted",
10321
- "error"
10322
- ]);
10323
- }
10324
- });
10325
-
10326
10430
  // src/mesh/mesh-events-stale.ts
10327
10431
  function findRecentTerminalLedgerEvidence(args) {
10328
10432
  if (!args.sessionId && !args.nodeId) return null;
@@ -11874,7 +11978,14 @@ function tryAssignQueueTask(components, meshId, nodeId, sessionId, providerType)
11874
11978
  targetSessionId: sessionId,
11875
11979
  cliType: providerType,
11876
11980
  action: "send_chat",
11877
- message: task.message
11981
+ message: task.message,
11982
+ meshContext: {
11983
+ meshId,
11984
+ nodeId,
11985
+ taskId: task.id,
11986
+ ...readNonEmptyString2(loadConfig().machineId) ? { coordinatorDaemonId: readNonEmptyString2(loadConfig().machineId) } : {},
11987
+ ...readNonEmptyString2(task.sourceCoordinatorSessionId) ? { coordinatorSessionId: readNonEmptyString2(task.sourceCoordinatorSessionId) } : {}
11988
+ }
11878
11989
  }),
11879
11990
  {
11880
11991
  meshId,
@@ -19544,6 +19655,15 @@ var init_cli_state_engine = __esm({
19544
19655
  currentStatus = "starting";
19545
19656
  isWaitingForResponse = false;
19546
19657
  currentTurnScope = null;
19658
+ // ARCH-REFACTOR R1 (per-turn task identity): the mesh taskId bound to the most
19659
+ // recently STARTED turn. Unlike currentTurnScope (nulled the moment the turn
19660
+ // settles, before the completion event is even built), this persists past
19661
+ // completion and is only overwritten when the NEXT turn starts. That window is
19662
+ // exactly what the completion path needs: when a turn settles to idle, this still
19663
+ // holds THAT turn's taskId (the next task's turn cannot have started yet — it is
19664
+ // queued in pendingOutbound and only flushed asynchronously after idle), so the
19665
+ // completion event carries the correct id instead of the racy session scalar.
19666
+ currentTurnTaskId = null;
19547
19667
  activeModal = null;
19548
19668
  // ── Approval ─────────────────────────────────────
19549
19669
  lastApprovalResolvedAt = 0;
@@ -19653,6 +19773,7 @@ var init_cli_state_engine = __esm({
19653
19773
  this.finishRetryCount = 0;
19654
19774
  this.clearIdleFinishCandidate("send_message");
19655
19775
  this.currentTurnScope = turnScope;
19776
+ this.currentTurnTaskId = typeof turnScope.taskId === "string" && turnScope.taskId.trim() ? turnScope.taskId : null;
19656
19777
  this.responseEpoch += 1;
19657
19778
  }
19658
19779
  /** Called when PTY exits */
@@ -21605,15 +21726,18 @@ ${lastSnapshot}`;
21605
21726
  }
21606
21727
  async sendMessage(text, options = {}) {
21607
21728
  if (options.force === true) {
21608
- await this.forceSendMessage(text);
21729
+ await this.forceSendMessage(text, options.meshTaskId);
21609
21730
  return;
21610
21731
  }
21611
- await this.sendMessageNow(text, true);
21732
+ await this.sendMessageNow(text, true, options.meshTaskId);
21612
21733
  }
21613
- async forceSendMessage(text) {
21734
+ async forceSendMessage(text, meshTaskId) {
21614
21735
  if (!this.ptyProcess) throw new Error(`${this.cliName} is not running`);
21615
21736
  const content = String(text || "");
21616
21737
  if (!content.trim()) return;
21738
+ if (typeof meshTaskId === "string" && meshTaskId.trim()) {
21739
+ this.engine.currentTurnTaskId = meshTaskId;
21740
+ }
21617
21741
  if (this.engine.currentStatus === "waiting_approval" || this.engine.hasActionableApproval()) {
21618
21742
  LOG.info("CLI", `[${this.cliType}] force-send held \u2014 session parked on approval modal (status=${this.engine.currentStatus})`);
21619
21743
  return;
@@ -21626,7 +21750,7 @@ ${lastSnapshot}`;
21626
21750
  async waitForForceSubmitSettle() {
21627
21751
  await new Promise((resolve24) => setTimeout(resolve24, FORCE_SUBMIT_SETTLE_MS));
21628
21752
  }
21629
- enqueuePendingOutboundMessage(text, reason) {
21753
+ enqueuePendingOutboundMessage(text, reason, meshTaskId) {
21630
21754
  const content = String(text || "");
21631
21755
  const duplicate = this.pendingOutboundQueue.some((message2) => message2.content === content);
21632
21756
  if (duplicate) {
@@ -21638,7 +21762,8 @@ ${lastSnapshot}`;
21638
21762
  role: "user",
21639
21763
  content,
21640
21764
  queuedAt,
21641
- source: "sendMessage"
21765
+ source: "sendMessage",
21766
+ ...typeof meshTaskId === "string" && meshTaskId.trim() ? { meshTaskId } : {}
21642
21767
  };
21643
21768
  this.pendingOutboundQueue.push(message);
21644
21769
  LOG.info("CLI", `[${this.cliType}] queued outbound message while busy (${reason}); queue=${this.pendingOutboundQueue.length}`);
@@ -21681,7 +21806,7 @@ ${lastSnapshot}`;
21681
21806
  if (this.engine.currentStatus !== "idle" || this.engine.isWaitingForResponse || this.engine.hasActionableApproval()) break;
21682
21807
  const next = this.pendingOutboundQueue[0];
21683
21808
  try {
21684
- await this.sendMessageNow(next.content, false);
21809
+ await this.sendMessageNow(next.content, false, next.meshTaskId);
21685
21810
  this.pendingOutboundQueue.shift();
21686
21811
  this.onStatusChange?.();
21687
21812
  } catch (error) {
@@ -21694,7 +21819,7 @@ ${lastSnapshot}`;
21694
21819
  this.pendingOutboundFlushInFlight = false;
21695
21820
  }
21696
21821
  }
21697
- async sendMessageNow(text, allowQueue) {
21822
+ async sendMessageNow(text, allowQueue, meshTaskId) {
21698
21823
  if (!this.ptyProcess) throw new Error(`${this.cliName} is not running`);
21699
21824
  const allowInputDuringGeneration = this.provider.allowInputDuringGeneration === true;
21700
21825
  const allowInterventionPrompt = allowInputDuringGeneration && this.engine.isWaitingForResponse && !this.engine.hasActionableApproval();
@@ -21714,7 +21839,7 @@ ${lastSnapshot}`;
21714
21839
  })() : null;
21715
21840
  const queueReason = this.shouldQueuePendingOutboundMessage(parsedStatusBeforeSend);
21716
21841
  if (allowQueue && queueReason) {
21717
- this.enqueuePendingOutboundMessage(text, queueReason);
21842
+ this.enqueuePendingOutboundMessage(text, queueReason, meshTaskId);
21718
21843
  return;
21719
21844
  }
21720
21845
  if (!allowInterventionPrompt) {
@@ -21731,7 +21856,7 @@ ${lastSnapshot}`;
21731
21856
  }
21732
21857
  if (!this.ready) {
21733
21858
  if (allowQueue) {
21734
- this.enqueuePendingOutboundMessage(text, "not_ready_pending_prompt");
21859
+ this.enqueuePendingOutboundMessage(text, "not_ready_pending_prompt", meshTaskId);
21735
21860
  return;
21736
21861
  }
21737
21862
  throw new Error(`${this.cliName} not ready (status: ${this.engine.currentStatus})`);
@@ -21745,7 +21870,7 @@ ${lastSnapshot}`;
21745
21870
  const terminalLooksIdle = this.engine.currentStatus === "idle" && this.runDetectStatus(this.recentOutputBuffer) === "idle" && !this.engine.isWaitingForResponse && !this.engine.currentTurnScope && !this.engine.hasActionableApproval() && !parsedHasActionableModal;
21746
21871
  if (!terminalLooksIdle) {
21747
21872
  if (allowQueue) {
21748
- this.enqueuePendingOutboundMessage(text, `parsed_status_${parsedSessionStatus}`);
21873
+ this.enqueuePendingOutboundMessage(text, `parsed_status_${parsedSessionStatus}`, meshTaskId);
21749
21874
  return;
21750
21875
  }
21751
21876
  throw new Error(`${this.cliName} is still processing the previous prompt`);
@@ -21755,7 +21880,7 @@ ${lastSnapshot}`;
21755
21880
  const snap = this.getSnapshot();
21756
21881
  if (!this.engine.clearStaleIdleResponseGuard("send_message_guard", snap) && !this.engine.clearParsedIdleResponseGuard("send_message_parsed_idle_guard", parsedStatusBeforeSend, snap)) {
21757
21882
  if (allowQueue) {
21758
- this.enqueuePendingOutboundMessage(text, "waiting_for_response");
21883
+ this.enqueuePendingOutboundMessage(text, "waiting_for_response", meshTaskId);
21759
21884
  return;
21760
21885
  }
21761
21886
  throw new Error(`${this.cliName} is still processing the previous prompt`);
@@ -21766,7 +21891,11 @@ ${lastSnapshot}`;
21766
21891
  prompt: text,
21767
21892
  startedAt: Date.now(),
21768
21893
  bufferStart: this.accumulatedBuffer.length,
21769
- rawBufferStart: this.accumulatedRawBuffer.length
21894
+ rawBufferStart: this.accumulatedRawBuffer.length,
21895
+ // ARCH-REFACTOR R1: bind this turn to its mesh task. engine.onTurnStarted
21896
+ // copies this into currentTurnTaskId so the turn's completion event carries
21897
+ // the right id even if a later task overwrites the session scalar meanwhile.
21898
+ ...typeof meshTaskId === "string" && meshTaskId.trim() ? { taskId: meshTaskId } : {}
21770
21899
  };
21771
21900
  LOG.info("CLI", `[${this.cliType}] sendMessage turn scope buffer=${turnScope.bufferStart} raw=${turnScope.rawBufferStart} prompt=${JSON.stringify(text).slice(0, 120)}`);
21772
21901
  if (this.submitRetryTimer) {
@@ -22116,6 +22245,13 @@ ${lastSnapshot}`;
22116
22245
  set currentTurnScope(v) {
22117
22246
  this.engine.currentTurnScope = v;
22118
22247
  }
22248
+ // ARCH-REFACTOR R1: the mesh taskId bound to the most recently started turn,
22249
+ // surviving past turn settle until the next turn starts. The provider instance
22250
+ // reads this when stamping completion events so they carry the completing turn's
22251
+ // task rather than the racy last-write-wins session scalar.
22252
+ get currentTurnTaskId() {
22253
+ return this.engine.currentTurnTaskId;
22254
+ }
22119
22255
  get responseEpoch() {
22120
22256
  return this.engine.responseEpoch;
22121
22257
  }
@@ -40705,11 +40841,28 @@ var CliProviderInstance = class _CliProviderInstance {
40705
40841
  isMeshWorkerSession() {
40706
40842
  return !!(this.settings.meshNodeFor || this.settings.meshActiveTaskId || this.settings.meshNodeId || this.settings.launchedByCoordinator);
40707
40843
  }
40844
+ /**
40845
+ * ARCH-REFACTOR R1: the taskId to attribute the CURRENTLY-completing turn to.
40846
+ * Prefers the per-turn binding (engine.currentTurnTaskId, set when the turn was
40847
+ * submitted and surviving until the next turn starts) over the last-write-wins
40848
+ * session scalar (settings.meshActiveTaskId). The scalar is retained only as a
40849
+ * backward-compat alias for the "current/last assignment" and is the source of the
40850
+ * NOTIF-MISDELIVER / TASK-MSG-MISROUTE race: a second task attaching before this
40851
+ * turn completes overwrites it. Returns undefined for a non-task ad-hoc turn.
40852
+ */
40853
+ completingTurnTaskId() {
40854
+ const turnTaskId = this.adapter?.currentTurnTaskId;
40855
+ if (typeof turnTaskId === "string" && turnTaskId.trim()) return turnTaskId;
40856
+ const scalar = this.settings.meshActiveTaskId;
40857
+ return typeof scalar === "string" && scalar.trim() ? scalar : void 0;
40858
+ }
40708
40859
  // EVTTRACE correlation context for this session's completion lifecycle. taskId is
40709
40860
  // the primary grep anchor; instanceId is the session fallback.
40710
40861
  meshTraceCtx(event = "agent:generating_completed") {
40711
40862
  return {
40712
- taskId: this.settings.meshActiveTaskId,
40863
+ // ARCH-REFACTOR R1: trace the per-turn taskId (falling back to the scalar) so
40864
+ // EvtTrace anchors on the same id the completion event actually carries.
40865
+ taskId: this.completingTurnTaskId(),
40713
40866
  sessionId: this.instanceId,
40714
40867
  nodeId: this.settings.meshNodeId,
40715
40868
  meshId: this.settings.meshNodeFor,
@@ -40768,6 +40921,8 @@ var CliProviderInstance = class _CliProviderInstance {
40768
40921
  chatTitle: pending.chatTitle,
40769
40922
  duration: pending.duration,
40770
40923
  timestamp: pending.timestamp,
40924
+ // ARCH-REFACTOR R1: attribute to the turn captured at idle-transition.
40925
+ ...pending.taskId ? { taskId: pending.taskId } : {},
40771
40926
  // When finalization is forced past the timeout on a `parsed_status:` block
40772
40927
  // (the parser never confirmed a final assistant turn) we previously rode an
40773
40928
  // empty `finalSummary` unconditionally. That empty value propagates to the
@@ -40793,6 +40948,8 @@ var CliProviderInstance = class _CliProviderInstance {
40793
40948
  chatTitle: pending.chatTitle,
40794
40949
  duration: pending.duration,
40795
40950
  timestamp: pending.timestamp,
40951
+ // ARCH-REFACTOR R1: attribute to the turn captured at idle-transition.
40952
+ ...pending.taskId ? { taskId: pending.taskId } : {},
40796
40953
  finalSummary: this.completionFinalSummary(this.adapter?.getScriptParsedStatus()?.messages)
40797
40954
  });
40798
40955
  this.completedDebouncePending = null;
@@ -41069,7 +41226,11 @@ var CliProviderInstance = class _CliProviderInstance {
41069
41226
  duration,
41070
41227
  timestamp: now,
41071
41228
  firstObservedAt: now,
41072
- previousStatus: this.lastStatus
41229
+ previousStatus: this.lastStatus,
41230
+ // ARCH-REFACTOR R1: snapshot the completing turn's taskId NOW (sync),
41231
+ // before any follow-up task's flush can start a new turn and move
41232
+ // engine.currentTurnTaskId.
41233
+ ...this.completingTurnTaskId() ? { taskId: this.completingTurnTaskId() } : {}
41073
41234
  };
41074
41235
  const ownsExternalHistory = !!this.adapter?.chatMessagesOwnedExternally;
41075
41236
  const meshWorkerSession = this.isMeshWorkerSession();
@@ -41172,10 +41333,11 @@ var CliProviderInstance = class _CliProviderInstance {
41172
41333
  workspace: typeof event.workspace === "string" && event.workspace.trim() ? event.workspace : this.workingDir,
41173
41334
  providerSessionId: typeof event.providerSessionId === "string" && event.providerSessionId.trim() ? event.providerSessionId : this.providerSessionId
41174
41335
  };
41175
- if (this.isMeshWorkerSession() && this.settings.meshActiveTaskId) {
41336
+ if (this.isMeshWorkerSession()) {
41176
41337
  const existingTaskId = typeof enrichedEvent.taskId === "string" && enrichedEvent.taskId.trim() ? enrichedEvent.taskId : void 0;
41177
41338
  if (!existingTaskId) {
41178
- enrichedEvent.taskId = this.settings.meshActiveTaskId;
41339
+ const resolved = this.completingTurnTaskId();
41340
+ if (resolved) enrichedEvent.taskId = resolved;
41179
41341
  }
41180
41342
  }
41181
41343
  if (this.context?.emitProviderEvent) {
@@ -44055,11 +44217,15 @@ Run 'adhdev doctor' for detailed diagnostics.`
44055
44217
  }
44056
44218
  const message = input.textFallback;
44057
44219
  if (!message) throw new Error("message required for send_chat");
44220
+ const meshTaskId = meshContext && typeof meshContext === "object" && typeof meshContext.taskId === "string" && meshContext.taskId.trim() ? meshContext.taskId : void 0;
44058
44221
  const forceSend = args?.force === true || args?.forceSend === true;
44059
44222
  if (forceSend && typeof adapter.forceSendMessage === "function") {
44060
- await adapter.forceSendMessage(message);
44223
+ if (meshTaskId) await adapter.forceSendMessage(message, meshTaskId);
44224
+ else await adapter.forceSendMessage(message);
44061
44225
  } else if (forceSend) {
44062
- await adapter.sendMessage(message, { force: true });
44226
+ await adapter.sendMessage(message, meshTaskId ? { force: true, meshTaskId } : { force: true });
44227
+ } else if (meshTaskId) {
44228
+ await adapter.sendMessage(message, { meshTaskId });
44063
44229
  } else {
44064
44230
  await adapter.sendMessage(message);
44065
44231
  }
@@ -48587,6 +48753,11 @@ var meshCrudHandlers = {
48587
48753
  baseBranch,
48588
48754
  meshName: mesh.name
48589
48755
  });
48756
+ if (result.baseSync?.warning) {
48757
+ console.warn(`[mesh] clone_mesh_node base sync (${result.baseSync.action}): ${result.baseSync.warning}`);
48758
+ } else if (result.baseSync && result.baseSync.action !== "up_to_date") {
48759
+ console.log(`[mesh] clone_mesh_node base sync: ${result.baseSync.action} (startRef=${result.baseSync.startRef})`);
48760
+ }
48590
48761
  let node;
48591
48762
  if (meshRecord.inline) {
48592
48763
  const { randomUUID: randomUUID15 } = await import("crypto");
@@ -48777,6 +48948,8 @@ var meshCrudHandlers = {
48777
48948
  node,
48778
48949
  worktreePath: result.worktreePath,
48779
48950
  branch: result.branch,
48951
+ ...result.baseSync ? { baseSync: result.baseSync } : {},
48952
+ ...result.baseSync?.warning ? { baseStaleWarning: result.baseSync.warning } : {},
48780
48953
  worktreeBootstrap: runningBootstrapState,
48781
48954
  worktreeSetup: {
48782
48955
  status: "running",
@@ -48792,6 +48965,8 @@ var meshCrudHandlers = {
48792
48965
  node,
48793
48966
  worktreePath: result.worktreePath,
48794
48967
  branch: result.branch,
48968
+ ...result.baseSync ? { baseSync: result.baseSync } : {},
48969
+ ...result.baseSync?.warning ? { baseStaleWarning: result.baseSync.warning } : {},
48795
48970
  submodulesInitialized,
48796
48971
  worktreeBootstrap: bootstrapState
48797
48972
  };