/**
 * scripts/rows — the `script` row: built from one call, filed through ONE
 * writer, read back per turn, and bounded.
 *
 * Pattern: Map + one writer (the `findings/ledger.ts` · `recordFindings`
 *          twin for this kind): `scriptRowFor` builds, `recordScriptRow` is
 *          the only thing that writes a `script` row, `scriptRowsOfTurn` is
 *          the one reader the match and the attachment share.
 * Role:    core/ layer leaf. Called by the dispatch loop (`stages/toolCalls.ts`)
 *          at each place a call of a declared code-running tool pauses or
 *          settles; read by the Route decider's judge and the final branch.
 * Emits:   N/A — the row is state; the runner's facts already rode
 *          `agentfootprint.tools.code_run`, which never carries the code.
 *
 * ## One unit, and the bounds (design § 4.4)
 *
 * UTF-8 payload bytes of the program, measured at record time
 * (`lib/utf8.ts` · `utf8Length`) — never characters: 32,768 characters of a
 * 3-byte character are 98,304 bytes.
 *
 * - **Per script.** A program over {@link MAX_SCRIPT_BYTES} keeps a row with
 *   `bytes`, `lines` and the outcome, and no `text`: it can be neither matched
 *   nor attached.
 * - **Per turn.** {@link MAX_SCRIPT_ROWS} calls keep a row; a further call of
 *   the turn files none and is counted in `AgentState.scriptsDropped`.
 * - **Eligible text.** A row's `text` lives for its own turn: the seed stage's
 *   restore drops it from every earlier turn's row (`withoutEarlierScriptText`),
 *   so the text the ledger holds is at most 16 × 32,768 bytes = 512 KiB before
 *   serialization, whatever the conversation's length. That bounds eligible
 *   text only — prior turns' metadata, history and the answers that carried an
 *   attached script are outside it.
 *
 * ## Append only, last wins
 *
 * A call PAUSED before it settles (a check-in, a consent, an ask, a tool that
 * asked a person) files a `submitted` row at the pause, WITHOUT its text: the
 * settled row filed when the call resumes is the one that carries it, so a
 * program is never held twice. A reader takes the LAST row per call of the
 * turn (the ledger's own law). A row that never settles stays `submitted`.
 */
import type { ToolScript } from '../../../tools/script.js';
import type { FindingsLedger } from '../findings/types.js';
import { type CallSettlement, type RunnerOutcome } from './label.js';
import type { ScriptRow } from './types.js';
/** A program longer than this (UTF-8 bytes) keeps a row with no text. Design § 4.4. */
export declare const MAX_SCRIPT_BYTES = 32768;
/** Calls per turn that keep a row; the rest are counted. Design § 4.4. */
export declare const MAX_SCRIPT_ROWS = 16;
/** Lines of a program: LF-separated, `0` for an empty one. */
export declare function linesOf(program: string): number;
/** One call of a declared code-running tool, as the dispatch loop knows it. */
export interface ScriptCall {
    readonly script: ToolScript;
    /** The name the model called. */
    readonly tool: string;
    readonly toolCallId: string;
    readonly iteration: number;
    /** `AgentState.turnNumber`. */
    readonly turn: number;
    /**
     * The declared argument's VALUE as the model proposed it — read once, as
     * the call arrived, before any before-tool rule ran (`programIn`). A string
     * is immutable: no code that runs later can change what was captured.
     */
    readonly proposed: unknown;
    /**
     * The declared argument's value as handed to `execute` — read once, just
     * before the tool ran, after every rule. Absent: the call never got there,
     * and the proposal stands.
     */
    readonly submitted?: unknown;
    readonly settlement: CallSettlement;
    /** The runner's facts, when the tool filed them. */
    readonly facts?: RunnerOutcome;
    /** The tool's own ceiling replaced the delivered result. */
    readonly withheld?: boolean;
    /** A pause: the row is filed without its text (the settled row carries it). */
    readonly paused?: boolean;
}
/**
 * The declared argument's value in `args` — the one read a call's program is
 * captured with. Read it at the boundary it names (as the call arrives; just
 * before `execute`) and keep the value: never the arguments object, which app
 * code may edit after it was handed over.
 */
export declare function programIn(script: ToolScript, args: Readonly<Record<string, unknown>> | undefined): unknown;
/** A row before the writer gives it its dispatch identity. */
export type ScriptRowDraft = Omit<ScriptRow, 'dispatch'>;
/**
 * The row for one call, or `undefined` when the call carried no program — the
 * declared argument is not a string (an argument check refuses such a call;
 * there is nothing to record as "the program submitted").
 */
export declare function scriptRowFor(call: ScriptCall): ScriptRowDraft | undefined;
/** The scope surface the writer needs. Structurally a `TypedScope<AgentState>`. */
export interface ScriptScope {
    findingsLedger?: FindingsLedger;
    scriptsDropped?: number;
}
/**
 * THE ONE WRITER of a `script` row, and the one place a call gets its
 * DISPATCH identity: the 1-based order of the actual dispatch within its turn.
 * A call is a dispatch, never a provider id: a later call that reuses an id is
 * a new dispatch. `options.dispatch` names a dispatch that already has a row
 * (a paused call, settling): its row joins that dispatch.
 *
 * Appended, unless the turn already holds {@link MAX_SCRIPT_ROWS} other
 * dispatches — then the call files nothing and `scriptsDropped` counts it
 * (value-conditional: absent until a call is dropped). A dispatch that already
 * has a row is never dropped, and a PAUSE is never counted (`paused`): its call
 * is counted once, when it settles. Returns the dispatch the row was filed
 * under, `undefined` when it was dropped. Synchronous: one read, one write, no
 * await between.
 */
export declare function recordScriptRow(scope: ScriptScope, draft: ScriptRowDraft, options?: {
    readonly paused?: boolean;
    readonly dispatch?: number;
}): number | undefined;
/** This turn's calls — the LAST row of each dispatch, in the order those rows were filed. */
export interface TurnScripts {
    readonly current: readonly ScriptRow[];
    /** Calls of EARLIER turns on the ledger: counted, never compared. */
    readonly earlier: number;
}
/**
 * The one reader of a turn's script rows: the last row per DISPATCH wins, and
 * a dispatch sits where its last row was filed — execution order, so a call
 * that settles after a later one ran is read after it. Earlier turns counted.
 */
export declare function scriptRowsOfTurn(ledger: readonly unknown[] | undefined, turn: number): TurnScripts;
/**
 * The restore door's half of the bound (seed): every `script` row of a turn
 * BEFORE `turn` keeps its facts — ids, counts, outcome — and loses its `text`.
 * The same reference when there is nothing to drop, so a ledger without
 * script text is restored byte for byte.
 */
export declare function withoutEarlierScriptText<T>(ledger: readonly T[], turn: number): readonly T[];
/**
 * Whether a value read from a stored checkpoint is a `script` row this library
 * could have written — the checkpoint door's arm (`core/runCheckpoint.ts`).
 * An older runtime refuses a checkpoint carrying one.
 */
export declare function scriptRowIsWellFormed(r: Readonly<Record<string, unknown>>): boolean;
