import type { FlowChart, FlowChartBuilder, StructureRecorder, TypedScope } from 'footprintjs';
import type { ExternalGround } from '../../../integrity/unsupported-argument/check.js';
import type { ToolOf } from '../arguments/resolve.js';
import type { ZoneName } from '../../../time/zone.js';
import type { RanCall, ResultsLayerState } from '../results/subflow.js';
import type { AgentState } from '../types.js';
/** What an armed agent hands the inputs layer's mount — closures, never scope. */
export interface InputsMountDeps {
    /** Filter refused references before input planning can consult host-supplied sources. */
    readonly findings?: true;
    /**
     * The evidence gate's revision turns the tools off (an enforcing answer
     * validation) — present only then. The layer hands Route's dispatch test
     * the run's `toolsOffAfterRevision`, so it never asks about a call Route
     * will not run.
     */
    readonly toolsOffAfterRevision?: true;
    /** The implementation that will answer a name — the shared dispatch resolver's. */
    readonly toolOf: ToolOf;
    /**
     * A before-tool middleware chain is configured (`.toolMiddleware()`), so a
     * rewrite can supersede one of the layer's rows (the call then ran with the
     * rewrite's value). Read by the final branch's "Assumed" block
     * (`stages/prepareFinal.ts` · `prepareFinalWithLimitsAndAssumedStage`),
     * which then reads `middlewareDecisions`; absent, that key can hold no tool
     * rewrite and is never read. The mount itself does not read it.
     */
    readonly rewrites?: true;
    /**
     * DECLARED SOURCES ARE ARMED (`.findings({ argumentSources: true })` or
     * `.inputsLayer({ argumentSources: true })`) — present only then. The mount hands the layer the pieces its checks read
     * and the closures that read them; `externalGrounds` is the app's own
     * vouched-for values (`AgentOptions.externalGrounds`), an `app` source with
     * its label.
     */
    readonly sources?: {
        readonly externalGrounds?: () => readonly ExternalGround[];
        /**
         * The findings ledger is armed beside declared sources (`.findings()`) —
         * present only then: a call that declares a basis files a BASIS row in
         * ToolCalls, and that row carries the count of dropped `from` entries.
         * Absent (declared sources without the ledger), no basis row is ever
         * filed, so the count rides the call's first argument row
         * (`sourceCorpus.ts` · `declaredSourcesOf`).
         */
        readonly basisRows?: true;
        /**
         * A tool in reach may carry an arguments view — one the agent registers
         * carries one (`core/toolShownArgs.ts` · `carriesArgumentView`), or a
         * ToolProvider is wired (whatever it lists: its list is known only per
         * iteration) — present only then: no quote the model wrote is shown on a
         * row or an ask, since a quote may hold the value such a tool hides
         * (`arguments/resolve.ts` · `quotesMayShow`).
         */
        readonly argumentViews?: true;
    };
    /**
     * THE TIME LAYER IS ARMED (`.time()`) — present only then. The mount hands
     * the layer this turn's `clock` row and `time-reading` rows (`timeInputs`),
     * and the layer files one `call-window` row per call to a tool whose period
     * declares forms (`time/bind.ts`), merged into the ledger beside the
     * argument rows in the same ONE write.
     */
    readonly time?: {
        /** The app's `.time({ zone })` — the zone of a form declaring `wallZone: 'app'`. */
        readonly appZone?: ZoneName;
    };
}
/**
 * The `sf-inputs` subflow: Declare → Verify → Record → Resolve, four thin
 * stages over the pure steps of `arguments/resolve.ts`.
 */
export declare function buildInputsSubflow(deps: InputsMountDeps): FlowChart;
/**
 * Mount the inputs layer after the LLM call and before Route — or return the
 * builder untouched when the layer is not armed (`deps === undefined`), so an
 * agent without it builds the chart it always built. Both chart builders call
 * this, at the same place.
 */
export declare function mountInputsLayer<B extends FlowChartBuilder>(builder: B, deps: InputsMountDeps | undefined): B;
/** What an armed agent hands the results layer's mount — closures, never scope. */
export interface ResultsMountDeps {
    /** The implementation that answered a name — the shared dispatch resolver's. */
    readonly toolOf: ToolOf;
}
/**
 * The `sf-results` subflow: Declare → Verify → Record → Resolve, four thin
 * stages over the pure steps of `results/subflow.ts`.
 */
export declare function buildResultsSubflow(deps: ResultsMountDeps): FlowChart;
/**
 * WHICH BATCH the loop head hands the results layer on this visit — the
 * iteration that dispatched it, or `undefined` when there is none to judge.
 *
 * `stamp` is the iteration ToolCalls wrote beside the batch it dispatched
 * (`AgentState.toolResultsIteration`, under the arm); `iteration` is the loop
 * head's. ToolCalls advances the iteration by exactly one and loops straight
 * here; every other way back — the schema re-ask, the step nudge, the evidence
 * recheck, the wrap-up — runs no tool, leaves the batch in place and advances
 * the iteration again. So the batch is new on this visit exactly when
 * `iteration === stamp + 1`: each batch judged ONCE per run.
 *
 * Never by call id. A provider's synthetic counter restarts with each provider
 * instance (`<prefix>-call-${++toolCallSeq}`), so a resumed leg repeats the ids
 * of the leg that failed — whose rows the conversation checkpoint carries — and
 * nothing stops a provider reusing an id across batches of one run. A stamp is
 * per run: no conversation checkpoint carries it, so a resumed leg starts with
 * none. Were the invariant above ever broken, a batch would be judged twice —
 * an over-report, never a hidden verdict.
 */
export declare function batchToJudge(iteration: number, stamp: unknown): number | undefined;
/**
 * Under `.time()` (step T8): each call's time rows — its `call-window` row
 * and its `call` row's `drift` — and the turn's clock `now`, for the result
 * checks (`time/check.ts` · `periodTimeCheck`). Nothing when the turn has
 * no clock (an agent without `.time()`), so an unarmed run hands the layer the
 * input it always did. "This turn" is checked, not assumed: a ledger carried
 * forward (a checkpoint's `findingsLedger` from an agent that had `.time()`,
 * resumed and then run on by one that has not) holds an EARLIER turn's clock,
 * and that clock's `now` must not judge this turn's calls. Exported for that
 * test only.
 */
export declare function timeOfBatch(parent: Record<string, unknown>, calls: readonly RanCall[]): Pick<ResultsLayerState, 'times' | 'now'>;
/**
 * Mount the results layer at the LOOP HEAD — or return the builder untouched
 * when the layer is not armed (`deps === undefined`), so an agent without it
 * builds the chart it always built. Both chart builders call this at the same
 * place — immediately before the window strategy's `Compact` stage (or the
 * loop target that stands there) — and make the mount the loop target
 * (`RESULTS_LOOP_TARGET`), the `Compact` precedent: the layer reads the batch
 * just run before any window strategy folds it away.
 *
 * Returned (the output mapping, `arrayMerge: Replace` — the loop-crossed mount
 * law): the rows, merged into the ledger in ONE write by the ledger's pure
 * half. Nothing to return → nothing is written.
 */
export declare function mountResultsLayer<B extends FlowChartBuilder>(builder: B, deps: ResultsMountDeps | undefined): B;
/** The loop target the results layer's mount becomes when armed — `tool-calls` and every re-ask loop back to it. */
export declare const RESULTS_LOOP_TARGET: string;
/** A committed key the one fold (`assessment/assess.ts` · `assessAnswer`) reads. */
export type AnswerFoldKey = 'history' | 'turnNumber' | 'pausedToolCallId' | 'findingsLedger' | 'coverageDeclared' | 'stoppedEarly' | 'unsupportedValues' | 'answerValidation' | 'argumentAsk' | 'middlewareDecisions';
/** What an agent with the answer layer armed hands the final branch — build-time facts, never scope. */
export interface AnswerMountDeps {
    /** The committed keys the fold reads — only those this agent's arms can write (`answerFoldReads`). */
    readonly reads: readonly AnswerFoldKey[];
    /**
     * `.answerLayer({ standingLine })` — compose one line for a prose answer, in
     * the answers its mode says it for (`true` is `'always'`).
     */
    readonly standingLine?: import('../assessment/compose.js').StandingLineWhen;
    /** `.answerValidation()` is armed: an answer its report withholds is never assessed. */
    readonly validated?: true;
    /**
     * A tool's `displayName` (the app's words), read through the agent's own
     * tools — present only where a tool can declare one; the line names a
     * reason's calls in those words (`assessment/stage.ts`).
     */
    readonly displayNameOf?: (toolName: string) => string | undefined;
}
/**
 * THE READ LIST — which committed keys the answer layer's fold reads, from
 * the agent's arms: a key no arm of this agent can write is never read (a
 * tracked read of a key a run never writes is a phantom context source —
 * honesty law 9). Over-approximates on purpose: a key an arm CAN write is
 * read whether or not this run wrote it, so the in-run fold never misses a row
 * the read-after fold sees (the equality law).
 *
 * - always: `history`, `turnNumber`, `pausedToolCallId` (seed writes them),
 *   `findingsLedger` (the witness rows, and any rows a continued conversation
 *   restores — the restore is wired while a layer is armed) and
 *   `stoppedEarly` — the Route decider writes it on EVERY agent
 *   (`stages/route.ts` · `recordEarlyStop`): a limit cuts a turn short
 *   whenever the model asked for calls, whether or not this agent registered
 *   a tool that could answer them;
 * - a tool surface: `coverageDeclared` (only a tool that ran declares
 *   coverage);
 * - the evidence gate: `unsupportedValues`;
 * - `.answerValidation()`: `answerValidation`;
 * - the inputs layer: `argumentAsk`, and `middlewareDecisions` when a
 *   before-tool chain can rewrite a filled value.
 *
 * Every key's writers were checked against this list: a writer that no arm
 * gates puts its key in the always group — decide by the writer, never by the
 * usual path to it.
 *
 * @example
 * ```ts
 * answerFoldReads({ tools: true, evidenceGate: false, answerValidation: false, inputs: false, toolMiddleware: false });
 * // ['history', 'turnNumber', 'pausedToolCallId', 'findingsLedger', 'stoppedEarly', 'coverageDeclared']
 * ```
 */
export declare function answerFoldReads(arms: {
    readonly tools: boolean;
    readonly evidenceGate: boolean;
    readonly answerValidation: boolean;
    readonly inputs: boolean;
    readonly toolMiddleware: boolean;
}): readonly AnswerFoldKey[];
/**
 * Start the final branch: the answer layer's stage first when it is armed,
 * then PrepareFinal — or PrepareFinal alone when it is not, built exactly as
 * both chart builders always built it (same name, stage id, options and tags),
 * so an agent without the layer builds a byte-identical branch. Both builders
 * call this, so the twins cannot drift.
 */
export declare function startFinalBranch(answer: AnswerMountDeps | undefined, prepareFinal: (scope: TypedScope<AgentState>) => void | Promise<void>, structureRecorders: readonly StructureRecorder[] | undefined): FlowChartBuilder<any, TypedScope<AgentState>>;
