/**
 * servedView — the request an epoch was SERVED, rebuilt from what was
 * committed, plus an honest list of what the log cannot rebuild.
 *
 * Role:  Fold. `servedAt` reads a finished run's commit log and returns the
 *        model-facing request that epoch's call assembled; `receiptAt` reads
 *        the fingerprint that call left behind. Neither executes anything,
 *        records anything, or stores anything beside the log.
 * Reads: a recording, through `epochs.ts` (which log, which index) and
 *        footprintjs's `commitValueAt`.
 * Emits: N/A.
 *
 * ── THE LAW ────────────────────────────────────────────────────────────────
 *
 *     hash(servedAt(k)) === receiptAt(k).hash
 *
 * The receipt is minted at the stop, from the values about to go out. The
 * served view is rebuilt afterwards, from the values that were committed. When
 * the two agree, the record is complete: everything the model read is derivable
 * from the trace. When they disagree, something reached the model that the run
 * never wrote down — and that is a defect in the RECORD, not in the check.
 * `test/time-travel/receipt-conformance.test.ts` is where the law is
 * enforced; five real divergences were found by running it and each one was
 * closed by committing a fact or declaring a gap, never by loosening it.
 *
 * ── WHY THE REBUILD DOES NOT RE-IMPLEMENT THE ASSEMBLY ─────────────────────
 * The joined system string is a local inside the calling stage; it is never
 * committed, only its pieces are. So the rebuild has to apply the identical
 * join to the identical records — which is why the join is one exported
 * function, `composeRequest.ts` · `joinSystemPrompt`, called by the stage on
 * the way out and by this file on the way back. Same for the framework-field
 * strip and the staged-refs nudge. A second implementation of any of them would
 * make this file agree with itself and disagree with the wire.
 *
 * ── WHAT A GAP IS ──────────────────────────────────────────────────────────
 * A `ServedGap` is a fact this view cannot PROVE — because the log cannot
 * rebuild it, because the recording travelled without the base it folds
 * against, or because the fact lives past the boundary a receipt is minted at.
 * It is on the view rather than left implicit because a rebuild that quietly
 * omits a piece looks exactly like a rebuild that proved the piece was absent.
 * Naming the gap is what keeps the two apart.
 *
 * ── A GAP, NOT AN `undefined` ──────────────────────────────────────────────
 * When the rebuild cannot recover the conversation at all — a chart that
 * commits neither `history` nor `messagesInjections`, or a recording whose
 * fold base did not travel — `servedAt` still returns a view, carrying a gap,
 * rather than `undefined`.
 *
 * The alternative was tried and it is worse. Returning `undefined` withholds
 * the system prompt, the tool list and the request-only lines, all of which
 * this recording CAN prove, in order to avoid overstating one field it cannot.
 * A Lens may omit; it may not deny — and dropping four proved facts to hide
 * one hole omits more than the hole does. The gap says exactly which field is
 * unproved, in wording a renderer prints verbatim, and leaves the rest
 * standing.
 *
 * ── EVERY CHART THAT SERVES A MODEL MINTS, EXCEPT WHERE IT CANNOT SALT ─────
 * Until 9.91.0 `buildReceipt` was called from exactly one place — the agent
 * charts' `call-llm` stage (`stages/callLLM.ts`) — and the three other charts
 * that hand a model a request (`LLMCall.ts` · `callLLM`,
 * `buildMessageApiChart`, `buildAgentMessageApiChart`) left
 * `no-receipt-on-chart` on every view they produced. Two reasons were recorded
 * for that at the time. NEITHER survived.
 *
 * The first was the cache verdict: `Receipt.cache.transform` was said to have
 * no honest value on a chart that runs no cache strategy, because
 * `'unchanged'` would claim a strategy returned what it was given when none
 * ran. But an `Agent` running a pass-through strategy records exactly that
 * today — `buildReceipt` compares the request it was handed against itself —
 * and `receipt-conformance.test.ts` asserts it and calls it correct. No fourth
 * enum value was needed, and none was added.
 *
 * The second was the SALT, and it survives on exactly two of the three charts
 * and not for the reason first written down. `LLMCall` owns its executor and
 * mints a run id per run exactly as `Agent` does (a paragraph here said
 * otherwise until 9.88.0, in a sentence a renderer printed verbatim), so it
 * mints. The message-API charts are exported chart BUILDERS handed to an
 * executor the CALLER owns, and nothing in a stage's scope carries that
 * executor's run id — so their deps take one (`getRunId`), and they mint when
 * they are given one. Given none they mint NOTHING rather than salting every
 * hash with an empty string, because the salt is what makes shipping
 * fingerprints in a recording safe (`core/agent/receipt/receipt.ts`, the third law).
 *
 * So a receipt-less view is still a shape this library produces — a chart
 * builder run without a run id, a run that declined with `recordReceipt:
 * false`, a consumer's own `call-llm` stage, a recording made before 9.88.0 —
 * and the absence is DECLARED: `no-receipt-on-chart` names the fields only a
 * receipt carries and says what follows for them. The rebuild never needed the
 * receipt to work; what it loses is the WITNESS.
 *
 * ── AND THE CAUSE IS A VALUE, NOT A LIST INSIDE A SENTENCE ────────────────
 * That gap's sentence used to end with the causes that produce it. That is
 * PROSE DOING DATA'S JOB: a frozen constant cannot know what happened at the
 * site it is printed beside, so it listed the causes somebody could think of —
 * and a path it had never accounted for, the shape refusal in `readReceipt`
 * below, made the count AND the verdict false with nobody editing the string.
 * The discriminating fact moved to the one place that holds it: `readReceipt`
 * reports whether the receipt key held nothing or held something it refused,
 * and {@link ServedGap.cause} carries that answer out.
 *
 * ── AND THEN THE MECHANISM WENT TOO (9.88.0, sixth round) ─────────────────
 * Five rounds tried to write TRUE mechanism sentences, and the rate of new
 * falsehoods did not fall. The sixth round applied one question to all ten
 * printed sentences — COULD THIS BECOME FALSE WITHOUT ANYONE EDITING IT? —
 * and nine could, two of them being false the day they shipped. Exactly one
 * could not, and it is the one that makes no claim about code at all:
 * `UNGAPPED_FIELDS.gaps`, which says what its field MEANS inside the account.
 * Nothing outside that sentence can falsify it.
 *
 * So the conclusion was not to write mechanism sentences better. It was to
 * STOP WRITING THEM. A printed gap sentence may now say only: which fields it
 * covers; what they mean on this view for the person reading (unproven,
 * possibly short, absent-means-unknown, unchecked against what went out); and
 * what to do differently. It may not name a module, a function, a key, a
 * version, a chart, a strategy, an option, or any mechanism at all. If a
 * sentence needs one of those words to be understood, it is explaining WHY the
 * gap exists, which is not the printed sentence's job.
 *
 * NONE OF IT IS LOST. The mechanism is in the comment above each catalogue
 * entry, where a maintainer reads it and review catches its rot, with the
 * `file · symbol` pointers that are correct there and banned in printed prose.
 * The cause is already data. The docs may explain the mechanism at length,
 * because a doc is versioned with the code and its reader can open the file.
 * The rule is enforced by `test/helpers/gapProseClaims.ts`, which on the
 * printed surface admits no code-shaped token and no mechanism verb — close to
 * a whitelist, and a whitelist has no synonyms.
 *
 * ── AND THE SEVENTH ROUND MEASURED WHAT THE SIXTH HAD CLAIMED ─────────────
 * The sixth round said the reduction ENDED the class: a sentence with no code
 * claim in it cannot go false when the code changes. That was checked, sentence
 * by sentence, by driving a real run for each one — and it is not true. TEN of
 * the eleven reduced sentences still make a claim a code edit falsifies. The
 * one that does not is `UNGAPPED_FIELDS.gaps`, and it survives because it is
 * SELF-REFERENTIAL: it says what its field is inside the account, not anything
 * about the request. That is not a shape the other ten can copy. "May be
 * SHORT", "absent means unknown", "the list is complete and the schemas are one
 * short" are all claims about how the rebuild behaves, and the rebuild is code.
 * The reduction changed the VOCABULARY of the claims, not their CLASS.
 *
 * The same round proved what does close it, by finding a BRAND-NEW false
 * sentence in the round written to end false sentences: `no-run-log` shipped
 * "The fields below could not be fully recovered here", and on the ordinary
 * view that raises it nothing is lost at all. No rule caught that. A run
 * caught it.
 *
 * SO THE POSITION IS: a gap sentence MAY make a code claim, because a sentence
 * that makes none cannot inform. Every claim it makes is ASSERTED against a
 * real view in `test/time-travel/gap-sentences.test.ts`, which drives one
 * run per entry and checks the claim rather than the firing. The prose rule
 * STAYS — it keeps the sentences short and readable and stops the enumerations
 * coming back — but it is not what makes them true. The assertion is, and its
 * blind spot is honest and small: a claim nobody wrote an assertion for.
 */
import type { LLMMessage, LLMToolSchema } from '../provider-contract/types.js';
import type { ContextRole, ContextSlot, ContextSource } from '../events/types.js';
import { type StoredReceipt } from '../core/agent/receipt/receipt.js';
/** One piece of the composed system string, in wire order. */
export interface ServedPiece {
    readonly text: string;
    readonly slot: ContextSlot;
    readonly source: ContextSource;
}
/** A line that was on the request and in no history. */
export interface ServedRequestOnly {
    readonly role: ContextRole;
    readonly text: string;
    /** Which library mechanism composed it — `'staged-refs-nudge'`, `'time-window-line'` (step T6b)
     *  or `'evidence-conclusion'` (the evidence gate's figures dial). */
    readonly reason: string;
}
/** The kinds of thing this view cannot prove. */
export type ServedGapKind = 'findings-layout' | 'cache-transform' | 'thinking-replay' | 'forced-tool-schema' | 'provider-defaults' | 'no-fold-base' | 'no-conversation-on-record' | 'no-run-log' | 'no-receipt-on-chart';
/**
 * WHAT STOOD IN THE WAY, as far as the record shows — computed at the read that
 * failed, so it is a value and not a sentence.
 *
 * It exists because the alternative was tried and it went false. A gap's `why`
 * listed the causes somebody could think of; a cause nobody had thought of was
 * added; the sentence was wrong and nobody had edited it. A frozen constant
 * cannot know what happened at the site it is printed beside. The site can.
 *
 * The set is closed AT THE SITE, which is narrower than everything that can go
 * wrong upstream and is meant to be. A recording made before the receipt
 * existed, a chart whose LLM stage mints none, and a run that declined with
 * `recordReceipt: false` all leave the SAME record — no value under the receipt
 * key — so they all land on `'no-receipt-committed'`. Claiming to tell them
 * apart there would be this field repeating the defect it was added to fix.
 *
 * - `'no-receipt-committed'` — nothing was committed under the receipt key on
 *   this epoch's call.
 * - `'receipt-shape-rejected'` — something WAS committed there and the read
 *   refused it, because it carries no basis and a value without one is not a
 *   receipt. This is the value that means DAMAGE: a recording that lost or
 *   rewrote part of its own log. The other means the run simply never minted.
 */
export type ServedGapCause = 'no-receipt-committed' | 'receipt-shape-rejected';
/** One named limit on the rebuild, with the fields it covers — a hole the log
 *  cannot fill, or a boundary the record cannot see past. */
export interface ServedGap {
    readonly gap: ServedGapKind;
    /**
     * The fields this gap covers, in dotted `Receipt` form. A reader that
     * renders one of them should render this gap's sentence beside it.
     *
     * TWO RELATIONS LIVE ON THIS LIST, and a consumer that treats them as one
     * will draw a wrong conclusion in one direction or the other:
     *
     * - MOST gaps mean *the rebuild cannot produce this field* — the recording
     *   does not hold what it would take. `no-fold-base`, `no-run-log`,
     *   `no-conversation-on-record`, `no-receipt-on-chart`, `forced-tool-schema`,
     *   and the `cache.*` entries of `cache-transform` are all this kind. A
     *   checker may treat these as an EXCUSE.
     * - `cache-transform`'s COMPOSITION fields (`system.*`, `messages.*`,
     *   `tools.*`) are the other kind. WHEN NO OTHER GAP ON THE SAME VIEW NAMES
     *   THE SAME FIELD, the rebuild produces them and they agree with the
     *   receipt; both describe the request handed TO the cache strategy, and the
     *   port may have got something else. That is a CAVEAT to print, not an
     *   excuse to grant — a checker that excused these would stop checking
     *   fields the record proves perfectly well.
     *
     *   The qualifier is load-bearing and was missing until 9.88.0. A view that
     *   carries `cache-transform` may also carry `no-fold-base`, and there the
     *   rebuild does NOT agree: measured on a base-less recording, the receipt
     *   said 27 system chars over 3 turns and the rebuild produced 0 over 1.
     *   Read this entry as "up to the cache strategy" and read the OTHER gaps on
     *   the view for whether the rebuild got there at all.
     *
     *   Since 9.93.0 the entry is raised only where a strategy could have
     *   rewritten anything: where the receipt names one (`cache.strategy`), or
     *   where no receipt can say. A view whose receipt says `null` — `LLMCall`,
     *   the message-API charts — does not carry it, because nothing stood
     *   between assembly and the port for the caveat to be about.
     *
     * `provider-defaults`/`params` is the caveat kind too, and is the one field
     * read past the strategy: it describes the request the port really got, and
     * only the vendor lies beyond it. Its opposite number is
     * `no-receipt-on-chart`, which is the missing kind: no receipt was minted, so
     * `params` and everything else only a receipt carries is simply absent.
     *
     * `Receipt` paths WHEREVER THE TWO SHAPES HOLD THE SAME FACT, even though the
     * thing rendered beside them is usually a {@link ServedView}, because the two
     * sides of the law are checked field by field and only one of them can name
     * the fields. Three spellings differ and a renderer has to map them:
     * `system.hash` / `system.chars` are the view's `system.text`,
     * `messages.entries` / `messages.count` are its `messages.asSent`, and
     * `tools.schemaHashes` is its `tools.schemas`. The rest — `system.pieces`,
     * `messages.requestOnly`, `tools.names`, `tools.forced`, `tools.withheld`,
     * `params`, `cache.*`, `omittedForAttention` — are spelled the same on both,
     * or exist on the receipt alone.
     *
     * THE ONE EXCEPTION is the epoch number, and it is an exception because the
     * two shapes do not hold one fact there: they hold two RECORDS of it that can
     * disagree. The view's `epoch` is what the fold produced (a position, when it
     * could not read `iteration`) and `no-fold-base` names it under that
     * spelling; the receipt's `basis.epoch` was minted live from the run's own
     * counter and `no-receipt-on-chart` names it, because losing the receipt is
     * the only thing that loses it. Translating one to the other would print
     * whichever sentence is wrong: a missing base does not touch the receipt's
     * number, and a missing receipt does not touch the view's.
     *
     * A list rather than one name because a single missing fact can leave
     * several fields unproved: losing the run log costs the forced tool's name,
     * the tool list it belongs on, and the request-only lines composed from
     * `toolWantsByName`.
     */
    readonly fields: readonly string[];
    /**
     * The gap in the words a renderer prints — WHICH FIELDS it covers, WHAT THEY
     * MEAN ON THIS VIEW, WHAT TO DO DIFFERENTLY, and nothing else.
     *
     * IT NAMES NO MECHANISM. Not a module, not a function, not a key, not a
     * version, not a chart, not a strategy, not an option — because naming one
     * makes a sentence read like a description of code a reader cannot open, and
     * because the enumerations that went false in five review rounds all arrived
     * through that door. The mechanism is in the comment above each catalogue
     * entry, and the cause is data on {@link ServedGap.cause}.
     *
     * IT STILL MAKES CLAIMS, AND THAT IS THE POINT. The rule was sold for one
     * release as ending the class of sentences a code edit can falsify. Measured
     * sentence by sentence against real runs, it does not: ten of the eleven
     * reduced sentences claim something the code decides — that a count may be
     * short, that an empty list means unknown, that a tool list is complete. Only
     * `UNGAPPED_FIELDS.gaps` is claim-free, and only because it describes the
     * account rather than the request. A sentence that claims nothing cannot
     * inform, so the claims stay.
     *
     * WHAT MAKES THEM TRUE is `test/time-travel/gap-sentences.test.ts`: one
     * real run per entry, and an assertion for each claim the sentence makes —
     * not that the gap fired, but that what it says about the view holds. The
     * checker keeps the sentences short and readable; the assertions keep them
     * true. The blind spot is a claim nobody wrote an assertion for.
     */
    readonly why: string;
    /**
     * WHY this gap fired, where the site could establish it — {@link ServedGapCause}.
     *
     * Carried by `no-receipt-on-chart`, which is the gap whose sentence used to
     * list its causes. Absent elsewhere: a gap carries a cause when the site that
     * raised it read something that told it, and supplying one anywhere else
     * would be the enumeration coming back as a field.
     */
    readonly cause?: ServedGapCause;
}
/**
 * The gap catalogue. Exported because a reader that renders a served view
 * renders its gaps beside it, and a renderer should print the library's own
 * sentence rather than invent one.
 */
export declare const SERVED_GAPS: Readonly<Record<ServedGapKind, Omit<ServedGap, 'gap'>>>;
/**
 * The fields no gap names, and the reason each one needs none — the OTHER half
 * of the account.
 *
 * WHY IT EXISTS. `SERVED_GAPS` was hand-checked against the two shapes three
 * times in one release and came up short every time, because "is every field
 * named by a gap?" was a question a person answered by reading. It is now a
 * question a walk answers: `test/time-travel/gap-catalogue-walk.test.ts`
 * enumerates every field a real `Receipt` and a real `ServedView` carry and
 * requires each one to be named by a gap OR to be a key here. A field in
 * neither fails, by name.
 *
 * So this is not an exemption list. It is the place a field goes when NO GAP'S
 * MECHANISM EXPLAINS IT, and the value is the reason in one sentence, for the
 * next person who asks why the field has no gap. Adding a key here is as
 * reviewable as adding one to a gap, and that is the point: both are a claim
 * somebody wrote down.
 *
 * TWO reasons qualified when this list was written, and one of them has since
 * emptied out:
 *
 *   • NO FOLD CAN FAIL TO PRODUCE IT — the field is read straight off the
 *     located epoch, never through a fold. `callRuntimeStageId` is this kind.
 *   • ITS ABSENCE IS UNIVERSAL AND HAS NOTHING TO DO WITH THIS RECORDING — no
 *     chart IN THIS LIBRARY supplies it, on any run, so no gap about a limit of
 *     the rebuild describes it. `omittedForAttention` WAS this kind from
 *     9.88.0's fourth review round to 9.93.0, and is not any more: the
 *     measurement it rested on ("no chart drops for attention") had missed the
 *     agent chart's window stage, which evicts turns for budget on every run
 *     whose strategy engages and now files them on the receipt. A recorded
 *     drop can be lost in exactly one way — with the receipt — so the field is
 *     named by `no-receipt-on-chart` and is not here. The kind is kept on this
 *     list because the next universally-absent field will need it, and because
 *     a reason that was true for five releases and then measured false is
 *     worth a sentence where the next person looks.
 *
 * A field a gap DOES name never belongs here, whatever else is also true of it.
 * `epoch` was a key here through three rounds, on the true-but-irrelevant
 * ground that `servedAt(k)` hands `k` back; what a base-less fold changes is
 * what that number MEANS, `servedViews()` returns the fold's number outright,
 * and `no-fold-base` names it now.
 *
 * Paths are spelled as they are on the shape that HAS the field — both keys
 * here are `ServedView` fields. Gap `fields` are spelled as `Receipt` paths —
 * see {@link ServedGap.fields} for the places the two shapes differ.
 *
 * @example
 * ```ts
 * import { SERVED_GAPS, UNGAPPED_FIELDS } from 'agentfootprint';
 *
 * // Why does nothing explain `callRuntimeStageId`? Because nothing has to.
 * UNGAPPED_FIELDS['callRuntimeStageId'];
 * Object.keys(SERVED_GAPS).length; // 7 gap kinds
 * ```
 */
export declare const UNGAPPED_FIELDS: Readonly<Record<string, string>>;
/**
 * THE SERVED VIEW: what the model was handed on one epoch, rebuilt.
 *
 * A SERVED VIEW IS A VALUE. The whole of it is frozen — the object, its four
 * sub-objects and all six containers, down to the pieces and gaps it holds —
 * so the `readonly` on every field below is a fact and not a hint. Two of those
 * containers are also COPIES (`messages.asSent`, `tools.schemas`), because
 * those alone would otherwise alias the fold's memoized answers; see
 * `detachedList`. Copy before you edit: `structuredClone`, or a spread.
 *
 * @example
 * ```ts
 * import { servedAt } from 'agentfootprint';
 *
 * const view = servedAt(agent.getSnapshot()!, 1)!;
 * view.system.text;            // the joined system prompt, as sent
 * view.messages.asSent.length; // the turns that went out
 * view.tools.names;            // including a forced answer tool
 * view.basis?.model;           // which model saw it
 * view.gaps.map((g) => g.gap); // ['cache-transform', 'provider-defaults'] on an agent
 * ```
 */
export interface ServedView {
    /**
     * WHICH TURN THIS IS, as the fold read it — the run's own committed
     * `iteration`, and its POSITION in run order when the fold could not read
     * that (`EpochLocation.epoch`). `servedAt(k)` hands `k` back either way;
     * `servedViews()` returns the fold's number outright, so a base-less
     * recording can number a turn differently from the receipt that turn minted.
     * `gaps` carries `no-fold-base` exactly when that is possible.
     */
    readonly epoch: number;
    readonly callRuntimeStageId: string;
    /**
     * WHICH MODEL SAW THIS, and through which provider — read off the receipt's
     * own `basis`, which is the only place the run records them.
     *
     * Absent when this epoch's call left no receipt for the read to find. The
     * absence is DECLARED, not left to be noticed: `gaps` then carries
     * `no-receipt-on-chart`, which names this field, and that gap's
     * {@link ServedGap.cause} carries what the read established — the receipt key
     * held nothing, or held something that is not a receipt. The sentence itself
     * does not tell those apart and used to claim it did; a frozen sentence
     * cannot, which is why the fact is a field.
     *
     * It is the one field on this view that does not come from the rebuild, and
     * it is here because a served view without it cannot answer "what did THIS
     * model read" — only "what did something read". It is deliberately not part
     * of the conformance law: there is no committed counterpart to check it
     * against.
     *
     * @example
     * ```ts
     * import { servedAt } from 'agentfootprint';
     *
     * const view = servedAt(agent.getSnapshot()!, 1)!;
     * `${view.basis?.model ?? 'unknown model'} read ${view.system.text.length} chars`;
     * ```
     */
    readonly basis?: {
        readonly model: string;
        readonly provider: string;
        /** The salt every hash on this epoch's receipt was taken with. */
        readonly runId: string;
    };
    readonly system: {
        readonly text: string;
        readonly pieces: readonly ServedPiece[];
    };
    readonly messages: {
        /** The conversation as it went out, post-strip, in wire order. FROZEN, and
         *  so are its messages: they come from a fold whose answers seed every
         *  later epoch's — see `keyedFold.ts` · `freezeDeep`. Copy to edit. */
        readonly asSent: readonly LLMMessage[];
        /** Lines composed for this request and written to no history. */
        readonly requestOnly: readonly ServedRequestOnly[];
    };
    readonly tools: {
        /** Every tool name on the request, forced answer tool included. */
        readonly names: readonly string[];
        /** The schemas the log holds. Short of `names` by the forced tool — see
         *  {@link SERVED_GAPS}. FROZEN, for the same reason `asSent` is. */
        readonly schemas: readonly LLMToolSchema[];
        /** The tool the model was forced to answer through. */
        readonly forced?: string;
        /** Why the tool list is empty when it would not otherwise be. */
        readonly withheld?: 'wrap-up' | 'evidence-revision';
    };
    /** What this rebuild could NOT recover, each naming the receipt field it
     *  explains. Never empty — see {@link SERVED_GAPS}. */
    readonly gaps: readonly ServedGap[];
}
/**
 * Rebuild what the model was SERVED on epoch `k`, from the run's committed
 * pieces alone.
 *
 * Works on a live snapshot and on a recording read back from JSON, in both
 * chart shapes, on a run whose conversation lives in `messagesInjections`
 * rather than `history` (`LLMCall`, the message-API charts), on a resumed run
 * (every read folds from the checkpoint the run was seeded with), on a
 * redacted run (the pieces are read exactly as the run committed them — a
 * redacted piece rebuilds to its redacted bytes, which is what the record says
 * a reader is allowed to see) and on a recording made before the receipt
 * existed.
 *
 * It returns `undefined` for ONE reason only: the run has no such epoch.
 * Anything it cannot prove about an epoch that DOES exist comes back as a
 * named entry in `gaps`, never as a missing view and never as a confident
 * empty one.
 *
 * @param source a runner (`Agent`, `LLMCall`) or a snapshot. Where no receipt
 *   was minted — a message-API chart handed no run id, a run that declined with
 *   `recordReceipt: false`, a chart of the caller's own — the rebuild is
 *   complete but UNCHECKED: `basis` is absent and `gaps` carries
 *   `no-receipt-on-chart` saying so.
 * @param epoch  the iteration number, 1-based — the run's own count.
 *
 * @example
 * ```ts
 * import { receiptAt, receiptHash, servedAt } from 'agentfootprint';
 *
 * const snapshot = agent.getSnapshot()!;
 * const view = servedAt(snapshot, 1)!;
 * const receipt = receiptAt(snapshot, 1)!;
 * receiptHash(receipt.basis.runId, view.system.text) === receipt.system.hash; // true
 * ```
 */
export declare function servedAt(source: unknown, epoch: number): ServedView | undefined;
/**
 * Every epoch's served view, in run order — `servedAt` for a whole run, with
 * one pass over the recording instead of one per epoch.
 *
 * @example
 * ```ts
 * servedViews(agent.getSnapshot()!).map((v) => v.tools.names.length); // [3, 3, 0]
 * ```
 */
export declare function servedViews(source: unknown): ServedView[];
/**
 * The receipt epoch `k`'s call left behind, or `undefined`.
 *
 * What comes back is a {@link StoredReceipt}: the receipt AS STORED, written
 * by the release that minted it. A recording is older than the reader that
 * opens it, so a container a later release added (`cache.strategy`, 9.93.0)
 * may be absent — and it is handed back absent, not repaired, because the
 * narrowing checks the basis and promises nothing past it. A reader reads the
 * receipt it is handed; a missing container is a fact about the vintage,
 * never a throw.
 *
 * `undefined` means one of two things on the record, and the same epoch's
 * `servedAt(...)` view carries which: its `no-receipt-on-chart` gap has a
 * {@link ServedGapCause}. Either nothing was committed under the receipt key —
 * a recording made before the receipt existed, a chart whose LLM stage mints
 * none, a run with `recordReceipt: false`, all of which leave that same record
 * — or something WAS committed there and `readReceipt` refused it, because it
 * is not a non-null object with a number at `basis.epoch`, and handing back a
 * half-object a caller reads `.basis.runId` off is worse than saying no.
 *
 * It also returns `undefined` when the run has no epoch `k` at all, which is
 * the answer `epochAt` gives and is not a fact about receipts; ask
 * `servedAt(source, k)` if you need to tell a missing epoch from a missing
 * receipt, because that one returns `undefined` for the missing epoch only.
 *
 * `servedAt` still rebuilds the view of an epoch that exists in every one of
 * these cases, which is what makes an old recording readable instead of
 * unreadable.
 *
 * The receipt comes back DEEP-FROZEN and is the same object every caller gets
 * for this epoch: it is a value folded out of the log, and a fold's answers are
 * detached (`keyedFold.ts` · `freezeDeep`). Copy it if you need to edit one.
 *
 * @example
 * ```ts
 * import { receiptAt } from 'agentfootprint';
 *
 * receiptAt(agent.getSnapshot()!, 3)?.tools.withheld; // 'wrap-up' on a wrap-up call
 * ```
 */
export declare function receiptAt(source: unknown, epoch: number): StoredReceipt | undefined;
