/**
 * The settlement record and the gate outcome — the L0 vocabulary of what ONE tool-gate pass decided,
 * what ask it settled and who asked. One structure, minted once (the gate's exit; the decide lane for a
 * durable park) and projected three times without re-derivation: the `permissionDenied` observer's
 * payload, the call's `tool_end` frame, and the durable row's resolved outcome. Lives beside
 * `tool-policy.ts` rather than in it because it is a different concern from the permission verdict a
 * policy composes: a policy says allow / ask / deny; this file says how the pass that consumed that
 * verdict ended.
 */
import { type AskClass, type AskOrigin, type AssertAllKeysHandled, type ModeReleaseReason, type PermissionMode, type PersistedRuleMandate } from "./ask-origin.js";
import { type AutoModeClassifierRound, type AutoModeFallbackCause } from "./auto-mode.js";
/**
 * How the wait an ask was in ENDED — the closed set. One word per way a wait can end; the `who` on the
 * record says which party ended it and is fixed BY the word (see {@link Settlement}).
 *  - `human_allowed` / `human_refused` — a person (or the approver acting for one) decided; the refusal's
 *    own note, when the decider attached one, rides `note`.
 *  - `policy_allowed` / `policy_refused` — the DEPLOYMENT'S OWN POLICY decided: the approval channel reported
 *    that a machine, not a person, answered this ask (an unattended lane answering by class, a headless lane
 *    with no interactive approval surface, a standing deployment posture). A person and a policy are the two
 *    DECIDERS: each answers either way, with the same capabilities, and differs only in whose decision the
 *    record names. A policy's refusal is distinct from `human_refused` because the model is told a different
 *    thing: a person's "no" is the user's direction, a policy's is a capability of this run. Distinct from
 *    `no_approver` because an approval channel WAS wired and answered — core did not fall back to its own
 *    headless posture. The refusal's own note, when the channel attached one, reaches the model as the
 *    policy's words and NOT as a person's; it is not on this record (the note seat belongs to the person's
 *    two words, whose ABSENCE is a control-flow fact the policy's do not have).
 *  - `approval_window_expired` — an approval window elapsed with no answer: the engine's own approval
 *    factory window (`createApprovalPolicy.approvalTimeoutMs`), or a synchronous host approver that
 *    reported its own window elapsed.
 *  - `denial_limit_window_expired` — the classifier denial-limit fallback's auto-deny window (core's own
 *    timer over the synchronous leg) elapsed with no answer.
 *  - `park_sla_expired` — a DURABLE park's SLA deadline passed and the host's sweep resolved it as a deny
 *    (FACET A). A store `expire`/`reap` produces no `tool_end` and therefore no settlement.
 *  - `no_approver` — headless: no approver (or no question face) is wired, or the deny posture string.
 *  - `approver_unavailable` — the approver (or an ancestor's frozen approver) answered the ROUTING question
 *    "nobody reachable", and no park took the ask.
 *  - `approver_error` — the approver threw.
 *  - `approver_contract` — the approver answered outside its contract (a non-boolean verdict, an
 *    unreadable member, a timeout-settled allow, a refused attribution…).
 *  - `presentation_failed` — the args or the edit could not be safely presented/adopted (unclonable).
 *  - `blanket_allow_refused` — an allow NO PERSON JUDGED met a `requiresRealApproval` ask: a blanket
 *    `onAsk:"allow"`, or an approver's allow it reported as the deployment's policy (`settledBy: "policy"`).
 *  - `task_aborted` — the wait's abort signal ended it (the run's own end, or a turn-level interrupt).
 */
export declare const SETTLEMENT_KINDS: readonly ["human_allowed", "human_refused", "approval_window_expired", "denial_limit_window_expired", "park_sla_expired", "no_approver", "approver_unavailable", "approver_error", "approver_contract", "presentation_failed", "blanket_allow_refused", "policy_allowed", "policy_refused", "task_aborted"];
export type SettlementKind = (typeof SETTLEMENT_KINDS)[number];
/** Membership test for {@link SettlementKind} — the word crosses process boundaries on `tool_end`, so a
 *  consumer validating one it received must not hand-roll the set. */
export declare function isSettlementKind(v: unknown): v is SettlementKind;
/**
 * The settlement record: WHAT ended the wait (`kind`), WHO ended it (`who` — its shape is decided by the
 * word: the person's two words carry a person, the policy's two words the policy, the window words say whose
 * window, the park word the host, the fail-closed family nobody), WHEN (epoch ms, written at the settlement site), and for a person's
 * refusal the decider's own NOTE when one was attached (a refusal WITHOUT a note is a bare "no", the arm
 * the runner treats as a control-flow boundary for the issuing batch).
 *
 * It is a discriminated union and not a free product of `kind` × `who` on purpose: a free product can
 * express "human_allowed, ended by the engine's window" — a structurally complete record that contradicts
 * itself — and a consumer would then need the pairing rules this shape makes unwritable.
 *
 * @contract settlement.single_mint — every `Settlement` kind is composed by CORE at the site whose wait
 * ended (the ask resolver's arms, the approval factory's arms, the decide lane over a host's decision
 * FACTS), and the four DECIDER words by one composer ({@link settledByDecider}). A host never mints a kind: a synchronous approver reports `"human"`/`"timeout"`/`"policy"` on its
 * outcome and a durable decide reports `hostDecision.decidedBy` (`"person"`/`"sla_timeout"`/`"policy"`) — facts
 * core turns into the word. A settlement reaches the gate's exit only inside an engine-minted record on the decision
 * (`PermissionResult.attestation`, {@link import("./tool-policy.js").EngineAttestation}), which a policy cannot compose:
 * the receipt refuses a record the engine did not mint.
 */
export type Settlement = {
    kind: "human_allowed" | "human_refused";
    who: {
        party: "person";
        approver?: string;
    };
    when: number;
    note?: string;
} | {
    kind: "policy_allowed" | "policy_refused";
    who: {
        party: "policy";
        approver?: string;
    };
    when: number;
} | {
    kind: "approval_window_expired";
    who: {
        party: "engine";
        window: "approval_factory";
    } | {
        party: "host";
    };
    when: number;
} | {
    kind: "denial_limit_window_expired";
    who: {
        party: "engine";
        window: "denial_limit";
    };
    when: number;
} | {
    kind: "park_sla_expired";
    who: {
        party: "host";
        approver?: string;
    };
    when: number;
} | {
    kind: "no_approver" | "approver_unavailable" | "approver_error" | "approver_contract" | "presentation_failed" | "blanket_allow_refused" | "task_aborted";
    who: {
        party: "none";
    };
    when: number;
};
/**
 * WHO ended a wait — the closed set of `Settlement.who.party` words, one per party a record can name:
 * `person` (a person decided), `policy` (the deployment's own policy decided), `engine` (one of the engine's
 * own windows elapsed), `host` (the host's window or its park sweep), `none` (nobody: the engine ended the
 * wait itself — no approver, a throw, an abort, an out-of-contract answer). Which party a word names is
 * fixed by the word ({@link Settlement}); the word crosses process boundaries on `tool_end`, so a consumer
 * validating a record it received reads this set rather than hand-rolling one.
 */
export declare const SETTLEMENT_PARTIES: readonly ["person", "policy", "engine", "host", "none"];
export type SettlementParty = (typeof SETTLEMENT_PARTIES)[number];
/** Compile-time fence: `never` while the closed set and the record's `who.party` union are the same words. */
export type SettlementPartiesMatchTheRecord = AssertAllKeysHandled<Exclude<Settlement["who"]["party"], SettlementParty> | Exclude<SettlementParty, Settlement["who"]["party"]>>;
/** Membership test for {@link SettlementParty}. */
export declare function isSettlementParty(v: unknown): v is SettlementParty;
/** Who REPORTED a durable decide (`hostDecision.decidedBy`): a person, the host's own SLA sweep at the row's deadline, or the
 *  deployment's policy — the closed set; a host's decide door mirrors the words it accepts from this one. */
export declare const HOST_DECIDERS: readonly ["person", "sla_timeout", "policy"];
export type HostDecider = (typeof HOST_DECIDERS)[number];
export declare const isHostDecider: (word: unknown) => word is HostDecider;
/** The host's DECISION FACTS on a durable decide — who ended the wait, and the attribution the approval channel
 *  reported for that party. ONE shape for every decide that records its decider (a tool approval's and a plan
 *  pause's); core mints the settlement word from it ({@link settlementOfHostDecision}), the host never supplies one. */
export interface HostDecisionFacts {
    decidedBy: HostDecider;
    approver?: string;
}
/** The DECIDER arms of {@link Settlement} — a person's and the deployment policy's, the two parties that
 *  answer an ask either way. Named so a site that both composes one and quotes its note can read the seat
 *  off the record instead of re-deriving it. */
export type DeciderSettlement = Extract<Settlement, {
    who: {
        party: "person" | "policy";
    };
}>;
/**
 * A decider's NOTE, normalised — the one rule for "did the decider say anything": empty text is a
 * decider who attached nothing and reads as absent wherever the note travels. Whitespace-only text is
 * not empty by this rule and stays a note: that half is PINNED CURRENT BEHAVIOUR, not a promise —
 * nothing here requires a note to carry content, and narrowing it is a separate decision with its own
 * consumers to warn.
 */
export declare function decidersNote(text: string | undefined): string | undefined;
/**
 * THE mint for a decider's settlement — the party (a person, or the deployment's own policy) and its verdict
 * pick the word, and the channel's attribution is transcribed onto `who`. The synchronous resolver's arms,
 * the approval factory's arms and the durable decide lane all compose their decider record here, so one
 * answer cannot end as two different records depending on which path carried it, and the two parties are
 * one rule with a parameter rather than two composers.
 *
 * @contract settlement.note — the `note` seat is the PERSON's: filled exactly when the person attached a
 * reason, and its absence is how the record says the refusal was bare (the runner reads that absence, and
 * nothing else, as the issuing batch's control-flow boundary). Empty text folds to absence HERE, once, for
 * every path that fills the seat ({@link decidersNote}); a site that hand-builds the record instead is a
 * second answer to the same question, which is how one path came to halt a batch the other let run. A
 * policy's record has no note seat — its words reach the model inside the policy sentence, and a policy's
 * refusal is never a control-flow boundary — so a note handed with the policy party is not filed here.
 */
export declare function settledByDecider(party: DeciderSettlement["who"]["party"], verdict: "allowed" | "refused", approver: string | undefined, note?: string): DeciderSettlement;
/**
 * THE mint for a durable decide's settlement, from the host's decision FACTS: the SLA sweep's word is the host's own
 * record (`park_sla_expired`, whatever the verdict — the capture refuses a sweep that allows), a person's and the
 * deployment policy's go through {@link settledByDecider}. Every durable decide that records its decider — a tool
 * approval's and a plan pause's — composes its record here, so one answer cannot end as two records depending on
 * which kind of row it resolved. `note` is the decider's own text on a refusal (filed on the person's refusal only).
 */
export declare function settlementOfHostDecision(facts: HostDecisionFacts, verdict: "allowed" | "refused", note?: string): Settlement;
/** Which settlement kinds are REFUSALS (the ask ended as a deny). Total over the closed set — the fence
 *  below refuses a member without a row — so invariant I2 is a table lookup, not a list in a condition. */
export declare const SETTLEMENT_IS_REFUSAL: {
    readonly human_allowed: false;
    readonly human_refused: true;
    readonly approval_window_expired: true;
    readonly denial_limit_window_expired: true;
    readonly park_sla_expired: true;
    readonly no_approver: true;
    readonly approver_unavailable: true;
    readonly approver_error: true;
    readonly approver_contract: true;
    readonly presentation_failed: true;
    readonly blanket_allow_refused: true;
    readonly policy_allowed: false;
    readonly policy_refused: true;
    readonly task_aborted: true;
};
/** Compile-time fence: `never` while every settlement kind has a refusal row. */
export type SettlementRefusalTableCoversEveryKind = AssertAllKeysHandled<Exclude<SettlementKind, keyof typeof SETTLEMENT_IS_REFUSAL>>;
/**
 * Which settlement kinds are a refusal NOBODY JUDGED — the wait ended because this run has no one who
 * could answer the question, not because someone considered it and said no. The classifier's
 * denial-limit fallback reads it: that fallback exists to bound a classifier that would otherwise deny
 * without end, and its last resort is to STOP the run rather than let the model keep re-asking a
 * question nothing in this deployment can answer.
 *
 * It is a TABLE and not a condition for the reason the sibling above is: this question used to be a
 * hand-written two-word disjunction at one site and a three-word one at another, so a settlement word
 * added later answered it by falling out of both — which is exactly what `policy_refused` did on the
 * commit that introduced it (a headless lane that refused by policy stopped reaching the stop seat that
 * the same lane reached when it refused by returning a bare `false`).
 *
 * The rows that say `false` each say something:
 *  - the person's two words, `policy_allowed` and the window words — someone WAS asked; a decider answered,
 *    or a window ran out. The run is not out of judges. (`policy_refused` is `true`: the deployment's own
 *    policy declined a question it exists to answer, so nothing in this run will say yes to it.)
 *  - `approver_unavailable` — a ROUTING answer, not a posture: the main gate owns that arm (it may park
 *    the ask on a durable queue instead), and the two sites that treat it as headless anyway say so at
 *    their own call, because they are the ones with no park route left.
 *  - `approver_error` / `approver_contract` / `presentation_failed` — the approver was there and the
 *    engine could not use it. A defect to report, not a deployment with nobody home.
 *  - `task_aborted` — the run ended; nothing is escalating anywhere.
 */
export declare const SETTLEMENT_NOBODY_JUDGED: {
    readonly human_allowed: false;
    readonly human_refused: false;
    readonly approval_window_expired: false;
    readonly denial_limit_window_expired: false;
    readonly park_sla_expired: false;
    readonly no_approver: true;
    readonly approver_unavailable: false;
    readonly approver_error: false;
    readonly approver_contract: false;
    readonly presentation_failed: false;
    readonly blanket_allow_refused: true;
    readonly policy_allowed: false;
    readonly policy_refused: true;
    readonly task_aborted: false;
};
/** Compile-time fence: `never` while every settlement kind has a nobody-judged row. */
export type NobodyJudgedTableCoversEveryKind = AssertAllKeysHandled<Exclude<SettlementKind, keyof typeof SETTLEMENT_NOBODY_JUDGED>>;
/**
 * WHO REFUSED a call — the layer whose verdict is the deny. The other question a deny raises, "who ASKED",
 * is answered by {@link GateOutcome.origin} (an {@link import("./ask-origin.js").AskOrigin}); the two used
 * to share one seven-word list (`PermissionDeniedSource`) in which `classifier` meant both "the classifier
 * asked" and "the classifier denied".
 *  - `policy` — the deployment `ToolPolicy` denied (directly, or re-checking an approved edit), or the
 *    approval-edit chain hit its round cap.
 *  - `hook` — a PreToolUse hook denied, threw, or never answered (the engine's fail-closed block on a
 *    hook that made no decision counts as the hook layer's refusal for attribution).
 *  - `org` — an organization policy rule denied; or, on a durable resume, the org's current verdict demands a person and
 *    the recorded decider is the deployment's policy, not a person.
 *  - `classifier` — the auto-mode classifier denied directly (its ASK-side role is `origin:
 *    "denial_limit_fallback"`).
 *  - `persisted_rule` — the person's persisted-rule lane refused: a deny row (live), or, on a durable resume, a deny
 *    row, a call unreadable against the rows, or a wait for them the task's cancel ended.
 *  - `compliance` — the compliance call-time lock.
 *  - `write_protection` — an approved edit was rewritten by the restriction chain onto a write-protected
 *    path that no approval covers.
 *  - `ask_resolution` — the ask's own settlement is the refusal (a person said no, a window elapsed,
 *    nobody could be asked…); the detail is on {@link GateOutcome.settlement}.
 *  - `read_boundary` — the shell read station refused: a deny-listed read (refused on every seat, with no
 *    ask), a read the read-only shell face may not make, or a rewritten / re-established command whose reads
 *    no longer are what a person approved.
 *  - `mode` — the permission MODE refused a surviving ask at the gate's arbitration point: `dontAsk` turns every ask
 *    but a hook's own into a refusal, and `bypassPermissions` refuses a write whose protection
 *    could not be judged. The disposition carries `mode`, `askClass` and `classes` beside the word.
 */
export declare const DENIED_BY_VALUES: readonly ["policy", "hook", "org", "persisted_rule", "classifier", "compliance", "write_protection", "ask_resolution", "read_boundary", "mode"];
export type DeniedBy = (typeof DENIED_BY_VALUES)[number];
/** Membership test for {@link DeniedBy}. */
export declare function isDeniedBy(v: unknown): v is DeniedBy;
/** Which layers may VETO an approval a decider already gave (invariant I3: an approval settlement — a
 *  non-refusal kind, a person's or a policy's — beside a `denied` disposition names one of these). The
 *  approval-edit re-screen (hook), the policy, org and persisted-rule re-checks, and the write-protection
 *  re-judge run AFTER the decider's yes; the
 *  classifier and compliance run before any ask exists, and `ask_resolution` IS the
 *  settlement, not a veto of it. `persisted_rule` = a person's own standing DENY row (their settings'
 *  deny list, imported) — the personal-store sibling of `org`, and like it re-judged on an edited
 *  command. `read_boundary` vetoes too: the rewrite re-judge and the pre-spawn re-establishment run after
 *  the decider's yes, on bytes or targets the decider never saw. */
export declare const DENIED_BY_MAY_VETO: {
    readonly policy: true;
    readonly hook: true;
    readonly org: true;
    readonly persisted_rule: true;
    readonly classifier: false;
    readonly compliance: false;
    readonly write_protection: true;
    readonly ask_resolution: false;
    readonly read_boundary: true;
    readonly mode: false;
};
/** Compile-time fence: `never` while every deny layer has a veto row. */
export type VetoTableCoversEveryDeniedBy = AssertAllKeysHandled<Exclude<DeniedBy, keyof typeof DENIED_BY_MAY_VETO>>;
/**
 * The FORM of an auto-mode classifier deny — the one structural position a consumer branches on when a
 * deny came through the classifier station. The classifier ends a round three ways, and until this
 * member the wire carried the three as one layer word plus prose:
 *  - `unavailable` — the classifier could not run (the model leg threw / rejected / ran past the cap):
 *    a fail-closed refusal that SAYS SO — the call may simply be retried later (CC 2.1.250 `x1t`);
 *  - `parse_error` — the classifier answered outside its verdict contract: blocked for safety, counted by
 *    the denial limit like a ruling (CC 2.1.250 `Ure`);
 *  - ABSENT beside `deniedBy: "classifier"` — the classifier's own RULING (a `<block>yes` verdict).
 * The WHY behind an `unavailable` (error vs timeout) is not a branching fact: the deny sentence spells it
 * and the `auto_mode.classified` trace frame carries it (`cause: "error" | "timeout"`).
 */
export declare const CLASSIFIER_DENY_CAUSES: readonly ["unavailable", "parse_error"];
export type ClassifierDenyCause = (typeof CLASSIFIER_DENY_CAUSES)[number];
/** Membership test for {@link ClassifierDenyCause}. */
export declare function isClassifierDenyCause(v: unknown): v is ClassifierDenyCause;
/** Which deny layers a classifier cause may stand beside: the gate's own classifier station (`classifier`),
 *  and an ANCESTOR's frozen classifier reached through the inherited policy chain, whose deny the child's
 *  gate attributes to the chain (`policy`, station row 14) — the cause is attested by the station that
 *  minted the deny, so the word beside it is whichever layer word the child's ledger assigns. */
export declare const DENIED_BY_MAY_CARRY_CAUSE: {
    readonly policy: true;
    readonly hook: false;
    readonly org: false;
    readonly persisted_rule: false;
    readonly classifier: true;
    readonly compliance: false;
    readonly write_protection: false;
    readonly ask_resolution: false;
    readonly read_boundary: false;
    readonly mode: false;
};
/** Compile-time fence: `never` while every deny layer has a cause row. */
export type CauseTableCoversEveryDeniedBy = AssertAllKeysHandled<Exclude<DeniedBy, keyof typeof DENIED_BY_MAY_CARRY_CAUSE>>;
/** The final disposition of a gate pass. `cause` is present exactly when the deny came out of an auto-mode
 *  classifier round that did not RULE ({@link ClassifierDenyCause}); a ruling block and every non-classifier
 *  deny carry none. Invariant I5 ({@link screenGateOutcome}): a cause stands only beside a layer word in
 *  {@link DENIED_BY_MAY_CARRY_CAUSE}.
 *
 *  `classifier` — the classification's model attribution, on BOTH arms (a classification ends either way,
 *  allow or deny) and from BOTH stations (this gate's own classifier step, and an ANCESTOR's frozen
 *  classifier reached through the inherited policy chain, whose allow and deny carry it out on the same seat
 *  that carries the FORM): which model it was for, which one answered, and — only when the ladder moved —
 *  the rung it left and why. It is the classification's account, not the settlement's: a classification that
 *  RULED keeps it whoever then decided the call — a call whose question a person then answered (an ask a
 *  station after the classifier raised, or a block at the DENIAL-LIMIT bound, which becomes an ask) carries
 *  it beside that person's settlement on {@link GateOutcome}; who decided is read from the settlement
 *  (`human_allowed`, `policy_allowed`, …), never from this member's presence. ABSENT reads UNKNOWN, never
 *  "the seat answered" (that is `fallback` absent WITH the member present), and a consumer cannot tell its
 *  three causes apart from the record alone: no classification happened; one ran on a decider given no
 *  candidate ladder and can name no model (a hand-built decider; a parked ancestor's cross-process rebuild,
 *  whose single fresh leg has none); or one did not rule (it could not run, or replied with no verdict) and
 *  handed the question to the approval seat, whose settlement then names the resolution that ask reached.
 *  Additive. Invariant I6 ({@link screenGateOutcome}) screens its shape. */
export type GateDisposition = {
    kind: "allowed";
    classifier?: AutoModeClassifierRound;
    released?: ModeRelease;
} | {
    kind: "denied";
    deniedBy: DeniedBy;
    cause?: ClassifierDenyCause;
    classifier?: AutoModeClassifierRound;
    mode?: ModeRefusal["mode"];
    askClass?: AskClass;
    classes?: readonly AskClass[];
};
/**
 * A permission MODE released a surviving ask — the allowed disposition's account of the question it did not put
 * to anyone: the mode, the disclosed class word (`askClass`, the first member of the folded set in `ASK_CLASSES`
 * order — one of {@link releasableAskClassesFor} on the call's face), the whole set, and the origin / mandate words the card would
 * have shown. `reason` is a member of {@link import("./ask-origin.js").MODE_RELEASE_REASONS} (`isModeReleaseReason`):
 * `"target_unresolved"` marks a release (the shell face) over a write target whose reading could not say where it leads;
 * absent, the release names none. The record carries no face, so the
 * screen asks that SOME face releases the class.
 */
export interface ModeRelease {
    mode: PermissionMode;
    askClass: AskClass;
    classes: readonly AskClass[];
    origin?: AskOrigin;
    mandate?: PersistedRuleMandate;
    reason?: ModeReleaseReason;
}
/** The two modes that refuse on their own account (`deniedBy: "mode"`): `dontAsk` every ask but a hook's own,
 *  `bypassPermissions` a write whose protection could not be judged. `plan` refuses nothing here — its questions ask. */
export interface ModeRefusal {
    mode: "bypassPermissions" | "dontAsk";
    askClass: AskClass;
    classes: readonly AskClass[];
}
/**
 * The WHOLE record of one tool-gate pass: the final disposition, plus — when this pass settled an ask —
 * the settlement it consumed and the ask's origin. Minted ONCE (the gate's exit; the decide lane for a
 * durable park) and projected three times without re-derivation: the `permissionDenied` observer's
 * payload, the call's `tool_end` frame, and the durable row's resolved outcome. The three faces are the
 * same object graph, so they cannot tell different stories.
 *
 * The three members are orthogonal but bound by four invariants ({@link screenGateOutcome}):
 *  I1  `settlement` present ⇔ `origin` present (they describe the same ask);
 *  I2  `disposition.deniedBy === "ask_resolution"` ⇒ `settlement` present and a refusal kind;
 *  I3  `settlement` an approval (a kind {@link SETTLEMENT_IS_REFUSAL} says is not a refusal) ∧
 *      `disposition.kind === "denied"` ⇒ `deniedBy` is a veto layer ({@link DENIED_BY_MAY_VETO}) — a decider
 *      approved, a later re-check refused; the approver stays on the settlement (it is not the approver's
 *      refusal);
 *  I4  `disposition.kind === "allowed"` ⇒ `settlement` absent or an approval (not a refusal kind);
 *  I5  `disposition.cause` present ⇒ a member of {@link CLASSIFIER_DENY_CAUSES} beside a layer word
 *      {@link DENIED_BY_MAY_CARRY_CAUSE} admits (the classifier station, or the inherited chain's `policy`);
 *  I6  `disposition.classifier` present ⇒ both model ids are non-empty strings, and a `fallback` on it
 *      names a `to` that IS `modelUsed` (the ladder landed where the record says) with a cause in
 *      {@link import("./auto-mode.js").AUTO_MODE_FALLBACK_CAUSES} — a record whose `to` and `modelUsed`
 *      disagree would let a reader answer "which model decided this call?" two ways;
 *  I7  `disposition.released` present ⇒ `kind === "allowed"`, no settlement, `mode` is `bypassPermissions`,
 *      `askClass` is an ask class (a member of the closed set — SHAPE; whether the class was releasable is the mint's
 *      law at mint time, read by the gate's mode-release arm, never re-judged here against today's table: a persisted
 *      record outlives the policy of its day), every member of `classes` is an ask class, `origin` / `mandate` / `reason`,
 *      when present, are members of their closed sets, and `reason` names a member of `classes` (the mint takes it from
 *      that set) — a mode releases nothing a person answered;
 *  I8  `deniedBy === "mode"` ⇔ `mode` present (`bypassPermissions` | `dontAsk`) with `askClass` and `classes`.
 * Nothing here is read out of an ABSENCE: an ordinary allow with no ask is `{ disposition: { kind: "allowed" } }`,
 * a direct policy deny is `{ disposition: { kind: "denied", deniedBy: "policy" } }`, and neither carries a
 * settlement because neither settled one.
 */
export interface GateOutcome {
    disposition: GateDisposition;
    settlement?: Settlement;
    origin?: AskOrigin;
}
/** A release as `major.minor.patch`: the version whose engine stopped minting a retired word. */
type ReleaseVersion = `${number}.${number}.${number}`;
/**
 * The words that LEFT a closed set a gate record carries, one list per set, each word with the version whose engine stopped
 * minting it. A persisted record outlives the vocabulary of its day as it outlives the policy of its day, so the screen's
 * archive reading ({@link screenGateOutcome}) reads each set as its live members plus these, and its producer reading reads the
 * live members alone. Every set the screen reads has a list (empty when nothing left it); no word is both live and retired
 * ({@link RetiredMembersAreNotLive}). A word-indexed table ({@link DENIED_BY_MAY_VETO}, {@link DENIED_BY_MAY_CARRY_CAUSE},
 * {@link SETTLEMENT_IS_REFUSAL}) keeps rows for live words only: a retired word is read as granted nothing by it.
 */
export declare const RETIRED_MEMBERS: Readonly<{
    askClass: readonly (Readonly<{
        word: "write_protection_unresolved";
        retiredIn: ReleaseVersion;
    }> | Readonly<{
        word: "governance_unavailable";
        retiredIn: ReleaseVersion;
    }>)[];
    modeReleaseReason: readonly (Readonly<{
        word: "write_protection_unresolved";
        retiredIn: ReleaseVersion;
    }> | Readonly<{
        word: "rule_unreadable";
        retiredIn: ReleaseVersion;
    }>)[];
    askOrigin: readonly Readonly<{
        word: "unresolvable";
        retiredIn: ReleaseVersion;
    }>[];
    persistedRuleMandate: readonly Readonly<{
        word: "write_protection_unresolved";
        retiredIn: ReleaseVersion;
    }>[];
    deniedBy: readonly Readonly<{
        word: "plan_mode";
        retiredIn: ReleaseVersion;
    }>[];
    settlementKind: readonly [];
    settlementParty: readonly [];
    classifierDenyCause: readonly [];
    permissionMode: readonly [];
    autoModeFallbackCause: readonly [];
}>;
type MemberSet = keyof typeof RETIRED_MEMBERS;
type RetiredWord<S extends MemberSet> = (typeof RETIRED_MEMBERS)[S][number]["word"];
/** Compile-time fence: `never` while no retired word is also a live member of its set. */
export type RetiredMembersAreNotLive = AssertAllKeysHandled<Extract<RetiredWord<"askClass">, AskClass> | Extract<RetiredWord<"modeReleaseReason">, ModeReleaseReason> | Extract<RetiredWord<"askOrigin">, AskOrigin> | Extract<RetiredWord<"persistedRuleMandate">, PersistedRuleMandate> | Extract<RetiredWord<"deniedBy">, DeniedBy> | Extract<RetiredWord<"settlementKind">, SettlementKind> | Extract<RetiredWord<"settlementParty">, SettlementParty> | Extract<RetiredWord<"classifierDenyCause">, ClassifierDenyCause> | Extract<RetiredWord<"permissionMode">, PermissionMode> | Extract<RetiredWord<"autoModeFallbackCause">, AutoModeFallbackCause>>;
/** Compile-time fence: `never` while every reason word, live or retired, is an ask class of its day (I7 reads it in `classes`). */
export type RetiredReasonsAreClassWords = AssertAllKeysHandled<Exclude<RetiredWord<"modeReleaseReason">, AskClass | RetiredWord<"askClass">>>;
/** Whether `word` left the closed set `set` ({@link RETIRED_MEMBERS}). A set name outside the registry throws. */
export declare function isRetiredMember<S extends MemberSet>(set: S, word: unknown): word is RetiredWord<S>;
/**
 * The release law of THIS engine (I7's policy half): a mode release names a set of classes that one face of the engine's table
 * releases whole (`releasableAskClassesFor`) — the arbitration releases a set only when no member is immune on the call's face.
 * Policy, not shape — it moves between versions — so only the producer reading of {@link screenGateOutcome} reads it.
 * Module-level only; not part of the package root.
 */
export declare function releasePolicyDefects(g: unknown): string[];
/** The members only the denied arm of a {@link GateDisposition} carries. */
declare const DENY_ONLY_MEMBERS: readonly ["deniedBy", "cause", "mode", "askClass", "classes"];
type DenyOnlyMember = Exclude<keyof Extract<GateDisposition, {
    kind: "denied";
}>, keyof Extract<GateDisposition, {
    kind: "allowed";
}>>;
/** Compile-time fence: `never` while the list is exactly the denied arm's own members. */
export type DenyOnlyMembersAreListed = AssertAllKeysHandled<Exclude<DenyOnlyMember, (typeof DENY_ONLY_MEMBERS)[number]> | Exclude<(typeof DENY_ONLY_MEMBERS)[number], DenyOnlyMember>>;
/**
 * The one invariant screen for a {@link GateOutcome} (I1–I8 above, plus the closed-set word each member carries). Two readings:
 *  - `"archive"` (the default) — a record read back from where it was kept (a replay, a ledger, a durable row): its shape, with
 *    every closed set read as its live members plus {@link RETIRED_MEMBERS}. A record lawful when minted is not a defect later.
 *  - `"producer"` — a record THIS engine is composing or publishing now: the live sets alone, and the engine's release law
 *    ({@link releasePolicyDefects}). The gate's exit and its station screen read this.
 * The record is read as whatever it holds (`unknown`): a member that is not the shape the type names — `null`, an array, a
 * primitive where a record belongs, an object where a word belongs — is a defect naming its position, never an exception, and
 * every class, reason, origin and mandate word is read wherever the record carries it.
 * Returns the defects as sentences (an empty list is a clean record); the caller decides the fail-loud form (report + withhold,
 * or refuse), never silently repairs the record. An options value that is not an object, or a reading outside the two, throws.
 */
export declare function screenGateOutcome(g: unknown, opts?: {
    readonly reading?: "archive" | "producer";
}): string[];
export {};
