@adhdev/daemon-core 0.9.82-rc.59 → 0.9.82-rc.60

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.
@@ -89,6 +89,10 @@ export declare class DaemonCommandRouter {
89
89
  private inlineMeshCache;
90
90
  /** Coordinator-owned whole-mesh aggregate status snapshots. Browser callers read this by default. */
91
91
  private aggregateMeshStatusCache;
92
+ /** In-memory async Refinery jobs keyed by meshId:nodeId to reject/return duplicate in-flight requests. */
93
+ private runningRefineJobs;
94
+ /** Terminal async Refinery jobs preserve a clear answer after the worktree node has been removed. */
95
+ private terminalRefineJobs;
92
96
  constructor(deps: CommandRouterDeps);
93
97
  private cloneJsonValue;
94
98
  private hydrateCachedAggregateMeshStatusFromInline;
@@ -121,6 +125,13 @@ export declare class DaemonCommandRouter {
121
125
  * @param source Log source ('ws' | 'p2p' | 'standalone' | etc.)
122
126
  */
123
127
  execute(cmd: string, args: any, source?: string): Promise<CommandRouterResult>;
128
+ private buildRefineJobKey;
129
+ private buildRefineJobHandle;
130
+ private queueRefineJobEvent;
131
+ private appendRefineJobLedger;
132
+ private executeMeshRefineNodeSynchronously;
133
+ private finishMeshRefineJob;
134
+ private startMeshRefineJob;
124
135
  /**
125
136
  * Daemon-level command execution (IDE start/stop/restart, CLI, detect, logs).
126
137
  * Returns null if not handled at this level → caller delegates to CommandHandler.
package/dist/index.js CHANGED
@@ -26254,6 +26254,10 @@ var DaemonCommandRouter = class {
26254
26254
  inlineMeshCache = /* @__PURE__ */ new Map();
26255
26255
  /** Coordinator-owned whole-mesh aggregate status snapshots. Browser callers read this by default. */
26256
26256
  aggregateMeshStatusCache = /* @__PURE__ */ new Map();
26257
+ /** In-memory async Refinery jobs keyed by meshId:nodeId to reject/return duplicate in-flight requests. */
26258
+ runningRefineJobs = /* @__PURE__ */ new Map();
26259
+ /** Terminal async Refinery jobs preserve a clear answer after the worktree node has been removed. */
26260
+ terminalRefineJobs = /* @__PURE__ */ new Map();
26257
26261
  constructor(deps) {
26258
26262
  this.deps = deps;
26259
26263
  }
@@ -26883,6 +26887,340 @@ var DaemonCommandRouter = class {
26883
26887
  throw e;
26884
26888
  }
26885
26889
  }
26890
+ buildRefineJobKey(meshId, nodeId) {
26891
+ return `${meshId}:${nodeId}`;
26892
+ }
26893
+ buildRefineJobHandle(args) {
26894
+ return {
26895
+ success: true,
26896
+ async: true,
26897
+ status: args.status || "accepted",
26898
+ jobId: args.jobId || `refine_${createInteractionId()}`,
26899
+ interactionId: args.interactionId || createInteractionId(),
26900
+ meshId: args.meshId,
26901
+ nodeId: args.nodeId,
26902
+ targetNodeId: args.nodeId,
26903
+ targetDaemonId: readStringValue(args.node?.daemonId),
26904
+ workspace: readStringValue(args.node?.workspace),
26905
+ startedAt: args.startedAt || (/* @__PURE__ */ new Date()).toISOString(),
26906
+ ...args.completedAt ? { completedAt: args.completedAt } : {},
26907
+ eventDelivery: { pendingEvents: true, ledger: true },
26908
+ evidence: {
26909
+ pendingEventsCommand: "get_pending_mesh_events",
26910
+ ledgerCommand: "get_mesh_ledger_slice",
26911
+ taskHistoryKind: args.status === "completed" ? "task_completed" : args.status === "failed" ? "task_failed" : "task_dispatched"
26912
+ }
26913
+ };
26914
+ }
26915
+ queueRefineJobEvent(event, handle, result) {
26916
+ queuePendingMeshCoordinatorEvent({
26917
+ event,
26918
+ meshId: handle.meshId,
26919
+ nodeLabel: handle.targetNodeId,
26920
+ nodeId: handle.targetNodeId,
26921
+ workspace: handle.workspace,
26922
+ metadataEvent: {
26923
+ source: "refine_mesh_node_async_job",
26924
+ jobId: handle.jobId,
26925
+ interactionId: handle.interactionId,
26926
+ meshId: handle.meshId,
26927
+ nodeId: handle.targetNodeId,
26928
+ targetDaemonId: handle.targetDaemonId,
26929
+ workspace: handle.workspace,
26930
+ status: handle.status,
26931
+ startedAt: handle.startedAt,
26932
+ completedAt: handle.completedAt,
26933
+ ...result ? { result } : {}
26934
+ },
26935
+ queuedAt: Date.now()
26936
+ });
26937
+ }
26938
+ async appendRefineJobLedger(kind, handle, result) {
26939
+ try {
26940
+ const { appendLedgerEntry: appendLedgerEntry2 } = await Promise.resolve().then(() => (init_mesh_ledger(), mesh_ledger_exports));
26941
+ appendLedgerEntry2(handle.meshId, {
26942
+ kind,
26943
+ nodeId: handle.targetNodeId,
26944
+ payload: {
26945
+ source: "refine_mesh_node_async_job",
26946
+ refineJob: {
26947
+ jobId: handle.jobId,
26948
+ interactionId: handle.interactionId,
26949
+ status: handle.status,
26950
+ meshId: handle.meshId,
26951
+ nodeId: handle.targetNodeId,
26952
+ targetDaemonId: handle.targetDaemonId,
26953
+ workspace: handle.workspace,
26954
+ startedAt: handle.startedAt,
26955
+ completedAt: handle.completedAt
26956
+ },
26957
+ async: true,
26958
+ ...result ? {
26959
+ success: result.success === true,
26960
+ result,
26961
+ finalBranchConvergenceState: result.finalBranchConvergenceState
26962
+ } : {}
26963
+ }
26964
+ });
26965
+ } catch (e) {
26966
+ LOG.warn("Mesh", `[Refinery] Failed to append async refine ledger entry: ${e?.message || e}`);
26967
+ }
26968
+ }
26969
+ async executeMeshRefineNodeSynchronously(meshId, nodeId, args) {
26970
+ const refineStages = [];
26971
+ try {
26972
+ const meshRecord = await this.getMeshForCommand(meshId, args?.inlineMesh);
26973
+ const mesh = meshRecord?.mesh;
26974
+ const node = mesh?.nodes?.find((n) => n.id === nodeId || n.nodeId === nodeId);
26975
+ if (!node) return { success: false, error: `Node '${nodeId}' not found in mesh`, refineStages };
26976
+ if (!node.isLocalWorktree || !node.workspace) {
26977
+ return { success: false, error: `Refinery requires a local worktree node`, refineStages };
26978
+ }
26979
+ const sourceNode = node.clonedFromNodeId ? mesh?.nodes.find((n) => n.id === node.clonedFromNodeId || n.nodeId === node.clonedFromNodeId) : mesh?.nodes.find((n) => !n.isLocalWorktree);
26980
+ const repoRoot = sourceNode?.repoRoot || sourceNode?.workspace;
26981
+ if (!repoRoot) return { success: false, error: "Source node repoRoot not found", refineStages };
26982
+ const { execFile: execFile3 } = await import("child_process");
26983
+ const { promisify: promisify3 } = await import("util");
26984
+ const execFileAsync3 = promisify3(execFile3);
26985
+ const resolveStarted = Date.now();
26986
+ const { stdout: branchStdout } = await execFileAsync3("git", ["branch", "--show-current"], { cwd: node.workspace, encoding: "utf8" });
26987
+ const branch = branchStdout.trim();
26988
+ if (!branch) return { success: false, error: "Could not determine branch of the worktree node", refineStages };
26989
+ const { stdout: baseBranchStdout } = await execFileAsync3("git", ["branch", "--show-current"], { cwd: repoRoot, encoding: "utf8" });
26990
+ const baseBranch = baseBranchStdout.trim();
26991
+ const { stdout: baseHeadStdout } = await execFileAsync3("git", ["rev-parse", "HEAD"], { cwd: repoRoot, encoding: "utf8" });
26992
+ const { stdout: branchHeadStdout } = await execFileAsync3("git", ["rev-parse", branch], { cwd: node.workspace, encoding: "utf8" });
26993
+ const baseHead = baseHeadStdout.trim();
26994
+ const branchHead = branchHeadStdout.trim();
26995
+ recordMeshRefineStage(refineStages, "resolve_refs", "passed", resolveStarted, { branch, baseBranch, baseHead, branchHead });
26996
+ const validationStarted = Date.now();
26997
+ const validationSummary = await runMeshRefineValidationGate(mesh, node.workspace);
26998
+ recordMeshRefineStage(
26999
+ refineStages,
27000
+ "validation",
27001
+ validationSummary.status === "passed" ? "passed" : validationSummary.status === "failed" ? "failed" : "skipped",
27002
+ validationStarted,
27003
+ { validationStatus: validationSummary.status, commandsRun: validationSummary.commandsRun.length }
27004
+ );
27005
+ if (validationSummary.status === "failed") {
27006
+ return {
27007
+ success: false,
27008
+ code: "validation_failed",
27009
+ convergenceStatus: "blocked_review",
27010
+ error: "Refinery validation gate failed; merge/refine was not attempted.",
27011
+ branch,
27012
+ into: baseBranch,
27013
+ validationSummary,
27014
+ refineStages,
27015
+ finalBranchConvergenceState: {
27016
+ branch,
27017
+ baseBranch,
27018
+ merged: false,
27019
+ removed: false,
27020
+ validation: "failed",
27021
+ status: "blocked_review"
27022
+ }
27023
+ };
27024
+ }
27025
+ if (validationSummary.status === "skipped") {
27026
+ return {
27027
+ success: false,
27028
+ code: "validation_unavailable",
27029
+ convergenceStatus: "blocked_review",
27030
+ error: "Refinery validation gate is required but no allowlisted validation command was available; merge/refine was not attempted.",
27031
+ branch,
27032
+ into: baseBranch,
27033
+ validationSummary,
27034
+ refineStages,
27035
+ finalBranchConvergenceState: {
27036
+ branch,
27037
+ baseBranch,
27038
+ merged: false,
27039
+ removed: false,
27040
+ validation: "unavailable",
27041
+ status: "blocked_review"
27042
+ }
27043
+ };
27044
+ }
27045
+ const patchEquivalenceStarted = Date.now();
27046
+ const patchEquivalence = await runMeshRefinePatchEquivalenceGate(repoRoot, baseHead, branchHead);
27047
+ recordMeshRefineStage(refineStages, "patch_equivalence", patchEquivalence.status, patchEquivalenceStarted, {
27048
+ equivalent: patchEquivalence.equivalent,
27049
+ expectedPatchId: patchEquivalence.expectedPatchId,
27050
+ actualPatchId: patchEquivalence.actualPatchId,
27051
+ error: patchEquivalence.error
27052
+ });
27053
+ if (!patchEquivalence.equivalent) {
27054
+ return {
27055
+ success: false,
27056
+ code: "patch_equivalence_failed",
27057
+ convergenceStatus: "blocked_review",
27058
+ error: "Refinery patch-equivalence preflight failed; merge/refine was not attempted.",
27059
+ branch,
27060
+ into: baseBranch,
27061
+ validationSummary,
27062
+ patchEquivalence,
27063
+ refineStages,
27064
+ finalBranchConvergenceState: {
27065
+ branch,
27066
+ baseBranch,
27067
+ merged: false,
27068
+ removed: false,
27069
+ validation: "passed",
27070
+ patchEquivalence: "failed",
27071
+ status: "blocked_review"
27072
+ }
27073
+ };
27074
+ }
27075
+ let mergeResult;
27076
+ const mergeStarted = Date.now();
27077
+ try {
27078
+ const result = await execFileAsync3("git", ["merge", "--no-ff", branch, "-m", `Auto-merge branch '${branch}' via Refinery`], { cwd: repoRoot, encoding: "utf8" });
27079
+ mergeResult = {
27080
+ stdout: truncateValidationOutput(result.stdout),
27081
+ stderr: truncateValidationOutput(result.stderr),
27082
+ durationMs: Date.now() - mergeStarted
27083
+ };
27084
+ recordMeshRefineStage(refineStages, "merge", "passed", mergeStarted, mergeResult);
27085
+ } catch (e) {
27086
+ recordMeshRefineStage(refineStages, "merge", "failed", mergeStarted, {
27087
+ error: e?.message || String(e),
27088
+ stdout: truncateValidationOutput(e?.stdout),
27089
+ stderr: truncateValidationOutput(e?.stderr)
27090
+ });
27091
+ return {
27092
+ success: false,
27093
+ error: `Merge failed (conflicts?): ${e.message}`,
27094
+ validationSummary,
27095
+ patchEquivalence,
27096
+ refineStages,
27097
+ finalBranchConvergenceState: {
27098
+ branch,
27099
+ baseBranch,
27100
+ merged: false,
27101
+ removed: false,
27102
+ validation: "passed",
27103
+ patchEquivalence: "passed",
27104
+ status: "not_mergeable"
27105
+ }
27106
+ };
27107
+ }
27108
+ const cleanupStarted = Date.now();
27109
+ const removeResult = await this.execute("remove_mesh_node", {
27110
+ meshId,
27111
+ nodeId,
27112
+ sessionCleanupMode: "preserve",
27113
+ inlineMesh: args?.inlineMesh
27114
+ });
27115
+ recordMeshRefineStage(refineStages, "cleanup", removeResult?.success === false ? "failed" : "passed", cleanupStarted, {
27116
+ removed: removeResult?.removed,
27117
+ code: removeResult?.code,
27118
+ error: removeResult?.error
27119
+ });
27120
+ let ledgerError;
27121
+ const ledgerStarted = Date.now();
27122
+ try {
27123
+ const { appendLedgerEntry: appendLedgerEntry2 } = await Promise.resolve().then(() => (init_mesh_ledger(), mesh_ledger_exports));
27124
+ appendLedgerEntry2(meshId, {
27125
+ kind: "node_removed",
27126
+ nodeId,
27127
+ payload: { refined: true, mergedBranch: branch, into: baseBranch, validationSummary, patchEquivalence }
27128
+ });
27129
+ recordMeshRefineStage(refineStages, "ledger", "passed", ledgerStarted);
27130
+ } catch (e) {
27131
+ ledgerError = e?.message || String(e);
27132
+ recordMeshRefineStage(refineStages, "ledger", "failed", ledgerStarted, { error: ledgerError });
27133
+ }
27134
+ const finalBranchConvergenceState = {
27135
+ branch: baseBranch,
27136
+ mergedBranch: branch,
27137
+ baseBranch,
27138
+ merged: true,
27139
+ removed: removeResult?.success !== false,
27140
+ validation: "passed",
27141
+ patchEquivalence: "passed",
27142
+ status: removeResult?.success === false ? "merged_cleanup_failed" : "merged"
27143
+ };
27144
+ if (removeResult?.success === false) {
27145
+ return {
27146
+ success: false,
27147
+ code: "cleanup_failed",
27148
+ error: "Refinery merge completed but worktree cleanup failed; manual cleanup/retry is required.",
27149
+ merged: true,
27150
+ branch,
27151
+ into: baseBranch,
27152
+ removeResult,
27153
+ validationSummary,
27154
+ patchEquivalence,
27155
+ mergeResult,
27156
+ refineStages,
27157
+ ...ledgerError ? { ledgerError } : {},
27158
+ finalBranchConvergenceState
27159
+ };
27160
+ }
27161
+ return {
27162
+ success: true,
27163
+ merged: true,
27164
+ branch,
27165
+ into: baseBranch,
27166
+ removeResult,
27167
+ validationSummary,
27168
+ patchEquivalence,
27169
+ mergeResult,
27170
+ refineStages,
27171
+ ...ledgerError ? { ledgerError } : {},
27172
+ finalBranchConvergenceState
27173
+ };
27174
+ } catch (e) {
27175
+ return { success: false, error: e.message, refineStages };
27176
+ }
27177
+ }
27178
+ async finishMeshRefineJob(handle, args) {
27179
+ const key = this.buildRefineJobKey(handle.meshId, handle.targetNodeId);
27180
+ let result;
27181
+ try {
27182
+ result = await this.executeMeshRefineNodeSynchronously(handle.meshId, handle.targetNodeId, args);
27183
+ } catch (e) {
27184
+ result = { success: false, error: e?.message || String(e) };
27185
+ }
27186
+ const completedAt = (/* @__PURE__ */ new Date()).toISOString();
27187
+ const terminalHandle = this.buildRefineJobHandle({
27188
+ meshId: handle.meshId,
27189
+ nodeId: handle.targetNodeId,
27190
+ status: result.success === true ? "completed" : "failed",
27191
+ startedAt: handle.startedAt,
27192
+ completedAt,
27193
+ jobId: handle.jobId,
27194
+ interactionId: handle.interactionId,
27195
+ node: { daemonId: handle.targetDaemonId, workspace: handle.workspace }
27196
+ });
27197
+ const terminal = { ...terminalHandle, result };
27198
+ this.terminalRefineJobs.set(key, terminal);
27199
+ this.runningRefineJobs.delete(key);
27200
+ this.invalidateAggregateMeshStatus(handle.meshId);
27201
+ await this.appendRefineJobLedger(result.success === true ? "task_completed" : "task_failed", terminalHandle, result);
27202
+ this.queueRefineJobEvent(result.success === true ? "refine:completed" : "refine:failed", terminalHandle, result);
27203
+ }
27204
+ async startMeshRefineJob(meshId, nodeId, args) {
27205
+ const key = this.buildRefineJobKey(meshId, nodeId);
27206
+ const running = this.runningRefineJobs.get(key);
27207
+ if (running) return { ...running, duplicate: true };
27208
+ const terminal = this.terminalRefineJobs.get(key);
27209
+ if (terminal) return { ...terminal, duplicate: true };
27210
+ const meshRecord = await this.getMeshForCommand(meshId, args?.inlineMesh);
27211
+ const mesh = meshRecord?.mesh;
27212
+ const node = mesh?.nodes?.find((n) => n.id === nodeId || n.nodeId === nodeId);
27213
+ if (!node) return { success: false, error: `Node '${nodeId}' not found in mesh` };
27214
+ if (!node.isLocalWorktree || !node.workspace) return { success: false, error: `Refinery requires a local worktree node` };
27215
+ const handle = this.buildRefineJobHandle({ meshId, nodeId, node });
27216
+ this.runningRefineJobs.set(key, handle);
27217
+ await this.appendRefineJobLedger("task_dispatched", handle);
27218
+ this.queueRefineJobEvent("refine:accepted", handle);
27219
+ setImmediate(() => {
27220
+ void this.finishMeshRefineJob(handle, args);
27221
+ });
27222
+ return handle;
27223
+ }
26886
27224
  // ─── Daemon-level command core ───────────────────
26887
27225
  /**
26888
27226
  * Daemon-level command execution (IDE start/stop/restart, CLI, detect, logs).
@@ -27968,213 +28306,7 @@ var DaemonCommandRouter = class {
27968
28306
  const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
27969
28307
  const nodeId = typeof args?.nodeId === "string" ? args.nodeId.trim() : "";
27970
28308
  if (!meshId || !nodeId) return { success: false, error: "meshId and nodeId required" };
27971
- const refineStages = [];
27972
- try {
27973
- const meshRecord = await this.getMeshForCommand(meshId, args?.inlineMesh);
27974
- const mesh = meshRecord?.mesh;
27975
- const node = mesh?.nodes?.find((n) => n.id === nodeId || n.nodeId === nodeId);
27976
- if (!node) return { success: false, error: `Node '${nodeId}' not found in mesh`, refineStages };
27977
- if (!node.isLocalWorktree || !node.workspace) {
27978
- return { success: false, error: `Refinery requires a local worktree node`, refineStages };
27979
- }
27980
- const sourceNode = node.clonedFromNodeId ? mesh?.nodes.find((n) => n.id === node.clonedFromNodeId || n.nodeId === node.clonedFromNodeId) : mesh?.nodes.find((n) => !n.isLocalWorktree);
27981
- const repoRoot = sourceNode?.repoRoot || sourceNode?.workspace;
27982
- if (!repoRoot) return { success: false, error: "Source node repoRoot not found", refineStages };
27983
- const { execFile: execFile3 } = await import("child_process");
27984
- const { promisify: promisify3 } = await import("util");
27985
- const execFileAsync3 = promisify3(execFile3);
27986
- const resolveStarted = Date.now();
27987
- const { stdout: branchStdout } = await execFileAsync3("git", ["branch", "--show-current"], { cwd: node.workspace, encoding: "utf8" });
27988
- const branch = branchStdout.trim();
27989
- if (!branch) return { success: false, error: "Could not determine branch of the worktree node", refineStages };
27990
- const { stdout: baseBranchStdout } = await execFileAsync3("git", ["branch", "--show-current"], { cwd: repoRoot, encoding: "utf8" });
27991
- const baseBranch = baseBranchStdout.trim();
27992
- const { stdout: baseHeadStdout } = await execFileAsync3("git", ["rev-parse", "HEAD"], { cwd: repoRoot, encoding: "utf8" });
27993
- const { stdout: branchHeadStdout } = await execFileAsync3("git", ["rev-parse", branch], { cwd: node.workspace, encoding: "utf8" });
27994
- const baseHead = baseHeadStdout.trim();
27995
- const branchHead = branchHeadStdout.trim();
27996
- recordMeshRefineStage(refineStages, "resolve_refs", "passed", resolveStarted, { branch, baseBranch, baseHead, branchHead });
27997
- const validationStarted = Date.now();
27998
- const validationSummary = await runMeshRefineValidationGate(mesh, node.workspace);
27999
- recordMeshRefineStage(
28000
- refineStages,
28001
- "validation",
28002
- validationSummary.status === "passed" ? "passed" : validationSummary.status === "failed" ? "failed" : "skipped",
28003
- validationStarted,
28004
- { validationStatus: validationSummary.status, commandsRun: validationSummary.commandsRun.length }
28005
- );
28006
- if (validationSummary.status === "failed") {
28007
- return {
28008
- success: false,
28009
- code: "validation_failed",
28010
- convergenceStatus: "blocked_review",
28011
- error: "Refinery validation gate failed; merge/refine was not attempted.",
28012
- branch,
28013
- into: baseBranch,
28014
- validationSummary,
28015
- refineStages,
28016
- finalBranchConvergenceState: {
28017
- branch,
28018
- baseBranch,
28019
- merged: false,
28020
- removed: false,
28021
- validation: "failed",
28022
- status: "blocked_review"
28023
- }
28024
- };
28025
- }
28026
- if (validationSummary.status === "skipped") {
28027
- return {
28028
- success: false,
28029
- code: "validation_unavailable",
28030
- convergenceStatus: "blocked_review",
28031
- error: "Refinery validation gate is required but no allowlisted validation command was available; merge/refine was not attempted.",
28032
- branch,
28033
- into: baseBranch,
28034
- validationSummary,
28035
- refineStages,
28036
- finalBranchConvergenceState: {
28037
- branch,
28038
- baseBranch,
28039
- merged: false,
28040
- removed: false,
28041
- validation: "unavailable",
28042
- status: "blocked_review"
28043
- }
28044
- };
28045
- }
28046
- const patchEquivalenceStarted = Date.now();
28047
- const patchEquivalence = await runMeshRefinePatchEquivalenceGate(repoRoot, baseHead, branchHead);
28048
- recordMeshRefineStage(refineStages, "patch_equivalence", patchEquivalence.status, patchEquivalenceStarted, {
28049
- equivalent: patchEquivalence.equivalent,
28050
- expectedPatchId: patchEquivalence.expectedPatchId,
28051
- actualPatchId: patchEquivalence.actualPatchId,
28052
- error: patchEquivalence.error
28053
- });
28054
- if (!patchEquivalence.equivalent) {
28055
- return {
28056
- success: false,
28057
- code: "patch_equivalence_failed",
28058
- convergenceStatus: "blocked_review",
28059
- error: "Refinery patch-equivalence preflight failed; merge/refine was not attempted.",
28060
- branch,
28061
- into: baseBranch,
28062
- validationSummary,
28063
- patchEquivalence,
28064
- refineStages,
28065
- finalBranchConvergenceState: {
28066
- branch,
28067
- baseBranch,
28068
- merged: false,
28069
- removed: false,
28070
- validation: "passed",
28071
- patchEquivalence: "failed",
28072
- status: "blocked_review"
28073
- }
28074
- };
28075
- }
28076
- let mergeResult;
28077
- const mergeStarted = Date.now();
28078
- try {
28079
- const result = await execFileAsync3("git", ["merge", "--no-ff", branch, "-m", `Auto-merge branch '${branch}' via Refinery`], { cwd: repoRoot, encoding: "utf8" });
28080
- mergeResult = {
28081
- stdout: truncateValidationOutput(result.stdout),
28082
- stderr: truncateValidationOutput(result.stderr),
28083
- durationMs: Date.now() - mergeStarted
28084
- };
28085
- recordMeshRefineStage(refineStages, "merge", "passed", mergeStarted, mergeResult);
28086
- } catch (e) {
28087
- recordMeshRefineStage(refineStages, "merge", "failed", mergeStarted, {
28088
- error: e?.message || String(e),
28089
- stdout: truncateValidationOutput(e?.stdout),
28090
- stderr: truncateValidationOutput(e?.stderr)
28091
- });
28092
- return {
28093
- success: false,
28094
- error: `Merge failed (conflicts?): ${e.message}`,
28095
- validationSummary,
28096
- patchEquivalence,
28097
- refineStages,
28098
- finalBranchConvergenceState: {
28099
- branch,
28100
- baseBranch,
28101
- merged: false,
28102
- removed: false,
28103
- validation: "passed",
28104
- patchEquivalence: "passed",
28105
- status: "not_mergeable"
28106
- }
28107
- };
28108
- }
28109
- const cleanupStarted = Date.now();
28110
- const removeResult = await this.execute("remove_mesh_node", {
28111
- meshId,
28112
- nodeId,
28113
- sessionCleanupMode: "preserve",
28114
- inlineMesh: args?.inlineMesh
28115
- });
28116
- recordMeshRefineStage(refineStages, "cleanup", removeResult?.success === false ? "failed" : "passed", cleanupStarted, {
28117
- removed: removeResult?.removed,
28118
- code: removeResult?.code,
28119
- error: removeResult?.error
28120
- });
28121
- let ledgerError;
28122
- const ledgerStarted = Date.now();
28123
- try {
28124
- const { appendLedgerEntry: appendLedgerEntry2 } = await Promise.resolve().then(() => (init_mesh_ledger(), mesh_ledger_exports));
28125
- appendLedgerEntry2(meshId, {
28126
- kind: "node_removed",
28127
- nodeId,
28128
- payload: { refined: true, mergedBranch: branch, into: baseBranch, validationSummary, patchEquivalence }
28129
- });
28130
- recordMeshRefineStage(refineStages, "ledger", "passed", ledgerStarted);
28131
- } catch (e) {
28132
- ledgerError = e?.message || String(e);
28133
- recordMeshRefineStage(refineStages, "ledger", "failed", ledgerStarted, { error: ledgerError });
28134
- }
28135
- const finalBranchConvergenceState = {
28136
- branch: baseBranch,
28137
- mergedBranch: branch,
28138
- baseBranch,
28139
- merged: true,
28140
- removed: removeResult?.success !== false,
28141
- validation: "passed",
28142
- patchEquivalence: "passed",
28143
- status: removeResult?.success === false ? "merged_cleanup_failed" : "merged"
28144
- };
28145
- if (removeResult?.success === false) {
28146
- return {
28147
- success: false,
28148
- code: "cleanup_failed",
28149
- error: "Refinery merge completed but worktree cleanup failed; manual cleanup/retry is required.",
28150
- merged: true,
28151
- branch,
28152
- into: baseBranch,
28153
- removeResult,
28154
- validationSummary,
28155
- patchEquivalence,
28156
- mergeResult,
28157
- refineStages,
28158
- ...ledgerError ? { ledgerError } : {},
28159
- finalBranchConvergenceState
28160
- };
28161
- }
28162
- return {
28163
- success: true,
28164
- merged: true,
28165
- branch,
28166
- into: baseBranch,
28167
- removeResult,
28168
- validationSummary,
28169
- patchEquivalence,
28170
- mergeResult,
28171
- refineStages,
28172
- ...ledgerError ? { ledgerError } : {},
28173
- finalBranchConvergenceState
28174
- };
28175
- } catch (e) {
28176
- return { success: false, error: e.message, refineStages };
28177
- }
28309
+ return this.startMeshRefineJob(meshId, nodeId, args);
28178
28310
  }
28179
28311
  case "remove_mesh_node": {
28180
28312
  const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";