import type { DaemonCommandRouter, CommandRouterResult } from './router.js';
import { MeshRefineAsyncJobStatus, MeshRefineBatchJobHandle, MeshRefineBatchJobStatus, MeshRefineJobHandle, RefineContext, RefineStageOutcome } from '../mesh/mesh-refine-gates.js';
export declare function buildRefineJobKey(self: DaemonCommandRouter, meshId: string, nodeId: string): string;
export declare function buildRefineJobHandle(self: DaemonCommandRouter, args: {
    meshId: string;
    nodeId: string;
    node?: any;
    status?: MeshRefineAsyncJobStatus;
    startedAt?: string;
    completedAt?: string;
    jobId?: string;
    interactionId?: string;
    retryOfJobId?: string;
    coordinatorDaemonId?: string;
}): MeshRefineJobHandle;
/**
 * QW2: extract a compact failure diagnostic from a validation summary — the first
 * failing command's name, its exit code, its failureKind, and a bounded output tail.
 * Surfaced in BOTH the slim coordinator event and the ledger blockerContext so a
 * coordinator can decide next-step without pulling and parsing the full ledger record.
 *
 * A command record carries `passed` (boolean), never `success` (see QW1) — the first
 * record with passed===false is the gate's failing command. Returns undefined when the
 * summary did not fail on a command (e.g. bootstrap-stage failure with no commandsRun
 * entry), in which case the top-level failureCode/failureKind still describe the cause.
 */
export declare function extractValidationFailureDiagnostics(validationSummary: Record<string, unknown> | undefined): {
    firstFailedCommand?: string;
    exitCode?: unknown;
    failureKind?: unknown;
    outputTail?: string;
} | undefined;
/**
 * Slim the terminal-stage refine result down to the fields a coordinator needs to
 * decide next-step, dropping the heavy per-command / per-entry detail.
 *
 * The full `CommandRouterResult` (with `validationSummary.commandsRun[]` carrying
 * per-command stdout/stderr, `rejectedCommands`, `suggestions`, `suggestedConfig`,
 * the full `patchEquivalence`, and `submoduleReachability.entries[]`/`.unreachable[]`)
 * routinely exceeds 70KB and overflows the coordinator token limit when surfaced as a
 * coordinator event payload. The full detail is still persisted verbatim to the ledger
 * (`appendRefineJobLedger`) and `terminalRefineJobs`, so slimming only the EVENT loses
 * nothing — the coordinator can pull the full record on demand via
 * `evidence.ledgerCommand` / `taskHistoryKind`.
 */
export declare function slimRefineEventResult(result: Record<string, unknown>): Record<string, unknown>;
export declare function queueRefineJobEvent(self: DaemonCommandRouter, event: 'refine:accepted' | 'refine:completed' | 'refine:failed', handle: MeshRefineJobHandle, result?: Record<string, unknown>): void;
export declare function appendRefineJobLedger(self: DaemonCommandRouter, kind: 'task_dispatched' | 'task_completed' | 'task_failed', handle: MeshRefineJobHandle, result?: Record<string, unknown>): Promise<void>;
/**
 * On daemon restart, scan all mesh ledgers for refine jobs that were dispatched
 * but never completed/failed (i.e. the daemon died mid-job).  Re-queue each one
 * so the job runs to completion automatically without coordinator intervention.
 */
export declare function resumePendingRefineJobsOnStartup(self: DaemonCommandRouter): Promise<void>;
/**
 * Synchronous refinery for a single worktree node — the gate pipeline that
 * validates, preflights (patch-equivalence / submodule-reachability /
 * no-op), merges, aligns submodules, cleans up the worktree node and
 * (optionally) pushes. The body is a flat sequence of stage methods; each
 * stage either returns a terminal CommandRouterResult (gate failure or a
 * successful already-merged short-circuit) or `continue` with the extended
 * context. Behavior — stage order, every early-exit, and every result shape —
 * is identical to the previous single inlined body.
 */
export declare function executeMeshRefineNodeSynchronously(self: DaemonCommandRouter, meshId: string, nodeId: string, args: any): Promise<CommandRouterResult>;
/**
 * resolve_refs stage: resolve the mesh / worktree node / source node /
 * repoRoot, then the worktree branch, base branch, fetched base head and
 * branch head. Seeds the RefineContext consumed by every later stage.
 */
export declare function refineResolveRefsStage(self: DaemonCommandRouter, meshId: string, nodeId: string, args: any, refineStages: Array<Record<string, unknown>>): Promise<RefineStageOutcome>;
/**
 * DS2 sync_base stage: bring the worktree branch up to the pinned baseHead BEFORE
 * validation, so every later gate (validation, patch_equivalence, merge) sees the
 * final rebased tree rather than a stale pre-rebase one.
 *
 * The old auto-rebase lived inside patch_equivalence and only fired when branchHead
 * was a STRICT ANCESTOR of baseHead (`merge-base --is-ancestor`). A diverged laggard
 * — the branch has its own commits AND base moved underneath it (ahead>0 AND behind>0)
 * — failed that ancestor check, so it was never rebased and fell straight to
 * patch_equivalence_failed / blocked_review even though a clean rebase would have
 * converged it. Here we compute ahead/behind explicitly and rebase whenever behind>0
 * (strictly-behind OR diverged), aborting to blocked_review only on a real conflict.
 *
 * On a successful rebase we recompute branchHead and re-derive changeImpact against
 * the rebased tree (its baseHead..branchHead diff changed), and record the
 * `patch_equivalence_after_auto_rebase` stage so the batch/ancestry assertions can see
 * the rebase happened. When the branch is already up to date (behind===0), this is a
 * no-op passed stage.
 */
export declare function refineSyncBaseStage(self: DaemonCommandRouter, ctx: RefineContext): Promise<RefineStageOutcome>;
/**
 * validation stage: run the refinery validation gate (typecheck / test /
 * lint / build per node config) and block on failure or when no allowlisted
 * command was available. On pass, stores the summary on the context.
 */
export declare function refineValidationStage(self: DaemonCommandRouter, ctx: RefineContext): Promise<RefineStageOutcome>;
/**
 * patch_equivalence stage: preflight that the worktree branch's cumulative patch is
 * equivalent to base+branch. The DS2 sync_base stage already rebased any behind/diverged
 * branch onto the pinned baseHead, so this is now a pure check: equivalent → continue;
 * empty merge-tree with real branch changes → already-merged-via-another-path
 * short-circuit to cleanup; otherwise → patch_equivalence_failed / blocked_review.
 */
export declare function refinePatchEquivalenceStage(self: DaemonCommandRouter, ctx: RefineContext): Promise<RefineStageOutcome>;
/**
 * submodule_reachability stage: verify every submodule gitlink commit that
 * would land via the merge is reachable from its configured remote main
 * branch (optionally auto-publishing when policy allows). Blocks the merge
 * when any commit is unreachable. Stores the result on the context.
 */
export declare function refineSubmoduleReachabilityStage(self: DaemonCommandRouter, ctx: RefineContext): Promise<RefineStageOutcome>;
/**
 * effective_diff stage (no-op guard): block a silent no-op merge where the
 * branch produces no effective root-tree diff against base — typically a
 * submodule that has commits but whose root-level gitlink (pointer) bump was
 * never committed, so the merge would land nothing real on main.
 */
export declare function refineEffectiveDiffStage(self: DaemonCommandRouter, ctx: RefineContext): Promise<RefineStageOutcome>;
/**
 * DS3: after a successful Refinery push advanced origin/<baseBranch>, bring the
 * ORIGINATING COORDINATOR daemon's own local base checkout up to the pushed commit so
 * the coordinator isn't silently left behind (the "merged to main but my local main is
 * stale" gap). Guarded and NON-destructive:
 *
 *   - If the coordinator's base node is hosted by THIS daemon and is reachable locally,
 *     run fastForwardMeshNode(mode:'merge') on it directly. That helper is itself the
 *     guard: it only ff-only-merges when the workspace is clean, ahead=0 and behind>0;
 *     an ahead/diverged/dirty coordinator returns a structured block (never a rebase).
 *   - If the coordinator is a DIFFERENT daemon (remote), we cannot touch its checkout
 *     from here, so we queue a `coordinator_catchup` pending event targeted at that
 *     coordinator daemon; its reconcile loop / next mesh-tool call drains it and runs the
 *     same guarded fast-forward locally (busy → naturally deferred to the next idle edge).
 *
 * Best-effort and advisory: the caller never fails the refine on a catch-up problem. The
 * refine's own repoRoot IS the base it just merged+pushed, so when the coordinator IS this
 * daemon and IS repoRoot the ff is a no-op `already_up_to_date` — correct and harmless.
 * Returns a compact summary for the stage record, or undefined when there's nothing to do.
 */
export declare function requestCoordinatorLocalCatchup(self: DaemonCommandRouter, params: {
    meshId: string;
    ctx: RefineContext;
    mesh: any;
    baseBranch: string;
    repoRoot: string;
}): Promise<Record<string, unknown> | undefined>;
/**
 * merge + finalize stage: perform the --no-ff merge, align submodule
 * checkouts after merge, clean up (remove) the worktree node per policy,
 * append the refinery ledger entry, and (unless approval is required) push the
 * base branch. Always terminal — produces the final CommandRouterResult.
 */
export declare function refineMergeAndFinalizeStage(self: DaemonCommandRouter, ctx: RefineContext): Promise<RefineStageOutcome>;
/**
 * DS2 CAS + DS1 order: the base-lease-protected core of merge/finalize. Before the
 * merge it re-fetches origin/<baseBranch> and compare-and-swaps the live origin SHA
 * against the pinned baseHead from resolve_refs; if the base moved, it terminates
 * retryable (base_moved) WITHOUT merging so a re-run rebases onto and validates the
 * new base. DS1: on the auto-push path the order is merge → push → cleanup, so a push
 * failure leaves the worktree/branch intact (cleanup withheld) and is reported as a
 * terminal blocked state — the batch never counts an un-pushed node as merged.
 */
export declare function runRefineMergeAndFinalizeLocked(self: DaemonCommandRouter, ctx: RefineContext): Promise<RefineStageOutcome>;
/**
 * Batch refinery: converge multiple sibling worktree nodes onto the base branch
 * in one sequential pipeline, absorbing the rebase + patch-equivalence churn that
 * arises when several siblings touch the same submodule.
 *
 * Reuses executeMeshRefineNodeSynchronously per node — every node goes through the
 * exact same validation / patch-equivalence / submodule-reachability / merge / cleanup
 * gates, including its built-in auto-rebase onto fresh origin/<base>. Because each
 * node fetches origin/<base> at the start of its own refine, a node merged earlier in
 * the batch advances the base, and the next node's refine auto-rebases onto it before
 * re-running patch-equivalence. No force-push, no reset — conflicting nodes are
 * isolated as blocked_review while the rest of the batch proceeds.
 */
export declare function batchRefineMeshNodes(self: DaemonCommandRouter, meshId: string, requestedNodeIds: string[] | undefined, args: any): Promise<CommandRouterResult>;
export type BatchNodeConvergence = 'merged_to_main' | 'blocked_review' | 'skipped_patch_equivalent' | 'not_mergeable';
export declare function classifyBatchNodeConvergence(result: Record<string, unknown>): {
    convergence: BatchNodeConvergence;
    code: string;
    stage?: string;
    retryable: boolean;
};
/**
 * Convergence core shared by the synchronous batch entry and the async batch job.
 * Refines each node in order: the per-node refine pipeline fetches origin/<base>
 * fresh, so each merged sibling advances the base before the next node's auto-rebase
 * + patch-equivalence re-check. A blocked/failed node is isolated; the batch
 * continues with the remaining nodes. Does NOT touch the per-node merge logic — it
 * only sequences calls to executeMeshRefineNodeSynchronously and aggregates outcomes.
 */
export declare function runMeshRefineBatchConvergence(self: DaemonCommandRouter, meshId: string, orderedNodes: any[], ordering: {
    order: string[];
    rationale?: unknown;
}, args: any): Promise<CommandRouterResult>;
export declare function buildRefineBatchJobKey(self: DaemonCommandRouter, meshId: string): string;
export declare function buildRefineBatchJobHandle(self: DaemonCommandRouter, args: {
    meshId: string;
    nodeIds: string[];
    order: string[];
    status?: MeshRefineBatchJobStatus;
    startedAt?: string;
    completedAt?: string;
    jobId?: string;
    interactionId?: string;
    coordinatorDaemonId?: string;
}): MeshRefineBatchJobHandle;
/**
 * Emit a batch Refinery terminal/accepted event through the SAME pending-event +
 * forward mechanism single-node refine uses (queueRefineJobEvent), so the
 * coordinator's existing refine:accepted/completed/failed handling and message
 * renderer apply unchanged. The aggregate per-node results ride along in `result`.
 */
export declare function queueRefineBatchJobEvent(self: DaemonCommandRouter, event: 'refine:accepted' | 'refine:completed' | 'refine:failed', handle: MeshRefineBatchJobHandle, result?: Record<string, unknown>): void;
export declare function appendRefineBatchJobLedger(self: DaemonCommandRouter, kind: 'task_dispatched' | 'task_completed' | 'task_failed', handle: MeshRefineBatchJobHandle, result?: Record<string, unknown>): Promise<void>;
export declare function finishMeshRefineBatchJob(self: DaemonCommandRouter, handle: MeshRefineBatchJobHandle, orderedNodes: any[], ordering: {
    order: string[];
    rationale?: unknown;
}, args: any): Promise<void>;
/**
 * Async entry for the batch Refinery execute path. Mirrors startMeshRefineJob:
 * resolves the plan synchronously (so target/ordering errors and the dry-run shape
 * stay synchronous), then for execute=true registers an in-flight batch job, returns
 * {async:true, status:'accepted', batch:true, ...plan} immediately, and runs the
 * convergence loop in the background — emitting the same terminal refine event.
 * Idempotent: a batch already in flight for this mesh returns the running handle
 * with duplicate:true rather than spawning a second background job.
 */
export declare function startMeshRefineBatchJob(self: DaemonCommandRouter, meshId: string, requestedNodeIds: string[] | undefined, args: any): Promise<CommandRouterResult>;
export declare function finishMeshRefineJob(self: DaemonCommandRouter, handle: MeshRefineJobHandle, args: any): Promise<void>;
export declare function startMeshRefineJob(self: DaemonCommandRouter, meshId: string, nodeId: string, args: any): Promise<CommandRouterResult>;
