@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.js CHANGED
@@ -256,6 +256,29 @@ var init_git_executor = __esm({
256
256
  }
257
257
  });
258
258
 
259
+ // src/build-info.ts
260
+ function readInjected(value) {
261
+ if (typeof value !== "string") return void 0;
262
+ const trimmed = value.trim();
263
+ if (!trimmed || trimmed === "unknown") return void 0;
264
+ return trimmed;
265
+ }
266
+ function getDaemonBuildInfo() {
267
+ if (cached) return cached;
268
+ const commit = readInjected(true ? "2cf602f99ce68b3d3f1af02b429f6fb7a7c8e686" : void 0) ?? "unknown";
269
+ const commitShort = readInjected(true ? "2cf602f" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
270
+ const version = readInjected(true ? "0.9.82-rc.263" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
271
+ const builtAt = readInjected(true ? "2026-06-14T13:48:10.699Z" : void 0);
272
+ cached = builtAt ? { commit, commitShort, version, builtAt } : { commit, commitShort, version };
273
+ return cached;
274
+ }
275
+ var cached;
276
+ var init_build_info = __esm({
277
+ "src/build-info.ts"() {
278
+ "use strict";
279
+ }
280
+ });
281
+
259
282
  // src/git/git-status.ts
260
283
  async function getGitRepoStatus(workspace, options = {}) {
261
284
  const lastCheckedAt = Date.now();
@@ -278,6 +301,7 @@ async function getGitRepoStatus(workspace, options = {}) {
278
301
  }
279
302
  const submoduleDirty = (submodules || []).some((submodule) => submodule.dirty || submodule.outOfSync || !!submodule.error);
280
303
  const dirty = parsed.staged + parsed.modified + parsed.untracked + parsed.deleted + parsed.renamed > 0 || parsed.conflictFiles.length > 0 || stashCount > 0 || submoduleDirty;
304
+ const daemonBuildBehind = await detectDaemonBuildBehind(repo, submodules, options);
281
305
  return {
282
306
  workspace: repo.workspace,
283
307
  repoRoot: repo.repoRoot,
@@ -301,7 +325,8 @@ async function getGitRepoStatus(workspace, options = {}) {
301
325
  conflictFiles: parsed.conflictFiles,
302
326
  stashCount,
303
327
  lastCheckedAt,
304
- submodules
328
+ submodules,
329
+ ...daemonBuildBehind ? { daemonBuildBehind } : {}
305
330
  };
306
331
  } catch (error) {
307
332
  if (error instanceof GitCommandError) {
@@ -314,6 +339,35 @@ async function getGitRepoStatus(workspace, options = {}) {
314
339
  );
315
340
  }
316
341
  }
342
+ async function detectDaemonBuildBehind(repo, submodules, options) {
343
+ const build = options.daemonBuildInfo ?? getDaemonBuildInfo();
344
+ if (!build.commit || build.commit === "unknown") return void 0;
345
+ const scopes = [
346
+ { scope: "root", repoPath: repo.repoRoot || repo.workspace }
347
+ ];
348
+ for (const sub of submodules || []) {
349
+ if (sub.repoPath && !sub.error) scopes.push({ scope: sub.path, repoPath: sub.repoPath });
350
+ }
351
+ for (const { scope, repoPath } of scopes) {
352
+ try {
353
+ await runGit(repoPath, ["cat-file", "-e", `${build.commit}^{commit}`], options);
354
+ const headResult = await runGit(repoPath, ["rev-parse", "HEAD"], options);
355
+ const head = headResult.stdout.trim();
356
+ if (!head || head === build.commit) continue;
357
+ await runGit(repoPath, ["merge-base", "--is-ancestor", build.commit, "HEAD"], options);
358
+ return {
359
+ buildCommit: build.commit,
360
+ buildCommitShort: build.commitShort,
361
+ head,
362
+ scope,
363
+ 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.`
364
+ };
365
+ } catch {
366
+ continue;
367
+ }
368
+ }
369
+ return void 0;
370
+ }
317
371
  async function readPorcelainStatus(repo, options) {
318
372
  const statusOutput = await runGit(repo, ["status", "--porcelain=v2", "--branch"], options);
319
373
  return parsePorcelainV2Status(statusOutput.stdout);
@@ -530,6 +584,7 @@ var init_git_status = __esm({
530
584
  "src/git/git-status.ts"() {
531
585
  "use strict";
532
586
  init_git_executor();
587
+ init_build_info();
533
588
  }
534
589
  });
535
590
 
@@ -2386,8 +2441,8 @@ function readLedgerFromStore(meshId) {
2386
2441
  }
2387
2442
  function getCachedRawEntries(meshId) {
2388
2443
  const now = Date.now();
2389
- const cached = ledgerReadCache.get(meshId);
2390
- if (cached && now - cached.cachedAt < LEDGER_CACHE_TTL_MS) return cached.entries;
2444
+ const cached2 = ledgerReadCache.get(meshId);
2445
+ if (cached2 && now - cached2.cachedAt < LEDGER_CACHE_TTL_MS) return cached2.entries;
2391
2446
  let entries;
2392
2447
  try {
2393
2448
  entries = readLedgerFromStore(meshId);
@@ -2650,6 +2705,7 @@ __export(mesh_work_queue_exports, {
2650
2705
  cancelTask: () => cancelTask,
2651
2706
  claimNextTask: () => claimNextTask,
2652
2707
  cleanupTerminalDirectDispatches: () => cleanupTerminalDirectDispatches,
2708
+ deleteDirectDispatchesByTaskId: () => deleteDirectDispatchesByTaskId,
2653
2709
  describeTaskDependencyState: () => describeTaskDependencyState,
2654
2710
  enqueueTask: () => enqueueTask,
2655
2711
  getActiveDirectDispatches: () => getActiveDirectDispatches,
@@ -3058,6 +3114,13 @@ function markStaleDirectDispatches(meshId, olderThanMs = 60 * 6e4) {
3058
3114
  } catch {
3059
3115
  }
3060
3116
  }
3117
+ function deleteDirectDispatchesByTaskId(meshId, taskIds) {
3118
+ try {
3119
+ return MeshRuntimeStore.getInstance().deleteDirectDispatchesByTaskId(meshId, taskIds);
3120
+ } catch {
3121
+ return 0;
3122
+ }
3123
+ }
3061
3124
  function recordMeshToolCall(opts) {
3062
3125
  try {
3063
3126
  return MeshRuntimeStore.getInstance().recordMeshToolCall(opts);
@@ -3691,6 +3754,24 @@ var init_mesh_runtime_store = __esm({
3691
3754
  deleteDirectDispatches(meshId) {
3692
3755
  this.db.prepare(`DELETE FROM mesh_direct_dispatches WHERE mesh_id = ?`).run(meshId);
3693
3756
  }
3757
+ /**
3758
+ * Delete specific direct dispatch rows by taskId for a mesh. Used by the staleDirect prune
3759
+ * path to remove orphaned/terminal dispatch records whose node/session is no longer in the
3760
+ * live mesh. Returns the number of rows actually deleted. No-op for an empty taskId list.
3761
+ */
3762
+ deleteDirectDispatchesByTaskId(meshId, taskIds) {
3763
+ const ids = (taskIds || []).map((id) => typeof id === "string" ? id.trim() : "").filter(Boolean);
3764
+ if (!ids.length) return 0;
3765
+ const stmt = this.db.prepare(`DELETE FROM mesh_direct_dispatches WHERE mesh_id = ? AND task_id = ?`);
3766
+ let deleted = 0;
3767
+ const run = this.db.transaction((rows) => {
3768
+ for (const taskId of rows) {
3769
+ deleted += stmt.run(meshId, taskId).changes;
3770
+ }
3771
+ });
3772
+ run(ids);
3773
+ return deleted;
3774
+ }
3694
3775
  markStaleDirectDispatches(meshId, olderThanMs) {
3695
3776
  const cutoff = new Date(Date.now() - olderThanMs).toISOString();
3696
3777
  const now = (/* @__PURE__ */ new Date()).toISOString();
@@ -5359,11 +5440,14 @@ async function fastForwardMeshNode(args) {
5359
5440
  const trigger = normalizeOptionalString(args.trigger) || "manual";
5360
5441
  const updateSubmodules = args.updateSubmodules === true;
5361
5442
  const dryRun = args.dryRun === true || args.execute !== true;
5362
- const plannedSteps = buildPlannedSteps(updateSubmodules);
5443
+ const mode = args.mode === "push" ? "push" : "merge";
5444
+ const pushSubmodules = mode === "push" && args.pushSubmodules === true;
5445
+ const plannedSteps = buildPlannedSteps(mode, updateSubmodules, pushSubmodules);
5363
5446
  const base = {
5364
5447
  ...nodeId ? { nodeId } : {},
5365
5448
  ...meshId ? { meshId } : {},
5366
5449
  workspace,
5450
+ mode,
5367
5451
  dryRun,
5368
5452
  updateSubmodules,
5369
5453
  plannedSteps,
@@ -5377,13 +5461,24 @@ async function fastForwardMeshNode(args) {
5377
5461
  submoduleIgnorePaths: args.submoduleIgnorePaths,
5378
5462
  timeoutMs: args.timeoutMs ?? STATUS_OPTIONS.timeoutMs
5379
5463
  });
5464
+ if (mode === "push") {
5465
+ return pushMeshNode(base, args, current, {
5466
+ pushSubmodules,
5467
+ allowAutoPublishSubmoduleMainCommits: args.allowAutoPublishSubmoduleMainCommits === true
5468
+ });
5469
+ }
5380
5470
  const earlyBlockers = collectPreflightBlockers(current, requestedBranch);
5381
5471
  if (earlyBlockers.length > 0) {
5472
+ const blockCode = chooseBlockCode(current, earlyBlockers);
5382
5473
  const result2 = {
5383
- ...block(base, chooseBlockCode(current, earlyBlockers), earlyBlockers),
5474
+ ...block(base, blockCode, earlyBlockers),
5384
5475
  current,
5385
- finalBranchConvergenceState: buildConvergenceState(current, codeToConvergenceStatus(chooseBlockCode(current, earlyBlockers)))
5476
+ finalBranchConvergenceState: buildConvergenceState(current, codeToConvergenceStatus(blockCode))
5386
5477
  };
5478
+ if (blockCode === "branch_ahead" && current.ahead > 0 && current.behind === 0 && otherBlockersAreOnlyAhead(earlyBlockers)) {
5479
+ result2.code = "ahead_needs_push";
5480
+ 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.';
5481
+ }
5387
5482
  await appendFastForwardLedger(result2, "blocked");
5388
5483
  return result2;
5389
5484
  }
@@ -5494,7 +5589,246 @@ async function fastForwardMeshNode(args) {
5494
5589
  await appendFastForwardLedger(result, success ? "executed" : "failed");
5495
5590
  return result;
5496
5591
  }
5497
- function buildPlannedSteps(updateSubmodules) {
5592
+ async function pushMeshNode(base, args, current, options) {
5593
+ const workspace = base.workspace;
5594
+ const requestedBranch = normalizeOptionalString(args.branch);
5595
+ const dryRun = base.dryRun;
5596
+ const blockers = collectPushPreflightBlockers(current, requestedBranch);
5597
+ if (blockers.length > 0) {
5598
+ const code2 = choosePushBlockCode(current, blockers);
5599
+ const result2 = {
5600
+ ...block(base, code2, blockers),
5601
+ current,
5602
+ preStatus: current,
5603
+ finalBranchConvergenceState: buildConvergenceState(current, codeToConvergenceStatus(code2))
5604
+ };
5605
+ await appendFastForwardLedger(result2, "blocked");
5606
+ return result2;
5607
+ }
5608
+ const target = parseUpstreamTarget(current.upstream || "");
5609
+ if (!target) {
5610
+ const result2 = {
5611
+ ...block(base, "upstream_unparseable", ["upstream_unparseable"]),
5612
+ current,
5613
+ preStatus: current,
5614
+ finalBranchConvergenceState: buildConvergenceState(current, "blocked")
5615
+ };
5616
+ await appendFastForwardLedger(result2, "blocked");
5617
+ return result2;
5618
+ }
5619
+ const refspec = `HEAD:refs/heads/${target.remoteBranch}`;
5620
+ const pushTarget = { remote: target.remote, remoteBranch: target.remoteBranch, refspec };
5621
+ if (current.ahead <= 0) {
5622
+ const result2 = {
5623
+ ...base,
5624
+ success: true,
5625
+ code: "nothing_to_push",
5626
+ allowed: true,
5627
+ willRun: false,
5628
+ executed: false,
5629
+ blockingReasons: [],
5630
+ current,
5631
+ preStatus: current,
5632
+ postStatus: current,
5633
+ pushTarget,
5634
+ finalBranchConvergenceState: buildConvergenceState(current, "up_to_date")
5635
+ };
5636
+ await appendFastForwardLedger(result2, "noop");
5637
+ return result2;
5638
+ }
5639
+ const descendant = await verifyUpstreamIsAncestorOfHead(workspace, current.upstream || "", args.timeoutMs);
5640
+ if (!descendant.ok) {
5641
+ const result2 = {
5642
+ ...block(base, "non_fast_forward_push", ["head_is_not_descendant_of_upstream"]),
5643
+ current,
5644
+ preStatus: current,
5645
+ pushTarget,
5646
+ operationError: descendant.error,
5647
+ 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.",
5648
+ finalBranchConvergenceState: buildConvergenceState(current, "not_mergeable")
5649
+ };
5650
+ await appendFastForwardLedger(result2, "blocked");
5651
+ return result2;
5652
+ }
5653
+ if (dryRun) {
5654
+ const result2 = {
5655
+ ...base,
5656
+ success: true,
5657
+ code: "push_available",
5658
+ allowed: true,
5659
+ willRun: false,
5660
+ executed: false,
5661
+ blockingReasons: [],
5662
+ current,
5663
+ preStatus: current,
5664
+ pushTarget,
5665
+ ...options.pushSubmodules ? { submodulePushes: await planSubmodulePushes(current, options, args.timeoutMs) } : {},
5666
+ finalBranchConvergenceState: buildConvergenceState(current, "push_available")
5667
+ };
5668
+ await appendFastForwardLedger(result2, "dry_run");
5669
+ return result2;
5670
+ }
5671
+ try {
5672
+ await runGit(workspace, ["push", target.remote, refspec], { timeoutMs: args.timeoutMs ?? 3e4 });
5673
+ } catch (error) {
5674
+ const result2 = {
5675
+ ...block(base, "push_ff_only_failed", ["push_ff_only_failed"]),
5676
+ current,
5677
+ preStatus: current,
5678
+ pushTarget,
5679
+ operationError: formatGitError2(error),
5680
+ finalBranchConvergenceState: buildConvergenceState(current, "not_mergeable")
5681
+ };
5682
+ await appendFastForwardLedger(result2, "failed");
5683
+ return result2;
5684
+ }
5685
+ let submodulePushes;
5686
+ if (options.pushSubmodules) {
5687
+ submodulePushes = await executeSubmodulePushes(current, options, args.timeoutMs);
5688
+ }
5689
+ const postStatus = await getGitRepoStatus(workspace, {
5690
+ ...STATUS_OPTIONS,
5691
+ submoduleIgnorePaths: args.submoduleIgnorePaths,
5692
+ timeoutMs: args.timeoutMs ?? STATUS_OPTIONS.timeoutMs
5693
+ });
5694
+ const submodulePushFailed = (submodulePushes || []).some((entry) => !entry.pushed && !entry.skipped);
5695
+ const blockingReasons = [];
5696
+ if (postStatus.ahead !== 0) blockingReasons.push("post_branch_ahead");
5697
+ if (submodulePushFailed) blockingReasons.push("submodule_push_failed");
5698
+ const success = blockingReasons.length === 0;
5699
+ const code = success ? "push_applied" : submodulePushFailed && postStatus.ahead === 0 ? "push_applied_submodule_push_failed" : "post_push_verify_failed";
5700
+ const result = {
5701
+ ...base,
5702
+ success,
5703
+ code,
5704
+ allowed: true,
5705
+ willRun: true,
5706
+ executed: true,
5707
+ blockingReasons,
5708
+ current,
5709
+ preStatus: current,
5710
+ postStatus,
5711
+ pushTarget,
5712
+ ...submodulePushes ? { submodulePushes } : {},
5713
+ finalBranchConvergenceState: buildConvergenceState(postStatus, success ? "pushed" : "post_verify_failed")
5714
+ };
5715
+ await appendFastForwardLedger(result, success ? "executed" : "failed");
5716
+ return result;
5717
+ }
5718
+ function collectPushPreflightBlockers(status, requestedBranch) {
5719
+ const blockers = [];
5720
+ if (!status.isGitRepo) blockers.push("not_git_repo");
5721
+ if (!status.branch) blockers.push("detached_head_or_unknown_branch");
5722
+ if (requestedBranch && status.branch !== requestedBranch) blockers.push("branch_mismatch");
5723
+ if (!status.upstream) blockers.push("upstream_missing");
5724
+ if (status.upstreamStatus !== "fresh") blockers.push("upstream_not_fresh");
5725
+ if (status.hasConflicts) blockers.push("conflicts_present");
5726
+ if (status.staged > 0) blockers.push("staged_changes_present");
5727
+ if (status.modified > 0) blockers.push("modified_changes_present");
5728
+ if (status.untracked > 0) blockers.push("untracked_changes_present");
5729
+ if (status.deleted > 0) blockers.push("deleted_changes_present");
5730
+ if (status.renamed > 0) blockers.push("renamed_changes_present");
5731
+ if (status.stashCount > 0) blockers.push("stash_entries_present");
5732
+ if (status.ahead > 0 && status.behind > 0) blockers.push("branch_diverged_from_upstream");
5733
+ else if (status.behind > 0) blockers.push("branch_behind_upstream");
5734
+ return blockers;
5735
+ }
5736
+ function choosePushBlockCode(status, blockers) {
5737
+ if (blockers.includes("not_git_repo")) return "not_git_repo";
5738
+ if (blockers.includes("branch_mismatch")) return "branch_mismatch";
5739
+ if (blockers.includes("upstream_missing")) return "upstream_missing";
5740
+ if (blockers.includes("upstream_not_fresh")) return "upstream_not_fresh";
5741
+ if (blockers.includes("branch_diverged_from_upstream")) return "branch_diverged";
5742
+ if (blockers.includes("branch_behind_upstream")) return "non_fast_forward_push";
5743
+ if (blockers.some((reason) => reason.includes("changes") || reason.includes("conflicts") || reason.includes("stash"))) return "dirty_worktree";
5744
+ return "preflight_blocked";
5745
+ }
5746
+ function parseUpstreamTarget(upstream) {
5747
+ const trimmed = upstream.trim();
5748
+ const slash = trimmed.indexOf("/");
5749
+ if (slash <= 0 || slash >= trimmed.length - 1) return null;
5750
+ return { remote: trimmed.slice(0, slash), remoteBranch: trimmed.slice(slash + 1) };
5751
+ }
5752
+ async function verifyUpstreamIsAncestorOfHead(workspace, upstream, timeoutMs) {
5753
+ if (!upstream) return { ok: false, error: "missing upstream" };
5754
+ try {
5755
+ await runGit(workspace, ["merge-base", "--is-ancestor", upstream, "HEAD"], { timeoutMs: timeoutMs ?? 15e3 });
5756
+ return { ok: true };
5757
+ } catch (error) {
5758
+ return { ok: false, error: formatGitError2(error) };
5759
+ }
5760
+ }
5761
+ async function planSubmodulePushes(status, options, timeoutMs) {
5762
+ return resolveSubmodulePushes(status, options, false, timeoutMs);
5763
+ }
5764
+ async function executeSubmodulePushes(status, options, timeoutMs) {
5765
+ return resolveSubmodulePushes(status, options, true, timeoutMs);
5766
+ }
5767
+ async function resolveSubmodulePushes(status, options, execute, timeoutMs) {
5768
+ const submodules = Array.isArray(status.submodules) ? status.submodules : [];
5769
+ const results = [];
5770
+ for (const submodule of submodules) {
5771
+ const base = {
5772
+ path: submodule.path,
5773
+ commit: submodule.commit,
5774
+ remote: "origin",
5775
+ remoteBranch: "main",
5776
+ pushed: false,
5777
+ skipped: true,
5778
+ code: "submodule_push_skipped"
5779
+ };
5780
+ if (!options.allowAutoPublishSubmoduleMainCommits) {
5781
+ results.push({ ...base, code: "submodule_push_policy_disabled", error: "allowAutoPublishSubmoduleMainCommits is not enabled" });
5782
+ continue;
5783
+ }
5784
+ if (submodule.error || submodule.dirty) {
5785
+ results.push({ ...base, code: "submodule_not_clean", error: submodule.error || "submodule worktree is dirty" });
5786
+ continue;
5787
+ }
5788
+ const repoPath = submodule.repoPath;
5789
+ if (!repoPath || !submodule.commit) {
5790
+ results.push({ ...base, code: "submodule_status_incomplete" });
5791
+ continue;
5792
+ }
5793
+ try {
5794
+ await runGit(repoPath, ["-c", "protocol.file.allow=always", "fetch", "origin", "refs/heads/main:refs/remotes/origin/main"], { timeoutMs: timeoutMs ?? 3e4 });
5795
+ } catch (error) {
5796
+ results.push({ ...base, code: "submodule_fetch_failed", error: formatGitError2(error) });
5797
+ continue;
5798
+ }
5799
+ let alreadyReachable = false;
5800
+ try {
5801
+ await runGit(repoPath, ["merge-base", "--is-ancestor", submodule.commit, "refs/remotes/origin/main"], { timeoutMs: timeoutMs ?? 15e3 });
5802
+ alreadyReachable = true;
5803
+ } catch {
5804
+ }
5805
+ if (alreadyReachable) {
5806
+ results.push({ ...base, pushed: false, skipped: true, code: "submodule_already_reachable" });
5807
+ continue;
5808
+ }
5809
+ try {
5810
+ await runGit(repoPath, ["merge-base", "--is-ancestor", "refs/remotes/origin/main", submodule.commit], { timeoutMs: timeoutMs ?? 15e3 });
5811
+ } catch (error) {
5812
+ results.push({ ...base, pushed: false, skipped: false, code: "submodule_non_fast_forward", error: formatGitError2(error) });
5813
+ continue;
5814
+ }
5815
+ const refspec = `${submodule.commit}:refs/heads/main`;
5816
+ if (!execute) {
5817
+ results.push({ ...base, pushed: false, skipped: false, code: "submodule_push_available", refspec });
5818
+ continue;
5819
+ }
5820
+ try {
5821
+ await runGit(repoPath, ["push", "origin", refspec], { timeoutMs: timeoutMs ?? 3e4 });
5822
+ await runGit(repoPath, ["-c", "protocol.file.allow=always", "fetch", "origin", "refs/heads/main:refs/remotes/origin/main"], { timeoutMs: timeoutMs ?? 3e4 });
5823
+ await runGit(repoPath, ["merge-base", "--is-ancestor", submodule.commit, "refs/remotes/origin/main"], { timeoutMs: timeoutMs ?? 15e3 });
5824
+ results.push({ ...base, pushed: true, skipped: false, code: "submodule_pushed", refspec });
5825
+ } catch (error) {
5826
+ results.push({ ...base, pushed: false, skipped: false, code: "submodule_push_failed", refspec, error: formatGitError2(error) });
5827
+ }
5828
+ }
5829
+ return results;
5830
+ }
5831
+ function buildPlannedSteps(mode, updateSubmodules, pushSubmodules) {
5498
5832
  const steps = [
5499
5833
  {
5500
5834
  operation: "refresh_upstream",
@@ -5507,20 +5841,49 @@ function buildPlannedSteps(updateSubmodules) {
5507
5841
  description: "Require clean staged/modified/untracked/deleted/renamed/conflict/stash/submodule state.",
5508
5842
  safe: true,
5509
5843
  willMutateWorktree: false
5510
- },
5511
- {
5512
- operation: "verify_fast_forward",
5513
- description: "Require ahead=0, behind>0, and HEAD to be an ancestor of the upstream ref.",
5844
+ }
5845
+ ];
5846
+ if (mode === "push") {
5847
+ steps.push({
5848
+ operation: "verify_push_descendant",
5849
+ description: "Require HEAD to be a descendant of origin/<branch> (origin/<branch> is an ancestor of HEAD); refuse any non-fast-forward push.",
5514
5850
  safe: true,
5515
5851
  willMutateWorktree: false
5516
- },
5517
- {
5518
- operation: "merge_ff_only",
5519
- description: "Apply git merge --ff-only against the tracked upstream; no force, reset, rebase, push, or deploy.",
5852
+ });
5853
+ steps.push({
5854
+ operation: "push_ff_only",
5855
+ 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.",
5520
5856
  safe: true,
5521
- willMutateWorktree: true
5857
+ willMutateWorktree: false
5858
+ });
5859
+ if (pushSubmodules) {
5860
+ steps.push({
5861
+ operation: "push_submodules_ff_only",
5862
+ 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.",
5863
+ safe: true,
5864
+ willMutateWorktree: false
5865
+ });
5522
5866
  }
5523
- ];
5867
+ steps.push({
5868
+ operation: "verify_post_status",
5869
+ description: "Re-read daemon-owned git status and report final branch convergence state.",
5870
+ safe: true,
5871
+ willMutateWorktree: false
5872
+ });
5873
+ return steps;
5874
+ }
5875
+ steps.push({
5876
+ operation: "verify_fast_forward",
5877
+ description: "Require ahead=0, behind>0, and HEAD to be an ancestor of the upstream ref.",
5878
+ safe: true,
5879
+ willMutateWorktree: false
5880
+ });
5881
+ steps.push({
5882
+ operation: "merge_ff_only",
5883
+ description: "Apply git merge --ff-only against the tracked upstream; no force, reset, rebase, push, or deploy.",
5884
+ safe: true,
5885
+ willMutateWorktree: true
5886
+ });
5524
5887
  if (updateSubmodules) {
5525
5888
  steps.push({
5526
5889
  operation: "submodule_update",
@@ -5537,6 +5900,10 @@ function buildPlannedSteps(updateSubmodules) {
5537
5900
  });
5538
5901
  return steps;
5539
5902
  }
5903
+ function otherBlockersAreOnlyAhead(blockers) {
5904
+ const aheadOnly = /* @__PURE__ */ new Set(["branch_has_local_commits"]);
5905
+ return blockers.every((reason) => aheadOnly.has(reason));
5906
+ }
5540
5907
  function collectPreflightBlockers(status, requestedBranch) {
5541
5908
  const blockers = [];
5542
5909
  if (!status.isGitRepo) blockers.push("not_git_repo");
@@ -5593,7 +5960,7 @@ function chooseBlockCode(status, blockers) {
5593
5960
  return "preflight_blocked";
5594
5961
  }
5595
5962
  function codeToConvergenceStatus(code) {
5596
- if (code === "branch_diverged" || code === "branch_ahead" || code === "non_fast_forward") return "not_mergeable";
5963
+ if (code === "branch_diverged" || code === "branch_ahead" || code === "non_fast_forward" || code === "non_fast_forward_push" || code === "upstream_unparseable") return "not_mergeable";
5597
5964
  if (code === "dirty_worktree" || code === "submodule_not_clean") return "blocked_review";
5598
5965
  return "blocked";
5599
5966
  }
@@ -5676,6 +6043,7 @@ async function appendFastForwardLedger(result, outcome) {
5676
6043
  ...result.nodeId ? { nodeId: result.nodeId } : {},
5677
6044
  payload: {
5678
6045
  operation: "mesh_fast_forward_node",
6046
+ mode: result.mode,
5679
6047
  trigger: result.trigger || "manual",
5680
6048
  outcome,
5681
6049
  code: result.code,
@@ -5686,6 +6054,7 @@ async function appendFastForwardLedger(result, outcome) {
5686
6054
  executed: result.executed,
5687
6055
  branch: result.postStatus?.branch ?? result.current?.branch,
5688
6056
  upstream: result.postStatus?.upstream ?? result.current?.upstream,
6057
+ ...result.pushTarget ? { pushTarget: result.pushTarget } : {},
5689
6058
  before: result.current ? {
5690
6059
  headCommit: result.current.headCommit,
5691
6060
  ahead: result.current.ahead,
@@ -5696,6 +6065,16 @@ async function appendFastForwardLedger(result, outcome) {
5696
6065
  ahead: result.postStatus.ahead,
5697
6066
  behind: result.postStatus.behind
5698
6067
  } : void 0,
6068
+ ...result.submodulePushes ? {
6069
+ submodulePushes: result.submodulePushes.map((entry) => ({
6070
+ path: entry.path,
6071
+ commit: entry.commit,
6072
+ pushed: entry.pushed,
6073
+ skipped: entry.skipped,
6074
+ code: entry.code,
6075
+ ...entry.refspec ? { refspec: entry.refspec } : {}
6076
+ }))
6077
+ } : {},
5699
6078
  blockingReasons: result.blockingReasons
5700
6079
  }
5701
6080
  });
@@ -6866,8 +7245,8 @@ var init_mesh_routing = __esm({
6866
7245
  // src/mesh/mesh-events-coordinator.ts
6867
7246
  function getCachedMeshByWorkspace(workspace) {
6868
7247
  const now = Date.now();
6869
- const cached = meshByWorkspaceCache.get(workspace);
6870
- if (cached && now - cached.cachedAt < MESH_WORKSPACE_CACHE_TTL_MS) return cached.mesh;
7248
+ const cached2 = meshByWorkspaceCache.get(workspace);
7249
+ if (cached2 && now - cached2.cachedAt < MESH_WORKSPACE_CACHE_TTL_MS) return cached2.mesh;
6871
7250
  const mesh = getMeshByRepo(workspace);
6872
7251
  meshByWorkspaceCache.set(workspace, { mesh, cachedAt: now });
6873
7252
  return mesh;
@@ -11759,10 +12138,10 @@ ${lastSnapshot}`;
11759
12138
  return this.accumulatedRawBuffer.replace(/\x1B\][^\x07]*(?:\x07|\x1B\\)/g, "").replace(/\x1B[P^_X][\s\S]*?(?:\x07|\x1B\\)/g, "").replace(/\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])/g, "");
11760
12139
  }
11761
12140
  getFreshParsedStatusCache() {
11762
- const cached = this.parsedStatusCache;
12141
+ const cached2 = this.parsedStatusCache;
11763
12142
  const accumulatedRawBufferKey = this.getAccumulatedRawBufferCacheKey();
11764
- 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) {
11765
- return cached.result;
12143
+ 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) {
12144
+ return cached2.result;
11766
12145
  }
11767
12146
  return null;
11768
12147
  }
@@ -12222,10 +12601,10 @@ ${lastSnapshot}`;
12222
12601
  getScriptParsedStatus() {
12223
12602
  const screenText = this.readTerminalScreenText();
12224
12603
  const parseScreenText = this.getParseScreenText(screenText);
12225
- const cached = this.parsedStatusCache;
12604
+ const cached2 = this.parsedStatusCache;
12226
12605
  const accumulatedRawBufferKey = this.getAccumulatedRawBufferCacheKey();
12227
- 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) {
12228
- return cached.result;
12606
+ 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) {
12607
+ return cached2.result;
12229
12608
  }
12230
12609
  const parsed = this.runParseSession();
12231
12610
  if (!parsed || !Array.isArray(parsed.messages)) {
@@ -14091,6 +14470,7 @@ __export(index_exports, {
14091
14470
  MIN_SESSION_HOST_DIAGNOSTICS_SUBSCRIPTION_INTERVAL_MS: () => MIN_SESSION_HOST_DIAGNOSTICS_SUBSCRIPTION_INTERVAL_MS,
14092
14471
  NodePtyTransportFactory: () => NodePtyTransportFactory,
14093
14472
  P2pRelayFailureError: () => P2pRelayFailureError,
14473
+ PRUNABLE_ORPHAN_STALE_REASONS: () => PRUNABLE_ORPHAN_STALE_REASONS,
14094
14474
  ProviderCliAdapter: () => ProviderCliAdapter,
14095
14475
  ProviderInstanceManager: () => ProviderInstanceManager,
14096
14476
  ProviderLoader: () => ProviderLoader,
@@ -14144,6 +14524,7 @@ __export(index_exports, {
14144
14524
  classifyChatMessageVisibility: () => classifyChatMessageVisibility,
14145
14525
  classifyHotChatSessionsForSubscriptionFlush: () => classifyHotChatSessionsForSubscriptionFlush,
14146
14526
  classifyP2pRelayFailure: () => classifyP2pRelayFailure,
14527
+ classifyStaleDirectForPrune: () => classifyStaleDirectForPrune,
14147
14528
  cleanupTerminalDirectDispatches: () => cleanupTerminalDirectDispatches,
14148
14529
  clearDebugTrace: () => clearDebugTrace,
14149
14530
  clearPendingMeshCoordinatorEvents: () => clearPendingMeshCoordinatorEvents,
@@ -14163,6 +14544,7 @@ __export(index_exports, {
14163
14544
  createNativeHistoryDispatcher: () => createNativeHistoryDispatcher,
14164
14545
  createSessionDelivery: () => createSessionDelivery,
14165
14546
  createWorktree: () => createWorktree,
14547
+ deleteDirectDispatchesByTaskId: () => deleteDirectDispatchesByTaskId,
14166
14548
  deleteMesh: () => deleteMesh,
14167
14549
  deriveMeshReviewInboxItems: () => deriveMeshReviewInboxItems,
14168
14550
  describeTaskDependencyState: () => describeTaskDependencyState,
@@ -14191,6 +14573,7 @@ __export(index_exports, {
14191
14573
  getAvailableIdeIds: () => getAvailableIdeIds,
14192
14574
  getCoordinatorForSession: () => getCoordinatorForSession,
14193
14575
  getCurrentDaemonLogPath: () => getCurrentDaemonLogPath,
14576
+ getDaemonBuildInfo: () => getDaemonBuildInfo,
14194
14577
  getDaemonDataDir: () => getDaemonDataDir,
14195
14578
  getDaemonLogDir: () => getDaemonLogDir,
14196
14579
  getDebugRuntimeConfig: () => getDebugRuntimeConfig,
@@ -17037,6 +17420,17 @@ function buildMeshActiveWork(opts) {
17037
17420
  }
17038
17421
  return { activeWork: records, staleDirectWork, staleDirectWorkNote, terminalDirectWork, summary };
17039
17422
  }
17423
+ var PRUNABLE_ORPHAN_STALE_REASONS = /* @__PURE__ */ new Set([
17424
+ "direct task node is no longer in the live mesh",
17425
+ "direct task session is not present in live session records",
17426
+ "direct task has no node id"
17427
+ ]);
17428
+ function classifyStaleDirectForPrune(record, opts = {}) {
17429
+ if (record.staleDispatchUnacknowledged === true) return "preserve_unacknowledged";
17430
+ if (record.terminal === true) return opts.includeTerminal ? "prunable_terminal" : "preserve_active";
17431
+ if (record.staleReason && PRUNABLE_ORPHAN_STALE_REASONS.has(record.staleReason)) return "prunable_orphan";
17432
+ return "preserve_active";
17433
+ }
17040
17434
  function buildCompactStaleDirectWorkSummary(staleDirectWork, opts = {}) {
17041
17435
  const sampleLimit = Math.max(0, Math.min(10, Math.floor(opts.sampleLimit ?? 3)));
17042
17436
  const reasonCounts = {};
@@ -20260,9 +20654,9 @@ function computeSavedHistorySessionSummaries(agentType, dir, files, fileSignatur
20260
20654
  for (const file of files.slice().sort()) {
20261
20655
  const filePath = path12.join(dir, file);
20262
20656
  const signature = fileSignatures.get(file) || `${file}:missing`;
20263
- const cached = savedHistoryFileSummaryCache.get(filePath);
20657
+ const cached2 = savedHistoryFileSummaryCache.get(filePath);
20264
20658
  const persisted = persistedEntries.get(file);
20265
- const reusableEntry = cached?.signature === signature ? cached : persisted?.signature === signature ? persisted : null;
20659
+ const reusableEntry = cached2?.signature === signature ? cached2 : persisted?.signature === signature ? persisted : null;
20266
20660
  const fileSummary = reusableEntry?.summary || computeSavedHistoryFileSummary(dir, file);
20267
20661
  const nextEntry = reusableEntry || {
20268
20662
  signature,
@@ -20714,23 +21108,23 @@ function listSavedHistorySessions(agentType, options = {}, historyBehavior) {
20714
21108
  savedHistorySessionCache.delete(sanitized);
20715
21109
  return { sessions: [], hasMore: false };
20716
21110
  }
20717
- const cached = savedHistorySessionCache.get(sanitized);
21111
+ const cached2 = savedHistorySessionCache.get(sanitized);
20718
21112
  const offset = Math.max(0, options.offset || 0);
20719
21113
  const limit = Math.max(1, options.limit || 30);
20720
21114
  const indexSignature = buildSavedHistoryIndexFileSignature(dir);
20721
21115
  let cacheWasInvalidated = false;
20722
- if (cached) {
20723
- const cacheLooksPersisted = cached.signature.startsWith("index:");
20724
- const cacheStillValid = cacheLooksPersisted ? cached.signature === indexSignature : (() => {
21116
+ if (cached2) {
21117
+ const cacheLooksPersisted = cached2.signature.startsWith("index:");
21118
+ const cacheStillValid = cacheLooksPersisted ? cached2.signature === indexSignature : (() => {
20725
21119
  const files2 = listHistoryFiles(dir);
20726
21120
  const fileSignatures2 = buildSavedHistoryFileSignatureMap(dir, files2);
20727
- return cached.signature === buildSavedHistoryCacheSignature(files2, fileSignatures2);
21121
+ return cached2.signature === buildSavedHistoryCacheSignature(files2, fileSignatures2);
20728
21122
  })();
20729
21123
  if (cacheStillValid) {
20730
- const sliced2 = cached.summaries.slice(offset, offset + limit);
21124
+ const sliced2 = cached2.summaries.slice(offset, offset + limit);
20731
21125
  return {
20732
21126
  sessions: sliced2,
20733
- hasMore: cached.summaries.length > offset + limit
21127
+ hasMore: cached2.summaries.length > offset + limit
20734
21128
  };
20735
21129
  }
20736
21130
  cacheWasInvalidated = true;
@@ -37319,8 +37713,8 @@ var ProviderLoader = class _ProviderLoader {
37319
37713
  return null;
37320
37714
  }
37321
37715
  registerProviderScriptRootSafely(path30.dirname(path30.dirname(providerDir)));
37322
- const cached = this.scriptsCache.get(dir);
37323
- if (cached) return cached;
37716
+ const cached2 = this.scriptsCache.get(dir);
37717
+ if (cached2) return cached2;
37324
37718
  const scriptsJs = path30.join(dir, "scripts.js");
37325
37719
  if (fs20.existsSync(scriptsJs)) {
37326
37720
  try {
@@ -39318,6 +39712,9 @@ function buildStatusSnapshot(options) {
39318
39712
  };
39319
39713
  }
39320
39714
 
39715
+ // src/commands/router.ts
39716
+ init_build_info();
39717
+
39321
39718
  // src/commands/upgrade-helper.ts
39322
39719
  var import_child_process7 = require("child_process");
39323
39720
  var import_child_process8 = require("child_process");
@@ -40103,13 +40500,13 @@ function sanitizeInlineMesh(inlineMesh) {
40103
40500
  nodes
40104
40501
  };
40105
40502
  }
40106
- function reconcileInlineMeshCache(cached, incoming) {
40107
- if (!cached || typeof cached !== "object" || Array.isArray(cached)) return incoming;
40108
- if (!incoming || typeof incoming !== "object" || Array.isArray(incoming)) return cached;
40109
- const cachedNodes = Array.isArray(cached.nodes) ? cached.nodes : [];
40503
+ function reconcileInlineMeshCache(cached2, incoming) {
40504
+ if (!cached2 || typeof cached2 !== "object" || Array.isArray(cached2)) return incoming;
40505
+ if (!incoming || typeof incoming !== "object" || Array.isArray(incoming)) return cached2;
40506
+ const cachedNodes = Array.isArray(cached2.nodes) ? cached2.nodes : [];
40110
40507
  const incomingNodes = Array.isArray(incoming.nodes) ? incoming.nodes : [];
40111
- if (!cachedNodes.length || !incomingNodes.length) return { ...cached, ...incoming };
40112
- const cachedUpdatedAt = Date.parse(readStringValue(cached.updatedAt, cached.updated_at) || "");
40508
+ if (!cachedNodes.length || !incomingNodes.length) return { ...cached2, ...incoming };
40509
+ const cachedUpdatedAt = Date.parse(readStringValue(cached2.updatedAt, cached2.updated_at) || "");
40113
40510
  const incomingUpdatedAt = Date.parse(readStringValue(incoming.updatedAt, incoming.updated_at) || "");
40114
40511
  const preserveCachedMembership = Number.isFinite(cachedUpdatedAt) && (!Number.isFinite(incomingUpdatedAt) || cachedUpdatedAt > incomingUpdatedAt);
40115
40512
  const cachedById = /* @__PURE__ */ new Map();
@@ -40138,7 +40535,7 @@ function reconcileInlineMeshCache(cached, incoming) {
40138
40535
  }
40139
40536
  }
40140
40537
  return {
40141
- ...cached,
40538
+ ...cached2,
40142
40539
  ...incoming,
40143
40540
  nodes
40144
40541
  };
@@ -41822,13 +42219,13 @@ var DaemonCommandRouter = class {
41822
42219
  };
41823
42220
  }
41824
42221
  getCachedAggregateMeshStatus(meshId, mesh, options) {
41825
- const cached = this.aggregateMeshStatusCache.get(meshId);
41826
- if (!cached?.snapshot || cached.snapshot.success !== true || !Array.isArray(cached.snapshot.nodes)) return null;
41827
- if (cached.queueRevision !== getMeshQueueRevision(meshId)) return null;
41828
- let snapshot = this.cloneJsonValue(cached.snapshot);
42222
+ const cached2 = this.aggregateMeshStatusCache.get(meshId);
42223
+ if (!cached2?.snapshot || cached2.snapshot.success !== true || !Array.isArray(cached2.snapshot.nodes)) return null;
42224
+ if (cached2.queueRevision !== getMeshQueueRevision(meshId)) return null;
42225
+ let snapshot = this.cloneJsonValue(cached2.snapshot);
41829
42226
  snapshot = this.hydrateCachedAggregateMeshStatusFromInline(snapshot, mesh, options);
41830
42227
  if (shouldRefreshStalePendingAggregate(snapshot, options)) return null;
41831
- const ageMs = Math.max(0, Date.now() - cached.builtAt);
42228
+ const ageMs = Math.max(0, Date.now() - cached2.builtAt);
41832
42229
  const sourceOfTruth = snapshot.sourceOfTruth && typeof snapshot.sourceOfTruth === "object" ? snapshot.sourceOfTruth : {};
41833
42230
  snapshot.sourceOfTruth = {
41834
42231
  ...sourceOfTruth,
@@ -41839,7 +42236,7 @@ var DaemonCommandRouter = class {
41839
42236
  source: "memory",
41840
42237
  refreshReason: "memory_cache_hit",
41841
42238
  ageMs,
41842
- cachedAt: new Date(cached.builtAt).toISOString(),
42239
+ cachedAt: new Date(cached2.builtAt).toISOString(),
41843
42240
  returnedAt: (/* @__PURE__ */ new Date()).toISOString()
41844
42241
  }
41845
42242
  };
@@ -41883,9 +42280,9 @@ var DaemonCommandRouter = class {
41883
42280
  warmInlineMeshCache(meshId, inlineMesh) {
41884
42281
  if (!inlineMesh || typeof inlineMesh !== "object") return void 0;
41885
42282
  const sanitizedInlineMesh = sanitizeInlineMesh(inlineMesh);
41886
- const cached = this.inlineMeshCache.get(meshId);
41887
- if (cached) {
41888
- const merged = reconcileInlineMeshCache(cached, sanitizedInlineMesh);
42283
+ const cached2 = this.inlineMeshCache.get(meshId);
42284
+ if (cached2) {
42285
+ const merged = reconcileInlineMeshCache(cached2, sanitizedInlineMesh);
41889
42286
  this.inlineMeshCache.set(meshId, merged);
41890
42287
  return merged;
41891
42288
  }
@@ -41895,14 +42292,14 @@ var DaemonCommandRouter = class {
41895
42292
  async getMeshForCommand(meshId, inlineMesh, options) {
41896
42293
  const preferInline = options?.preferInline === true;
41897
42294
  if (preferInline) {
41898
- const cached2 = this.getCachedInlineMesh(meshId);
41899
- if (cached2) {
42295
+ const cached3 = this.getCachedInlineMesh(meshId);
42296
+ if (cached3) {
41900
42297
  if (inlineMeshCarriesTransientNodeTruth(inlineMesh)) {
41901
- const merged = reconcileInlineMeshCache(cached2, inlineMesh);
42298
+ const merged = reconcileInlineMeshCache(cached3, inlineMesh);
41902
42299
  this.inlineMeshCache.set(meshId, sanitizeInlineMesh(merged));
41903
42300
  return { mesh: merged, inline: true, source: "inline_cache" };
41904
42301
  }
41905
- return { mesh: cached2, inline: true, source: "inline_cache" };
42302
+ return { mesh: cached3, inline: true, source: "inline_cache" };
41906
42303
  }
41907
42304
  if (inlineMeshCarriesTransientNodeTruth(inlineMesh)) {
41908
42305
  this.warmInlineMeshCache(meshId, inlineMesh);
@@ -41915,8 +42312,8 @@ var DaemonCommandRouter = class {
41915
42312
  if (mesh) return { mesh, inline: false, source: "local_config" };
41916
42313
  } catch {
41917
42314
  }
41918
- const cached = this.getCachedInlineMesh(meshId);
41919
- if (cached) return { mesh: cached, inline: true, source: "inline_cache" };
42315
+ const cached2 = this.getCachedInlineMesh(meshId);
42316
+ if (cached2) return { mesh: cached2, inline: true, source: "inline_cache" };
41920
42317
  const warmedInline = this.warmInlineMeshCache(meshId, inlineMesh);
41921
42318
  return warmedInline ? { mesh: warmedInline, inline: true, source: "inline_bootstrap" } : null;
41922
42319
  }
@@ -42223,6 +42620,8 @@ var DaemonCommandRouter = class {
42223
42620
  const skippedSessionIds = [];
42224
42621
  const skippedLiveSessionIds = [];
42225
42622
  const skippedCoordinatorSessionIds = [];
42623
+ const skippedLiveSessionReasons = [];
42624
+ const actedLiveDelegateSessionIds = [];
42226
42625
  const deleteUnsupportedSessionIds = [];
42227
42626
  const recordsRemainSessionIds = [];
42228
42627
  const errors = [];
@@ -42256,16 +42655,31 @@ var DaemonCommandRouter = class {
42256
42655
  const surfaceKind = getSessionHostSurfaceKind(record);
42257
42656
  const liveRuntime = surfaceKind === "live_runtime";
42258
42657
  const coordinatorSession = readStringValue(record?.meta?.meshCoordinatorFor) === args.meshId;
42658
+ const recordNodeId = readStringValue(record?.meta?.meshNodeId);
42659
+ const recordMeshNodeFor = readStringValue(record?.meta?.meshNodeFor);
42660
+ const delegateBoundToThisNode = !!recordNodeId && recordNodeId === args.nodeId && (!recordMeshNodeFor || recordMeshNodeFor === args.meshId);
42259
42661
  if (!hasExplicitSessionIds && coordinatorSession) {
42260
42662
  skippedSessionIds.push(sessionId);
42261
42663
  skippedCoordinatorSessionIds.push(sessionId);
42262
42664
  continue;
42263
42665
  }
42264
- if (!hasExplicitSessionIds && liveRuntime) {
42666
+ if (!hasExplicitSessionIds && liveRuntime && !delegateBoundToThisNode) {
42667
+ skippedSessionIds.push(sessionId);
42668
+ skippedLiveSessionIds.push(sessionId);
42669
+ const matchedByWorkspaceOnly = !recordNodeId;
42670
+ 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";
42671
+ skippedLiveSessionReasons.push({ sessionId, reason });
42672
+ continue;
42673
+ }
42674
+ if (!hasExplicitSessionIds && liveRuntime && delegateBoundToThisNode && args.mode === "delete_stopped") {
42265
42675
  skippedSessionIds.push(sessionId);
42266
42676
  skippedLiveSessionIds.push(sessionId);
42677
+ skippedLiveSessionReasons.push({ sessionId, reason: "live_delegate_preserved_by_delete_stopped_mode_use_stop_or_stop_and_delete" });
42267
42678
  continue;
42268
42679
  }
42680
+ if (!hasExplicitSessionIds && liveRuntime && delegateBoundToThisNode) {
42681
+ actedLiveDelegateSessionIds.push(sessionId);
42682
+ }
42269
42683
  try {
42270
42684
  if (args.mode === "stop") {
42271
42685
  if (!completed) {
@@ -42327,6 +42741,8 @@ var DaemonCommandRouter = class {
42327
42741
  skippedSessionIds,
42328
42742
  skippedLiveSessionIds,
42329
42743
  skippedCoordinatorSessionIds,
42744
+ ...actedLiveDelegateSessionIds.length ? { actedLiveDelegateSessionIds } : {},
42745
+ ...skippedLiveSessionReasons.length ? { skippedLiveSessionReasons } : {},
42330
42746
  ...deleteUnsupported ? {
42331
42747
  deleteUnsupported: true,
42332
42748
  effectiveCleanup: args.mode === "stop_and_delete" ? "stopped_only_records_remain" : "delete_unsupported_records_remain",
@@ -43254,8 +43670,8 @@ ${hintLines.join("\n")}` : "",
43254
43670
  const repoRootBaseRef = /* @__PURE__ */ new Map();
43255
43671
  const submodulePathsByRepoRoot = /* @__PURE__ */ new Map();
43256
43672
  const resolveBaseRef = async (repoRoot) => {
43257
- const cached = repoRootBaseRef.get(repoRoot);
43258
- if (cached) return cached;
43673
+ const cached2 = repoRootBaseRef.get(repoRoot);
43674
+ if (cached2) return cached2;
43259
43675
  let baseBranch = "main";
43260
43676
  try {
43261
43677
  const { stdout } = await execFileAsync4("git", ["branch", "--show-current"], { cwd: repoRoot, encoding: "utf8" });
@@ -44153,7 +44569,7 @@ ${hintLines.join("\n")}` : "",
44153
44569
  version: this.deps.statusVersion || "unknown",
44154
44570
  profile: "metadata"
44155
44571
  });
44156
- return { success: true, status: snapshot };
44572
+ return { success: true, status: snapshot, daemonBuild: getDaemonBuildInfo() };
44157
44573
  }
44158
44574
  case "get_machine_runtime_stats": {
44159
44575
  return {
@@ -45123,6 +45539,7 @@ ${hintLines.join("\n")}` : "",
45123
45539
  let workspace = typeof args?.workspace === "string" ? args.workspace.trim() : "";
45124
45540
  let submoduleIgnorePaths = Array.isArray(args?.submoduleIgnorePaths) ? args.submoduleIgnorePaths.filter((value) => typeof value === "string") : void 0;
45125
45541
  let nodeDaemonId;
45542
+ let allowAutoPublishSubmoduleMainCommits = false;
45126
45543
  if (meshId && nodeId) {
45127
45544
  const meshRecord = await this.getMeshForCommand(meshId, args?.inlineMesh, { preferInline: true });
45128
45545
  const mesh = meshRecord?.mesh;
@@ -45133,6 +45550,7 @@ ${hintLines.join("\n")}` : "",
45133
45550
  if (!submoduleIgnorePaths && Array.isArray(node?.policy?.submoduleIgnorePaths)) {
45134
45551
  submoduleIgnorePaths = node.policy.submoduleIgnorePaths.filter((value) => typeof value === "string");
45135
45552
  }
45553
+ allowAutoPublishSubmoduleMainCommits = mesh?.policy?.allowAutoPublishSubmoduleMainCommits === true;
45136
45554
  nodeDaemonId = typeof node?.daemonId === "string" ? node.daemonId.trim() : void 0;
45137
45555
  }
45138
45556
  const selfDaemonId = this.deps.statusInstanceId;
@@ -45153,7 +45571,10 @@ ${hintLines.join("\n")}` : "",
45153
45571
  execute: args?.execute === true,
45154
45572
  dryRun: args?.dryRun === true,
45155
45573
  updateSubmodules: args?.updateSubmodules === true,
45156
- submoduleIgnorePaths
45574
+ submoduleIgnorePaths,
45575
+ mode: args?.mode === "push" ? "push" : "merge",
45576
+ pushSubmodules: args?.pushSubmodules === true,
45577
+ allowAutoPublishSubmoduleMainCommits
45157
45578
  });
45158
45579
  return result;
45159
45580
  }
@@ -46853,6 +47274,7 @@ var DaemonStatusReporter = class {
46853
47274
  };
46854
47275
 
46855
47276
  // src/index.ts
47277
+ init_build_info();
46856
47278
  init_logger();
46857
47279
  init_debug_config();
46858
47280
 
@@ -55124,6 +55546,7 @@ var V1_CONTRACT_VERSION = "1.0.0";
55124
55546
  MIN_SESSION_HOST_DIAGNOSTICS_SUBSCRIPTION_INTERVAL_MS,
55125
55547
  NodePtyTransportFactory,
55126
55548
  P2pRelayFailureError,
55549
+ PRUNABLE_ORPHAN_STALE_REASONS,
55127
55550
  ProviderCliAdapter,
55128
55551
  ProviderInstanceManager,
55129
55552
  ProviderLoader,
@@ -55177,6 +55600,7 @@ var V1_CONTRACT_VERSION = "1.0.0";
55177
55600
  classifyChatMessageVisibility,
55178
55601
  classifyHotChatSessionsForSubscriptionFlush,
55179
55602
  classifyP2pRelayFailure,
55603
+ classifyStaleDirectForPrune,
55180
55604
  cleanupTerminalDirectDispatches,
55181
55605
  clearDebugTrace,
55182
55606
  clearPendingMeshCoordinatorEvents,
@@ -55196,6 +55620,7 @@ var V1_CONTRACT_VERSION = "1.0.0";
55196
55620
  createNativeHistoryDispatcher,
55197
55621
  createSessionDelivery,
55198
55622
  createWorktree,
55623
+ deleteDirectDispatchesByTaskId,
55199
55624
  deleteMesh,
55200
55625
  deriveMeshReviewInboxItems,
55201
55626
  describeTaskDependencyState,
@@ -55224,6 +55649,7 @@ var V1_CONTRACT_VERSION = "1.0.0";
55224
55649
  getAvailableIdeIds,
55225
55650
  getCoordinatorForSession,
55226
55651
  getCurrentDaemonLogPath,
55652
+ getDaemonBuildInfo,
55227
55653
  getDaemonDataDir,
55228
55654
  getDaemonLogDir,
55229
55655
  getDebugRuntimeConfig,