/** * Capsule declaration locking {@link chooseRung} — the escalation chooser, the * READER of {@link PolicyNode} — as a standing `policyGate` contract. This is the * FIRST concrete `policyGate` instance (ADR-0008's closure rule requires one): * `chooseRung` is the canonical permission/authz check in LiteShip — it admits * (`allow`) or rejects (`deny`) a capability RUNG for a policy on a runtime site, * with a reason naming WHY. The arm ADR-0008 reserved for "permission / authz * check" finally has the decision it was reserved for. * * WHY `policyGate` (not `pureTransform`): a policyGate's job is to resolve a * verdict — `allow`/`deny` + a reason chain — against a typed subject. That is * exactly `chooseRung`: a `{policy, site}` subject in, a verdict out. Filing it as * a `pureTransform` (the prior classification) only described what it ISN'T (no * receipt byte law, no mutate channel); `policyGate` describes what it IS. The * `decide` core stays PURE and TOTAL (the same determinism discipline a * `pureTransform` `run` holds), so the harness can drive allow/deny coverage, * reason-chain integrity, and determinism for real. A policyGate returns a * verdict; it never enforces it — the side-effecting admission (refusing the * projection target) lives downstream in the compositor escalation gate * (`compositor.ts`), per ADR-0014 "no built-in authority". * * WHY THE SUBJECT IS SEED MATERIAL (not a raw `PolicyNode`): a `PolicyNode` is a * content-addressed graph node — its `id` is minted ONLY through `sealNode` over * its payload, and `chooseRung` keys its memo on that `id`. A schema-arbitrary * cannot mint that address, so the SUBJECT schema generates a fully-supported seed * (the policy's `requires`/`grants`/`sites`/`budgets` fields plus the runtime * site to decide on), and `decide` SEALS a real `PolicyNode` from it before calling * the chooser. The invariants then assert over the REAL chooser verdict, never a * weakened stand-in. To keep determinism honest under the shared memo, `decide` * resets the memo per call (the memo is a process-global cache, not part of the * value-level contract under test). * * @module */ import { Schema } from 'effect'; import type { Decision } from '../capsule.js'; import type { PolicyNode } from '../document-graph.js'; import type { EscalationResult, RungChoice } from '../escalation.js'; /** * Seed material the schema-arbitrary CAN produce: the policy's capability / * constraint fields plus the runtime site the chooser decides on. `decide` seals a * real {@link PolicyNode} from this and calls `chooseRung`. This IS the policyGate * SUBJECT — the typed thing the verdict is resolved against. */ declare const EscalationSubject: Schema.Struct<{ /** The required {@link CapTier} — the rung ceiling the chooser starts at and only DOWNGRADES from. */ readonly requires: Schema.Union, Schema.Literal<"styled">, Schema.Literal<"reactive">, Schema.Literal<"animated">, Schema.Literal<"gpu">]>; /** The granted rungs — a rung the chooser would pick must be granted here. */ readonly grants: Schema.$Array, Schema.Literal<"styled">, Schema.Literal<"reactive">, Schema.Literal<"animated">, Schema.Literal<"gpu">]>>; /** The runtime sites the policy admits. */ readonly sites: Schema.$Array, Schema.Literal<"browser">, Schema.Literal<"worker">, Schema.Literal<"edge">]>>; /** The site the chooser decides on — may or may not be in `sites` (the deny path). */ readonly site: Schema.Union, Schema.Literal<"browser">, Schema.Literal<"worker">, Schema.Literal<"edge">]>; /** Optional p95 latency budget (ms) — below a rung's floor forces a downgrade. */ readonly p95Ms: Schema.optional; /** Optional working-set budget (MB) — below a rung's floor forces a downgrade. */ readonly memoryMb: Schema.optional; /** Optional allocation class — `'zero'` forbids the heap-hungry `gpu` rung. */ readonly allocClass: Schema.optional, Schema.Literal<"bounded">, Schema.Literal<"unbounded">]>>; }>; type EscalationSubjectValue = Schema.Schema.Type; /** Build the budgets sub-record from the subject, omitting unspecified axes (so they stay `undefined`). */ declare function buildBudgets(subject: EscalationSubjectValue): PolicyNode['budgets']; /** Seal a real, content-addressed {@link PolicyNode} from a subject (its `id` is minted from the payload). */ declare function buildPolicy(subject: EscalationSubjectValue): PolicyNode; /** Narrow an {@link EscalationResult} to the success branch. */ declare function isChoice(r: EscalationResult): r is RungChoice; /** * Classify a deny `EscalationResult` into a stable, machine-readable reason * `code`. The site gate is the only branch the chooser distinguishes by message * ("does not admit runtime site"); every other unsatisfiability collapses to "no * rung admits". The `message` is the REAL chooser error string verbatim — never a * fabricated reason. */ declare function denyCode(error: string): string; /** * The pure verdict core: seal a real policy from the subject, run the chooser, and * map its result to a {@link Decision}. The reason chain justifies a REJECTION: * an `allow` is a bare admission with an EMPTY chain (there is nothing to refuse); * a `deny` carries exactly one reason whose `message` is the REAL chooser error * string verbatim — never a fabricated reason. This keeps the policyGate law * crisp: `reasons` is non-empty EXACTLY when the verdict is `deny`. * * PURE + TOTAL: every well-formed subject yields exactly one verdict, no throw. * The memo is reset per call so the value-level determinism law is proved cold, * not via a warm-cache hit. */ declare function decideEscalation(subject: EscalationSubjectValue): Decision; /** * Declared policyGate capsule for the escalation chooser. Registered in the * module-level catalog at import time; walked by the factory compiler. The * generated traversal samples subjects from {@link EscalationSubject}, drives the * REAL `decide` (which seals a real policy and calls `chooseRung`), and the * invariants assert the minimal-downgrade / site-gate / verdict-shape laws over * the REAL verdict. */ export declare const escalationChooseRungCapsule: import("../assembly.js").CapsuleDef<"policyGate", { readonly sites: readonly ("node" | "browser" | "worker" | "edge")[]; readonly requires: "static" | "styled" | "reactive" | "animated" | "gpu"; readonly grants: readonly ("static" | "styled" | "reactive" | "animated" | "gpu")[]; readonly site: "node" | "browser" | "worker" | "edge"; readonly p95Ms?: number | undefined; readonly memoryMb?: number | undefined; readonly allocClass?: "zero" | "bounded" | "unbounded" | undefined; }, { readonly effect: "allow" | "deny"; readonly reasons: readonly { readonly message: string; readonly code: string; }[]; }, unknown>; /** Internal helpers exported for direct unit assertions over the subject→policy builder and verdict core. */ export declare const _escalationChooseRungInternals: { readonly buildPolicy: typeof buildPolicy; readonly buildBudgets: typeof buildBudgets; readonly isChoice: typeof isChoice; readonly denyCode: typeof denyCode; readonly decideEscalation: typeof decideEscalation; }; export {}; //# sourceMappingURL=escalation-choose-rung.d.ts.map