@adhdev/daemon-core 0.9.82-rc.259 → 0.9.82-rc.260

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
@@ -2662,6 +2662,7 @@ __export(mesh_work_queue_exports, {
2662
2662
  nodeSatisfiesRequiredTags: () => nodeSatisfiesRequiredTags,
2663
2663
  normalizeMeshCapabilityTags: () => normalizeMeshCapabilityTags,
2664
2664
  normalizeMeshTaskMode: () => normalizeMeshTaskMode,
2665
+ recordDirectDispatchTask: () => recordDirectDispatchTask,
2665
2666
  recordMeshToolCall: () => recordMeshToolCall,
2666
2667
  recordTaskAutoLaunch: () => recordTaskAutoLaunch,
2667
2668
  requeueTask: () => requeueTask,
@@ -2826,6 +2827,37 @@ function enqueueTask(meshId, message, opts) {
2826
2827
  return entry;
2827
2828
  });
2828
2829
  }
2830
+ function recordDirectDispatchTask(meshId, message, opts) {
2831
+ const missionId = typeof opts.missionId === "string" ? opts.missionId.trim() : "";
2832
+ if (!missionId) return null;
2833
+ const taskId = typeof opts.id === "string" ? opts.id.trim() : "";
2834
+ if (!taskId) return null;
2835
+ const modeValidation = validateMeshTaskModeRequest(opts.taskMode, message);
2836
+ if (!modeValidation.valid) {
2837
+ throw new Error(`live_debug_readonly_guardrail_violation: forbidden operations (${modeValidation.violations.join(", ")})`);
2838
+ }
2839
+ const now = opts.dispatchedAt && opts.dispatchedAt.trim() ? opts.dispatchedAt : (/* @__PURE__ */ new Date()).toISOString();
2840
+ return withQueueLock(meshId, () => {
2841
+ if (MeshRuntimeStore.getInstance().findQueueEntryById(meshId, taskId)) {
2842
+ return null;
2843
+ }
2844
+ const entry = {
2845
+ id: taskId,
2846
+ meshId,
2847
+ message,
2848
+ status: "assigned",
2849
+ ...modeValidation.taskMode ? { taskMode: modeValidation.taskMode } : {},
2850
+ missionId,
2851
+ ...opts.assignedNodeId ? { targetNodeId: opts.assignedNodeId, assignedNodeId: opts.assignedNodeId } : {},
2852
+ ...opts.assignedSessionId ? { targetSessionId: opts.assignedSessionId, assignedSessionId: opts.assignedSessionId } : {},
2853
+ dispatchTimestamp: now,
2854
+ createdAt: now,
2855
+ updatedAt: now
2856
+ };
2857
+ MeshRuntimeStore.getInstance().insertQueueEntry(entry);
2858
+ return entry;
2859
+ });
2860
+ }
2829
2861
  function getQueue(meshId, opts) {
2830
2862
  return MeshRuntimeStore.getInstance().getQueueEntries(meshId, opts?.status?.length ? opts.status : void 0);
2831
2863
  }
@@ -4407,9 +4439,48 @@ function buildMeshAsyncRefineJobs(args) {
4407
4439
  return (Number.isFinite(bTime) ? bTime : 0) - (Number.isFinite(aTime) ? aTime : 0);
4408
4440
  });
4409
4441
  }
4442
+ function jobActivityTime(job) {
4443
+ const raw = job.lastUpdatedAt || job.completedAt || job.startedAt || "";
4444
+ const t = new Date(raw).getTime();
4445
+ return Number.isFinite(t) ? t : 0;
4446
+ }
4447
+ function summarizeMeshAsyncRefineJobs(jobs) {
4448
+ const activeJobs = [];
4449
+ const terminalJobs = [];
4450
+ for (const job of jobs) {
4451
+ if (TERMINAL_REFINE_STATUSES.has(job.status)) terminalJobs.push(job);
4452
+ else activeJobs.push(job);
4453
+ }
4454
+ let newest = 0;
4455
+ for (const job of jobs) newest = Math.max(newest, jobActivityTime(job));
4456
+ const cutoff = newest - STALE_TERMINAL_REFINE_WINDOW_MS;
4457
+ const terminalByRecency = [...terminalJobs].sort(
4458
+ (a, b) => jobActivityTime(b) - jobActivityTime(a)
4459
+ );
4460
+ const freshTerminal = terminalByRecency.filter((job) => jobActivityTime(job) >= cutoff).slice(0, RECENT_TERMINAL_REFINE_CAP);
4461
+ const freshTerminalIds = new Set(freshTerminal.map((job) => job.jobId));
4462
+ const byStatus = {};
4463
+ for (const job of activeJobs) {
4464
+ byStatus[job.status] = (byStatus[job.status] ?? 0) + 1;
4465
+ }
4466
+ for (const job of freshTerminal) {
4467
+ byStatus[job.status] = (byStatus[job.status] ?? 0) + 1;
4468
+ }
4469
+ const staleTerminal = terminalJobs.length - freshTerminalIds.size;
4470
+ return {
4471
+ total: activeJobs.length + freshTerminal.length,
4472
+ byStatus,
4473
+ staleTerminal,
4474
+ activeJobs
4475
+ };
4476
+ }
4477
+ var TERMINAL_REFINE_STATUSES, STALE_TERMINAL_REFINE_WINDOW_MS, RECENT_TERMINAL_REFINE_CAP;
4410
4478
  var init_mesh_refine_status = __esm({
4411
4479
  "src/mesh/mesh-refine-status.ts"() {
4412
4480
  "use strict";
4481
+ TERMINAL_REFINE_STATUSES = /* @__PURE__ */ new Set(["completed", "failed"]);
4482
+ STALE_TERMINAL_REFINE_WINDOW_MS = 6 * 60 * 60 * 1e3;
4483
+ RECENT_TERMINAL_REFINE_CAP = 8;
4413
4484
  }
4414
4485
  });
4415
4486
 
@@ -10407,6 +10478,26 @@ var init_cli_state_engine = __esm({
10407
10478
  // ── Approval ─────────────────────────────────────
10408
10479
  lastApprovalResolvedAt = 0;
10409
10480
  lastResolvedModalMessage = "";
10481
+ /**
10482
+ * Monotonic counter bumped every time the FSM *enters* waiting_approval
10483
+ * with a freshly captured modal (see `applyWaitingApproval`). It is the
10484
+ * single discriminator between "the same approval re-observed across TUI
10485
+ * paint flaps" and "a genuinely new, distinct approval".
10486
+ *
10487
+ * The message-equality cooldown below (`lastResolvedModalMessage`) cannot
10488
+ * tell these apart on its own: claude-cli routinely presents consecutive
10489
+ * approvals whose modal message text is identical (e.g. two back-to-back
10490
+ * Bash-command prompts). When that second approval arrived inside
10491
+ * `approvalCooldown`, the message-equality guard silently swallowed the
10492
+ * key write and the approval stuck forever — fatal under auto-approval.
10493
+ *
10494
+ * `approvalEntrySeq` increments on every fresh entry; `lastResolvedEntrySeq`
10495
+ * records which entry the cooldown belongs to. We only short-circuit the
10496
+ * write when we are still resolving *that same* entry — a new entry (new
10497
+ * seq) is always a real, distinct approval and must be written.
10498
+ */
10499
+ approvalEntrySeq = 0;
10500
+ lastResolvedEntrySeq = -1;
10410
10501
  /**
10411
10502
  * When the engine previously held a modal but the latest parse failed
10412
10503
  * to extract one, we record the timestamp here and only drop the modal
@@ -10512,6 +10603,7 @@ var init_cli_state_engine = __esm({
10512
10603
  if (parsed?.status === "waiting_approval" && parsedModal) {
10513
10604
  modal = parsedModal;
10514
10605
  this.activeModal = parsedModal;
10606
+ this.approvalEntrySeq++;
10515
10607
  if (this.currentStatus !== "waiting_approval") {
10516
10608
  this.setStatus("waiting_approval", "resolve_modal_parse");
10517
10609
  this.callbacks.onStatusChange();
@@ -10525,12 +10617,14 @@ var init_cli_state_engine = __esm({
10525
10617
  if (!modal || !buttonsValid) return;
10526
10618
  const currentModalMessage = typeof modal?.message === "string" ? modal.message.trim() : "";
10527
10619
  const inCooldown = !!this.lastApprovalResolvedAt && Date.now() - this.lastApprovalResolvedAt < this.timeouts.approvalCooldown;
10528
- if (inCooldown && currentModalMessage === this.lastResolvedModalMessage) return;
10620
+ const sameEntryReResolve = this.approvalEntrySeq === this.lastResolvedEntrySeq;
10621
+ if (inCooldown && sameEntryReResolve && currentModalMessage === this.lastResolvedModalMessage) return;
10529
10622
  this.clearIdleFinishCandidate("resolve_modal");
10530
- this.recordTrace("resolve_modal", { buttonIndex, activeModal: modal });
10623
+ this.recordTrace("resolve_modal", { buttonIndex, activeModal: modal, approvalEntrySeq: this.approvalEntrySeq });
10531
10624
  this.activeModal = null;
10532
10625
  this.lastApprovalResolvedAt = Date.now();
10533
10626
  this.lastResolvedModalMessage = currentModalMessage;
10627
+ this.lastResolvedEntrySeq = this.approvalEntrySeq;
10534
10628
  this.responseSettleIgnoreUntil = Date.now() + this.timeouts.outputSettle + 400;
10535
10629
  if (this.approvalExitTimeout) {
10536
10630
  clearTimeout(this.approvalExitTimeout);
@@ -10887,7 +10981,7 @@ var init_cli_state_engine = __esm({
10887
10981
  this.callbacks.onStatusChange();
10888
10982
  return;
10889
10983
  }
10890
- if (!inCooldown) {
10984
+ if (!inCooldown || modal) {
10891
10985
  if (!modal) {
10892
10986
  LOG.warn("CLI", `[${this.provider.type}] detectStatus=waiting_approval but parseApproval returned null; ignoring`);
10893
10987
  if (this.currentStatus === "waiting_approval" && this.activeModal) {
@@ -10910,6 +11004,7 @@ var init_cli_state_engine = __esm({
10910
11004
  const nextBtnCount = Array.isArray(modal.buttons) ? modal.buttons.length : 0;
10911
11005
  if (!prev || prevBtnCount !== nextBtnCount) {
10912
11006
  this.activeModal = modal;
11007
+ this.approvalEntrySeq++;
10913
11008
  this.callbacks.onStatusChange();
10914
11009
  }
10915
11010
  if (this.idleTimeout) clearTimeout(this.idleTimeout);
@@ -12105,6 +12200,7 @@ ${lastSnapshot}`;
12105
12200
  messages: [],
12106
12201
  workingDir: this.workingDir,
12107
12202
  activeModal: effectiveModal,
12203
+ approvalEntrySeq: this.engine.approvalEntrySeq,
12108
12204
  pendingOutboundCount: this.pendingOutboundQueue.length,
12109
12205
  pendingOutboundMessages: this.pendingOutboundQueue.map((message) => ({
12110
12206
  id: message.id,
@@ -13998,7 +14094,9 @@ __export(index_exports, {
13998
14094
  ProviderCliAdapter: () => ProviderCliAdapter,
13999
14095
  ProviderInstanceManager: () => ProviderInstanceManager,
14000
14096
  ProviderLoader: () => ProviderLoader,
14097
+ RECENT_TERMINAL_REFINE_CAP: () => RECENT_TERMINAL_REFINE_CAP,
14001
14098
  RawTerminalAttachment: () => RawTerminalAttachment,
14099
+ STALE_TERMINAL_REFINE_WINDOW_MS: () => STALE_TERMINAL_REFINE_WINDOW_MS,
14002
14100
  STANDALONE_CDP_SCAN_INTERVAL_MS: () => STANDALONE_CDP_SCAN_INTERVAL_MS,
14003
14101
  SessionHostPtyTransportFactory: () => SessionHostPtyTransportFactory,
14004
14102
  TerminalAdapter: () => TerminalAdapter,
@@ -14206,6 +14304,7 @@ __export(index_exports, {
14206
14304
  reconcileDirectDispatchCompletionFromTranscript: () => reconcileDirectDispatchCompletionFromTranscript,
14207
14305
  recordCompletionConflict: () => recordCompletionConflict,
14208
14306
  recordDebugTrace: () => recordDebugTrace,
14307
+ recordDirectDispatchTask: () => recordDirectDispatchTask,
14209
14308
  recordMeshToolCall: () => recordMeshToolCall,
14210
14309
  registerExtensionProviders: () => registerExtensionProviders,
14211
14310
  registerMeshCoordinator: () => registerMeshCoordinator,
@@ -14242,6 +14341,7 @@ __export(index_exports, {
14242
14341
  startLocalIpcServer: () => startLocalIpcServer,
14243
14342
  suggestMeshRefineConfig: () => suggestMeshRefineConfig,
14244
14343
  summarizeGitStatus: () => summarizeGitStatus,
14344
+ summarizeMeshAsyncRefineJobs: () => summarizeMeshAsyncRefineJobs,
14245
14345
  summarizeMeshMission: () => summarizeMeshMission,
14246
14346
  summarizeMissionTasks: () => summarizeMissionTasks,
14247
14347
  triggerMeshQueue: () => triggerMeshQueue,
@@ -16506,7 +16606,7 @@ async function runMeshWorktreeBootstrap(mesh, workspace) {
16506
16606
  if (!validation.valid) {
16507
16607
  return { status: "failed", required, configSource: loaded.path || loaded.source, configSourceType: "invalid", error: String(validation.rejectedCommands[0]?.reason || validation.errors.join("; ")), commandsRun: [] };
16508
16608
  }
16509
- const execFileAsync3 = (0, import_node_util3.promisify)(import_node_child_process3.execFile);
16609
+ const execFileAsync4 = (0, import_node_util3.promisify)(import_node_child_process3.execFile);
16510
16610
  const state = {
16511
16611
  status: "running",
16512
16612
  required,
@@ -16532,7 +16632,7 @@ async function runMeshWorktreeBootstrap(mesh, workspace) {
16532
16632
  const startedAt = Date.now();
16533
16633
  state.lastCommand = command.displayCommand;
16534
16634
  try {
16535
- const result = await execFileAsync3(command.command, command.args, {
16635
+ const result = await execFileAsync4(command.command, command.args, {
16536
16636
  cwd,
16537
16637
  encoding: "utf8",
16538
16638
  timeout: command.timeoutMs || DEFAULT_TIMEOUT_MS2,
@@ -31646,7 +31746,9 @@ var CliProviderInstance = class {
31646
31746
  if (buttonIndex < 0) {
31647
31747
  return autoApproveActive;
31648
31748
  }
31749
+ const approvalEntrySeq = typeof adapterStatus?.approvalEntrySeq === "number" ? adapterStatus.approvalEntrySeq : 0;
31649
31750
  const signature = [
31751
+ approvalEntrySeq,
31650
31752
  typeof modal?.message === "string" ? modal.message.trim() : "",
31651
31753
  buttons.join("|"),
31652
31754
  buttonIndex
@@ -37318,8 +37420,8 @@ var ProviderLoader = class _ProviderLoader {
37318
37420
  }
37319
37421
  const https = require("https");
37320
37422
  const { exec: exec7 } = require("child_process");
37321
- const { promisify: promisify7 } = require("util");
37322
- const execAsync5 = promisify7(exec7);
37423
+ const { promisify: promisify8 } = require("util");
37424
+ const execAsync5 = promisify8(exec7);
37323
37425
  const metaPath = path30.join(this.upstreamDir, _ProviderLoader.META_FILE);
37324
37426
  let prevEtag = "";
37325
37427
  let prevTimestamp = 0;
@@ -38599,14 +38701,101 @@ init_mesh_routing();
38599
38701
  init_mesh_host_ownership();
38600
38702
  init_mesh_fast_forward();
38601
38703
 
38602
- // src/mesh/preview-freshness.ts
38704
+ // src/mesh/mesh-refine-batch.ts
38603
38705
  var import_node_child_process4 = require("child_process");
38706
+ var import_node_util4 = require("util");
38707
+ var execFileAsync3 = (0, import_node_util4.promisify)(import_node_child_process4.execFile);
38708
+ var MAX_CHANGED_FILES2 = 500;
38709
+ function topLevel(path39) {
38710
+ const slash = path39.indexOf("/");
38711
+ return slash === -1 ? path39 : path39.slice(0, slash);
38712
+ }
38713
+ async function analyzeMeshRefineNodeChangeArea(args) {
38714
+ const { nodeId, workspace, branch, baseRef, branchRef, diffCwd, submodulePaths } = args;
38715
+ const base = {
38716
+ nodeId,
38717
+ workspace,
38718
+ branch,
38719
+ changedTopLevelPaths: [],
38720
+ changedFiles: [],
38721
+ touchedSubmodulePaths: [],
38722
+ touchesSubmodule: false,
38723
+ aheadCount: 0
38724
+ };
38725
+ try {
38726
+ let mergeBase = baseRef;
38727
+ try {
38728
+ const { stdout } = await execFileAsync3("git", ["merge-base", baseRef, branchRef], { cwd: diffCwd, encoding: "utf8" });
38729
+ const resolved = stdout.trim();
38730
+ if (resolved) mergeBase = resolved;
38731
+ } catch {
38732
+ }
38733
+ const { stdout: countStdout } = await execFileAsync3(
38734
+ "git",
38735
+ ["rev-list", "--count", `${mergeBase}..${branchRef}`],
38736
+ { cwd: diffCwd, encoding: "utf8" }
38737
+ );
38738
+ base.aheadCount = Number.parseInt(countStdout.trim(), 10) || 0;
38739
+ const { stdout: nameStdout } = await execFileAsync3(
38740
+ "git",
38741
+ ["diff", "--name-only", `${mergeBase}..${branchRef}`],
38742
+ { cwd: diffCwd, encoding: "utf8" }
38743
+ );
38744
+ const files = nameStdout.split("\n").map((line) => line.trim()).filter(Boolean).slice(0, MAX_CHANGED_FILES2);
38745
+ base.changedFiles = files;
38746
+ const topSet = /* @__PURE__ */ new Set();
38747
+ const submoduleSet = /* @__PURE__ */ new Set();
38748
+ for (const file of files) {
38749
+ const top = topLevel(file);
38750
+ topSet.add(top);
38751
+ if (submodulePaths.has(file) || submodulePaths.has(top)) {
38752
+ submoduleSet.add(submodulePaths.has(file) ? file : top);
38753
+ }
38754
+ }
38755
+ base.changedTopLevelPaths = [...topSet].sort();
38756
+ base.touchedSubmodulePaths = [...submoduleSet].sort();
38757
+ base.touchesSubmodule = submoduleSet.size > 0;
38758
+ return base;
38759
+ } catch (e) {
38760
+ base.error = e?.message || String(e);
38761
+ return base;
38762
+ }
38763
+ }
38764
+ function orderMeshRefineBatchNodes(changeAreas) {
38765
+ const areaById = {};
38766
+ for (const area of changeAreas) areaById[area.nodeId] = area;
38767
+ const ranked = [...changeAreas].sort((a, b) => {
38768
+ const aSub = a.touchesSubmodule ? 1 : 0;
38769
+ const bSub = b.touchesSubmodule ? 1 : 0;
38770
+ if (aSub !== bSub) return aSub - bSub;
38771
+ const aBreadth = a.changedTopLevelPaths.length;
38772
+ const bBreadth = b.changedTopLevelPaths.length;
38773
+ if (aBreadth !== bBreadth) return aBreadth - bBreadth;
38774
+ return a.nodeId.localeCompare(b.nodeId);
38775
+ });
38776
+ const rationale = [];
38777
+ const nonSub = ranked.filter((a) => !a.touchesSubmodule).map((a) => a.nodeId);
38778
+ const sub = ranked.filter((a) => a.touchesSubmodule).map((a) => a.nodeId);
38779
+ if (nonSub.length) {
38780
+ rationale.push(`Non-submodule nodes first (no submodule-main advance, conflict-free ordering): ${nonSub.join(", ")}`);
38781
+ }
38782
+ if (sub.length) {
38783
+ rationale.push(`Submodule-touching nodes last, serialized (each merge advances submodule main, forcing rebase of the next): ${sub.join(", ")}`);
38784
+ }
38785
+ for (const area of ranked) {
38786
+ if (area.error) rationale.push(`Node ${area.nodeId}: change-area analysis degraded (${area.error}); placed with neutral priority.`);
38787
+ }
38788
+ return { order: ranked.map((a) => a.nodeId), changeAreas: areaById, rationale };
38789
+ }
38790
+
38791
+ // src/mesh/preview-freshness.ts
38792
+ var import_node_child_process5 = require("child_process");
38604
38793
  var import_node_fs4 = require("fs");
38605
38794
  var import_node_path2 = require("path");
38606
38795
  var PREVIEW_DEPLOY_RECORD = ".adhdev/preview-deploy.json";
38607
38796
  function runGit2(repoRoot, args) {
38608
38797
  try {
38609
- return (0, import_node_child_process4.execFileSync)("git", args, {
38798
+ return (0, import_node_child_process5.execFileSync)("git", args, {
38610
38799
  cwd: repoRoot,
38611
38800
  encoding: "utf8",
38612
38801
  stdio: ["ignore", "pipe", "ignore"],
@@ -39374,7 +39563,7 @@ init_repo_mesh_types();
39374
39563
  var import_os3 = require("os");
39375
39564
  var import_path10 = require("path");
39376
39565
  var fs23 = __toESM(require("fs"));
39377
- var import_node_child_process5 = require("child_process");
39566
+ var import_node_child_process6 = require("child_process");
39378
39567
  var CHANNEL_NPM_TAG = { stable: "latest", preview: "next" };
39379
39568
  var CHANNEL_SERVER_URL = {
39380
39569
  stable: "https://api.adhf.dev",
@@ -40532,7 +40721,7 @@ function buildPatchEquivalenceSubmoduleConflictHint(repoRoot, baseHead, branchHe
40532
40721
  }
40533
40722
  function readChangedGitlinkPaths(repoRoot, fromRef, toRef) {
40534
40723
  try {
40535
- const output = (0, import_node_child_process5.execFileSync)("git", ["diff", "--raw", "--no-abbrev", fromRef, toRef], {
40724
+ const output = (0, import_node_child_process6.execFileSync)("git", ["diff", "--raw", "--no-abbrev", fromRef, toRef], {
40536
40725
  cwd: repoRoot,
40537
40726
  encoding: "utf8",
40538
40727
  maxBuffer: REFINE_PATCH_EQUIVALENCE_OUTPUT_LIMIT_BYTES
@@ -40556,7 +40745,7 @@ function readChangedGitlinkPaths(repoRoot, fromRef, toRef) {
40556
40745
  }
40557
40746
  function readTreeObject(repoRoot, ref, path39) {
40558
40747
  try {
40559
- const output = (0, import_node_child_process5.execFileSync)("git", ["ls-tree", ref, "--", path39], {
40748
+ const output = (0, import_node_child_process6.execFileSync)("git", ["ls-tree", ref, "--", path39], {
40560
40749
  cwd: repoRoot,
40561
40750
  encoding: "utf8",
40562
40751
  maxBuffer: 1024 * 1024
@@ -40590,10 +40779,10 @@ async function alignRefinerySubmodulesAfterMerge(repoRoot, previousBaseHead, cur
40590
40779
  }
40591
40780
  const commandArgs = ["submodule", "update", "--init", "--recursive", "--", ...updatePaths];
40592
40781
  try {
40593
- const { execFile: execFile4 } = await import("child_process");
40594
- const { promisify: promisify7 } = await import("util");
40595
- const execFileAsync3 = promisify7(execFile4);
40596
- const result = await execFileAsync3("git", commandArgs, {
40782
+ const { execFile: execFile5 } = await import("child_process");
40783
+ const { promisify: promisify8 } = await import("util");
40784
+ const execFileAsync4 = promisify8(execFile5);
40785
+ const result = await execFileAsync4("git", commandArgs, {
40597
40786
  cwd: repoRoot,
40598
40787
  encoding: "utf8",
40599
40788
  maxBuffer: REFINE_PATCH_EQUIVALENCE_OUTPUT_LIMIT_BYTES,
@@ -40636,11 +40825,11 @@ async function runMeshRefineSubmoduleReachabilityGate(repoRoot, mergedTree, opti
40636
40825
  const startedAt = Date.now();
40637
40826
  const entries = [];
40638
40827
  try {
40639
- const { execFile: execFile4 } = await import("child_process");
40640
- const { promisify: promisify7 } = await import("util");
40641
- const execFileAsync3 = promisify7(execFile4);
40828
+ const { execFile: execFile5 } = await import("child_process");
40829
+ const { promisify: promisify8 } = await import("util");
40830
+ const execFileAsync4 = promisify8(execFile5);
40642
40831
  const runGit3 = async (cwd, args) => {
40643
- const { stdout } = await execFileAsync3("git", args, {
40832
+ const { stdout } = await execFileAsync4("git", args, {
40644
40833
  cwd,
40645
40834
  encoding: "utf8",
40646
40835
  timeout: 3e4,
@@ -40655,7 +40844,7 @@ async function runMeshRefineSubmoduleReachabilityGate(repoRoot, mergedTree, opti
40655
40844
  };
40656
40845
  const publishCommitToRemoteMain = async (submodulePath, commit, branch = "main") => {
40657
40846
  const refspec = `${commit}:refs/heads/${branch}`;
40658
- const { stdout, stderr } = await execFileAsync3("git", ["push", "origin", refspec], {
40847
+ const { stdout, stderr } = await execFileAsync4("git", ["push", "origin", refspec], {
40659
40848
  cwd: submodulePath,
40660
40849
  encoding: "utf8",
40661
40850
  timeout: 3e4,
@@ -40840,9 +41029,9 @@ function buildMeshRefineValidationPlan(mesh, workspace) {
40840
41029
  };
40841
41030
  }
40842
41031
  async function runMeshRefineValidationGate(mesh, workspace, opts) {
40843
- const { execFile: execFile4 } = await import("child_process");
40844
- const { promisify: promisify7 } = await import("util");
40845
- const execFileAsync3 = promisify7(execFile4);
41032
+ const { execFile: execFile5 } = await import("child_process");
41033
+ const { promisify: promisify8 } = await import("util");
41034
+ const execFileAsync4 = promisify8(execFile5);
40846
41035
  const selection = resolveMeshRefineValidationPlan(mesh, workspace);
40847
41036
  const summary = {
40848
41037
  status: "skipped",
@@ -40936,7 +41125,7 @@ async function runMeshRefineValidationGate(mesh, workspace, opts) {
40936
41125
  const cwd = candidate.cwd ? (0, import_path10.resolve)(workspace, candidate.cwd) : workspace;
40937
41126
  const timeout = candidate.timeoutMs || REFINE_VALIDATION_TIMEOUT_MS;
40938
41127
  try {
40939
- const result = await execFileAsync3(candidate.command, candidate.args, {
41128
+ const result = await execFileAsync4(candidate.command, candidate.args, {
40940
41129
  cwd,
40941
41130
  encoding: "utf8",
40942
41131
  timeout,
@@ -40978,7 +41167,7 @@ async function runMeshRefineValidationGate(mesh, workspace, opts) {
40978
41167
  return summary;
40979
41168
  }
40980
41169
  try {
40981
- const result = await execFileAsync3(candidate.command, candidate.args, {
41170
+ const result = await execFileAsync4(candidate.command, candidate.args, {
40982
41171
  cwd,
40983
41172
  encoding: "utf8",
40984
41173
  timeout,
@@ -41546,19 +41735,19 @@ var DaemonCommandRouter = class {
41546
41735
  const isSubmoduleGuard = /working trees containing submodules cannot be moved or removed/i.test(message);
41547
41736
  const submoduleForceBlocked = isSubmoduleGuard && !forceFallbackConvergence.allow;
41548
41737
  if (isSubmoduleGuard && forceFallbackConvergence.allow) {
41549
- const { execFile: execFile4 } = await import("child_process");
41550
- const { promisify: promisify7 } = await import("util");
41551
- const execFileAsync3 = promisify7(execFile4);
41738
+ const { execFile: execFile5 } = await import("child_process");
41739
+ const { promisify: promisify8 } = await import("util");
41740
+ const execFileAsync4 = promisify8(execFile5);
41552
41741
  const GIT_TIMEOUT_CLEANUP = 3e4;
41553
41742
  const GIT_MAX_BUFFER_CLEANUP = 4 * 1024 * 1024;
41554
41743
  try {
41555
- await execFileAsync3("git", ["-C", workspace, "submodule", "deinit", "--all", "-f"], {
41744
+ await execFileAsync4("git", ["-C", workspace, "submodule", "deinit", "--all", "-f"], {
41556
41745
  encoding: "utf8",
41557
41746
  timeout: GIT_TIMEOUT_CLEANUP,
41558
41747
  maxBuffer: GIT_MAX_BUFFER_CLEANUP,
41559
41748
  windowsHide: true
41560
41749
  });
41561
- await execFileAsync3("git", ["worktree", "remove", "--force", workspace], {
41750
+ await execFileAsync4("git", ["worktree", "remove", "--force", workspace], {
41562
41751
  cwd: repoRoot,
41563
41752
  encoding: "utf8",
41564
41753
  timeout: GIT_TIMEOUT_CLEANUP,
@@ -41577,7 +41766,7 @@ var DaemonCommandRouter = class {
41577
41766
  } catch (deinitError) {
41578
41767
  try {
41579
41768
  fs23.rmSync(workspace, { recursive: true, force: true });
41580
- await execFileAsync3("git", ["worktree", "prune"], {
41769
+ await execFileAsync4("git", ["worktree", "prune"], {
41581
41770
  cwd: repoRoot,
41582
41771
  encoding: "utf8",
41583
41772
  timeout: GIT_TIMEOUT_CLEANUP,
@@ -41621,11 +41810,11 @@ var DaemonCommandRouter = class {
41621
41810
  if (refinedConvergence === "merged_pushed" || refinedConvergence === "merged_to_main") {
41622
41811
  return { allow: true, status: refinedConvergence, source: "node_refine_state" };
41623
41812
  }
41624
- const { execFile: execFile4 } = await import("child_process");
41625
- const { promisify: promisify7 } = await import("util");
41626
- const execFileAsync3 = promisify7(execFile4);
41813
+ const { execFile: execFile5 } = await import("child_process");
41814
+ const { promisify: promisify8 } = await import("util");
41815
+ const execFileAsync4 = promisify8(execFile5);
41627
41816
  const runGit3 = async (gitArgs, cwd) => {
41628
- const { stdout } = await execFileAsync3("git", gitArgs, {
41817
+ const { stdout } = await execFileAsync4("git", gitArgs, {
41629
41818
  cwd,
41630
41819
  encoding: "utf8",
41631
41820
  timeout: 3e4,
@@ -42097,30 +42286,30 @@ var DaemonCommandRouter = class {
42097
42286
  const sourceNode = node.clonedFromNodeId ? mesh?.nodes.find((n) => n.id === node.clonedFromNodeId || n.nodeId === node.clonedFromNodeId) : mesh?.nodes.find((n) => !n.isLocalWorktree);
42098
42287
  const repoRoot = sourceNode?.repoRoot || sourceNode?.workspace;
42099
42288
  if (!repoRoot) return { success: false, error: "Source node repoRoot not found", refineStages };
42100
- const { execFile: execFile4 } = await import("child_process");
42101
- const { promisify: promisify7 } = await import("util");
42102
- const execFileAsync3 = promisify7(execFile4);
42289
+ const { execFile: execFile5 } = await import("child_process");
42290
+ const { promisify: promisify8 } = await import("util");
42291
+ const execFileAsync4 = promisify8(execFile5);
42103
42292
  const resolveStarted = Date.now();
42104
- const { stdout: branchStdout } = await execFileAsync3("git", ["branch", "--show-current"], { cwd: node.workspace, encoding: "utf8" });
42293
+ const { stdout: branchStdout } = await execFileAsync4("git", ["branch", "--show-current"], { cwd: node.workspace, encoding: "utf8" });
42105
42294
  const branch = branchStdout.trim();
42106
42295
  if (!branch) return { success: false, error: "Could not determine branch of the worktree node", refineStages };
42107
- const { stdout: baseBranchStdout } = await execFileAsync3("git", ["branch", "--show-current"], { cwd: repoRoot, encoding: "utf8" });
42296
+ const { stdout: baseBranchStdout } = await execFileAsync4("git", ["branch", "--show-current"], { cwd: repoRoot, encoding: "utf8" });
42108
42297
  const baseBranch = baseBranchStdout.trim();
42109
42298
  let fetchWarning;
42110
42299
  try {
42111
- await execFileAsync3("git", ["fetch", "origin", baseBranch], { cwd: repoRoot, encoding: "utf8" });
42300
+ await execFileAsync4("git", ["fetch", "origin", baseBranch], { cwd: repoRoot, encoding: "utf8" });
42112
42301
  } catch (e) {
42113
42302
  fetchWarning = `git fetch origin ${baseBranch} failed (proceeding with local HEAD): ${e?.message}`;
42114
42303
  }
42115
42304
  let baseHeadRaw;
42116
42305
  try {
42117
- const { stdout } = await execFileAsync3("git", ["rev-parse", `origin/${baseBranch}`], { cwd: repoRoot, encoding: "utf8" });
42306
+ const { stdout } = await execFileAsync4("git", ["rev-parse", `origin/${baseBranch}`], { cwd: repoRoot, encoding: "utf8" });
42118
42307
  baseHeadRaw = stdout.trim();
42119
42308
  } catch {
42120
- const { stdout: localHead } = await execFileAsync3("git", ["rev-parse", "HEAD"], { cwd: repoRoot, encoding: "utf8" });
42309
+ const { stdout: localHead } = await execFileAsync4("git", ["rev-parse", "HEAD"], { cwd: repoRoot, encoding: "utf8" });
42121
42310
  baseHeadRaw = localHead.trim();
42122
42311
  }
42123
- const { stdout: branchHeadStdout } = await execFileAsync3("git", ["rev-parse", branch], { cwd: node.workspace, encoding: "utf8" });
42312
+ const { stdout: branchHeadStdout } = await execFileAsync4("git", ["rev-parse", branch], { cwd: node.workspace, encoding: "utf8" });
42124
42313
  const baseHead = baseHeadRaw;
42125
42314
  let branchHead = branchHeadStdout.trim();
42126
42315
  recordMeshRefineStage(refineStages, "resolve_refs", "passed", resolveStarted, { branch, baseBranch, baseHead, branchHead, ...fetchWarning ? { fetchWarning } : {} });
@@ -42208,7 +42397,7 @@ ${tail}` : ""
42208
42397
  let didAutoRebase = false;
42209
42398
  let isBehindBase = false;
42210
42399
  try {
42211
- (0, import_node_child_process5.execFileSync)("git", ["merge-base", "--is-ancestor", branchHead, baseHead], {
42400
+ (0, import_node_child_process6.execFileSync)("git", ["merge-base", "--is-ancestor", branchHead, baseHead], {
42212
42401
  cwd: node.workspace,
42213
42402
  stdio: "ignore"
42214
42403
  });
@@ -42218,11 +42407,11 @@ ${tail}` : ""
42218
42407
  if (isBehindBase) {
42219
42408
  const autoRebaseStarted = Date.now();
42220
42409
  try {
42221
- (0, import_node_child_process5.execFileSync)("git", ["rebase", baseHead], {
42410
+ (0, import_node_child_process6.execFileSync)("git", ["rebase", baseHead], {
42222
42411
  cwd: node.workspace,
42223
42412
  stdio: ["ignore", "pipe", "pipe"]
42224
42413
  });
42225
- const { stdout: rebasedHeadStdout } = await execFileAsync3("git", ["rev-parse", "HEAD"], { cwd: node.workspace, encoding: "utf8" });
42414
+ const { stdout: rebasedHeadStdout } = await execFileAsync4("git", ["rev-parse", "HEAD"], { cwd: node.workspace, encoding: "utf8" });
42226
42415
  branchHead = rebasedHeadStdout.trim();
42227
42416
  const rebasedPatchEquivalence = await runMeshRefinePatchEquivalenceGate(repoRoot, baseHead, branchHead);
42228
42417
  recordMeshRefineStage(refineStages, "patch_equivalence_after_auto_rebase", rebasedPatchEquivalence.status, autoRebaseStarted, {
@@ -42259,7 +42448,7 @@ ${tail}` : ""
42259
42448
  }
42260
42449
  } catch (rebaseErr) {
42261
42450
  try {
42262
- (0, import_node_child_process5.execFileSync)("git", ["rebase", "--abort"], { cwd: node.workspace, stdio: "ignore" });
42451
+ (0, import_node_child_process6.execFileSync)("git", ["rebase", "--abort"], { cwd: node.workspace, stdio: "ignore" });
42263
42452
  } catch {
42264
42453
  }
42265
42454
  recordMeshRefineStage(refineStages, "patch_equivalence_after_auto_rebase", "failed", autoRebaseStarted, {
@@ -42466,7 +42655,7 @@ ${tail}` : ""
42466
42655
  let mergeResult;
42467
42656
  const mergeStarted = Date.now();
42468
42657
  try {
42469
- const result = await execFileAsync3("git", ["merge", "--no-ff", branch, "-m", `Auto-merge branch '${branch}' via Refinery`], { cwd: repoRoot, encoding: "utf8" });
42658
+ const result = await execFileAsync4("git", ["merge", "--no-ff", branch, "-m", `Auto-merge branch '${branch}' via Refinery`], { cwd: repoRoot, encoding: "utf8" });
42470
42659
  mergeResult = {
42471
42660
  stdout: truncateValidationOutput(result.stdout),
42472
42661
  stderr: truncateValidationOutput(result.stderr),
@@ -42600,7 +42789,7 @@ ${tail}` : ""
42600
42789
  if (!requireApprovalForPush) {
42601
42790
  const pushStarted = Date.now();
42602
42791
  try {
42603
- await execFileAsync3("git", ["push", "origin", baseBranch], { cwd: repoRoot, encoding: "utf8" });
42792
+ await execFileAsync4("git", ["push", "origin", baseBranch], { cwd: repoRoot, encoding: "utf8" });
42604
42793
  pushResult = { pushed: true, remote: "origin", branch: baseBranch, durationMs: Date.now() - pushStarted };
42605
42794
  recordMeshRefineStage(refineStages, "push", "passed", pushStarted, pushResult);
42606
42795
  finalBranchConvergenceState.status = "merged_pushed";
@@ -42641,6 +42830,223 @@ ${tail}` : ""
42641
42830
  return { success: false, error: e.message, refineStages };
42642
42831
  }
42643
42832
  }
42833
+ /**
42834
+ * Batch refinery: converge multiple sibling worktree nodes onto the base branch
42835
+ * in one sequential pipeline, absorbing the rebase + patch-equivalence churn that
42836
+ * arises when several siblings touch the same submodule.
42837
+ *
42838
+ * Reuses executeMeshRefineNodeSynchronously per node — every node goes through the
42839
+ * exact same validation / patch-equivalence / submodule-reachability / merge / cleanup
42840
+ * gates, including its built-in auto-rebase onto fresh origin/<base>. Because each
42841
+ * node fetches origin/<base> at the start of its own refine, a node merged earlier in
42842
+ * the batch advances the base, and the next node's refine auto-rebases onto it before
42843
+ * re-running patch-equivalence. No force-push, no reset — conflicting nodes are
42844
+ * isolated as blocked_review while the rest of the batch proceeds.
42845
+ */
42846
+ async batchRefineMeshNodes(meshId, requestedNodeIds, args) {
42847
+ const meshRecord = await this.getMeshForCommand(meshId, args?.inlineMesh, { preferInline: true });
42848
+ const mesh = meshRecord?.mesh;
42849
+ if (!mesh) return { success: false, error: `Mesh '${meshId}' not found` };
42850
+ const allNodes = Array.isArray(mesh.nodes) ? mesh.nodes : [];
42851
+ const isConvergeable = (n) => n?.isLocalWorktree && typeof n.workspace === "string" && n.workspace;
42852
+ let targetNodes;
42853
+ if (Array.isArray(requestedNodeIds) && requestedNodeIds.length > 0) {
42854
+ targetNodes = [];
42855
+ const missing = [];
42856
+ const nonWorktree = [];
42857
+ for (const nodeId of requestedNodeIds) {
42858
+ const node = allNodes.find((n) => n.id === nodeId || n.nodeId === nodeId);
42859
+ if (!node) {
42860
+ missing.push(nodeId);
42861
+ continue;
42862
+ }
42863
+ if (!isConvergeable(node)) {
42864
+ nonWorktree.push(nodeId);
42865
+ continue;
42866
+ }
42867
+ targetNodes.push(node);
42868
+ }
42869
+ if (missing.length || nonWorktree.length) {
42870
+ return {
42871
+ success: false,
42872
+ error: "One or more requested nodes are not convergeable local worktree nodes.",
42873
+ ...missing.length ? { missingNodeIds: missing } : {},
42874
+ ...nonWorktree.length ? { nonWorktreeNodeIds: nonWorktree } : {}
42875
+ };
42876
+ }
42877
+ } else {
42878
+ targetNodes = allNodes.filter(isConvergeable);
42879
+ }
42880
+ if (targetNodes.length === 0) {
42881
+ return { success: true, batch: true, dryRun: args?.dryRun !== false, nodeCount: 0, order: [], results: [], note: "No convergeable local worktree nodes found." };
42882
+ }
42883
+ const { execFile: execFile5 } = await import("child_process");
42884
+ const { promisify: promisify8 } = await import("util");
42885
+ const execFileAsync4 = promisify8(execFile5);
42886
+ const resolveRepoRootFor = (node) => {
42887
+ const sourceNode = node.clonedFromNodeId ? allNodes.find((n) => n.id === node.clonedFromNodeId || n.nodeId === node.clonedFromNodeId) : allNodes.find((n) => !n.isLocalWorktree);
42888
+ return sourceNode?.repoRoot || sourceNode?.workspace;
42889
+ };
42890
+ const repoRootBaseRef = /* @__PURE__ */ new Map();
42891
+ const submodulePathsByRepoRoot = /* @__PURE__ */ new Map();
42892
+ const resolveBaseRef = async (repoRoot) => {
42893
+ const cached = repoRootBaseRef.get(repoRoot);
42894
+ if (cached) return cached;
42895
+ let baseBranch = "main";
42896
+ try {
42897
+ const { stdout } = await execFileAsync4("git", ["branch", "--show-current"], { cwd: repoRoot, encoding: "utf8" });
42898
+ if (stdout.trim()) baseBranch = stdout.trim();
42899
+ } catch {
42900
+ }
42901
+ let baseRef = "HEAD";
42902
+ try {
42903
+ await execFileAsync4("git", ["fetch", "origin", baseBranch], { cwd: repoRoot, encoding: "utf8" });
42904
+ } catch {
42905
+ }
42906
+ try {
42907
+ const { stdout } = await execFileAsync4("git", ["rev-parse", `origin/${baseBranch}`], { cwd: repoRoot, encoding: "utf8" });
42908
+ baseRef = stdout.trim();
42909
+ } catch {
42910
+ try {
42911
+ const { stdout } = await execFileAsync4("git", ["rev-parse", "HEAD"], { cwd: repoRoot, encoding: "utf8" });
42912
+ baseRef = stdout.trim();
42913
+ } catch {
42914
+ }
42915
+ }
42916
+ repoRootBaseRef.set(repoRoot, baseRef);
42917
+ return baseRef;
42918
+ };
42919
+ const changeAreas = [];
42920
+ for (const node of targetNodes) {
42921
+ const repoRoot = resolveRepoRootFor(node);
42922
+ let branch = typeof node.worktreeBranch === "string" ? node.worktreeBranch : "";
42923
+ try {
42924
+ const { stdout } = await execFileAsync4("git", ["branch", "--show-current"], { cwd: node.workspace, encoding: "utf8" });
42925
+ if (stdout.trim()) branch = stdout.trim();
42926
+ } catch {
42927
+ }
42928
+ if (!repoRoot || !branch) {
42929
+ changeAreas.push({
42930
+ nodeId: node.id,
42931
+ workspace: node.workspace,
42932
+ branch: branch || "(unknown)",
42933
+ changedTopLevelPaths: [],
42934
+ changedFiles: [],
42935
+ touchedSubmodulePaths: [],
42936
+ touchesSubmodule: false,
42937
+ aheadCount: 0,
42938
+ error: !repoRoot ? "source repoRoot not found" : "branch not resolved"
42939
+ });
42940
+ continue;
42941
+ }
42942
+ if (!submodulePathsByRepoRoot.has(repoRoot)) {
42943
+ let subPaths = /* @__PURE__ */ new Set();
42944
+ try {
42945
+ const { stdout } = await execFileAsync4("git", ["config", "--file", ".gitmodules", "--get-regexp", "path"], { cwd: repoRoot, encoding: "utf8" });
42946
+ for (const line of stdout.split("\n")) {
42947
+ const trimmed = line.trim();
42948
+ const spaceIdx = trimmed.indexOf(" ");
42949
+ if (spaceIdx === -1) continue;
42950
+ const value = trimmed.slice(spaceIdx + 1).trim();
42951
+ if (value) subPaths.add(value);
42952
+ }
42953
+ } catch {
42954
+ subPaths = /* @__PURE__ */ new Set();
42955
+ }
42956
+ submodulePathsByRepoRoot.set(repoRoot, subPaths);
42957
+ }
42958
+ const baseRef = await resolveBaseRef(repoRoot);
42959
+ let branchRef = branch;
42960
+ try {
42961
+ const { stdout } = await execFileAsync4("git", ["rev-parse", branch], { cwd: node.workspace, encoding: "utf8" });
42962
+ branchRef = stdout.trim() || branch;
42963
+ } catch {
42964
+ }
42965
+ changeAreas.push(await analyzeMeshRefineNodeChangeArea({
42966
+ nodeId: node.id,
42967
+ workspace: node.workspace,
42968
+ branch,
42969
+ baseRef,
42970
+ branchRef,
42971
+ diffCwd: node.workspace,
42972
+ submodulePaths: submodulePathsByRepoRoot.get(repoRoot)
42973
+ }));
42974
+ }
42975
+ const ordering = orderMeshRefineBatchNodes(changeAreas);
42976
+ const orderedNodes = ordering.order.map((nodeId) => targetNodes.find((n) => n.id === nodeId || n.nodeId === nodeId)).filter((n) => !!n);
42977
+ const dryRun = args?.dryRun !== false && args?.execute !== true;
42978
+ if (dryRun) {
42979
+ return {
42980
+ success: true,
42981
+ batch: true,
42982
+ dryRun: true,
42983
+ nodeCount: orderedNodes.length,
42984
+ order: ordering.order,
42985
+ orderingRationale: ordering.rationale,
42986
+ changeAreas: ordering.changeAreas,
42987
+ plan: orderedNodes.map((node) => ({
42988
+ nodeId: node.id,
42989
+ workspace: node.workspace,
42990
+ validationPlan: buildMeshRefineValidationPlan(mesh, node.workspace),
42991
+ mergeWillRun: false
42992
+ })),
42993
+ note: "Dry-run: no validation, rebase, or merge was executed. Re-run with execute=true to converge nodes in this order."
42994
+ };
42995
+ }
42996
+ const results = [];
42997
+ for (const node of orderedNodes) {
42998
+ let result;
42999
+ try {
43000
+ result = await this.executeMeshRefineNodeSynchronously(meshId, node.id, args);
43001
+ } catch (e) {
43002
+ result = { success: false, error: e?.message || String(e) };
43003
+ }
43004
+ const code = typeof result.code === "string" ? result.code : "";
43005
+ let convergence;
43006
+ if (code === "already_merged" && result.alreadyMergedViaOtherPath) {
43007
+ convergence = "skipped_patch_equivalent";
43008
+ } else if (result.success === true) {
43009
+ convergence = "merged_to_main";
43010
+ } else if (code === "merge_failed") {
43011
+ convergence = "not_mergeable";
43012
+ } else {
43013
+ convergence = "blocked_review";
43014
+ }
43015
+ const fbcs = result.finalBranchConvergenceState && typeof result.finalBranchConvergenceState === "object" ? result.finalBranchConvergenceState : void 0;
43016
+ const stage = Array.isArray(result.refineStages) ? result.refineStages.filter((s) => s.status === "failed").map((s) => s.stage).filter(Boolean).pop() : void 0;
43017
+ results.push({
43018
+ nodeId: node.id,
43019
+ workspace: node.workspace,
43020
+ convergence,
43021
+ ...code ? { code } : {},
43022
+ ...typeof result.blockedReason === "string" ? { reason: result.blockedReason } : {},
43023
+ ...stage ? { stage } : {},
43024
+ ...typeof result.error === "string" ? { error: result.error } : {},
43025
+ ...fbcs ? { finalBranchConvergenceState: fbcs } : {}
43026
+ });
43027
+ }
43028
+ const summary = {
43029
+ merged: results.filter((r) => r.convergence === "merged_to_main").length,
43030
+ skipped: results.filter((r) => r.convergence === "skipped_patch_equivalent").length,
43031
+ blocked: results.filter((r) => r.convergence === "blocked_review").length,
43032
+ notMergeable: results.filter((r) => r.convergence === "not_mergeable").length
43033
+ };
43034
+ const allConverged = summary.blocked === 0 && summary.notMergeable === 0;
43035
+ return {
43036
+ success: true,
43037
+ batch: true,
43038
+ dryRun: false,
43039
+ nodeCount: orderedNodes.length,
43040
+ order: ordering.order,
43041
+ orderingRationale: ordering.rationale,
43042
+ summary,
43043
+ allConverged,
43044
+ results,
43045
+ ...allConverged ? {} : {
43046
+ nextStep: "Resolve blocked_review / not_mergeable nodes manually (see per-node code/stage/error), then re-run mesh_refine_batch for the remaining nodes."
43047
+ }
43048
+ };
43049
+ }
42644
43050
  async finishMeshRefineJob(handle, args) {
42645
43051
  const key = this.buildRefineJobKey(handle.meshId, handle.targetNodeId);
42646
43052
  let result;
@@ -44184,6 +44590,12 @@ ${tail}` : ""
44184
44590
  if (!meshId || !nodeId) return { success: false, error: "meshId and nodeId required" };
44185
44591
  return this.startMeshRefineJob(meshId, nodeId, args);
44186
44592
  }
44593
+ case "batch_refine_mesh_nodes": {
44594
+ const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
44595
+ if (!meshId) return { success: false, error: "meshId required" };
44596
+ const requestedNodeIds = Array.isArray(args?.nodeIds) ? args.nodeIds.filter((v) => typeof v === "string" && v.trim().length > 0).map((v) => v.trim()) : void 0;
44597
+ return this.batchRefineMeshNodes(meshId, requestedNodeIds, args);
44598
+ }
44187
44599
  case "remove_mesh_node": {
44188
44600
  const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
44189
44601
  const nodeId = typeof args?.nodeId === "string" ? args.nodeId.trim() : "";
@@ -54140,7 +54552,9 @@ var V1_CONTRACT_VERSION = "1.0.0";
54140
54552
  ProviderCliAdapter,
54141
54553
  ProviderInstanceManager,
54142
54554
  ProviderLoader,
54555
+ RECENT_TERMINAL_REFINE_CAP,
54143
54556
  RawTerminalAttachment,
54557
+ STALE_TERMINAL_REFINE_WINDOW_MS,
54144
54558
  STANDALONE_CDP_SCAN_INTERVAL_MS,
54145
54559
  SessionHostPtyTransportFactory,
54146
54560
  TerminalAdapter,
@@ -54348,6 +54762,7 @@ var V1_CONTRACT_VERSION = "1.0.0";
54348
54762
  reconcileDirectDispatchCompletionFromTranscript,
54349
54763
  recordCompletionConflict,
54350
54764
  recordDebugTrace,
54765
+ recordDirectDispatchTask,
54351
54766
  recordMeshToolCall,
54352
54767
  registerExtensionProviders,
54353
54768
  registerMeshCoordinator,
@@ -54384,6 +54799,7 @@ var V1_CONTRACT_VERSION = "1.0.0";
54384
54799
  startLocalIpcServer,
54385
54800
  suggestMeshRefineConfig,
54386
54801
  summarizeGitStatus,
54802
+ summarizeMeshAsyncRefineJobs,
54387
54803
  summarizeMeshMission,
54388
54804
  summarizeMissionTasks,
54389
54805
  triggerMeshQueue,