/**
 * Peer-sharing admission policy.
 *
 * Pure evaluation, no I/O — every input is passed in, so this module is cheap on
 * the hot path and directly exercisable from a test.
 *
 * The gate set is deliberately **orthogonal and AND-ed**: a grant may carry a
 * headroom floor *and* a window-slice ceiling *and* a model allowlist, and each
 * is checked independently. The effective allowance is therefore the minimum
 * across whatever is configured, which is what lets "share only what I am not
 * using, and never more than a fifth of it" be one grant rather than two
 * competing modes.
 *
 * Evaluation splits in two, because the two halves answer different questions:
 *
 * - `evaluateShareAdmission` — request-level. Is this borrower allowed to ask at
 *   all, right now, for this model?
 * - `filterAccountsForGrant` — account-level. Of the lender's accounts, which
 *   may serve this borrower? Headroom and slice ceilings live here because they
 *   are properties of an individual account's windows, not of the request.
 *
 * @module proxy/sharePolicy
 */
import type { ProxyShareAccountExclusion, ProxyShareAccountFilterResult, ProxyShareAccountView, ProxyShareAdmission, ProxyShareAdmissionInput, ProxyShareGates, ProxyShareGrant, ProxyShareRefusalReason, ProxyShareRefusedAdmission, ProxySharePoolUsage } from "../types/index.js";
/**
 * Narrow an admission to its refusing half.
 *
 * A plain `!admission.admitted` check would do this under `strict`, but one of
 * the package's build steps compiles without `strictNullChecks`, where TypeScript
 * declines to narrow a boolean discriminant at all. An explicit predicate holds
 * in both modes.
 */
export declare function isShareRefusal(admission: ProxyShareAdmission): admission is ProxyShareRefusedAdmission;
export declare function shareRefusalMessage(reason: ProxyShareRefusalReason): string;
/** HTTP status for a refusal. 401 is "who are you", 403 is "not you, not ever
 *  under this grant", 429 is "not now" — the borrower retries only the last. */
export declare function shareRefusalStatus(reason: ProxyShareRefusalReason): number;
/**
 * Is `now` inside the grant's allowed hours?
 *
 * A window whose start hour is greater than its end hour wraps midnight
 * (`21 → 9` means the night shift), which is the common case for lending
 * capacity you are asleep through.
 */
export declare function isWithinSchedule(schedule: {
    fromHour: number;
    toHour: number;
}, now: number): boolean;
/**
 * Does the requested model fall inside the allowlist?
 *
 * Entries are matched as case-insensitive substrings so a grant can name a tier
 * (`sonnet`) rather than having to track every dated model id.
 */
export declare function isModelAllowed(models: string[] | undefined, model: string | undefined): boolean;
/**
 * Request-level admission.
 *
 * Order matters: identity and lifecycle first (they are permanent refusals),
 * then scope, then the transient limits that carry a `Retry-After`. A borrower
 * that is told "paused" must not also be told "slow down".
 */
export declare function evaluateShareAdmission(input: ProxyShareAdmissionInput): ProxyShareAdmission;
/**
 * Is the account inside its spillover window — close enough to a reset, with
 * little enough consumed, that the remaining capacity would otherwise expire?
 *
 * Unknown reset times fail closed. A spillover grant is a promise about capacity
 * that is *about to be lost*; without a reset time there is no such promise to
 * keep, and guessing would hand out capacity the lender still intends to use.
 */
export declare function isSpilloverActive(gates: ProxyShareGates, account: ProxyShareAccountView, now: number): boolean;
/**
 * Split the pool into the accounts this grant may draw on and the rest.
 *
 * An entry in `gates.accounts` matches either the full store key
 * (`anthropic:alice`) or the bare label (`alice`), because operators think in
 * labels and the routing path thinks in keys.
 *
 * Exported because the scope decides more than admission: it is also the
 * denominator of the pool-wide slice, and computing that over accounts the grant
 * can never touch would loosen the ceiling in proportion to how many there are.
 */
export declare function accountsInGrantScope(gates: ProxyShareGates, accounts: readonly ProxyShareAccountView[]): {
    inScope: ProxyShareAccountView[];
    outOfScope: ProxyShareAccountView[];
};
/**
 * Decide which of the lender's accounts this grant may draw on.
 *
 * Returning exclusions alongside the survivors is deliberate: when nothing
 * survives, the caller needs to say *why* — "your slice is spent" and "I am
 * holding back my reserve" are different answers, and only one of them will
 * change on its own.
 */
export declare function filterAccountsForGrant(grant: ProxyShareGrant, accounts: readonly ProxyShareAccountView[], now: number, 
/**
 * Required, not optional. `gates.maxSlice` is a ceiling on what this grant
 * has already drawn from the pool, and with nothing to compare against the
 * only available answer is "not yet" — so an omitted argument would not relax
 * the ceiling, it would remove it. `readSharePoolWindowUsage` returns zeroed
 * fractions for a grant with no history, which is the honest empty value.
 */
poolUsage: ProxySharePoolUsage): ProxyShareAccountFilterResult;
/**
 * Collapse per-account exclusions into the single reason the borrower is told
 * when nothing survived. A transient cause outranks a structural one so the
 * borrower learns whether waiting is worth anything.
 */
export declare function summarizeAccountExclusions(excluded: readonly ProxyShareAccountExclusion[]): ProxyShareRefusalReason;
