/**
 * hosting/answerAccounts — the machinery behind the `answer-account` wire op:
 * one host's cache, its single-flight, and the pure step that turns a stored
 * recording into `{ account, shown }`.
 *
 * The op itself — its order, its refusals, its one door fact — lives inside
 * `standingAgent.ts · answerArtifact`, beside `head` and `get`, so its
 * ownership path cannot drift from theirs. This file owns only what that
 * branch must not re-derive per request:
 *
 *   • **The options, validated at boot.** `declarations` are the HOST's (a bad
 *     one throws when `standingAgent` is called, never per request), the
 *     ceiling and the cache size are numbers that must mean something.
 *   • **The cache key** — `(scope, ref, template-set version, declarations
 *     digest)`. The account is a pure function of the recording and the
 *     declarations, and the template-set version names the words, so a key
 *     that carries all four can never serve stale sentences: a library upgrade
 *     or a declarations change is a miss by construction.
 *   • **Single-flight** — ten concurrent clicks on one answer cause ONE store
 *     read and ONE parse. Joined waiters get the leader's outcome, failure
 *     included.
 *   • **An LRU bounded twice** — by entries (default 32) and by total
 *     serialized size ({@link ANSWER_ACCOUNT_CACHE_MAX_BYTES}). Only an
 *     account is ever cached; a failure is never an entry, so the next request
 *     tries again.
 *
 * What it deliberately does NOT own: whether the recording still exists. The
 * branch asks the store (a SILENT head) before it asks this cache — so a
 * swept or expired recording is "not available" even while its account sits
 * here (review R3-S1). A cache that answered first would serve derived record
 * data past the store's own retention.
 */
import type { ArtifactScope } from '../artifacts/types.js';
import type { AnswerAccountDeclarations } from '../answer-account/types.js';
import type { AnswerAccountWireBody } from './artifactWire.js';
/**
 * Opt in to the `answer-account` wire op — `standingAgent({ answerAccounts })`.
 *
 * `true` opts in with every default.
 */
export interface AnswerAccountsOptions {
    /**
     * What the APP declares about its skills, tools and routing (labels, a
     * result's `rowsAt`, "the app decides entries"). Validated once, when
     * `standingAgent` is called; every line filled from it is vouched `app`.
     * Never taken from a request.
     */
    readonly declarations?: AnswerAccountDeclarations;
    /**
     * The largest recording this host will explain, in bytes (the ticket's
     * `bytes`). Default {@link DEFAULT_ANSWER_ACCOUNT_MAX_RECORDING_BYTES}
     * (16 MiB). A recording over it is refused with
     * `RecordingTooLargeForAccountError` before any of its payload is read — it
     * bounds the worst single parse on the event loop every session shares. A
     * PACKED recording is held to it twice: its stored bytes, and the plain
     * recording it stands for (measured over the packed form, before anything is
     * expanded) — a few KB packed can stand for gigabytes.
     */
    readonly maxRecordingBytes?: number;
    /**
     * How many accounts to keep, least recently used out first. Default
     * {@link DEFAULT_ANSWER_ACCOUNT_CACHE_ENTRIES}. `0` caches nothing (the
     * single-flight still joins concurrent requests).
     */
    readonly cacheEntries?: number;
}
/** The default recording ceiling: 16 MiB — above the field median (≈7.5 MB). */
export declare const DEFAULT_ANSWER_ACCOUNT_MAX_RECORDING_BYTES: number;
/** The default number of cached accounts. */
export declare const DEFAULT_ANSWER_ACCOUNT_CACHE_ENTRIES = 32;
/** The cache's total bound, by the serialized size of what it holds: 8 MiB. */
export declare const ANSWER_ACCOUNT_CACHE_MAX_BYTES: number;
/** A stored recording as the branch loaded it: the payload and the run it is OF. */
export interface LoadedRecording {
    readonly data: unknown;
    /** The ticket's `meta.origin.runId` — preferred over the recording's own. */
    readonly runId?: string;
}
/**
 * One host's account service.
 *
 * @internal Built by `standingAgent` from {@link AnswerAccountsOptions}.
 */
export interface AnswerAccounts {
    readonly maxRecordingBytes: number;
    /** The cache key for a ref redeemed under `scope`. */
    keyFor(scope: ArtifactScope, ref: string): string;
    /** A cached answer, marked most recently used — or `undefined`. */
    cached(key: string): AnswerAccountWireBody | undefined;
    /**
     * Compute (or join the computation of) the answer for `key`. `load` runs at
     * most once per concurrent key and returns `null` when the record is not
     * available. Resolves `null` for anything that cannot be explained, and
     * rejects with `RecordingTooLargeForAccountError` when the payload in hand is
     * over the ceiling whatever its ticket said — neither is ever cached.
     */
    compute(key: string, load: () => Promise<LoadedRecording | null>): Promise<AnswerAccountWireBody | null>;
}
/**
 * Build one host's service, validating the options. Throws — at boot — naming
 * the first thing wrong.
 */
export declare function answerAccounts(options: AnswerAccountsOptions | true): AnswerAccounts;
/**
 * The pure step: a stored recording → `{ account, shown }`, frozen — or `null`
 * when the payload is not a recording this can read.
 *
 * Synchronous on purpose, and the reason for the ceiling: parse + fold +
 * show-me run on the event loop. Measured on the field recording in the af-3
 * worklog.
 *
 * The ceiling holds for a PACKED recording too, on the recording it stands for:
 * the fold and show-me walk the expanded recording as a tree, and a few KB
 * packed can stand for gigabytes (a value referred to ten times by values each
 * referred to ten times, …). So a packed payload whose plain form is over
 * `maxRecordingBytes` is refused exactly as that plain payload would be —
 * measured over the packed form, before anything is expanded.
 *
 * @throws RecordingTooLargeForAccountError for a packed recording whose plain
 *   form is over `maxRecordingBytes`.
 */
export declare function explainRecording(loaded: LoadedRecording, declarations: AnswerAccountDeclarations, maxRecordingBytes?: number): AnswerAccountWireBody | null;
/**
 * @internal Exported for its test.
 *
 * Freeze what the cache hands out. The same object is served to every reader
 * of that answer; a host that edited one reply would otherwise edit the next.
 */
export declare function deepFreeze<T>(value: T, seen?: WeakSet<object>): T;
//# sourceMappingURL=answerAccounts.d.ts.map