/**
 * design/164 件五 — DEPLOYMENT-level usage governance (the seam, its arithmetic, and the in-memory
 * reference implementation).
 *
 * This is a different axis from `TaskSpec.limits`: a task limit is the allowance ONE task asked for,
 * while a usage window is the allowance an OPERATOR grants a principal (or a whole deployment) ACROSS
 * tasks — the shape the industry converged on for account-level governance (a first-use window plus a
 * long rolling one). Core never invents a window: with `RunnerDeps.usageWindows` unset, nothing here
 * runs and no ledger is written.
 *
 * The arithmetic lives HERE, as pure functions over a per-key {@link UsageWindowRecord}, and every
 * store implementation is a persistence shell around them — that is what makes the in-memory and file
 * backends equivalent by construction rather than by two hand-written copies that drift.
 */
/**
 * One governed window. Its fields are allowances, not hints: `windowMs` is the window's WIDTH and
 * `maxTokens` / `maxCostUsd` the two CEILINGS it admits work under — each optional on its own, at least
 * one required (a window with neither is refused at the door). `anchor` picks between the two window
 * shapes that actually exist in the wild:
 *  - `"first-use"` — the window OPENS at the key's first charge and lasts `windowMs`; when it lapses with
 *    no further use, the next charge opens a fresh one. This is the "5 hours from when you started"
 *    shape: bursty use is admitted at full width, and an idle key is never penalized for old traffic.
 *  - `"rolling"` — a continuously sliding window: the charge from `now − windowMs` to `now`. This is the
 *    "7 days" shape: it never resets, so sustained use is bounded no matter how it is spread.
 */
export interface UsageWindow {
    /** Window width in ms. Must be finite and > 0 (a zero-width window admits nothing and expires
     *  instantly — refused at the door rather than silently governing every task to death). */
    windowMs: number;
    /**
     * Tokens the window admits before it is exhausted. Must be finite and >= 0 WHEN PRESENT; `0` is a real,
     * always-full window (an operator lock-out), not "unset" — absence is the only way to say "this window
     * does not govern tokens".
     *
     * OPTIONAL since the $ ceiling below became a peer rather than an addition: a deployment governed by
     * SPEND alone would otherwise have had to declare a token ceiling no run could reach, i.e. a number
     * nobody chose sitting in the field this door exists to keep honest. Either ceiling alone is a complete
     * declaration; a window that declares NEITHER is refused (`config.usage_window_invalid`) rather than
     * admitting everything silently.
     */
    maxTokens?: number;
    /**
     * The OTHER ceiling: the MONEY the window admits before it is exhausted, in absolute USD — the
     * same quantity and unit `TaskLimits.maxCostUsd` names, one governance level up (a task's own allowance
     * vs the allowance an operator grants a principal across tasks). Must be finite, >= 0, and must still be
     * finite once converted to the ledger's micro-USD unit (`× 1e6`, i.e. below ~1.79e302 USD — an Infinity
     * threshold is not the declared ceiling in the unit the ledger counts, so such a window would read as
     * governed while enforcing nothing it was given, and is refused at the door). `0` is a real,
     * always-full window, exactly as it is for `maxTokens`.
     *
     * The two ceilings are INDEPENDENT and every DECLARED one binds: a window is exhausted when either its
     * tokens reach `maxTokens` or its cost reaches `maxCostUsd` — whichever fills first — and a ceiling that
     * is absent is not a ceiling at all (never a zero, never an infinity: it simply does not participate).
     * Absent (the default, and every pre-existing deployment) means THIS window governs tokens only — its
     * own reading never asks for or enforces a cost. Whether cost is tracked/recorded at all is a
     * DEPLOYMENT-level fact, not a
     * per-window one (the `UsageSlot.costMicroUsd` / `UsageBucketRow` in-presence condition: "while the
     * deployment governs at least one `maxCostUsd` window"): in a MIXED declaration the shared ledger
     * rows carry cost under every window's bucket, and only a deployment with NO $ window anywhere keeps
     * its rows byte-identical to the pre-cost-arm shape.
     *
     * **Requires a PRICED run.** Cost is not a number the engine can invent: a run whose model has neither a
     * `RunnerDeps.pricing` entry nor a `Model.cost` declaration produces NO cost figure at all (not a zero),
     * so a $ ceiling over it is unevaluable and the task is refused at the door
     * (`config.usage_window_unpriced`) rather than charged a fabricated 0 that would let the ceiling
     * silently stop applying.
     */
    maxCostUsd?: number;
    /** Which of the two window shapes above this is. */
    anchor: "first-use" | "rolling";
}
/** One charge against a key: `tokens` charged at epoch ms `at`. The unit of the rolling lane's ledger. */
export interface UsageSlot {
    at: number;
    tokens: number;
    /** The charge's cost in integer micro-USD. **In-presence condition:** written only while the deployment
     *  governs at least one {@link UsageWindow.maxCostUsd} window AND the charge had a cost figure at all — a
     *  token-only deployment's ledger rows are byte-for-byte what they were before the cost arm existed, and
     *  so is the row for spend nothing could price. Absent therefore reads as "no money recorded here": a row
     *  written BEFORE a $ window was declared, or one whose model had no price table, contributes 0 to the
     *  money lane rather than back-dating a number nobody recorded. */
    costMicroUsd?: number;
    /** This charge's spend could NOT be priced (see {@link UsageWindowStore.charge}'s `null` arm).
     *  **In-presence condition:** only ever `true`, only on a row written while a $ window was governed and
     *  nothing could price the spend. It is what keeps "no money here" apart from "no money spent here": a
     *  window holding one of these reports a money figure that is a LOWER BOUND, and says so
     *  ({@link UsageWindowReading.costUnknown}). */
    costUnknown?: true;
}
/** The OPEN first-use window for one `windowMs` on one key. Rows for other widths coexist, so a
 *  deployment governing 5h and 7d windows keeps one row per width rather than one blended counter. */
export interface UsageBucketRow {
    /** The width this row belongs to — the row's identity, matched against {@link UsageWindow.windowMs}. */
    windowMs: number;
    /** Epoch ms the window opened (its first charge). */
    openedAt: number;
    /** Tokens charged into it since it opened. */
    tokens: number;
    /** Integer micro-USD charged into it since it opened. Same in-presence condition as {@link UsageSlot.costMicroUsd}. */
    costMicroUsd?: number;
    /** Some spend in this open window could not be priced. Same meaning and in-presence condition as
     *  {@link UsageSlot.costUnknown}; sticky for the life of the open bucket. */
    costUnknown?: true;
}
/** Everything one key's governance state consists of: the rolling lane's slots and the first-use lane's
 *  open buckets. Persisted verbatim by every backend (plain JSON, no methods). */
export interface UsageWindowRecord {
    slots: readonly UsageSlot[];
    buckets: readonly UsageBucketRow[];
}
/** The state of one window for one key, as of a given instant. */
export interface UsageWindowReading {
    /** The window this reading answers for (verbatim, so a caller can name the offending allowance). */
    window: UsageWindow;
    /** Tokens the window currently holds. */
    tokens: number;
    /** Integer micro-USD the window currently holds. **In-presence condition:** present exactly when
     *  `window.maxCostUsd !== undefined` — a reading for a token-only window is byte-identical to what it
     *  was before the cost arm existed, and a MISSING value on a $ window means the store did not evaluate
     *  the ceiling at all (refused loudly by {@link usageRetryAfterMs}, never read as an open ceiling). */
    costMicroUsd?: number;
    /** The window holds spend nothing could price, so `costMicroUsd` is a LOWER BOUND rather than the total.
     *  **In-presence condition:** only ever `true`, and only on a window that declares `maxCostUsd`. The
     *  ceiling still binds on what IS countable (an under-count can only postpone exhaustion, never invent
     *  it), and the engine announces the gap on every run that reads it — the alternative, treating the
     *  whole window as exhausted until the unpriced charge ages out, would lock a key out for as long as
     *  `windowMs` over one degraded turn, which is a larger outage than the gap it answers. */
    costUnknown?: true;
    /** The window admits no further work: (when the window declares one) `tokens >= window.maxTokens`, OR
     *  (when the window declares one) `costMicroUsd >= window.maxCostUsd` — the two ceilings are independent
     *  and every DECLARED one binds. An undeclared axis never binds, however much the window holds on it:
     *  `tokens` is still reported for a money-only window (what it holds), it is just not a ceiling there. */
    exhausted: boolean;
    /** Ms until this window next frees capacity: for `first-use`, when the open window lapses; for
     *  `rolling`, when its OLDEST in-window slot ages out (which frees that slot's tokens, not
     *  necessarily enough for a whole task — a driver that resumes then and re-suspends is behaving
     *  correctly, and each attempt gets a fresh, later hint). `0` when the window is not exhausted. */
    retryAfterMs: number;
}
/**
 * The cross-task token ledger the governance windows are evaluated against. Deliberately two methods and
 * no query language: core charges what a task spent and asks what the key's windows hold — everything
 * else (retention, sharding, multi-writer safety) belongs to the backend.
 *
 * **Keying**: the caller passes a key that is the PRINCIPAL when the task declares one, and a single
 * shared global key otherwise (see `GLOBAL_USAGE_KEY`) — so a multi-tenant deployment governs per tenant
 * and a single-tenant one governs the deployment, with no branch in either.
 */
export interface UsageWindowStore {
    /**
     * Charge `tokens` to `key` at epoch ms `at`. `windows` is the deployment's live window set: the store
     * needs it to know which first-use buckets to keep open and how far back the rolling lane must
     * remember, so the ledger stays bounded instead of growing for the life of the deployment.
     * Called once per accounting point; never with a negative or non-finite `tokens`.
     *
     * `costMicroUsd` is the same charge's MONEY, in integer micro-USD, or `null` when the spend is real but
     * NOTHING could price it. **In-presence condition:** one of the two is supplied exactly when the
     * deployment governs at least one {@link UsageWindow.maxCostUsd} window — a token-only deployment is
     * called with the pre-cost-arm argument list and must behave identically.
     *
     * A store that governs $ windows MUST FORWARD it (into `chargeUsageRecord`, or into its own equivalent)
     * and answer {@link UsageWindowReading.costMicroUsd} from what it persisted. A decorator written against
     * the pre-cost-arm signature drops the argument silently — which is why the arithmetic refuses an absent
     * cost outright (`usage_window.store_cost_unanswered`) instead of folding it to a 0 that would leave the
     * money ceiling open forever with nothing able to notice.
     *
     * IMPLEMENTER SELF-CHECK — three questions, in order. The in-presence condition above is a
     * DEPLOYMENT-wide property of the `windows` argument, not a per-window one, and a store that reasons one
     * window at a time is exactly where it gets missed:
     *  1. Does this call's window set carry ANY window declaring `maxCostUsd`? Then this is a COST charge
     *     for every row it writes — the rolling slot is ONE row every rolling window reads, and a first-use
     *     bucket is ONE row per width shared by every window of that width — so there is no "cost only on
     *     the $ windows" split to implement. A row written cost-less because a token-only window happened
     *     to be the one in view is a row the $ window later reads as unpriced.
     *  2. Was the spend real but unpriceable (no rate for the model, a provider that answered no usage)?
     *     Then carry the `null` through AS `null`, never as `0`: `0` asserts "this charge cost nothing" and
     *     silently raises the remaining allowance, while `null` is what lets the row say so and surfaces as
     *     {@link UsageWindowReading.costUnknown}, keeping the reported total honest as a LOWER BOUND.
     *  3. Cannot answer either — the argument never reached this layer? Then leave it `undefined` and let
     *     the charge be refused loudly. A guessed 0 is the one outcome the money ceiling cannot survive.
     */
    charge(key: string, tokens: number, at: number, windows: readonly UsageWindow[], costMicroUsd?: number | null): Promise<void>;
    /** Read `key`'s state for each window as of `now`, in the order the windows were given. */
    read(key: string, windows: readonly UsageWindow[], now: number): Promise<readonly UsageWindowReading[]>;
}
/** The ledger key for a task that declares NO principal: one shared bucket that governs the whole
 *  deployment. Distinctive on purpose — it must never collide with a real principal id. */
export declare const GLOBAL_USAGE_KEY = "__usage_global__";
/** A key with no history yet. Frozen: it is handed to callers as a starting value and must not be
 *  mutated into a shared-state bug. */
export declare const EMPTY_USAGE_WINDOW_RECORD: UsageWindowRecord;
/**
 * Validate `RunnerDeps.usageWindows` at the door and return it unchanged — the `resolveTaskLimits`
 * posture: an unevaluable governance window is not a governance window, and folding it to a default
 * would govern a deployment by a number nobody chose. Refuses with `config.usage_window_invalid`.
 */
export declare function resolveUsageWindows(windows: readonly UsageWindow[] | undefined): readonly UsageWindow[] | undefined;
/** Does the deployment govern MONEY at all? The one predicate that decides whether a cost figure is asked
 *  of the engine, written into the ledger, or answered in a reading — so a token-only deployment stays
 *  byte-for-byte what it was before the cost arm existed. */
export declare function windowsGovernCost(windows: readonly UsageWindow[]): boolean;
/**
 * Fold one charge into a key's record and return the NEW record (pure — the input is never mutated, so a
 * store that keeps records in a Map cannot be corrupted by a half-applied charge).
 *
 * Retention is part of the fold rather than a separate sweep: slots older than the widest ROLLING window
 * can never be read again, and a first-use bucket for a width the deployment no longer governs can never
 * be read again either, so both are dropped here. A record therefore stays bounded by (charges within the
 * widest rolling window) + (one row per governed first-use width).
 *
 * `costMicroUsd` rides the same fold as `tokens` (integer micro-USD, never a float USD: the ledger sums
 * thousands of charges and a float would accumulate error into a money ceiling), and it is a THREE-state
 * argument while the deployment governs a $ window:
 *  - a NUMBER — the charge's cost, folded into the money lane;
 *  - `null` — the tokens are known but their cost is NOT (an unpriced model served the spend). The row is
 *    written with its tokens and NO cost field: the token ceiling stays exact, and the money lane counts
 *    nothing rather than a fabricated 0. The engine refuses such a run anyway — this keeps the ledger
 *    honest about the spend that already happened before the refusal;
 *  - `undefined` — REFUSED. Core always supplies one of the two above when a $ window is governed, so an
 *    absent argument means some store in the chain (a pre-cost-arm decorator, most likely) dropped it, and
 *    folding it to 0 would leave the money ceiling permanently open with nothing able to detect it.
 * With NO $ window governed the argument is ignored entirely and rows keep their pre-cost-arm bytes.
 * Rows that already carry a cost keep it, so removing and re-adding a $ window neither loses the history
 * nor rewrites rows that predate it.
 */
export declare function chargeUsageRecord(record: UsageWindowRecord, tokens: number, at: number, windows: readonly UsageWindow[], costMicroUsd?: number | null): UsageWindowRecord;
/**
 * Read a key's record against the governed windows as of `now` (pure). The `first-use` lane reads the open
 * bucket; the `rolling` lane sums the slots inside `(now − windowMs, now]`.
 */
export declare function readUsageRecord(record: UsageWindowRecord, windows: readonly UsageWindow[], now: number): UsageWindowReading[];
/**
 * The TIGHTEST binding constraint across a set of readings: how long the caller must wait before ANY
 * window would admit work again. `undefined` when nothing is exhausted. The MAXIMUM (not the minimum) of
 * the exhausted windows' hints — resuming when the shortest one clears would immediately re-suspend on
 * the longer one.
 *
 * It is also the ONE choke point every governance read in the engine goes through, so the integrity
 * checks live here, in two arms:
 *  - **coverage** (when the caller supplies the declared `windows`): one reading per declared window,
 *    in the order the windows were given, with the window echoed verbatim on the fields that name the
 *    allowance (`windowMs`/`anchor`/`maxTokens`/`maxCostUsd`). The per-reading arm below is
 *    structurally blind to a reading that is MISSING — a decorator store that maps only the windows
 *    it recognizes, reorders the answer, or echoes a normalized copy with `maxCostUsd` stripped would
 *    otherwise un-govern a declared ceiling with zero symptoms. Every engine read passes its windows
 *    through; the parameter stays optional so a bare-readings caller keeps the pre-coverage face.
 *  - **per-reading**: a reading for a window that DECLARES `maxCostUsd` while carrying no
 *    `costMicroUsd` means the store never evaluated the money ceiling — its `exhausted` verdict then
 *    covers the token axis alone.
 * Both arms refuse with ONE code (`usage_window.store_cost_unanswered`) rather than read as an open
 * ceiling — an unanswered window and an answered-without-cost window are the same fact ("the store
 * never proved it evaluated the declared ceiling"): a governance ceiling that silently stops applying
 * is worse than one that never existed, which is the same posture the file backend takes when its
 * ledger is unreadable.
 */
export declare function usageRetryAfterMs(readings: readonly UsageWindowReading[], windows?: readonly UsageWindow[]): number | undefined;
/**
 * Process-local {@link UsageWindowStore} reference implementation. Governs correctly within ONE Runner
 * process and loses its ledger on restart — the right choice for tests and single-process deployments,
 * and explicitly NOT the right choice for a fleet (use the file backend, or a real database, when the
 * governance must survive a restart or span replicas).
 */
export declare class InMemoryUsageWindowStore implements UsageWindowStore {
    private readonly records;
    charge(key: string, tokens: number, at: number, windows: readonly UsageWindow[], costMicroUsd?: number | null): Promise<void>;
    read(key: string, windows: readonly UsageWindow[], now: number): Promise<readonly UsageWindowReading[]>;
}
