/**
 * contextLedger — the post-run bookkeeper (see types.ts for the WHY).
 *
 * DESIGN: a pure POST-RUN analyzer over the run's own commit log — no live
 * recorder lifecycle, no event-order coupling. Everything it counts is
 * already durably recorded by the engine (dogfooding: offers come from
 * `commitValueAt` folds, answer attribution from `sliceForKey` — the same
 * canonical queries every triage surface uses):
 *
 *   offers  — the context IN EFFECT at each LLM call. Call marker: a
 *             commit that wrote `totalInputTokens` (monotonic — never
 *             net-change-dropped) and did NOT write `userMessage` (which
 *             only the seed writes). At each call index, fold
 *             `activeInjections` + `dynamicToolSchemas`, and add the
 *             STATIC tool registry (duck-read from the runner's public
 *             `getUIGroup().extra.toolNames` — static registries live in a
 *             closure, never in scope state). NOTE offers are deliberately
 *             NOT "per context-key commit": the net-change filter drops
 *             identical re-commits, so stable context appears once in the
 *             log while still being offered (and paying tokens) per call.
 *             Static-registry tools count offers with approxTokens 0 in L1
 *             (their schema JSON isn't in the log) — earnRate, the gate
 *             signal, is unaffected; dynamicToolSchemas carries real sizes.
 *   uses    — tool: assistant messages' toolCalls in the final history;
 *             skill: `activatedInjectionIds`;
 *             injection: its SLOT's write sits on the final answer's
 *             backward slice (slot-granular, labeled).
 *   outcome — consumer label per run, credited to every offered piece.
 *
 * The slot→slice join needs NO id conventions: for each slot key
 * (INJECTION_KEYS.*), `findLastWriter` names the commit that fed the final
 * LLM call; membership of that writer in the answer slice IS the signal.
 *
 * Every read goes through footprintjs's BASIS twins (`commitValueAtWithBasis`,
 * `findLastWriterWithBasis`): an answer that rests on nested rows, the
 * pre-run state, a redaction or a delete says so on `RecordedRun.basis`
 * (per key, absent when every answer was exact) instead of being counted as
 * if it were exact.
 *
 * UNDER A REDACTION POLICY (an agent's `redact`, `src/redaction/`) the log
 * holds the placeholder wherever the policy selected a value — footprintjs
 * scrubs it as it is written. The gates decide what LATER runs are offered,
 * so a placeholder must never read as "never used":
 *   - a FINAL value the log keeps out (the history the tool calls are counted
 *     from, the slot records) is read from the run's LIVE end state when the
 *     source is a runner of this library (`sourceOf` — `core/runnerLive.ts`);
 *     only ids and counts reach a row, never a value;
 *   - a read nothing can answer (a value per call — the log is the only record
 *     of what each call was offered — or any read from a snapshot handed in)
 *     leaves its kind UNMETERED for the run (`READS_OF`): neither its offers
 *     nor its uses are counted, `RecordedRun.unmetered` names it, and a gate
 *     keeps offering it as it does a piece with too few offers to judge.
 */
import type { ContextLedger } from './types.js';
export declare function contextLedger(): ContextLedger;
//# sourceMappingURL=contextLedger.d.ts.map