/**
 * # session/controller — the transport-neutral incremental Session controller (kestrel-djm.4)
 *
 * The ONE programmatic, in-process interaction controller over {@link SessionCore}: it replaces the
 * file-polling author handshake ({@link import("./day.ts").runDaySession} / `fileHandshakeAgent`) with a
 * pure pull API — no filesystem, no directory, no transport — that a caller drives verb by verb:
 *
 *     start → advance → revise → resume → finalize          (+ submit — the explicit-binding wire path)
 *
 * It is the L1 (pure core: derive/admit/seal) + L2 (ergonomic surface) of djm.2's protocol v0.2 stack; L0
 * (the {@link SessionMessage} union, the {@link TurnEntry} pentad, {@link reconcileTurn}) already landed in
 * `src/protocol/session.ts`. Each response BINDS the transcript pentad `(sessionId, ordinal, parentHash,
 * frameRoot, authoredSha256)`, and every admit/refuse routes the idempotency + fail-closed ladder through
 * the SAME {@link reconcileTurn} primitive — never a bespoke check.
 *
 * ## NO-REIMPLEMENT — one truth (the non-negotiable)
 * The controller does not fork a second Session progression. It WRAPS {@link runSimulateSession} exactly
 * once via a **channel/coroutine {@link Agent}** whose `open`/`decide` suspend, hand the frozen Frame out to
 * the caller, and resume with the caller's answer. The driver's own WakeFrontier (`popNext` / `armStaleness`
 * / MIN_WAKE_SPACING / the staleness backstop) decides Wake eligibility, and the SAME `core.settle()` /
 * `core.blotter()` finalizes. So a controller-driven agent-day is BYTE-IDENTICAL to the one-shot/file path
 * over the same authored transcript (no golden churn): the coroutine emits the identical {@link AgentTurn}s
 * that a scripted `Agent` would, at the identical wake ts, onto the identical graded Bus.
 *
 * ## DETERMINISM
 * The genesis seals the pure-data spec, so `SessionId = sha256(genesis)` is a host-independent function of
 * `(bus, config, wakes, fillModel, rUsd, …)` — a different config axis ⇒ a different Session. Nothing on the
 * record path reads a wall clock or an unseeded RNG (the coroutine handoff is above the determinism line;
 * the returned turn is the only value that crosses). Identical Bus + identical authored transcript ⇒
 * byte-identical Blotter + graded-bus sha256, and `resume` IS re-derivation (nothing to restore).
 *
 * ## FAIL CLOSED — typed refusals, state untouched (djm.2 reuse)
 * An ineligible advance (`sealed` after finalize, `not-pending` at settle), a cursor mismatch
 * (`broken-chain`), or a changed-bytes-same-slot revision (`turn-conflict`) each REFUSE with a typed
 * {@link SessionDiagnostic}; a byte-identical re-submit is idempotent (content-addressing IS idempotency).
 * An explicit STAND_DOWN records a gradable `stand-down` body — FOREVER distinct from a host `failure`.
 *
 * ## 7dv.4 soft-sequencing note (bd note deferred to the orchestrator — hard rules forbid `.beads` writes)
 * The PUBLIC surface here is PROTOCOL-DEFINED (start/advance/revise/resume/finalize + submit, over the
 * SessionMessage/TurnEntry shapes of protocol v0.2), NOT today's internal driver shape. The INTERNAL wiring
 * to {@link runSimulateSession}/{@link SessionCore} is an implementation detail the later 7dv.4
 * session-unbundle may re-home WITHOUT changing this interface — the tests assert only the observable
 * contract (byte-identity, pentad binding, typed refusals), never a driver internal.
 */
import type { Blotter } from "../blotter/index.ts";
import type { EventCursor } from "../protocol/index.ts";
import { type SessionId, type TurnEntry } from "../protocol/session.ts";
import type { AgentConfig, CapturedTurns } from "./agent.ts";
import { type RunSimulateOptions } from "./simulate.ts";
import type { AuthoredResponse, BoundResponse, Delivery, SessionFrame, SessionResponse, SessionTranscript, TurnDisposition, TurnReceipt } from "./controller-types.ts";
export type { AuthoredResponse, BoundResponse, Delivery, SessionFrame, SessionResponse, SessionTranscript, TurnDisposition, TurnReceipt, };
/**
 * The pure-data knobs a Session runs on — exactly what {@link runSimulateSession} consumes minus the push
 * `agent` (the CALLER is the author now, answering incrementally) and minus any handshake directory (this is
 * in-process), PLUS the pinned {@link AgentConfig} comparison axis. Spec-as-data: the genesis seals THIS
 * object, so {@link SessionController.sessionId} is its deterministic content hash.
 */
export interface SessionSpec extends Omit<RunSimulateOptions, "agent"> {
    /** The comparison axis pinned to this Session (folded into the genesis ⇒ a different config = a different
     * Session). A NO-LLM Backtest carries {@link import("./agent.ts").BACKTEST_CONFIG}. */
    readonly config: AgentConfig;
}
/**
 * The sealed Session (`session/finalize`): the graded {@link Blotter} + the {@link CapturedTurns} the run
 * consumed + the run's {@link AgentConfig}, plus the Session id and `tipHash` — the receipt root a
 * CertifiedGrade can pin (the tail of the pentad chain).
 */
export interface SessionFinalized {
    readonly blotter: Blotter;
    readonly captured: CapturedTurns;
    readonly config: AgentConfig;
    readonly sessionId: SessionId;
    readonly tipHash: string;
}
/**
 * The transport-neutral incremental Session controller — the ONE programmatic surface over
 * {@link SessionCore}. Mint one with {@link openSession} (a live author) or {@link resumeSession} (re-derive
 * from a committed transcript). Every method is a pure driver OVER the existing progression, never a fork.
 */
export interface SessionController {
    /** The deterministic Session identity (= the genesis hash of the sealed spec). Available immediately. */
    readonly sessionId: SessionId;
    /** START: mint the run and deliver the date-blind OPEN Frame (ordinal {@link OPEN_ORDINAL}). */
    start(): Promise<Delivery>;
    /** AUTHORED-OR-STAND-DOWN: commit the pending slot, then deliver the next eligible Wake (or `null` at
     * settle). Fails closed if nothing is pending (`not-pending`) or the chain is sealed (`sealed`). */
    advance(response: AuthoredResponse): Promise<SessionResponse>;
    /** REVISION: author a superseding document at the current pending slot (disposition `revised` once armed).
     * Behaviourally identical to {@link advance} — a revision is just another turn at the delivered slot. */
    revise(response: AuthoredResponse): Promise<SessionResponse>;
    /** EXPLICIT-BINDING turn: reconcile a fully-bound {@link BoundResponse} against the recorded slot via
     * {@link reconcileTurn} — idempotent on a byte-identical re-send, typed-refusal on a conflict/mismatch. */
    submit(response: BoundResponse): Promise<SessionResponse>;
    /** RESUME: re-derive the committed transcript (pure — nothing to restore). `after` is accepted for the
     * cursor-replay contract; the full transcript is always a correct superset for re-derivation. */
    resume(after?: EventCursor): SessionTranscript;
    /** FINALIZE: drive to settle through the SAME Bus/Blotter/Grade path and seal the chain. */
    finalize(): Promise<SessionFinalized>;
}
/** Mint a live controller over `spec`: the caller authors each turn incrementally. */
export declare function openSession(spec: SessionSpec): SessionController;
/**
 * Re-derive a controller from a committed `transcript` (resume IS re-derivation). Construction is
 * synchronous (the {@link SessionController.sessionId} is available at once); {@link SessionController.finalize}
 * replays the transcript's authored turns through the SAME driver to reconstruct a byte-identical Blotter.
 */
export declare function resumeSession(spec: SessionSpec, transcript: readonly TurnEntry[]): SessionController;
//# sourceMappingURL=controller.d.ts.map