@adhdev/daemon-core 0.9.82-rc.454 → 0.9.82-rc.456

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.
@@ -0,0 +1,137 @@
1
+ import type { DaemonCommandRouter, CommandRouterResult } from './router.js';
2
+ import { MeshRefineAsyncJobStatus, MeshRefineBatchJobHandle, MeshRefineBatchJobStatus, MeshRefineJobHandle, RefineContext, RefineStageOutcome } from '../mesh/mesh-refine-gates.js';
3
+ export declare function buildRefineJobKey(self: DaemonCommandRouter, meshId: string, nodeId: string): string;
4
+ export declare function buildRefineJobHandle(self: DaemonCommandRouter, args: {
5
+ meshId: string;
6
+ nodeId: string;
7
+ node?: any;
8
+ status?: MeshRefineAsyncJobStatus;
9
+ startedAt?: string;
10
+ completedAt?: string;
11
+ jobId?: string;
12
+ interactionId?: string;
13
+ retryOfJobId?: string;
14
+ coordinatorDaemonId?: string;
15
+ }): MeshRefineJobHandle;
16
+ export declare function queueRefineJobEvent(self: DaemonCommandRouter, event: 'refine:accepted' | 'refine:completed' | 'refine:failed', handle: MeshRefineJobHandle, result?: Record<string, unknown>): void;
17
+ export declare function appendRefineJobLedger(self: DaemonCommandRouter, kind: 'task_dispatched' | 'task_completed' | 'task_failed', handle: MeshRefineJobHandle, result?: Record<string, unknown>): Promise<void>;
18
+ /**
19
+ * On daemon restart, scan all mesh ledgers for refine jobs that were dispatched
20
+ * but never completed/failed (i.e. the daemon died mid-job). Re-queue each one
21
+ * so the job runs to completion automatically without coordinator intervention.
22
+ */
23
+ export declare function resumePendingRefineJobsOnStartup(self: DaemonCommandRouter): Promise<void>;
24
+ /**
25
+ * Synchronous refinery for a single worktree node — the gate pipeline that
26
+ * validates, preflights (patch-equivalence / submodule-reachability /
27
+ * no-op), merges, aligns submodules, cleans up the worktree node and
28
+ * (optionally) pushes. The body is a flat sequence of stage methods; each
29
+ * stage either returns a terminal CommandRouterResult (gate failure or a
30
+ * successful already-merged short-circuit) or `continue` with the extended
31
+ * context. Behavior — stage order, every early-exit, and every result shape —
32
+ * is identical to the previous single inlined body.
33
+ */
34
+ export declare function executeMeshRefineNodeSynchronously(self: DaemonCommandRouter, meshId: string, nodeId: string, args: any): Promise<CommandRouterResult>;
35
+ /**
36
+ * resolve_refs stage: resolve the mesh / worktree node / source node /
37
+ * repoRoot, then the worktree branch, base branch, fetched base head and
38
+ * branch head. Seeds the RefineContext consumed by every later stage.
39
+ */
40
+ export declare function refineResolveRefsStage(self: DaemonCommandRouter, meshId: string, nodeId: string, args: any, refineStages: Array<Record<string, unknown>>): Promise<RefineStageOutcome>;
41
+ /**
42
+ * validation stage: run the refinery validation gate (typecheck / test /
43
+ * lint / build per node config) and block on failure or when no allowlisted
44
+ * command was available. On pass, stores the summary on the context.
45
+ */
46
+ export declare function refineValidationStage(self: DaemonCommandRouter, ctx: RefineContext): Promise<RefineStageOutcome>;
47
+ /**
48
+ * patch_equivalence stage: preflight that the worktree branch's cumulative
49
+ * patch is equivalent to base+branch. On a "behind base" branch, auto-rebase
50
+ * once and re-check; on an empty merge-tree with real branch changes, treat as
51
+ * already-merged-via-another-path and short-circuit to cleanup. Mutates the
52
+ * context's branchHead (after rebase) and patchEquivalence (rebased gate).
53
+ */
54
+ export declare function refinePatchEquivalenceStage(self: DaemonCommandRouter, ctx: RefineContext): Promise<RefineStageOutcome>;
55
+ /**
56
+ * submodule_reachability stage: verify every submodule gitlink commit that
57
+ * would land via the merge is reachable from its configured remote main
58
+ * branch (optionally auto-publishing when policy allows). Blocks the merge
59
+ * when any commit is unreachable. Stores the result on the context.
60
+ */
61
+ export declare function refineSubmoduleReachabilityStage(self: DaemonCommandRouter, ctx: RefineContext): Promise<RefineStageOutcome>;
62
+ /**
63
+ * effective_diff stage (no-op guard): block a silent no-op merge where the
64
+ * branch produces no effective root-tree diff against base — typically a
65
+ * submodule that has commits but whose root-level gitlink (pointer) bump was
66
+ * never committed, so the merge would land nothing real on main.
67
+ */
68
+ export declare function refineEffectiveDiffStage(self: DaemonCommandRouter, ctx: RefineContext): Promise<RefineStageOutcome>;
69
+ /**
70
+ * merge + finalize stage: perform the --no-ff merge, align submodule
71
+ * checkouts after merge, clean up (remove) the worktree node per policy,
72
+ * append the refinery ledger entry, and (unless approval is required) push the
73
+ * base branch. Always terminal — produces the final CommandRouterResult.
74
+ */
75
+ export declare function refineMergeAndFinalizeStage(self: DaemonCommandRouter, ctx: RefineContext): Promise<RefineStageOutcome>;
76
+ /**
77
+ * Batch refinery: converge multiple sibling worktree nodes onto the base branch
78
+ * in one sequential pipeline, absorbing the rebase + patch-equivalence churn that
79
+ * arises when several siblings touch the same submodule.
80
+ *
81
+ * Reuses executeMeshRefineNodeSynchronously per node — every node goes through the
82
+ * exact same validation / patch-equivalence / submodule-reachability / merge / cleanup
83
+ * gates, including its built-in auto-rebase onto fresh origin/<base>. Because each
84
+ * node fetches origin/<base> at the start of its own refine, a node merged earlier in
85
+ * the batch advances the base, and the next node's refine auto-rebases onto it before
86
+ * re-running patch-equivalence. No force-push, no reset — conflicting nodes are
87
+ * isolated as blocked_review while the rest of the batch proceeds.
88
+ */
89
+ export declare function batchRefineMeshNodes(self: DaemonCommandRouter, meshId: string, requestedNodeIds: string[] | undefined, args: any): Promise<CommandRouterResult>;
90
+ /**
91
+ * Convergence core shared by the synchronous batch entry and the async batch job.
92
+ * Refines each node in order: the per-node refine pipeline fetches origin/<base>
93
+ * fresh, so each merged sibling advances the base before the next node's auto-rebase
94
+ * + patch-equivalence re-check. A blocked/failed node is isolated; the batch
95
+ * continues with the remaining nodes. Does NOT touch the per-node merge logic — it
96
+ * only sequences calls to executeMeshRefineNodeSynchronously and aggregates outcomes.
97
+ */
98
+ export declare function runMeshRefineBatchConvergence(self: DaemonCommandRouter, meshId: string, orderedNodes: any[], ordering: {
99
+ order: string[];
100
+ rationale?: unknown;
101
+ }, args: any): Promise<CommandRouterResult>;
102
+ export declare function buildRefineBatchJobKey(self: DaemonCommandRouter, meshId: string): string;
103
+ export declare function buildRefineBatchJobHandle(self: DaemonCommandRouter, args: {
104
+ meshId: string;
105
+ nodeIds: string[];
106
+ order: string[];
107
+ status?: MeshRefineBatchJobStatus;
108
+ startedAt?: string;
109
+ completedAt?: string;
110
+ jobId?: string;
111
+ interactionId?: string;
112
+ coordinatorDaemonId?: string;
113
+ }): MeshRefineBatchJobHandle;
114
+ /**
115
+ * Emit a batch Refinery terminal/accepted event through the SAME pending-event +
116
+ * forward mechanism single-node refine uses (queueRefineJobEvent), so the
117
+ * coordinator's existing refine:accepted/completed/failed handling and message
118
+ * renderer apply unchanged. The aggregate per-node results ride along in `result`.
119
+ */
120
+ export declare function queueRefineBatchJobEvent(self: DaemonCommandRouter, event: 'refine:accepted' | 'refine:completed' | 'refine:failed', handle: MeshRefineBatchJobHandle, result?: Record<string, unknown>): void;
121
+ export declare function appendRefineBatchJobLedger(self: DaemonCommandRouter, kind: 'task_dispatched' | 'task_completed' | 'task_failed', handle: MeshRefineBatchJobHandle, result?: Record<string, unknown>): Promise<void>;
122
+ export declare function finishMeshRefineBatchJob(self: DaemonCommandRouter, handle: MeshRefineBatchJobHandle, orderedNodes: any[], ordering: {
123
+ order: string[];
124
+ rationale?: unknown;
125
+ }, args: any): Promise<void>;
126
+ /**
127
+ * Async entry for the batch Refinery execute path. Mirrors startMeshRefineJob:
128
+ * resolves the plan synchronously (so target/ordering errors and the dry-run shape
129
+ * stay synchronous), then for execute=true registers an in-flight batch job, returns
130
+ * {async:true, status:'accepted', batch:true, ...plan} immediately, and runs the
131
+ * convergence loop in the background — emitting the same terminal refine event.
132
+ * Idempotent: a batch already in flight for this mesh returns the running handle
133
+ * with duplicate:true rather than spawning a second background job.
134
+ */
135
+ export declare function startMeshRefineBatchJob(self: DaemonCommandRouter, meshId: string, requestedNodeIds: string[] | undefined, args: any): Promise<CommandRouterResult>;
136
+ export declare function finishMeshRefineJob(self: DaemonCommandRouter, handle: MeshRefineJobHandle, args: any): Promise<void>;
137
+ export declare function startMeshRefineJob(self: DaemonCommandRouter, meshId: string, nodeId: string, args: any): Promise<CommandRouterResult>;
@@ -0,0 +1,133 @@
1
+ import type { DaemonCommandRouter } from './router.js';
2
+ import type { RepoMeshSessionCleanupMode } from '../repo-mesh-types.js';
3
+ export declare function sessionMatchesMeshNode(self: DaemonCommandRouter, record: any, node: any, nodeId: string, sessionIds?: Set<string>): boolean;
4
+ /**
5
+ * Best-effort recursive removal of a managed worktree directory.
6
+ *
7
+ * The git-registry de-registration is the safety-critical step of worktree
8
+ * teardown; a leftover directory must never gate dropping the node from the
9
+ * mesh. On Windows, `fs.rmSync` can throw EINVAL/EPERM/EBUSY on submodule
10
+ * gitlink (`.git`) files, long paths, junctions, or while a just-stopped
11
+ * delegate session is still releasing a handle/cwd on the directory. This
12
+ * helper absorbs those errors (never throws), with bounded retries + backoff
13
+ * to give handles time to release, and reports whether residue remains.
14
+ */
15
+ export declare function bestEffortRemoveWorktreeDir(self: DaemonCommandRouter, dir: string): Promise<{
16
+ removed: boolean;
17
+ residue: boolean;
18
+ error?: string;
19
+ }>;
20
+ /**
21
+ * Non-destructive precheck mirroring every REFUSAL condition in
22
+ * {@link cleanupLocalWorktreeNode} — missing workspace / source-repo / branch
23
+ * metadata, unexpected (non-managed) path, branch mismatch — PLUS the
24
+ * dirty-worktree guard that `removeWorktree(requireClean)` enforces
25
+ * (`git status --porcelain`). It performs ZERO destructive actions: no
26
+ * `git worktree remove`, no `git worktree prune`, no directory deletion.
27
+ *
28
+ * remove_mesh_node calls this BEFORE any session cleanup so that a refusal
29
+ * (the common one being a dirty worktree) does not first stop/delete the
30
+ * delegated session and orphan it — the original ordering bug. Success/skip
31
+ * cases that the real cleanup handles idempotently (worktree path already
32
+ * gone, git-de-registered residue) are NOT refusals and return `{ ok: true }`.
33
+ *
34
+ * `force:true` skips the dirty guard, preserving `removeWorktree`'s
35
+ * `requireClean: !force` semantics. This is a read-only superset check; the
36
+ * authoritative `requireClean` guard inside `removeWorktree` is intentionally
37
+ * kept as a second line of defense against a precheck→execute race.
38
+ */
39
+ export declare function precheckLocalWorktreeRemovable(self: DaemonCommandRouter, args: {
40
+ mesh: any;
41
+ node: any;
42
+ nodeId: string;
43
+ force?: boolean;
44
+ }): Promise<{
45
+ ok: true;
46
+ } | {
47
+ ok: false;
48
+ code: string;
49
+ error: string;
50
+ recoveryHint: string;
51
+ }>;
52
+ export declare function cleanupLocalWorktreeNode(self: DaemonCommandRouter, args: {
53
+ mesh: any;
54
+ node: any;
55
+ nodeId: string;
56
+ force?: boolean;
57
+ }): Promise<{
58
+ success: true;
59
+ skipped?: boolean;
60
+ removedPath?: string;
61
+ repoRoot?: string;
62
+ reason?: string;
63
+ fallback?: string;
64
+ forced?: boolean;
65
+ convergence?: Record<string, unknown>;
66
+ recovered?: boolean;
67
+ residue?: boolean;
68
+ residueWarning?: string;
69
+ residueError?: string;
70
+ branchRefDeleted?: boolean;
71
+ branchRefReason?: string;
72
+ branchRefForced?: boolean;
73
+ branchRefWarning?: string;
74
+ } | {
75
+ success: false;
76
+ code: string;
77
+ error: string;
78
+ recoveryHint: string;
79
+ convergence?: Record<string, unknown>;
80
+ }>;
81
+ export declare function getWorktreeForceCleanupConvergence(self: DaemonCommandRouter, args: {
82
+ repoRoot: string;
83
+ workspace: string;
84
+ node: any;
85
+ }): Promise<{
86
+ allow: boolean;
87
+ status?: string;
88
+ source?: string;
89
+ ref?: string;
90
+ error?: string;
91
+ }>;
92
+ export declare function isCompletedHostedSession(self: DaemonCommandRouter, record: any): boolean;
93
+ export declare function recordIntentionalMeshSessionStop(self: DaemonCommandRouter, args: {
94
+ meshId: string;
95
+ nodeId: string;
96
+ node: any;
97
+ sessionId: string;
98
+ mode: RepoMeshSessionCleanupMode;
99
+ source: 'mesh_cleanup_sessions' | 'mesh_remove_node' | 'magi_session_cleanup';
100
+ action: 'stop_session' | 'delete_session_force';
101
+ }): Promise<void>;
102
+ export declare function cleanupMeshSessions(self: DaemonCommandRouter, args: {
103
+ meshId: string;
104
+ nodeId: string;
105
+ node: any;
106
+ mode: RepoMeshSessionCleanupMode;
107
+ sessionIds?: string[];
108
+ dryRun?: boolean;
109
+ source?: 'mesh_cleanup_sessions' | 'mesh_remove_node' | 'magi_session_cleanup';
110
+ /**
111
+ * MAGI auto-cleanup safety gate: a map of sessionId → the queue task id that
112
+ * session must have been AUTO-LAUNCHED for (record meta autoLaunchedForQueueTaskId).
113
+ * When set, a matched explicit session is only acted on if its record carries that
114
+ * exact marker. A reused idle session (no marker), the coordinator session, a
115
+ * re-assigned session, or any session whose marker points at a DIFFERENT task is
116
+ * skipped (reason 'auto_launch_marker_mismatch') — so MAGI never kills a session it
117
+ * didn't itself spawn for this fan-out. Only consulted alongside explicit sessionIds.
118
+ */
119
+ requireAutoLaunchedForTaskIds?: Record<string, string>;
120
+ /**
121
+ * Opt-in orphan reclaim (default false). See SESSION-ACCUMULATION-LEAK.
122
+ * When true, a workspace-only live_runtime session (no node binding) OR a
123
+ * live_runtime session bound to a node absent from `liveMeshNodeIds` is
124
+ * stopped instead of skipped by the conservative shared-daemon guard. A
125
+ * session whose meshNodeId is STILL in `liveMeshNodeIds` (active sibling)
126
+ * is never reclaimed — that is the shared-daemon safety this preserves.
127
+ */
128
+ reclaimOrphans?: boolean;
129
+ liveMeshNodeIds?: string[];
130
+ }): Promise<{
131
+ success: boolean;
132
+ [key: string]: unknown;
133
+ }>;
@@ -14,6 +14,8 @@ import { DaemonCliManager } from './cli-manager.js';
14
14
  import type { ProviderLoader } from '../providers/provider-loader.js';
15
15
  import type { ProviderInstanceManager } from '../providers/provider-instance-manager.js';
16
16
  import { SessionRegistry } from '../sessions/registry.js';
17
+ import type { RepoMeshSessionCleanupMode } from '../repo-mesh-types.js';
18
+ import { MeshRefineBatchJobHandle, MeshRefineBatchTerminalJob, MeshRefineJobHandle, MeshRefineTerminalJob } from '../mesh/mesh-refine-gates.js';
17
19
  export * from '../mesh/mesh-node-identity.js';
18
20
  export * from '../mesh/mesh-refine-gates.js';
19
21
  export * from '../mesh/mesh-coordinator-config.js';
@@ -96,7 +98,8 @@ export interface CommandRouterResult {
96
98
  export declare function normalizeStandaloneHostCommandUrl(hostAddress: string): string;
97
99
  export declare function buildMemberJoinNode(mesh: any, args: any, fallbackDaemonId?: string): Record<string, unknown> | null;
98
100
  export declare class DaemonCommandRouter {
99
- private deps;
101
+ /** Public (not private) so the extracted ./router-refine.ts orchestration can reach it via `self`. */
102
+ deps: CommandRouterDeps;
100
103
  /** In-memory cache for cloud-originating meshes passed via inlineMesh.
101
104
  * Allows the MCP server to query mesh data via get_mesh even when
102
105
  * the mesh doesn't exist in the local meshes.json file. */
@@ -120,14 +123,15 @@ export declare class DaemonCommandRouter {
120
123
  * flight — so a burst of interactive detail-opens serves the cached snapshot
121
124
  * and coalesces onto ONE background refresh instead of storming the peers. */
122
125
  private swrRefreshInFlight;
123
- /** In-memory async Refinery jobs keyed by meshId:nodeId to reject/return duplicate in-flight requests. */
124
- private runningRefineJobs;
126
+ /** In-memory async Refinery jobs keyed by meshId:nodeId to reject/return duplicate in-flight requests.
127
+ * Public (not private) so the extracted ./router-refine.ts orchestration can reach it via `self`. */
128
+ runningRefineJobs: Map<string, MeshRefineJobHandle>;
125
129
  /** Terminal async Refinery jobs preserve a clear answer after the worktree node has been removed. */
126
- private terminalRefineJobs;
130
+ terminalRefineJobs: Map<string, MeshRefineTerminalJob>;
127
131
  /** In-memory async batch Refinery jobs keyed by meshId (one batch convergence per mesh at a time). */
128
- private runningRefineBatchJobs;
132
+ runningRefineBatchJobs: Map<string, MeshRefineBatchJobHandle>;
129
133
  /** Terminal async batch Refinery jobs preserve the last batch outcome for late readers. */
130
- private terminalRefineBatchJobs;
134
+ terminalRefineBatchJobs: Map<string, MeshRefineBatchTerminalJob>;
131
135
  constructor(deps: CommandRouterDeps);
132
136
  private cloneJsonValue;
133
137
  private hydrateCachedAggregateMeshStatusFromInline;
@@ -181,8 +185,14 @@ export declare class DaemonCommandRouter {
181
185
  private collectMeshSessionOwnerCandidateNodes;
182
186
  getCachedInlineMesh(meshId: string, inlineMesh?: unknown): any | undefined;
183
187
  private warmInlineMeshCache;
184
- private getMeshForCommand;
185
- private invalidateAggregateMeshStatus;
188
+ getMeshForCommand(meshId: string, inlineMesh?: unknown, options?: {
189
+ preferInline?: boolean;
190
+ }): Promise<{
191
+ mesh: any;
192
+ inline: boolean;
193
+ source: 'inline_cache' | 'inline_bootstrap' | 'local_config';
194
+ } | null>;
195
+ invalidateAggregateMeshStatus(meshId: string): void;
186
196
  /**
187
197
  * Build the MedFamilyContext handed to RF-ROUTER MED family handlers. Binds the
188
198
  * router-private collaborators those handlers need (mesh resolution, owner
@@ -238,45 +248,91 @@ export declare class DaemonCommandRouter {
238
248
  * workspace is still absent from disk; if the workspace is back (genuine
239
249
  * re-registration), the tombstone is cleared and the node merges normally. */
240
250
  private applyInlineMeshNodeTombstones;
241
- private normalizeMeshSessionCleanupMode;
242
- private sessionMatchesMeshNode;
243
- /**
244
- * Best-effort recursive removal of a managed worktree directory.
245
- *
246
- * The git-registry de-registration is the safety-critical step of worktree
247
- * teardown; a leftover directory must never gate dropping the node from the
248
- * mesh. On Windows, `fs.rmSync` can throw EINVAL/EPERM/EBUSY on submodule
249
- * gitlink (`.git`) files, long paths, junctions, or while a just-stopped
250
- * delegate session is still releasing a handle/cwd on the directory. This
251
- * helper absorbs those errors (never throws), with bounded retries + backoff
252
- * to give handles time to release, and reports whether residue remains.
253
- */
254
- private bestEffortRemoveWorktreeDir;
255
- /**
256
- * Non-destructive precheck mirroring every REFUSAL condition in
257
- * {@link cleanupLocalWorktreeNode} — missing workspace / source-repo / branch
258
- * metadata, unexpected (non-managed) path, branch mismatch — PLUS the
259
- * dirty-worktree guard that `removeWorktree(requireClean)` enforces
260
- * (`git status --porcelain`). It performs ZERO destructive actions: no
261
- * `git worktree remove`, no `git worktree prune`, no directory deletion.
262
- *
263
- * remove_mesh_node calls this BEFORE any session cleanup so that a refusal
264
- * (the common one being a dirty worktree) does not first stop/delete the
265
- * delegated session and orphan it — the original ordering bug. Success/skip
266
- * cases that the real cleanup handles idempotently (worktree path already
267
- * gone, git-de-registered residue) are NOT refusals and return `{ ok: true }`.
268
- *
269
- * `force:true` skips the dirty guard, preserving `removeWorktree`'s
270
- * `requireClean: !force` semantics. This is a read-only superset check; the
271
- * authoritative `requireClean` guard inside `removeWorktree` is intentionally
272
- * kept as a second line of defense against a precheck→execute race.
273
- */
274
- private precheckLocalWorktreeRemovable;
275
- private cleanupLocalWorktreeNode;
276
- private getWorktreeForceCleanupConvergence;
277
- private isCompletedHostedSession;
278
- private recordIntentionalMeshSessionStop;
279
- private cleanupMeshSessions;
251
+ normalizeMeshSessionCleanupMode(value: unknown): RepoMeshSessionCleanupMode;
252
+ sessionMatchesMeshNode(record: any, node: any, nodeId: string, sessionIds?: Set<string>): boolean;
253
+ bestEffortRemoveWorktreeDir(dir: string): Promise<{
254
+ removed: boolean;
255
+ residue: boolean;
256
+ error?: string;
257
+ }>;
258
+ precheckLocalWorktreeRemovable(args: {
259
+ mesh: any;
260
+ node: any;
261
+ nodeId: string;
262
+ force?: boolean;
263
+ }): Promise<{
264
+ ok: true;
265
+ } | {
266
+ ok: false;
267
+ code: string;
268
+ error: string;
269
+ recoveryHint: string;
270
+ }>;
271
+ cleanupLocalWorktreeNode(args: {
272
+ mesh: any;
273
+ node: any;
274
+ nodeId: string;
275
+ force?: boolean;
276
+ }): Promise<{
277
+ success: true;
278
+ skipped?: boolean;
279
+ removedPath?: string;
280
+ repoRoot?: string;
281
+ reason?: string;
282
+ fallback?: string;
283
+ forced?: boolean;
284
+ convergence?: Record<string, unknown>;
285
+ recovered?: boolean;
286
+ residue?: boolean;
287
+ residueWarning?: string;
288
+ residueError?: string;
289
+ branchRefDeleted?: boolean;
290
+ branchRefReason?: string;
291
+ branchRefForced?: boolean;
292
+ branchRefWarning?: string;
293
+ } | {
294
+ success: false;
295
+ code: string;
296
+ error: string;
297
+ recoveryHint: string;
298
+ convergence?: Record<string, unknown>;
299
+ }>;
300
+ getWorktreeForceCleanupConvergence(args: {
301
+ repoRoot: string;
302
+ workspace: string;
303
+ node: any;
304
+ }): Promise<{
305
+ allow: boolean;
306
+ status?: string;
307
+ source?: string;
308
+ ref?: string;
309
+ error?: string;
310
+ }>;
311
+ isCompletedHostedSession(record: any): boolean;
312
+ recordIntentionalMeshSessionStop(args: {
313
+ meshId: string;
314
+ nodeId: string;
315
+ node: any;
316
+ sessionId: string;
317
+ mode: RepoMeshSessionCleanupMode;
318
+ source: 'mesh_cleanup_sessions' | 'mesh_remove_node' | 'magi_session_cleanup';
319
+ action: 'stop_session' | 'delete_session_force';
320
+ }): Promise<void>;
321
+ cleanupMeshSessions(args: {
322
+ meshId: string;
323
+ nodeId: string;
324
+ node: any;
325
+ mode: RepoMeshSessionCleanupMode;
326
+ sessionIds?: string[];
327
+ dryRun?: boolean;
328
+ source?: 'mesh_cleanup_sessions' | 'mesh_remove_node' | 'magi_session_cleanup';
329
+ requireAutoLaunchedForTaskIds?: Record<string, string>;
330
+ reclaimOrphans?: boolean;
331
+ liveMeshNodeIds?: string[];
332
+ }): Promise<{
333
+ success: boolean;
334
+ [key: string]: unknown;
335
+ }>;
280
336
  /**
281
337
  * Unified command routing.
282
338
  * Returns result for all commands:
@@ -289,113 +345,9 @@ export declare class DaemonCommandRouter {
289
345
  * @param source Log source ('ws' | 'p2p' | 'standalone' | etc.)
290
346
  */
291
347
  execute(cmd: string, args: any, source?: string): Promise<CommandRouterResult>;
292
- private buildRefineJobKey;
293
- private buildRefineJobHandle;
294
- private queueRefineJobEvent;
295
- private appendRefineJobLedger;
296
- /**
297
- * On daemon restart, scan all mesh ledgers for refine jobs that were dispatched
298
- * but never completed/failed (i.e. the daemon died mid-job). Re-queue each one
299
- * so the job runs to completion automatically without coordinator intervention.
300
- */
301
348
  resumePendingRefineJobsOnStartup(): Promise<void>;
302
- /**
303
- * Synchronous refinery for a single worktree node — the gate pipeline that
304
- * validates, preflights (patch-equivalence / submodule-reachability /
305
- * no-op), merges, aligns submodules, cleans up the worktree node and
306
- * (optionally) pushes. The body is a flat sequence of stage methods; each
307
- * stage either returns a terminal CommandRouterResult (gate failure or a
308
- * successful already-merged short-circuit) or `continue` with the extended
309
- * context. Behavior — stage order, every early-exit, and every result shape —
310
- * is identical to the previous single inlined body.
311
- */
312
- private executeMeshRefineNodeSynchronously;
313
- /**
314
- * resolve_refs stage: resolve the mesh / worktree node / source node /
315
- * repoRoot, then the worktree branch, base branch, fetched base head and
316
- * branch head. Seeds the RefineContext consumed by every later stage.
317
- */
318
- private refineResolveRefsStage;
319
- /**
320
- * validation stage: run the refinery validation gate (typecheck / test /
321
- * lint / build per node config) and block on failure or when no allowlisted
322
- * command was available. On pass, stores the summary on the context.
323
- */
324
- private refineValidationStage;
325
- /**
326
- * patch_equivalence stage: preflight that the worktree branch's cumulative
327
- * patch is equivalent to base+branch. On a "behind base" branch, auto-rebase
328
- * once and re-check; on an empty merge-tree with real branch changes, treat as
329
- * already-merged-via-another-path and short-circuit to cleanup. Mutates the
330
- * context's branchHead (after rebase) and patchEquivalence (rebased gate).
331
- */
332
- private refinePatchEquivalenceStage;
333
- /**
334
- * submodule_reachability stage: verify every submodule gitlink commit that
335
- * would land via the merge is reachable from its configured remote main
336
- * branch (optionally auto-publishing when policy allows). Blocks the merge
337
- * when any commit is unreachable. Stores the result on the context.
338
- */
339
- private refineSubmoduleReachabilityStage;
340
- /**
341
- * effective_diff stage (no-op guard): block a silent no-op merge where the
342
- * branch produces no effective root-tree diff against base — typically a
343
- * submodule that has commits but whose root-level gitlink (pointer) bump was
344
- * never committed, so the merge would land nothing real on main.
345
- */
346
- private refineEffectiveDiffStage;
347
- /**
348
- * merge + finalize stage: perform the --no-ff merge, align submodule
349
- * checkouts after merge, clean up (remove) the worktree node per policy,
350
- * append the refinery ledger entry, and (unless approval is required) push the
351
- * base branch. Always terminal — produces the final CommandRouterResult.
352
- */
353
- private refineMergeAndFinalizeStage;
354
- /**
355
- * Batch refinery: converge multiple sibling worktree nodes onto the base branch
356
- * in one sequential pipeline, absorbing the rebase + patch-equivalence churn that
357
- * arises when several siblings touch the same submodule.
358
- *
359
- * Reuses executeMeshRefineNodeSynchronously per node — every node goes through the
360
- * exact same validation / patch-equivalence / submodule-reachability / merge / cleanup
361
- * gates, including its built-in auto-rebase onto fresh origin/<base>. Because each
362
- * node fetches origin/<base> at the start of its own refine, a node merged earlier in
363
- * the batch advances the base, and the next node's refine auto-rebases onto it before
364
- * re-running patch-equivalence. No force-push, no reset — conflicting nodes are
365
- * isolated as blocked_review while the rest of the batch proceeds.
366
- */
367
349
  private batchRefineMeshNodes;
368
- /**
369
- * Convergence core shared by the synchronous batch entry and the async batch job.
370
- * Refines each node in order: the per-node refine pipeline fetches origin/<base>
371
- * fresh, so each merged sibling advances the base before the next node's auto-rebase
372
- * + patch-equivalence re-check. A blocked/failed node is isolated; the batch
373
- * continues with the remaining nodes. Does NOT touch the per-node merge logic — it
374
- * only sequences calls to executeMeshRefineNodeSynchronously and aggregates outcomes.
375
- */
376
- private runMeshRefineBatchConvergence;
377
- private buildRefineBatchJobKey;
378
- private buildRefineBatchJobHandle;
379
- /**
380
- * Emit a batch Refinery terminal/accepted event through the SAME pending-event +
381
- * forward mechanism single-node refine uses (queueRefineJobEvent), so the
382
- * coordinator's existing refine:accepted/completed/failed handling and message
383
- * renderer apply unchanged. The aggregate per-node results ride along in `result`.
384
- */
385
- private queueRefineBatchJobEvent;
386
- private appendRefineBatchJobLedger;
387
- private finishMeshRefineBatchJob;
388
- /**
389
- * Async entry for the batch Refinery execute path. Mirrors startMeshRefineJob:
390
- * resolves the plan synchronously (so target/ordering errors and the dry-run shape
391
- * stay synchronous), then for execute=true registers an in-flight batch job, returns
392
- * {async:true, status:'accepted', batch:true, ...plan} immediately, and runs the
393
- * convergence loop in the background — emitting the same terminal refine event.
394
- * Idempotent: a batch already in flight for this mesh returns the running handle
395
- * with duplicate:true rather than spawning a second background job.
396
- */
397
350
  private startMeshRefineBatchJob;
398
- private finishMeshRefineJob;
399
351
  private startMeshRefineJob;
400
352
  /**
401
353
  * Daemon-level command execution (IDE start/stop/restart, CLI, detect, logs).