@adhdev/daemon-core 0.9.82-rc.262 → 0.9.82-rc.263

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
@@ -251,6 +251,29 @@ var init_git_executor = __esm({
251
251
  }
252
252
  });
253
253
 
254
+ // src/build-info.ts
255
+ function readInjected(value) {
256
+ if (typeof value !== "string") return void 0;
257
+ const trimmed = value.trim();
258
+ if (!trimmed || trimmed === "unknown") return void 0;
259
+ return trimmed;
260
+ }
261
+ function getDaemonBuildInfo() {
262
+ if (cached) return cached;
263
+ const commit = readInjected(true ? "2cf602f99ce68b3d3f1af02b429f6fb7a7c8e686" : void 0) ?? "unknown";
264
+ const commitShort = readInjected(true ? "2cf602f" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
265
+ const version = readInjected(true ? "0.9.82-rc.263" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
266
+ const builtAt = readInjected(true ? "2026-06-14T13:48:10.699Z" : void 0);
267
+ cached = builtAt ? { commit, commitShort, version, builtAt } : { commit, commitShort, version };
268
+ return cached;
269
+ }
270
+ var cached;
271
+ var init_build_info = __esm({
272
+ "src/build-info.ts"() {
273
+ "use strict";
274
+ }
275
+ });
276
+
254
277
  // src/git/git-status.ts
255
278
  async function getGitRepoStatus(workspace, options = {}) {
256
279
  const lastCheckedAt = Date.now();
@@ -273,6 +296,7 @@ async function getGitRepoStatus(workspace, options = {}) {
273
296
  }
274
297
  const submoduleDirty = (submodules || []).some((submodule) => submodule.dirty || submodule.outOfSync || !!submodule.error);
275
298
  const dirty = parsed.staged + parsed.modified + parsed.untracked + parsed.deleted + parsed.renamed > 0 || parsed.conflictFiles.length > 0 || stashCount > 0 || submoduleDirty;
299
+ const daemonBuildBehind = await detectDaemonBuildBehind(repo, submodules, options);
276
300
  return {
277
301
  workspace: repo.workspace,
278
302
  repoRoot: repo.repoRoot,
@@ -296,7 +320,8 @@ async function getGitRepoStatus(workspace, options = {}) {
296
320
  conflictFiles: parsed.conflictFiles,
297
321
  stashCount,
298
322
  lastCheckedAt,
299
- submodules
323
+ submodules,
324
+ ...daemonBuildBehind ? { daemonBuildBehind } : {}
300
325
  };
301
326
  } catch (error) {
302
327
  if (error instanceof GitCommandError) {
@@ -309,6 +334,35 @@ async function getGitRepoStatus(workspace, options = {}) {
309
334
  );
310
335
  }
311
336
  }
337
+ async function detectDaemonBuildBehind(repo, submodules, options) {
338
+ const build = options.daemonBuildInfo ?? getDaemonBuildInfo();
339
+ if (!build.commit || build.commit === "unknown") return void 0;
340
+ const scopes = [
341
+ { scope: "root", repoPath: repo.repoRoot || repo.workspace }
342
+ ];
343
+ for (const sub of submodules || []) {
344
+ if (sub.repoPath && !sub.error) scopes.push({ scope: sub.path, repoPath: sub.repoPath });
345
+ }
346
+ for (const { scope, repoPath } of scopes) {
347
+ try {
348
+ await runGit(repoPath, ["cat-file", "-e", `${build.commit}^{commit}`], options);
349
+ const headResult = await runGit(repoPath, ["rev-parse", "HEAD"], options);
350
+ const head = headResult.stdout.trim();
351
+ if (!head || head === build.commit) continue;
352
+ await runGit(repoPath, ["merge-base", "--is-ancestor", build.commit, "HEAD"], options);
353
+ return {
354
+ buildCommit: build.commit,
355
+ buildCommitShort: build.commitShort,
356
+ head,
357
+ scope,
358
+ warning: `Live daemon was built from ${build.commitShort} which is behind ${scope === "root" ? "workspace" : scope} HEAD ${head.slice(0, 7)}. Merged code is NOT live until the daemon is rebuilt/redeployed and restarted \u2014 a local dist rebuild alone does not update a cloud daemon.`
359
+ };
360
+ } catch {
361
+ continue;
362
+ }
363
+ }
364
+ return void 0;
365
+ }
312
366
  async function readPorcelainStatus(repo, options) {
313
367
  const statusOutput = await runGit(repo, ["status", "--porcelain=v2", "--branch"], options);
314
368
  return parsePorcelainV2Status(statusOutput.stdout);
@@ -525,6 +579,7 @@ var init_git_status = __esm({
525
579
  "src/git/git-status.ts"() {
526
580
  "use strict";
527
581
  init_git_executor();
582
+ init_build_info();
528
583
  }
529
584
  });
530
585
 
@@ -2385,8 +2440,8 @@ function readLedgerFromStore(meshId) {
2385
2440
  }
2386
2441
  function getCachedRawEntries(meshId) {
2387
2442
  const now = Date.now();
2388
- const cached = ledgerReadCache.get(meshId);
2389
- if (cached && now - cached.cachedAt < LEDGER_CACHE_TTL_MS) return cached.entries;
2443
+ const cached2 = ledgerReadCache.get(meshId);
2444
+ if (cached2 && now - cached2.cachedAt < LEDGER_CACHE_TTL_MS) return cached2.entries;
2390
2445
  let entries;
2391
2446
  try {
2392
2447
  entries = readLedgerFromStore(meshId);
@@ -2645,6 +2700,7 @@ __export(mesh_work_queue_exports, {
2645
2700
  cancelTask: () => cancelTask,
2646
2701
  claimNextTask: () => claimNextTask,
2647
2702
  cleanupTerminalDirectDispatches: () => cleanupTerminalDirectDispatches,
2703
+ deleteDirectDispatchesByTaskId: () => deleteDirectDispatchesByTaskId,
2648
2704
  describeTaskDependencyState: () => describeTaskDependencyState,
2649
2705
  enqueueTask: () => enqueueTask,
2650
2706
  getActiveDirectDispatches: () => getActiveDirectDispatches,
@@ -3054,6 +3110,13 @@ function markStaleDirectDispatches(meshId, olderThanMs = 60 * 6e4) {
3054
3110
  } catch {
3055
3111
  }
3056
3112
  }
3113
+ function deleteDirectDispatchesByTaskId(meshId, taskIds) {
3114
+ try {
3115
+ return MeshRuntimeStore.getInstance().deleteDirectDispatchesByTaskId(meshId, taskIds);
3116
+ } catch {
3117
+ return 0;
3118
+ }
3119
+ }
3057
3120
  function recordMeshToolCall(opts) {
3058
3121
  try {
3059
3122
  return MeshRuntimeStore.getInstance().recordMeshToolCall(opts);
@@ -3685,6 +3748,24 @@ var init_mesh_runtime_store = __esm({
3685
3748
  deleteDirectDispatches(meshId) {
3686
3749
  this.db.prepare(`DELETE FROM mesh_direct_dispatches WHERE mesh_id = ?`).run(meshId);
3687
3750
  }
3751
+ /**
3752
+ * Delete specific direct dispatch rows by taskId for a mesh. Used by the staleDirect prune
3753
+ * path to remove orphaned/terminal dispatch records whose node/session is no longer in the
3754
+ * live mesh. Returns the number of rows actually deleted. No-op for an empty taskId list.
3755
+ */
3756
+ deleteDirectDispatchesByTaskId(meshId, taskIds) {
3757
+ const ids = (taskIds || []).map((id) => typeof id === "string" ? id.trim() : "").filter(Boolean);
3758
+ if (!ids.length) return 0;
3759
+ const stmt = this.db.prepare(`DELETE FROM mesh_direct_dispatches WHERE mesh_id = ? AND task_id = ?`);
3760
+ let deleted = 0;
3761
+ const run = this.db.transaction((rows) => {
3762
+ for (const taskId of rows) {
3763
+ deleted += stmt.run(meshId, taskId).changes;
3764
+ }
3765
+ });
3766
+ run(ids);
3767
+ return deleted;
3768
+ }
3688
3769
  markStaleDirectDispatches(meshId, olderThanMs) {
3689
3770
  const cutoff = new Date(Date.now() - olderThanMs).toISOString();
3690
3771
  const now = (/* @__PURE__ */ new Date()).toISOString();
@@ -5353,11 +5434,14 @@ async function fastForwardMeshNode(args) {
5353
5434
  const trigger = normalizeOptionalString(args.trigger) || "manual";
5354
5435
  const updateSubmodules = args.updateSubmodules === true;
5355
5436
  const dryRun = args.dryRun === true || args.execute !== true;
5356
- const plannedSteps = buildPlannedSteps(updateSubmodules);
5437
+ const mode = args.mode === "push" ? "push" : "merge";
5438
+ const pushSubmodules = mode === "push" && args.pushSubmodules === true;
5439
+ const plannedSteps = buildPlannedSteps(mode, updateSubmodules, pushSubmodules);
5357
5440
  const base = {
5358
5441
  ...nodeId ? { nodeId } : {},
5359
5442
  ...meshId ? { meshId } : {},
5360
5443
  workspace,
5444
+ mode,
5361
5445
  dryRun,
5362
5446
  updateSubmodules,
5363
5447
  plannedSteps,
@@ -5371,13 +5455,24 @@ async function fastForwardMeshNode(args) {
5371
5455
  submoduleIgnorePaths: args.submoduleIgnorePaths,
5372
5456
  timeoutMs: args.timeoutMs ?? STATUS_OPTIONS.timeoutMs
5373
5457
  });
5458
+ if (mode === "push") {
5459
+ return pushMeshNode(base, args, current, {
5460
+ pushSubmodules,
5461
+ allowAutoPublishSubmoduleMainCommits: args.allowAutoPublishSubmoduleMainCommits === true
5462
+ });
5463
+ }
5374
5464
  const earlyBlockers = collectPreflightBlockers(current, requestedBranch);
5375
5465
  if (earlyBlockers.length > 0) {
5466
+ const blockCode = chooseBlockCode(current, earlyBlockers);
5376
5467
  const result2 = {
5377
- ...block(base, chooseBlockCode(current, earlyBlockers), earlyBlockers),
5468
+ ...block(base, blockCode, earlyBlockers),
5378
5469
  current,
5379
- finalBranchConvergenceState: buildConvergenceState(current, codeToConvergenceStatus(chooseBlockCode(current, earlyBlockers)))
5470
+ finalBranchConvergenceState: buildConvergenceState(current, codeToConvergenceStatus(blockCode))
5380
5471
  };
5472
+ if (blockCode === "branch_ahead" && current.ahead > 0 && current.behind === 0 && otherBlockersAreOnlyAhead(earlyBlockers)) {
5473
+ result2.code = "ahead_needs_push";
5474
+ result2.nextStep = 'Local branch is ahead of origin with nothing to merge. Re-run mesh_fast_forward_node with mode="push" (execute=true) to ff-only push the local commits to origin.';
5475
+ }
5381
5476
  await appendFastForwardLedger(result2, "blocked");
5382
5477
  return result2;
5383
5478
  }
@@ -5488,7 +5583,246 @@ async function fastForwardMeshNode(args) {
5488
5583
  await appendFastForwardLedger(result, success ? "executed" : "failed");
5489
5584
  return result;
5490
5585
  }
5491
- function buildPlannedSteps(updateSubmodules) {
5586
+ async function pushMeshNode(base, args, current, options) {
5587
+ const workspace = base.workspace;
5588
+ const requestedBranch = normalizeOptionalString(args.branch);
5589
+ const dryRun = base.dryRun;
5590
+ const blockers = collectPushPreflightBlockers(current, requestedBranch);
5591
+ if (blockers.length > 0) {
5592
+ const code2 = choosePushBlockCode(current, blockers);
5593
+ const result2 = {
5594
+ ...block(base, code2, blockers),
5595
+ current,
5596
+ preStatus: current,
5597
+ finalBranchConvergenceState: buildConvergenceState(current, codeToConvergenceStatus(code2))
5598
+ };
5599
+ await appendFastForwardLedger(result2, "blocked");
5600
+ return result2;
5601
+ }
5602
+ const target = parseUpstreamTarget(current.upstream || "");
5603
+ if (!target) {
5604
+ const result2 = {
5605
+ ...block(base, "upstream_unparseable", ["upstream_unparseable"]),
5606
+ current,
5607
+ preStatus: current,
5608
+ finalBranchConvergenceState: buildConvergenceState(current, "blocked")
5609
+ };
5610
+ await appendFastForwardLedger(result2, "blocked");
5611
+ return result2;
5612
+ }
5613
+ const refspec = `HEAD:refs/heads/${target.remoteBranch}`;
5614
+ const pushTarget = { remote: target.remote, remoteBranch: target.remoteBranch, refspec };
5615
+ if (current.ahead <= 0) {
5616
+ const result2 = {
5617
+ ...base,
5618
+ success: true,
5619
+ code: "nothing_to_push",
5620
+ allowed: true,
5621
+ willRun: false,
5622
+ executed: false,
5623
+ blockingReasons: [],
5624
+ current,
5625
+ preStatus: current,
5626
+ postStatus: current,
5627
+ pushTarget,
5628
+ finalBranchConvergenceState: buildConvergenceState(current, "up_to_date")
5629
+ };
5630
+ await appendFastForwardLedger(result2, "noop");
5631
+ return result2;
5632
+ }
5633
+ const descendant = await verifyUpstreamIsAncestorOfHead(workspace, current.upstream || "", args.timeoutMs);
5634
+ if (!descendant.ok) {
5635
+ const result2 = {
5636
+ ...block(base, "non_fast_forward_push", ["head_is_not_descendant_of_upstream"]),
5637
+ current,
5638
+ preStatus: current,
5639
+ pushTarget,
5640
+ operationError: descendant.error,
5641
+ nextStep: "origin/<branch> has commits not in local HEAD; a ff-only push would lose them. Converge by rebasing onto origin first, then re-run. This operation never force-pushes.",
5642
+ finalBranchConvergenceState: buildConvergenceState(current, "not_mergeable")
5643
+ };
5644
+ await appendFastForwardLedger(result2, "blocked");
5645
+ return result2;
5646
+ }
5647
+ if (dryRun) {
5648
+ const result2 = {
5649
+ ...base,
5650
+ success: true,
5651
+ code: "push_available",
5652
+ allowed: true,
5653
+ willRun: false,
5654
+ executed: false,
5655
+ blockingReasons: [],
5656
+ current,
5657
+ preStatus: current,
5658
+ pushTarget,
5659
+ ...options.pushSubmodules ? { submodulePushes: await planSubmodulePushes(current, options, args.timeoutMs) } : {},
5660
+ finalBranchConvergenceState: buildConvergenceState(current, "push_available")
5661
+ };
5662
+ await appendFastForwardLedger(result2, "dry_run");
5663
+ return result2;
5664
+ }
5665
+ try {
5666
+ await runGit(workspace, ["push", target.remote, refspec], { timeoutMs: args.timeoutMs ?? 3e4 });
5667
+ } catch (error) {
5668
+ const result2 = {
5669
+ ...block(base, "push_ff_only_failed", ["push_ff_only_failed"]),
5670
+ current,
5671
+ preStatus: current,
5672
+ pushTarget,
5673
+ operationError: formatGitError2(error),
5674
+ finalBranchConvergenceState: buildConvergenceState(current, "not_mergeable")
5675
+ };
5676
+ await appendFastForwardLedger(result2, "failed");
5677
+ return result2;
5678
+ }
5679
+ let submodulePushes;
5680
+ if (options.pushSubmodules) {
5681
+ submodulePushes = await executeSubmodulePushes(current, options, args.timeoutMs);
5682
+ }
5683
+ const postStatus = await getGitRepoStatus(workspace, {
5684
+ ...STATUS_OPTIONS,
5685
+ submoduleIgnorePaths: args.submoduleIgnorePaths,
5686
+ timeoutMs: args.timeoutMs ?? STATUS_OPTIONS.timeoutMs
5687
+ });
5688
+ const submodulePushFailed = (submodulePushes || []).some((entry) => !entry.pushed && !entry.skipped);
5689
+ const blockingReasons = [];
5690
+ if (postStatus.ahead !== 0) blockingReasons.push("post_branch_ahead");
5691
+ if (submodulePushFailed) blockingReasons.push("submodule_push_failed");
5692
+ const success = blockingReasons.length === 0;
5693
+ const code = success ? "push_applied" : submodulePushFailed && postStatus.ahead === 0 ? "push_applied_submodule_push_failed" : "post_push_verify_failed";
5694
+ const result = {
5695
+ ...base,
5696
+ success,
5697
+ code,
5698
+ allowed: true,
5699
+ willRun: true,
5700
+ executed: true,
5701
+ blockingReasons,
5702
+ current,
5703
+ preStatus: current,
5704
+ postStatus,
5705
+ pushTarget,
5706
+ ...submodulePushes ? { submodulePushes } : {},
5707
+ finalBranchConvergenceState: buildConvergenceState(postStatus, success ? "pushed" : "post_verify_failed")
5708
+ };
5709
+ await appendFastForwardLedger(result, success ? "executed" : "failed");
5710
+ return result;
5711
+ }
5712
+ function collectPushPreflightBlockers(status, requestedBranch) {
5713
+ const blockers = [];
5714
+ if (!status.isGitRepo) blockers.push("not_git_repo");
5715
+ if (!status.branch) blockers.push("detached_head_or_unknown_branch");
5716
+ if (requestedBranch && status.branch !== requestedBranch) blockers.push("branch_mismatch");
5717
+ if (!status.upstream) blockers.push("upstream_missing");
5718
+ if (status.upstreamStatus !== "fresh") blockers.push("upstream_not_fresh");
5719
+ if (status.hasConflicts) blockers.push("conflicts_present");
5720
+ if (status.staged > 0) blockers.push("staged_changes_present");
5721
+ if (status.modified > 0) blockers.push("modified_changes_present");
5722
+ if (status.untracked > 0) blockers.push("untracked_changes_present");
5723
+ if (status.deleted > 0) blockers.push("deleted_changes_present");
5724
+ if (status.renamed > 0) blockers.push("renamed_changes_present");
5725
+ if (status.stashCount > 0) blockers.push("stash_entries_present");
5726
+ if (status.ahead > 0 && status.behind > 0) blockers.push("branch_diverged_from_upstream");
5727
+ else if (status.behind > 0) blockers.push("branch_behind_upstream");
5728
+ return blockers;
5729
+ }
5730
+ function choosePushBlockCode(status, blockers) {
5731
+ if (blockers.includes("not_git_repo")) return "not_git_repo";
5732
+ if (blockers.includes("branch_mismatch")) return "branch_mismatch";
5733
+ if (blockers.includes("upstream_missing")) return "upstream_missing";
5734
+ if (blockers.includes("upstream_not_fresh")) return "upstream_not_fresh";
5735
+ if (blockers.includes("branch_diverged_from_upstream")) return "branch_diverged";
5736
+ if (blockers.includes("branch_behind_upstream")) return "non_fast_forward_push";
5737
+ if (blockers.some((reason) => reason.includes("changes") || reason.includes("conflicts") || reason.includes("stash"))) return "dirty_worktree";
5738
+ return "preflight_blocked";
5739
+ }
5740
+ function parseUpstreamTarget(upstream) {
5741
+ const trimmed = upstream.trim();
5742
+ const slash = trimmed.indexOf("/");
5743
+ if (slash <= 0 || slash >= trimmed.length - 1) return null;
5744
+ return { remote: trimmed.slice(0, slash), remoteBranch: trimmed.slice(slash + 1) };
5745
+ }
5746
+ async function verifyUpstreamIsAncestorOfHead(workspace, upstream, timeoutMs) {
5747
+ if (!upstream) return { ok: false, error: "missing upstream" };
5748
+ try {
5749
+ await runGit(workspace, ["merge-base", "--is-ancestor", upstream, "HEAD"], { timeoutMs: timeoutMs ?? 15e3 });
5750
+ return { ok: true };
5751
+ } catch (error) {
5752
+ return { ok: false, error: formatGitError2(error) };
5753
+ }
5754
+ }
5755
+ async function planSubmodulePushes(status, options, timeoutMs) {
5756
+ return resolveSubmodulePushes(status, options, false, timeoutMs);
5757
+ }
5758
+ async function executeSubmodulePushes(status, options, timeoutMs) {
5759
+ return resolveSubmodulePushes(status, options, true, timeoutMs);
5760
+ }
5761
+ async function resolveSubmodulePushes(status, options, execute, timeoutMs) {
5762
+ const submodules = Array.isArray(status.submodules) ? status.submodules : [];
5763
+ const results = [];
5764
+ for (const submodule of submodules) {
5765
+ const base = {
5766
+ path: submodule.path,
5767
+ commit: submodule.commit,
5768
+ remote: "origin",
5769
+ remoteBranch: "main",
5770
+ pushed: false,
5771
+ skipped: true,
5772
+ code: "submodule_push_skipped"
5773
+ };
5774
+ if (!options.allowAutoPublishSubmoduleMainCommits) {
5775
+ results.push({ ...base, code: "submodule_push_policy_disabled", error: "allowAutoPublishSubmoduleMainCommits is not enabled" });
5776
+ continue;
5777
+ }
5778
+ if (submodule.error || submodule.dirty) {
5779
+ results.push({ ...base, code: "submodule_not_clean", error: submodule.error || "submodule worktree is dirty" });
5780
+ continue;
5781
+ }
5782
+ const repoPath = submodule.repoPath;
5783
+ if (!repoPath || !submodule.commit) {
5784
+ results.push({ ...base, code: "submodule_status_incomplete" });
5785
+ continue;
5786
+ }
5787
+ try {
5788
+ await runGit(repoPath, ["-c", "protocol.file.allow=always", "fetch", "origin", "refs/heads/main:refs/remotes/origin/main"], { timeoutMs: timeoutMs ?? 3e4 });
5789
+ } catch (error) {
5790
+ results.push({ ...base, code: "submodule_fetch_failed", error: formatGitError2(error) });
5791
+ continue;
5792
+ }
5793
+ let alreadyReachable = false;
5794
+ try {
5795
+ await runGit(repoPath, ["merge-base", "--is-ancestor", submodule.commit, "refs/remotes/origin/main"], { timeoutMs: timeoutMs ?? 15e3 });
5796
+ alreadyReachable = true;
5797
+ } catch {
5798
+ }
5799
+ if (alreadyReachable) {
5800
+ results.push({ ...base, pushed: false, skipped: true, code: "submodule_already_reachable" });
5801
+ continue;
5802
+ }
5803
+ try {
5804
+ await runGit(repoPath, ["merge-base", "--is-ancestor", "refs/remotes/origin/main", submodule.commit], { timeoutMs: timeoutMs ?? 15e3 });
5805
+ } catch (error) {
5806
+ results.push({ ...base, pushed: false, skipped: false, code: "submodule_non_fast_forward", error: formatGitError2(error) });
5807
+ continue;
5808
+ }
5809
+ const refspec = `${submodule.commit}:refs/heads/main`;
5810
+ if (!execute) {
5811
+ results.push({ ...base, pushed: false, skipped: false, code: "submodule_push_available", refspec });
5812
+ continue;
5813
+ }
5814
+ try {
5815
+ await runGit(repoPath, ["push", "origin", refspec], { timeoutMs: timeoutMs ?? 3e4 });
5816
+ await runGit(repoPath, ["-c", "protocol.file.allow=always", "fetch", "origin", "refs/heads/main:refs/remotes/origin/main"], { timeoutMs: timeoutMs ?? 3e4 });
5817
+ await runGit(repoPath, ["merge-base", "--is-ancestor", submodule.commit, "refs/remotes/origin/main"], { timeoutMs: timeoutMs ?? 15e3 });
5818
+ results.push({ ...base, pushed: true, skipped: false, code: "submodule_pushed", refspec });
5819
+ } catch (error) {
5820
+ results.push({ ...base, pushed: false, skipped: false, code: "submodule_push_failed", refspec, error: formatGitError2(error) });
5821
+ }
5822
+ }
5823
+ return results;
5824
+ }
5825
+ function buildPlannedSteps(mode, updateSubmodules, pushSubmodules) {
5492
5826
  const steps = [
5493
5827
  {
5494
5828
  operation: "refresh_upstream",
@@ -5501,20 +5835,49 @@ function buildPlannedSteps(updateSubmodules) {
5501
5835
  description: "Require clean staged/modified/untracked/deleted/renamed/conflict/stash/submodule state.",
5502
5836
  safe: true,
5503
5837
  willMutateWorktree: false
5504
- },
5505
- {
5506
- operation: "verify_fast_forward",
5507
- description: "Require ahead=0, behind>0, and HEAD to be an ancestor of the upstream ref.",
5838
+ }
5839
+ ];
5840
+ if (mode === "push") {
5841
+ steps.push({
5842
+ operation: "verify_push_descendant",
5843
+ description: "Require HEAD to be a descendant of origin/<branch> (origin/<branch> is an ancestor of HEAD); refuse any non-fast-forward push.",
5508
5844
  safe: true,
5509
5845
  willMutateWorktree: false
5510
- },
5511
- {
5512
- operation: "merge_ff_only",
5513
- description: "Apply git merge --ff-only against the tracked upstream; no force, reset, rebase, push, or deploy.",
5846
+ });
5847
+ steps.push({
5848
+ operation: "push_ff_only",
5849
+ description: "Run git push origin HEAD:<branch> as a strict ff-only push; never --force, --force-with-lease, reset, or rebase. Does not mutate the worktree.",
5514
5850
  safe: true,
5515
- willMutateWorktree: true
5851
+ willMutateWorktree: false
5852
+ });
5853
+ if (pushSubmodules) {
5854
+ steps.push({
5855
+ operation: "push_submodules_ff_only",
5856
+ description: "For each submodule, if allowAutoPublishSubmoduleMainCommits is enabled and the submodule HEAD is a descendant of its origin main, ff-only push it to submodule origin main; otherwise skip.",
5857
+ safe: true,
5858
+ willMutateWorktree: false
5859
+ });
5516
5860
  }
5517
- ];
5861
+ steps.push({
5862
+ operation: "verify_post_status",
5863
+ description: "Re-read daemon-owned git status and report final branch convergence state.",
5864
+ safe: true,
5865
+ willMutateWorktree: false
5866
+ });
5867
+ return steps;
5868
+ }
5869
+ steps.push({
5870
+ operation: "verify_fast_forward",
5871
+ description: "Require ahead=0, behind>0, and HEAD to be an ancestor of the upstream ref.",
5872
+ safe: true,
5873
+ willMutateWorktree: false
5874
+ });
5875
+ steps.push({
5876
+ operation: "merge_ff_only",
5877
+ description: "Apply git merge --ff-only against the tracked upstream; no force, reset, rebase, push, or deploy.",
5878
+ safe: true,
5879
+ willMutateWorktree: true
5880
+ });
5518
5881
  if (updateSubmodules) {
5519
5882
  steps.push({
5520
5883
  operation: "submodule_update",
@@ -5531,6 +5894,10 @@ function buildPlannedSteps(updateSubmodules) {
5531
5894
  });
5532
5895
  return steps;
5533
5896
  }
5897
+ function otherBlockersAreOnlyAhead(blockers) {
5898
+ const aheadOnly = /* @__PURE__ */ new Set(["branch_has_local_commits"]);
5899
+ return blockers.every((reason) => aheadOnly.has(reason));
5900
+ }
5534
5901
  function collectPreflightBlockers(status, requestedBranch) {
5535
5902
  const blockers = [];
5536
5903
  if (!status.isGitRepo) blockers.push("not_git_repo");
@@ -5587,7 +5954,7 @@ function chooseBlockCode(status, blockers) {
5587
5954
  return "preflight_blocked";
5588
5955
  }
5589
5956
  function codeToConvergenceStatus(code) {
5590
- if (code === "branch_diverged" || code === "branch_ahead" || code === "non_fast_forward") return "not_mergeable";
5957
+ if (code === "branch_diverged" || code === "branch_ahead" || code === "non_fast_forward" || code === "non_fast_forward_push" || code === "upstream_unparseable") return "not_mergeable";
5591
5958
  if (code === "dirty_worktree" || code === "submodule_not_clean") return "blocked_review";
5592
5959
  return "blocked";
5593
5960
  }
@@ -5670,6 +6037,7 @@ async function appendFastForwardLedger(result, outcome) {
5670
6037
  ...result.nodeId ? { nodeId: result.nodeId } : {},
5671
6038
  payload: {
5672
6039
  operation: "mesh_fast_forward_node",
6040
+ mode: result.mode,
5673
6041
  trigger: result.trigger || "manual",
5674
6042
  outcome,
5675
6043
  code: result.code,
@@ -5680,6 +6048,7 @@ async function appendFastForwardLedger(result, outcome) {
5680
6048
  executed: result.executed,
5681
6049
  branch: result.postStatus?.branch ?? result.current?.branch,
5682
6050
  upstream: result.postStatus?.upstream ?? result.current?.upstream,
6051
+ ...result.pushTarget ? { pushTarget: result.pushTarget } : {},
5683
6052
  before: result.current ? {
5684
6053
  headCommit: result.current.headCommit,
5685
6054
  ahead: result.current.ahead,
@@ -5690,6 +6059,16 @@ async function appendFastForwardLedger(result, outcome) {
5690
6059
  ahead: result.postStatus.ahead,
5691
6060
  behind: result.postStatus.behind
5692
6061
  } : void 0,
6062
+ ...result.submodulePushes ? {
6063
+ submodulePushes: result.submodulePushes.map((entry) => ({
6064
+ path: entry.path,
6065
+ commit: entry.commit,
6066
+ pushed: entry.pushed,
6067
+ skipped: entry.skipped,
6068
+ code: entry.code,
6069
+ ...entry.refspec ? { refspec: entry.refspec } : {}
6070
+ }))
6071
+ } : {},
5693
6072
  blockingReasons: result.blockingReasons
5694
6073
  }
5695
6074
  });
@@ -6860,8 +7239,8 @@ var init_mesh_routing = __esm({
6860
7239
  import { existsSync as existsSync14 } from "fs";
6861
7240
  function getCachedMeshByWorkspace(workspace) {
6862
7241
  const now = Date.now();
6863
- const cached = meshByWorkspaceCache.get(workspace);
6864
- if (cached && now - cached.cachedAt < MESH_WORKSPACE_CACHE_TTL_MS) return cached.mesh;
7242
+ const cached2 = meshByWorkspaceCache.get(workspace);
7243
+ if (cached2 && now - cached2.cachedAt < MESH_WORKSPACE_CACHE_TTL_MS) return cached2.mesh;
6865
7244
  const mesh = getMeshByRepo(workspace);
6866
7245
  meshByWorkspaceCache.set(workspace, { mesh, cachedAt: now });
6867
7246
  return mesh;
@@ -11754,10 +12133,10 @@ ${lastSnapshot}`;
11754
12133
  return this.accumulatedRawBuffer.replace(/\x1B\][^\x07]*(?:\x07|\x1B\\)/g, "").replace(/\x1B[P^_X][\s\S]*?(?:\x07|\x1B\\)/g, "").replace(/\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])/g, "");
11755
12134
  }
11756
12135
  getFreshParsedStatusCache() {
11757
- const cached = this.parsedStatusCache;
12136
+ const cached2 = this.parsedStatusCache;
11758
12137
  const accumulatedRawBufferKey = this.getAccumulatedRawBufferCacheKey();
11759
- if (cached && cached.responseBuffer === this.responseBuffer && cached.currentTurnScope === this.engine.currentTurnScope && cached.recentOutputBuffer === this.recentOutputBuffer && cached.accumulatedBuffer === this.accumulatedBuffer && cached.accumulatedRawBufferKey === accumulatedRawBufferKey && cached.screenText === this.lastScreenText && cached.currentStatus === this.engine.currentStatus && cached.activeModal === this.engine.activeModal && cached.cliName === this.cliName) {
11760
- return cached.result;
12138
+ if (cached2 && cached2.responseBuffer === this.responseBuffer && cached2.currentTurnScope === this.engine.currentTurnScope && cached2.recentOutputBuffer === this.recentOutputBuffer && cached2.accumulatedBuffer === this.accumulatedBuffer && cached2.accumulatedRawBufferKey === accumulatedRawBufferKey && cached2.screenText === this.lastScreenText && cached2.currentStatus === this.engine.currentStatus && cached2.activeModal === this.engine.activeModal && cached2.cliName === this.cliName) {
12139
+ return cached2.result;
11761
12140
  }
11762
12141
  return null;
11763
12142
  }
@@ -12217,10 +12596,10 @@ ${lastSnapshot}`;
12217
12596
  getScriptParsedStatus() {
12218
12597
  const screenText = this.readTerminalScreenText();
12219
12598
  const parseScreenText = this.getParseScreenText(screenText);
12220
- const cached = this.parsedStatusCache;
12599
+ const cached2 = this.parsedStatusCache;
12221
12600
  const accumulatedRawBufferKey = this.getAccumulatedRawBufferCacheKey();
12222
- if (!this.providerOwnsTranscript() && cached && cached.responseBuffer === this.responseBuffer && cached.currentTurnScope === this.engine.currentTurnScope && cached.recentOutputBuffer === this.recentOutputBuffer && cached.accumulatedBuffer === this.accumulatedBuffer && cached.accumulatedRawBufferKey === accumulatedRawBufferKey && cached.screenText === parseScreenText && cached.currentStatus === this.engine.currentStatus && cached.activeModal === this.engine.activeModal && cached.cliName === this.cliName) {
12223
- return cached.result;
12601
+ if (!this.providerOwnsTranscript() && cached2 && cached2.responseBuffer === this.responseBuffer && cached2.currentTurnScope === this.engine.currentTurnScope && cached2.recentOutputBuffer === this.recentOutputBuffer && cached2.accumulatedBuffer === this.accumulatedBuffer && cached2.accumulatedRawBufferKey === accumulatedRawBufferKey && cached2.screenText === parseScreenText && cached2.currentStatus === this.engine.currentStatus && cached2.activeModal === this.engine.activeModal && cached2.cliName === this.cliName) {
12602
+ return cached2.result;
12224
12603
  }
12225
12604
  const parsed = this.runParseSession();
12226
12605
  if (!parsed || !Array.isArray(parsed.messages)) {
@@ -16701,6 +17080,17 @@ function buildMeshActiveWork(opts) {
16701
17080
  }
16702
17081
  return { activeWork: records, staleDirectWork, staleDirectWorkNote, terminalDirectWork, summary };
16703
17082
  }
17083
+ var PRUNABLE_ORPHAN_STALE_REASONS = /* @__PURE__ */ new Set([
17084
+ "direct task node is no longer in the live mesh",
17085
+ "direct task session is not present in live session records",
17086
+ "direct task has no node id"
17087
+ ]);
17088
+ function classifyStaleDirectForPrune(record, opts = {}) {
17089
+ if (record.staleDispatchUnacknowledged === true) return "preserve_unacknowledged";
17090
+ if (record.terminal === true) return opts.includeTerminal ? "prunable_terminal" : "preserve_active";
17091
+ if (record.staleReason && PRUNABLE_ORPHAN_STALE_REASONS.has(record.staleReason)) return "prunable_orphan";
17092
+ return "preserve_active";
17093
+ }
16704
17094
  function buildCompactStaleDirectWorkSummary(staleDirectWork, opts = {}) {
16705
17095
  const sampleLimit = Math.max(0, Math.min(10, Math.floor(opts.sampleLimit ?? 3)));
16706
17096
  const reasonCounts = {};
@@ -19924,9 +20314,9 @@ function computeSavedHistorySessionSummaries(agentType, dir, files, fileSignatur
19924
20314
  for (const file of files.slice().sort()) {
19925
20315
  const filePath = path12.join(dir, file);
19926
20316
  const signature = fileSignatures.get(file) || `${file}:missing`;
19927
- const cached = savedHistoryFileSummaryCache.get(filePath);
20317
+ const cached2 = savedHistoryFileSummaryCache.get(filePath);
19928
20318
  const persisted = persistedEntries.get(file);
19929
- const reusableEntry = cached?.signature === signature ? cached : persisted?.signature === signature ? persisted : null;
20319
+ const reusableEntry = cached2?.signature === signature ? cached2 : persisted?.signature === signature ? persisted : null;
19930
20320
  const fileSummary = reusableEntry?.summary || computeSavedHistoryFileSummary(dir, file);
19931
20321
  const nextEntry = reusableEntry || {
19932
20322
  signature,
@@ -20378,23 +20768,23 @@ function listSavedHistorySessions(agentType, options = {}, historyBehavior) {
20378
20768
  savedHistorySessionCache.delete(sanitized);
20379
20769
  return { sessions: [], hasMore: false };
20380
20770
  }
20381
- const cached = savedHistorySessionCache.get(sanitized);
20771
+ const cached2 = savedHistorySessionCache.get(sanitized);
20382
20772
  const offset = Math.max(0, options.offset || 0);
20383
20773
  const limit = Math.max(1, options.limit || 30);
20384
20774
  const indexSignature = buildSavedHistoryIndexFileSignature(dir);
20385
20775
  let cacheWasInvalidated = false;
20386
- if (cached) {
20387
- const cacheLooksPersisted = cached.signature.startsWith("index:");
20388
- const cacheStillValid = cacheLooksPersisted ? cached.signature === indexSignature : (() => {
20776
+ if (cached2) {
20777
+ const cacheLooksPersisted = cached2.signature.startsWith("index:");
20778
+ const cacheStillValid = cacheLooksPersisted ? cached2.signature === indexSignature : (() => {
20389
20779
  const files2 = listHistoryFiles(dir);
20390
20780
  const fileSignatures2 = buildSavedHistoryFileSignatureMap(dir, files2);
20391
- return cached.signature === buildSavedHistoryCacheSignature(files2, fileSignatures2);
20781
+ return cached2.signature === buildSavedHistoryCacheSignature(files2, fileSignatures2);
20392
20782
  })();
20393
20783
  if (cacheStillValid) {
20394
- const sliced2 = cached.summaries.slice(offset, offset + limit);
20784
+ const sliced2 = cached2.summaries.slice(offset, offset + limit);
20395
20785
  return {
20396
20786
  sessions: sliced2,
20397
- hasMore: cached.summaries.length > offset + limit
20787
+ hasMore: cached2.summaries.length > offset + limit
20398
20788
  };
20399
20789
  }
20400
20790
  cacheWasInvalidated = true;
@@ -36988,8 +37378,8 @@ var ProviderLoader = class _ProviderLoader {
36988
37378
  return null;
36989
37379
  }
36990
37380
  registerProviderScriptRootSafely(path30.dirname(path30.dirname(providerDir)));
36991
- const cached = this.scriptsCache.get(dir);
36992
- if (cached) return cached;
37381
+ const cached2 = this.scriptsCache.get(dir);
37382
+ if (cached2) return cached2;
36993
37383
  const scriptsJs = path30.join(dir, "scripts.js");
36994
37384
  if (fs20.existsSync(scriptsJs)) {
36995
37385
  try {
@@ -38987,6 +39377,9 @@ function buildStatusSnapshot(options) {
38987
39377
  };
38988
39378
  }
38989
39379
 
39380
+ // src/commands/router.ts
39381
+ init_build_info();
39382
+
38990
39383
  // src/commands/upgrade-helper.ts
38991
39384
  import { execFileSync as execFileSync4 } from "child_process";
38992
39385
  import { spawn as spawn3 } from "child_process";
@@ -39772,13 +40165,13 @@ function sanitizeInlineMesh(inlineMesh) {
39772
40165
  nodes
39773
40166
  };
39774
40167
  }
39775
- function reconcileInlineMeshCache(cached, incoming) {
39776
- if (!cached || typeof cached !== "object" || Array.isArray(cached)) return incoming;
39777
- if (!incoming || typeof incoming !== "object" || Array.isArray(incoming)) return cached;
39778
- const cachedNodes = Array.isArray(cached.nodes) ? cached.nodes : [];
40168
+ function reconcileInlineMeshCache(cached2, incoming) {
40169
+ if (!cached2 || typeof cached2 !== "object" || Array.isArray(cached2)) return incoming;
40170
+ if (!incoming || typeof incoming !== "object" || Array.isArray(incoming)) return cached2;
40171
+ const cachedNodes = Array.isArray(cached2.nodes) ? cached2.nodes : [];
39779
40172
  const incomingNodes = Array.isArray(incoming.nodes) ? incoming.nodes : [];
39780
- if (!cachedNodes.length || !incomingNodes.length) return { ...cached, ...incoming };
39781
- const cachedUpdatedAt = Date.parse(readStringValue(cached.updatedAt, cached.updated_at) || "");
40173
+ if (!cachedNodes.length || !incomingNodes.length) return { ...cached2, ...incoming };
40174
+ const cachedUpdatedAt = Date.parse(readStringValue(cached2.updatedAt, cached2.updated_at) || "");
39782
40175
  const incomingUpdatedAt = Date.parse(readStringValue(incoming.updatedAt, incoming.updated_at) || "");
39783
40176
  const preserveCachedMembership = Number.isFinite(cachedUpdatedAt) && (!Number.isFinite(incomingUpdatedAt) || cachedUpdatedAt > incomingUpdatedAt);
39784
40177
  const cachedById = /* @__PURE__ */ new Map();
@@ -39807,7 +40200,7 @@ function reconcileInlineMeshCache(cached, incoming) {
39807
40200
  }
39808
40201
  }
39809
40202
  return {
39810
- ...cached,
40203
+ ...cached2,
39811
40204
  ...incoming,
39812
40205
  nodes
39813
40206
  };
@@ -41491,13 +41884,13 @@ var DaemonCommandRouter = class {
41491
41884
  };
41492
41885
  }
41493
41886
  getCachedAggregateMeshStatus(meshId, mesh, options) {
41494
- const cached = this.aggregateMeshStatusCache.get(meshId);
41495
- if (!cached?.snapshot || cached.snapshot.success !== true || !Array.isArray(cached.snapshot.nodes)) return null;
41496
- if (cached.queueRevision !== getMeshQueueRevision(meshId)) return null;
41497
- let snapshot = this.cloneJsonValue(cached.snapshot);
41887
+ const cached2 = this.aggregateMeshStatusCache.get(meshId);
41888
+ if (!cached2?.snapshot || cached2.snapshot.success !== true || !Array.isArray(cached2.snapshot.nodes)) return null;
41889
+ if (cached2.queueRevision !== getMeshQueueRevision(meshId)) return null;
41890
+ let snapshot = this.cloneJsonValue(cached2.snapshot);
41498
41891
  snapshot = this.hydrateCachedAggregateMeshStatusFromInline(snapshot, mesh, options);
41499
41892
  if (shouldRefreshStalePendingAggregate(snapshot, options)) return null;
41500
- const ageMs = Math.max(0, Date.now() - cached.builtAt);
41893
+ const ageMs = Math.max(0, Date.now() - cached2.builtAt);
41501
41894
  const sourceOfTruth = snapshot.sourceOfTruth && typeof snapshot.sourceOfTruth === "object" ? snapshot.sourceOfTruth : {};
41502
41895
  snapshot.sourceOfTruth = {
41503
41896
  ...sourceOfTruth,
@@ -41508,7 +41901,7 @@ var DaemonCommandRouter = class {
41508
41901
  source: "memory",
41509
41902
  refreshReason: "memory_cache_hit",
41510
41903
  ageMs,
41511
- cachedAt: new Date(cached.builtAt).toISOString(),
41904
+ cachedAt: new Date(cached2.builtAt).toISOString(),
41512
41905
  returnedAt: (/* @__PURE__ */ new Date()).toISOString()
41513
41906
  }
41514
41907
  };
@@ -41552,9 +41945,9 @@ var DaemonCommandRouter = class {
41552
41945
  warmInlineMeshCache(meshId, inlineMesh) {
41553
41946
  if (!inlineMesh || typeof inlineMesh !== "object") return void 0;
41554
41947
  const sanitizedInlineMesh = sanitizeInlineMesh(inlineMesh);
41555
- const cached = this.inlineMeshCache.get(meshId);
41556
- if (cached) {
41557
- const merged = reconcileInlineMeshCache(cached, sanitizedInlineMesh);
41948
+ const cached2 = this.inlineMeshCache.get(meshId);
41949
+ if (cached2) {
41950
+ const merged = reconcileInlineMeshCache(cached2, sanitizedInlineMesh);
41558
41951
  this.inlineMeshCache.set(meshId, merged);
41559
41952
  return merged;
41560
41953
  }
@@ -41564,14 +41957,14 @@ var DaemonCommandRouter = class {
41564
41957
  async getMeshForCommand(meshId, inlineMesh, options) {
41565
41958
  const preferInline = options?.preferInline === true;
41566
41959
  if (preferInline) {
41567
- const cached2 = this.getCachedInlineMesh(meshId);
41568
- if (cached2) {
41960
+ const cached3 = this.getCachedInlineMesh(meshId);
41961
+ if (cached3) {
41569
41962
  if (inlineMeshCarriesTransientNodeTruth(inlineMesh)) {
41570
- const merged = reconcileInlineMeshCache(cached2, inlineMesh);
41963
+ const merged = reconcileInlineMeshCache(cached3, inlineMesh);
41571
41964
  this.inlineMeshCache.set(meshId, sanitizeInlineMesh(merged));
41572
41965
  return { mesh: merged, inline: true, source: "inline_cache" };
41573
41966
  }
41574
- return { mesh: cached2, inline: true, source: "inline_cache" };
41967
+ return { mesh: cached3, inline: true, source: "inline_cache" };
41575
41968
  }
41576
41969
  if (inlineMeshCarriesTransientNodeTruth(inlineMesh)) {
41577
41970
  this.warmInlineMeshCache(meshId, inlineMesh);
@@ -41584,8 +41977,8 @@ var DaemonCommandRouter = class {
41584
41977
  if (mesh) return { mesh, inline: false, source: "local_config" };
41585
41978
  } catch {
41586
41979
  }
41587
- const cached = this.getCachedInlineMesh(meshId);
41588
- if (cached) return { mesh: cached, inline: true, source: "inline_cache" };
41980
+ const cached2 = this.getCachedInlineMesh(meshId);
41981
+ if (cached2) return { mesh: cached2, inline: true, source: "inline_cache" };
41589
41982
  const warmedInline = this.warmInlineMeshCache(meshId, inlineMesh);
41590
41983
  return warmedInline ? { mesh: warmedInline, inline: true, source: "inline_bootstrap" } : null;
41591
41984
  }
@@ -41892,6 +42285,8 @@ var DaemonCommandRouter = class {
41892
42285
  const skippedSessionIds = [];
41893
42286
  const skippedLiveSessionIds = [];
41894
42287
  const skippedCoordinatorSessionIds = [];
42288
+ const skippedLiveSessionReasons = [];
42289
+ const actedLiveDelegateSessionIds = [];
41895
42290
  const deleteUnsupportedSessionIds = [];
41896
42291
  const recordsRemainSessionIds = [];
41897
42292
  const errors = [];
@@ -41925,16 +42320,31 @@ var DaemonCommandRouter = class {
41925
42320
  const surfaceKind = getSessionHostSurfaceKind(record);
41926
42321
  const liveRuntime = surfaceKind === "live_runtime";
41927
42322
  const coordinatorSession = readStringValue(record?.meta?.meshCoordinatorFor) === args.meshId;
42323
+ const recordNodeId = readStringValue(record?.meta?.meshNodeId);
42324
+ const recordMeshNodeFor = readStringValue(record?.meta?.meshNodeFor);
42325
+ const delegateBoundToThisNode = !!recordNodeId && recordNodeId === args.nodeId && (!recordMeshNodeFor || recordMeshNodeFor === args.meshId);
41928
42326
  if (!hasExplicitSessionIds && coordinatorSession) {
41929
42327
  skippedSessionIds.push(sessionId);
41930
42328
  skippedCoordinatorSessionIds.push(sessionId);
41931
42329
  continue;
41932
42330
  }
41933
- if (!hasExplicitSessionIds && liveRuntime) {
42331
+ if (!hasExplicitSessionIds && liveRuntime && !delegateBoundToThisNode) {
42332
+ skippedSessionIds.push(sessionId);
42333
+ skippedLiveSessionIds.push(sessionId);
42334
+ const matchedByWorkspaceOnly = !recordNodeId;
42335
+ const reason = recordNodeId && recordNodeId !== args.nodeId ? `live_delegate_bound_to_other_node:${recordNodeId}` : matchedByWorkspaceOnly ? "live_session_matched_by_workspace_only_no_node_binding" : "live_session_not_bound_to_this_node";
42336
+ skippedLiveSessionReasons.push({ sessionId, reason });
42337
+ continue;
42338
+ }
42339
+ if (!hasExplicitSessionIds && liveRuntime && delegateBoundToThisNode && args.mode === "delete_stopped") {
41934
42340
  skippedSessionIds.push(sessionId);
41935
42341
  skippedLiveSessionIds.push(sessionId);
42342
+ skippedLiveSessionReasons.push({ sessionId, reason: "live_delegate_preserved_by_delete_stopped_mode_use_stop_or_stop_and_delete" });
41936
42343
  continue;
41937
42344
  }
42345
+ if (!hasExplicitSessionIds && liveRuntime && delegateBoundToThisNode) {
42346
+ actedLiveDelegateSessionIds.push(sessionId);
42347
+ }
41938
42348
  try {
41939
42349
  if (args.mode === "stop") {
41940
42350
  if (!completed) {
@@ -41996,6 +42406,8 @@ var DaemonCommandRouter = class {
41996
42406
  skippedSessionIds,
41997
42407
  skippedLiveSessionIds,
41998
42408
  skippedCoordinatorSessionIds,
42409
+ ...actedLiveDelegateSessionIds.length ? { actedLiveDelegateSessionIds } : {},
42410
+ ...skippedLiveSessionReasons.length ? { skippedLiveSessionReasons } : {},
41999
42411
  ...deleteUnsupported ? {
42000
42412
  deleteUnsupported: true,
42001
42413
  effectiveCleanup: args.mode === "stop_and_delete" ? "stopped_only_records_remain" : "delete_unsupported_records_remain",
@@ -42923,8 +43335,8 @@ ${hintLines.join("\n")}` : "",
42923
43335
  const repoRootBaseRef = /* @__PURE__ */ new Map();
42924
43336
  const submodulePathsByRepoRoot = /* @__PURE__ */ new Map();
42925
43337
  const resolveBaseRef = async (repoRoot) => {
42926
- const cached = repoRootBaseRef.get(repoRoot);
42927
- if (cached) return cached;
43338
+ const cached2 = repoRootBaseRef.get(repoRoot);
43339
+ if (cached2) return cached2;
42928
43340
  let baseBranch = "main";
42929
43341
  try {
42930
43342
  const { stdout } = await execFileAsync4("git", ["branch", "--show-current"], { cwd: repoRoot, encoding: "utf8" });
@@ -43822,7 +44234,7 @@ ${hintLines.join("\n")}` : "",
43822
44234
  version: this.deps.statusVersion || "unknown",
43823
44235
  profile: "metadata"
43824
44236
  });
43825
- return { success: true, status: snapshot };
44237
+ return { success: true, status: snapshot, daemonBuild: getDaemonBuildInfo() };
43826
44238
  }
43827
44239
  case "get_machine_runtime_stats": {
43828
44240
  return {
@@ -44792,6 +45204,7 @@ ${hintLines.join("\n")}` : "",
44792
45204
  let workspace = typeof args?.workspace === "string" ? args.workspace.trim() : "";
44793
45205
  let submoduleIgnorePaths = Array.isArray(args?.submoduleIgnorePaths) ? args.submoduleIgnorePaths.filter((value) => typeof value === "string") : void 0;
44794
45206
  let nodeDaemonId;
45207
+ let allowAutoPublishSubmoduleMainCommits = false;
44795
45208
  if (meshId && nodeId) {
44796
45209
  const meshRecord = await this.getMeshForCommand(meshId, args?.inlineMesh, { preferInline: true });
44797
45210
  const mesh = meshRecord?.mesh;
@@ -44802,6 +45215,7 @@ ${hintLines.join("\n")}` : "",
44802
45215
  if (!submoduleIgnorePaths && Array.isArray(node?.policy?.submoduleIgnorePaths)) {
44803
45216
  submoduleIgnorePaths = node.policy.submoduleIgnorePaths.filter((value) => typeof value === "string");
44804
45217
  }
45218
+ allowAutoPublishSubmoduleMainCommits = mesh?.policy?.allowAutoPublishSubmoduleMainCommits === true;
44805
45219
  nodeDaemonId = typeof node?.daemonId === "string" ? node.daemonId.trim() : void 0;
44806
45220
  }
44807
45221
  const selfDaemonId = this.deps.statusInstanceId;
@@ -44822,7 +45236,10 @@ ${hintLines.join("\n")}` : "",
44822
45236
  execute: args?.execute === true,
44823
45237
  dryRun: args?.dryRun === true,
44824
45238
  updateSubmodules: args?.updateSubmodules === true,
44825
- submoduleIgnorePaths
45239
+ submoduleIgnorePaths,
45240
+ mode: args?.mode === "push" ? "push" : "merge",
45241
+ pushSubmodules: args?.pushSubmodules === true,
45242
+ allowAutoPublishSubmoduleMainCommits
44826
45243
  });
44827
45244
  return result;
44828
45245
  }
@@ -46522,6 +46939,7 @@ var DaemonStatusReporter = class {
46522
46939
  };
46523
46940
 
46524
46941
  // src/index.ts
46942
+ init_build_info();
46525
46943
  init_logger();
46526
46944
  init_debug_config();
46527
46945
 
@@ -54799,6 +55217,7 @@ export {
54799
55217
  MIN_SESSION_HOST_DIAGNOSTICS_SUBSCRIPTION_INTERVAL_MS,
54800
55218
  NodePtyTransportFactory,
54801
55219
  P2pRelayFailureError,
55220
+ PRUNABLE_ORPHAN_STALE_REASONS,
54802
55221
  ProviderCliAdapter,
54803
55222
  ProviderInstanceManager,
54804
55223
  ProviderLoader,
@@ -54852,6 +55271,7 @@ export {
54852
55271
  classifyChatMessageVisibility,
54853
55272
  classifyHotChatSessionsForSubscriptionFlush,
54854
55273
  classifyP2pRelayFailure,
55274
+ classifyStaleDirectForPrune,
54855
55275
  cleanupTerminalDirectDispatches,
54856
55276
  clearDebugTrace,
54857
55277
  clearPendingMeshCoordinatorEvents,
@@ -54871,6 +55291,7 @@ export {
54871
55291
  createNativeHistoryDispatcher,
54872
55292
  createSessionDelivery,
54873
55293
  createWorktree,
55294
+ deleteDirectDispatchesByTaskId,
54874
55295
  deleteMesh,
54875
55296
  deriveMeshReviewInboxItems,
54876
55297
  describeTaskDependencyState,
@@ -54899,6 +55320,7 @@ export {
54899
55320
  getAvailableIdeIds,
54900
55321
  getCoordinatorForSession,
54901
55322
  getCurrentDaemonLogPath,
55323
+ getDaemonBuildInfo,
54902
55324
  getDaemonDataDir,
54903
55325
  getDaemonLogDir,
54904
55326
  getDebugRuntimeConfig,