/**
 * design/376 片② — the host CONSOLIDATION DRIVER verb: one call that takes a long-accumulated,
 * never-consolidated library to its fold fixpoint through the four engine verbs, as a PERSISTENT
 * MULTI-CYCLE RUN.
 *
 * Why a run is a first-class object: under factory defaults a cold-start consolidation is a
 * dozen-plus cycles with a hard 60-second throttle floor between them — a persistent job measured
 * in minutes, not a call. The engine deliberately keeps NO driver state (its gate row settles per
 * plan and clears the session count), so without a durable run account a process exit between two
 * cycles would strand the work: no open plan to reconcile, no session edge to re-arm, and a naive
 * re-entry would re-mint the whole plan at full model cost. The run row under the control plane is
 * the resume seat: `runMemoryConsolidation` first looks for a PENDING run of the scope and
 * CONTINUES it (same plan cache, same force requestId, zero new mint) — the idempotent re-entry
 * GD-15 pins.
 *
 * Boundary reminders (design/339 §1.1, unchanged by this module):
 *  - the engine adjudicates and commits; this driver only proposes and schedules — every write
 *    goes through `commitConsolidationPlan`, nothing here touches the store;
 *  - the engine holds no model seat; the model reaches this module as an explicit chat function;
 *  - core still owns no timer: the throttle waits here run INSIDE a host's explicit call (or the
 *    auto lane's task-boundary tick), never on a background schedule of core's own.
 */
import type { EngineNotice } from "../types.js";
import { type ConsolidationGateRow, CONSOLIDATION_WRITE_REFUSED_CODE, type ConsolidationRunStopReason, type MemoryConsolidationOptions } from "./consolidation.js";
import { type ConsolidationPlanFoldEvidence, type ConsolidationPlanSummary } from "./engine.js";
import type { SyntheticWriteVerdict } from "../synthetic-read-verdict.js";
import { mintLlmConsolidationPlan, type ConsolidationDriveCycleRow, type ConsolidationDriveEngine, type ConsolidationFoldState, type DistillerChatFn, type LlmConsolidationPlan, type LlmConsolidationPlanProduct, type LlmDistillerContract } from "./distiller.js";
export declare const CONSOLIDATION_DRIVER_RUNS_FILE = "distiller-runs.json";
/** §1.6-4 — the mint archive: what was shown to the model and what it answered, verbatim, per run
 *  (the fold law's audit other-half; strict-family placement beside the plan workbook). */
export declare const CONSOLIDATION_DRIVER_PLANS_DIR = "distiller-plans";
export interface ConsolidationDriverRunRow {
    runId: string;
    scope: string;
    /** The WRITER claim: every open/resume bumps this under the run
     *  store's lock, and every later write of the row is conditional on (runId, attempt) still
     *  standing — of two invocations that raced onto one scope, exactly one keeps writing; the
     *  superseded one stops with a coded error instead of silently clobbering the winner's counters
     *  or terminal state. (Model spend under a genuine concurrent double-call is still at-least-once
     *  — the claim serializes the ACCOUNT; the engine's plan-seat CAS serializes the store, and
     *  cross-node cost suppression is the engine lease seat's job.) */
    attempt: number;
    /** The run-scoped force credential: ONE requestId across every forced snapshot of the run (the
     *  engine dedups the FORCED audit announcement on it — one line per run). */
    requestId: string;
    /** The contract version of the run's surviving MINT — stamped at open, RE-stamped (with
     *  {@link model}) by a resume that re-mints. */
    contractVersion: string;
    /** The id that minted the run's surviving plan: stamped at open; RE-stamped on a resume that
     *  re-mints (the plan cache absent — nothing of the opening mint survived, so the current seat
     *  mints every byte this run commits). The per-attempt plan archive is the byte-level anchor
     *  either way. */
    model: string;
    startedAt: number;
    state: "pending" | "settled";
    /** Terminal only; the ONE closed set the receipt and the `_incomplete` notice share. */
    outcome?: ConsolidationRunStopReason;
    settledAt?: number;
    stopDetail?: string;
    /** The minted plan's replayable half (mint ONCE per run; each cycle filters, never re-mints).
     *  design/376-C1: `mintExposure` + `servedCandidates` ride the cache — the attestation threads
     *  onto every cycle's proposal, the roster feeds the cross-cycle invalidation predicate. Rows
     *  cached before the fields existed replay UN-attested with no roster check (run-level fold —
     *  exactly the treatment their whole-library prompts earned). */
    planCache?: {
        maxInputsPerProduct: number;
        products: LlmConsolidationPlanProduct[];
        mintExposure?: "partitioned";
        servedCandidates?: Array<{
            id: string;
            rev: string;
            marked: boolean;
        }>;
    };
    /** design/376-C1 A-5 disclosure — marked candidates withheld from the clean arm's prompts at
     *  mint time (present ⇔ the partition engaged over a marked library). */
    withheldFromCleanArm?: number;
    /** design/383 §1.5 ③ — of {@link withheldFromCleanArm}, how many rows were withheld from EVERY
     *  call, i.e. never sent to the provider at all (a lone marked row has no group to fold, so no
     *  arm renders it). Recorded at mint time rather than derived from the roster later: the roster
     *  dies with a discarded cache, and "your data never left this machine" must not become
     *  unanswerable because an unrelated guard fired. */
    withheldNeverSent?: number;
    /** The archived mint transcript's file name under {@link CONSOLIDATION_DRIVER_PLANS_DIR}. */
    planArchive?: string;
    /** COMMITTED cycles only (the store moved): a refused/fuse-blocked/zero-delta cycle row does
     *  not count — the receipt's "committed cycle(s)" label and the incomplete notice's zero-cycle
     *  branch both read this number as writes. */
    cyclesDone: number;
    /** Store-delta superseded total across EVERY invocation of this run (the conservation wall's
     *  evidence half — see the convergence check in the verb). Accumulated per cycle AFTER the
     *  commit, so a crash between a cycle's commit and its row write loses that cycle's delta —
     *  {@link foldBaseline} is the wall's immune second witness for exactly that window. */
    entriesSuperseded: number;
    /** The scope's fold-state `superseded` count at run OPEN (fresh claim; absent on rows opened
     *  before the field existed). The conservation wall's STORE anchor: `final.superseded − this`
     *  attests the run's folds even when a crash lands between a cycle's commit and its account
     *  write — the seat serializes this scope's folds, so the since-open delta is this run's. */
    foldBaseline?: {
        superseded: number;
    };
    planIds: string[];
    usage: {
        calls: number;
        promptTokens: number;
        completionTokens: number;
        retries: number;
        truncations: number;
    };
    repairs: {
        hallucinatedMembers: number;
        duplicateMembers: number;
        nonIntegerMembers: number;
        emptyGroups: number;
        oversizeGroups: number;
    };
    writeFailures: Array<{
        key: string;
        members: number;
        reason: string | null;
    }>;
    residue?: Array<{
        name: string;
        targets: number;
    }>;
    /** The next moment a snapshot can pass the hard throttle (resume scheduling hint). */
    nextEligibleAt?: number;
}
/** Host read face: the scope's latest driver run row (pending = resumable; settled = audit). */
export declare function readConsolidationDriverRun(controlDir: string, scope: string): ConsolidationDriverRunRow | undefined;
/** Archive one mint (prompts + transcript verbatim) beside the run account. The name carries the
 *  CLAIM (`attempt`): two invocations that raced onto one run each archive
 *  under their own name, so a superseded worker can never overwrite the winning transcript — the
 *  run row's `planArchive` (written under the attempt guard) names the one that counts. */
export declare function distillerPlanArchiveName(runId: string, attempt: number): string;
export declare function archiveDistillerPlan(controlDir: string, runId: string, plan: LlmConsolidationPlan, attempt?: number): string;
/** The engine face this verb consumes — `MemoryEngine` satisfies it structurally.
 *  (`readConsolidationPlanFoldEvidence` joined in design/376 slice ③, #436: the conservation
 *  wall's terminal witness is member-level, so the face is REQUIRED — an engine without it could
 *  only offer the store-delta counts an interleaved fold can numerically offset.) */
export interface ConsolidationDriverEngine extends ConsolidationDriveEngine {
    readConsolidationGate(scope: string): ConsolidationGateRow | undefined;
    listConsolidationPlans(): ConsolidationPlanSummary[];
    readConsolidationPlanFoldEvidence(planId: string): ConsolidationPlanFoldEvidence;
    readConsolidationFoldState(scope: string): Promise<ConsolidationFoldState>;
    /** The canonical directory a commit lands the scope's products in (the write judge's early question). */
    consolidationWriteHome(scope: string): string;
    readonly controlPlaneRoot: string;
}
/** One write the judge is asked about: `path` is a file (or the library directory) of `scope`'s library, absolute and canonical. */
export interface ConsolidationWriteTarget {
    scope: string;
    path: string;
}
/** The write judge's seat: one target in, the synthetic-write judge's verdict out (only `no_objection` permits the write). */
export type ConsolidationWriteJudge = (target: ConsolidationWriteTarget) => Promise<SyntheticWriteVerdict> | SyntheticWriteVerdict;
export { CONSOLIDATION_WRITE_REFUSED_CODE };
export interface RunMemoryConsolidationOptions {
    /** The explicit model seat (design/339 §1.1: the ENGINE holds none). Build one with
     *  `openAiCompatChatSeat` or hand any JSON-only completion function. */
    chat: DistillerChatFn;
    /** The explicit model id, recorded into the run and the archive (alias spellings refuse). */
    model: string;
    /** The write judge — REQUIRED. A run writes the library with nobody watching, so it asks the judgment a foreground write
     *  into the same library meets: the person's standing path rules and the deployment's policy, read through the ONE judge
     *  (`createSyntheticWriteJudge`; the Runner's auto lane passes the leg's own). It is asked in two places over the run, with the same
     *  seat and the same refusal: once for the library directory before any claim, seat or model call (an early refusal that
     *  spends nothing), and — the authority — where a plan is applied (a commit, a replay of a suspended plan, the drive's
     *  recovery), at the backend's final spelling of every product before any is written: a refusal there writes nothing and
     *  discards the plan.
     *  Anything but `no_objection` — a deny, an ask (nobody is present to answer it), an unreadable rule source, a
     *  throw — refuses the run with `memory.consolidation_write_refused`, and nothing is written. A host that holds no rules
     *  says so by passing a judge that answers `no_objection`; an absent seat refuses, it never reads as "no rules". */
    writeJudge: ConsolidationWriteJudge;
    /** Audit locator recorded into the archive when the seat is endpoint-shaped. */
    baseUrl?: string;
    /** The frozen prompt contract; default = the product v1 (dl-3 byte-identical). A different
     *  version here is a deployment's explicit measured choice. */
    contract?: LlmDistillerContract;
    /** The PROTOCOL knobs — pass the same object the engine was constructed with
     *  (`MemoryEngineOptions.consolidation`); the driver derives its throttle window and per-plan
     *  caps from it. Defaults = the factory defaults. */
    consolidation?: MemoryConsolidationOptions;
    /** Abort the run after this many cycles in THIS call (the run row stays pending only on crash;
     *  a reached bound settles `max_cycles`). Positive integer; default 64. */
    maxCycles?: number;
    /** R2 — the structural-repair budget over the mint's member references: the ratio of member
     *  claims the sanitiser had to DROP (hallucinated + duplicate + non-integer) to all member
     *  claims the model made. Above this, the plan does not represent the model's intent and the
     *  run aborts with zero writes rather than committing a harness-repaired fold. In [0, 1];
     *  default 0.10. (Empty groups are the same drops counted at group grain; oversize groups are
     *  not repairs — they ride on, named, and the schedule reports them infeasible. Format repairs
     *  and retries are disclosed separately and bounded by the contract's own retry count.) */
    mintRepairBudget?: number;
    /** The run's force credential; defaults to a minted id. A RESUMED run keeps its original. */
    requestId?: string;
    /** Host seams for the throttle waits (tests and hosts with their own clocks). */
    now?: () => number;
    sleep?: (ms: number) => Promise<void>;
    /** Delivery sink for the run's advisory notices, when the caller wires one: delivered at the mint, once,
     *  through the engine's notice throat, and still on the receipt. Absent ⇒ the receipt alone carries them. */
    onNotice?: (notice: EngineNotice) => void;
    onProgress?: Parameters<typeof mintLlmConsolidationPlan>[0]["onProgress"];
}
export interface ConsolidationRunReceipt {
    runId: string;
    scope: string;
    /** Whether this call CONTINUED a pending run (no new mint) instead of starting one. */
    resumed: boolean;
    outcome: ConsolidationRunStopReason;
    converged: boolean;
    stopDetail?: string;
    /** This call's cycles (store-delta accounted); `cyclesDone` is the run total across resumes. */
    cycles: ConsolidationDriveCycleRow[];
    cyclesDone: number;
    productsCommitted: number;
    entriesSuperseded: number;
    planIds: string[];
    model: string;
    contractVersion: string;
    usage: ConsolidationDriverRunRow["usage"];
    repairs: ConsolidationDriverRunRow["repairs"];
    writeFailures: ConsolidationDriverRunRow["writeFailures"];
    residue: Array<{
        name: string;
        targets: number;
    }>;
    /** design/376-C1 A-5 disclosure — marked candidates withheld from the clean arm's prompts
     *  (present ⇔ the partitioned mint engaged over a marked library). A host reading a clean
     *  product's silence about some fact key should know the current value may sit in a withheld
     *  (marked, handle-faced) row. */
    withheldFromCleanArm?: number;
    /** design/383 §1.5 ③ — of {@link withheldFromCleanArm}, the rows sent to NO call at all (never
     *  left this process). "Withheld from the clean arm" and "never sent to the provider" are
     *  different facts about a user's data; the receipt reports them separately so a host's wording
     *  can too. */
    withheldNeverSent?: number;
    planArchive?: string;
    /** Advisory notices minted for this run (the `_incomplete` disclosure when not converged). */
    notices: EngineNotice[];
    /** A failed announcement enqueue is disclosed, never allowed to fail the settled run. */
    announceFailures?: string[];
}
/**
 * Run (or RESUME) one scope's consolidation as a persistent multi-cycle job. See the module note
 * for the shape; the per-refusal behavior implements the design/376 §1.2 failure table:
 *
 *  - `_disabled` / a corrupt gate / an unreadable governance account BEFORE any commit: the coded
 *    error is rethrown (a configuration/store fault the host must repair — a pending run row, if
 *    one exists, stays resumable after the repair);
 *  - `_gated` (time/session gate): retried under the run's force requestId — the run-level force
 *    the design names; the FORCED audit line is engine-deduplicated to once per run;
 *  - `_gated` (hard throttle): the driver WAITS the window out (`min(minRunIntervalMs, 60s)`) and
 *    continues — a throttled cycle is scheduling, not a terminal;
 *  - `_busy`: never a blind snapshot retry (the seat refuses snapshots too — a blind loop spins
 *    forever): `reconcileConsolidation` first; a conflict/corrupt plan parks the run for the host
 *    valve; a live competing worker is waited out briefly, then reported;
 *  - model failures / a mint over the repair budget: the run settles `driver_failed` with ZERO
 *    writes — the mint sits between snapshot and commit, so no seat was taken, `lastRunAt` never
 *    moved and the time gate is not burned (the failure is free to retry);
 *  - a conflict plan mid-run parks (`parked`); fuse residue and the cycle bound settle
 *    `fuse_residue` / `max_cycles` with the residue named — the next run's FULL snapshot
 *    re-distills the shrunken library (cross-run = re-mint; in-run = plan cache).
 */
export declare function runMemoryConsolidationDriver(engine: ConsolidationDriverEngine, scope: string, opts: RunMemoryConsolidationOptions): Promise<ConsolidationRunReceipt>;
